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 if (fCurrentPowerState
== 0)
2496 getPMRootDomain()->handleActivityTickleForService(this);
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 // Initialize the change note.
2955 fHeadNoteFlags
= changeFlags
;
2956 fHeadNotePowerState
= powerState
;
2957 fHeadNotePowerArrayEntry
= &fPowerStates
[ powerState
];
2958 fHeadNoteParentConnection
= NULL
;
2960 if (changeFlags
& kIOPMWeInitiated
)
2962 if (changeFlags
& kIOPMSynchronize
)
2970 assert(changeFlags
& kIOPMParentInitiated
);
2971 fHeadNoteDomainFlags
= domainFlags
;
2972 fHeadNoteParentFlags
= parentFlags
;
2973 fHeadNoteParentConnection
= parentConnection
;
2974 return ParentChangeStart();
2978 //*********************************************************************************
2979 // [private] notifyInterestedDrivers
2980 //*********************************************************************************
2982 bool IOService::notifyInterestedDrivers ( void )
2984 IOPMinformee
* informee
;
2985 IOPMinformeeList
* list
= fInterestedDrivers
;
2986 DriverCallParam
* param
;
2989 PM_ASSERT_IN_GATE();
2990 assert( fDriverCallParamCount
== 0 );
2991 assert( fHeadNotePendingAcks
== 0 );
2993 fHeadNotePendingAcks
= 0;
2995 count
= list
->numberOfItems();
2997 goto done
; // no interested drivers
2999 // Allocate an array of interested drivers and their return values
3000 // for the callout thread. Everything else is still "owned" by the
3001 // PM work loop, which can run to process acknowledgePowerChange()
3004 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3005 if (count
> fDriverCallParamSlots
)
3007 if (fDriverCallParamSlots
)
3009 assert(fDriverCallParamPtr
);
3010 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
3011 fDriverCallParamPtr
= 0;
3012 fDriverCallParamSlots
= 0;
3015 param
= IONew(DriverCallParam
, count
);
3017 goto done
; // no memory
3019 fDriverCallParamPtr
= (void *) param
;
3020 fDriverCallParamSlots
= count
;
3023 informee
= list
->firstInList();
3025 for (IOItemCount i
= 0; i
< count
; i
++)
3027 informee
->timer
= -1;
3028 param
[i
].Target
= informee
;
3030 informee
= list
->nextInList( informee
);
3033 fDriverCallParamCount
= count
;
3034 fHeadNotePendingAcks
= count
;
3036 // Machine state will be blocked pending callout thread completion.
3039 assert( fLockedFlags
.DriverCallBusy
== false );
3040 fLockedFlags
.DriverCallBusy
= true;
3042 thread_call_enter( fDriverCallEntry
);
3046 // no interested drivers or did not schedule callout thread due to error.
3050 //*********************************************************************************
3051 // [private] notifyInterestedDriversDone
3052 //*********************************************************************************
3054 void IOService::notifyInterestedDriversDone ( void )
3056 IOPMinformee
* informee
;
3058 DriverCallParam
* param
;
3061 PM_ASSERT_IN_GATE();
3062 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3063 count
= fDriverCallParamCount
;
3065 assert( fLockedFlags
.DriverCallBusy
== false );
3066 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3070 for (IOItemCount i
= 0; i
< count
; i
++, param
++)
3072 informee
= (IOPMinformee
*) param
->Target
;
3073 result
= param
->Result
;
3075 if ((result
== IOPMAckImplied
) || (result
< 0))
3077 // Interested driver return IOPMAckImplied.
3078 // If informee timer is zero, it must have de-registered
3079 // interest during the thread callout. That also drops
3080 // the pending ack count.
3082 if (fHeadNotePendingAcks
&& informee
->timer
)
3083 fHeadNotePendingAcks
--;
3085 informee
->timer
= 0;
3087 else if (informee
->timer
)
3089 assert(informee
->timer
== -1);
3091 // Driver has not acked, and has returned a positive result.
3092 // Enforce a minimum permissible timeout value.
3093 // Make the min value large enough so timeout is less likely
3094 // to occur if a driver misinterpreted that the return value
3095 // should be in microsecond units. And make it large enough
3096 // to be noticeable if a driver neglects to ack.
3098 if (result
< kMinAckTimeoutTicks
)
3099 result
= kMinAckTimeoutTicks
;
3101 informee
->timer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3103 // else, child has already acked or driver has removed interest,
3104 // and head_note_pendingAcks decremented.
3105 // informee may have been removed from the interested drivers list,
3106 // thus the informee must be retained across the callout.
3108 informee
->release();
3111 fDriverCallParamCount
= 0;
3113 if ( fHeadNotePendingAcks
)
3115 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
3120 // Hop back to original machine state path (from notifyAll)
3121 fMachineState
= fNextMachineState
;
3126 //*********************************************************************************
3127 // [private] notifyChildren
3128 //*********************************************************************************
3130 void IOService::notifyChildren ( void )
3134 IOPowerConnection
* connection
;
3135 OSArray
* children
= 0;
3137 if (fStrictTreeOrder
)
3138 children
= OSArray::withCapacity(8);
3140 // Sum child power consumption in notifyChild()
3141 fHeadNotePowerArrayEntry
->staticPower
= 0;
3143 iter
= getChildIterator(gIOPowerPlane
);
3146 while ((next
= iter
->getNextObject()))
3148 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
3150 if (connection
->getReadyFlag() == false)
3152 PM_CONNECT("[%s] %s: connection not ready\n",
3153 getName(), __FUNCTION__
);
3158 children
->setObject( connection
);
3160 notifyChild( connection
,
3161 fDriverCallReason
== kDriverCallInformPreChange
);
3169 if (children
->getCount() == 0)
3171 children
->release();
3176 assert(fNotifyChildArray
== 0);
3177 fNotifyChildArray
= children
;
3178 fNextMachineState
= fMachineState
;
3179 fMachineState
= kIOPM_NotifyChildrenDone
;
3184 //*********************************************************************************
3185 // [private] notifyChildrenDone
3186 //*********************************************************************************
3188 void IOService::notifyChildrenDone ( void )
3190 PM_ASSERT_IN_GATE();
3191 assert(fNotifyChildArray
);
3192 assert(fMachineState
== kIOPM_NotifyChildrenDone
);
3194 // Interested drivers have all acked (if any), ack timer stopped.
3195 // Notify one child, wait for it to ack, then repeat for next child.
3196 // This is a workaround for some drivers with multiple instances at
3197 // the same branch in the power tree, but the driver is slow to power
3198 // up unless the tree ordering is observed. Problem observed only on
3199 // system wake, not on system sleep.
3201 // We have the ability to power off in reverse child index order.
3202 // That works nicely on some machines, but not on all HW configs.
3204 if (fNotifyChildArray
->getCount())
3206 IOPowerConnection
* connection
;
3207 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(0);
3208 fNotifyChildArray
->removeObject(0);
3209 notifyChild( connection
, fDriverCallReason
== kDriverCallInformPreChange
);
3213 fNotifyChildArray
->release();
3214 fNotifyChildArray
= 0;
3215 fMachineState
= fNextMachineState
;
3219 //*********************************************************************************
3220 // [private] notifyAll
3221 //*********************************************************************************
3223 IOReturn
IOService::notifyAll ( int nextMachineState
, bool is_prechange
)
3225 // Save the next machine_state to be restored by notifyInterestedDriversDone()
3227 PM_ASSERT_IN_GATE();
3228 fNextMachineState
= nextMachineState
;
3229 fMachineState
= kIOPM_DriverThreadCallDone
;
3230 fDriverCallReason
= is_prechange
?
3231 kDriverCallInformPreChange
: kDriverCallInformPostChange
;
3233 if (!notifyInterestedDrivers())
3234 notifyInterestedDriversDone();
3236 return IOPMWillAckLater
;
3239 //*********************************************************************************
3240 // [private, static] pmDriverCallout
3242 // Thread call context
3243 //*********************************************************************************
3245 IOReturn
IOService::actionDriverCalloutDone (
3247 void * arg0
, void * arg1
,
3248 void * arg2
, void * arg3
)
3250 IOServicePM
* pwrMgt
= (IOServicePM
*) arg0
;
3253 fLockedFlags
.DriverCallBusy
= false;
3256 if (gIOPMReplyQueue
)
3257 gIOPMReplyQueue
->signalWorkAvailable();
3259 return kIOReturnSuccess
;
3262 void IOService::pmDriverCallout ( IOService
* from
)
3265 switch (from
->fDriverCallReason
)
3267 case kDriverCallSetPowerState
:
3268 from
->driverSetPowerState();
3271 case kDriverCallInformPreChange
:
3272 case kDriverCallInformPostChange
:
3273 from
->driverInformPowerChange();
3277 panic("IOService::pmDriverCallout bad machine state %x",
3278 from
->fDriverCallReason
);
3281 gIOPMWorkLoop
->runAction(actionDriverCalloutDone
,
3283 /* arg0 */ (void *) from
->pwrMgt
);
3286 //*********************************************************************************
3287 // [private] driverSetPowerState
3289 // Thread call context
3290 //*********************************************************************************
3292 void IOService::driverSetPowerState ( void )
3295 unsigned long powerState
;
3296 DriverCallParam
* param
;
3300 assert( fLockedFlags
.DriverCallBusy
== true );
3301 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3303 assert( fDriverCallParamCount
== 1 );
3305 driver
= fControllingDriver
;
3306 powerState
= fHeadNotePowerState
;
3308 if (fLockedFlags
.PMStop
== false)
3310 OUR_PMLog( kPMLogProgramHardware
, (uintptr_t) this, powerState
);
3311 clock_get_uptime(&fDriverCallStartTime
);
3312 result
= driver
->setPowerState( powerState
, this );
3313 clock_get_uptime(&end
);
3314 OUR_PMLog((UInt32
) -kPMLogProgramHardware
, (uintptr_t) this, (UInt32
) result
);
3316 #if LOG_SETPOWER_TIMES
3317 if ((result
== IOPMAckImplied
) || (result
< 0))
3321 SUB_ABSOLUTETIME(&end
, &fDriverCallStartTime
);
3322 absolutetime_to_nanoseconds(end
, &nsec
);
3323 if (nsec
> LOG_SETPOWER_TIMES
)
3324 PM_DEBUG("%s::setPowerState(%p, %lu -> %lu) took %d ms\n",
3325 fName
, this, fCurrentPowerState
, powerState
, NS_TO_MS(nsec
));
3330 result
= kIOPMAckImplied
;
3332 param
->Result
= result
;
3335 //*********************************************************************************
3336 // [private] driverInformPowerChange
3338 // Thread call context
3339 //*********************************************************************************
3341 void IOService::driverInformPowerChange ( void )
3344 IOPMinformee
* informee
;
3347 IOPMPowerFlags powerFlags
;
3348 unsigned long powerState
;
3349 DriverCallParam
* param
;
3352 assert( fLockedFlags
.DriverCallBusy
== true );
3353 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3354 count
= fDriverCallParamCount
;
3355 assert( count
&& param
);
3357 powerFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
3358 powerState
= fHeadNotePowerState
;
3360 for (IOItemCount i
= 0; i
< count
; i
++)
3362 informee
= (IOPMinformee
*) param
->Target
;
3363 driver
= informee
->whatObject
;
3365 if ((fLockedFlags
.PMStop
== false) && informee
->active
)
3367 if (fDriverCallReason
== kDriverCallInformPreChange
)
3369 OUR_PMLog(kPMLogInformDriverPreChange
, (uintptr_t) this, powerState
);
3370 clock_get_uptime(&informee
->startTime
);
3371 result
= driver
->powerStateWillChangeTo(powerFlags
, powerState
, this);
3372 clock_get_uptime(&end
);
3373 OUR_PMLog((UInt32
)-kPMLogInformDriverPreChange
, (uintptr_t) this, result
);
3377 OUR_PMLog(kPMLogInformDriverPostChange
, (uintptr_t) this, powerState
);
3378 clock_get_uptime(&informee
->startTime
);
3379 result
= driver
->powerStateDidChangeTo(powerFlags
, powerState
, this);
3380 clock_get_uptime(&end
);
3381 OUR_PMLog((UInt32
)-kPMLogInformDriverPostChange
, (uintptr_t) this, result
);
3384 #if LOG_SETPOWER_TIMES
3385 if ((result
== IOPMAckImplied
) || (result
< 0))
3389 SUB_ABSOLUTETIME(&end
, &informee
->startTime
);
3390 absolutetime_to_nanoseconds(end
, &nsec
);
3391 if (nsec
> LOG_SETPOWER_TIMES
)
3392 PM_DEBUG("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) took %d ms\n",
3394 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
3395 driver
, fName
, fCurrentPowerState
, powerState
, NS_TO_MS(nsec
));
3400 result
= kIOPMAckImplied
;
3402 param
->Result
= result
;
3407 //*********************************************************************************
3408 // [private] notifyChild
3410 // Notify a power domain child of an upcoming power change.
3411 // If the object acknowledges the current change, we return TRUE.
3412 //*********************************************************************************
3414 bool IOService::notifyChild ( IOPowerConnection
* theNub
, bool is_prechange
)
3416 IOReturn ret
= IOPMAckImplied
;
3417 unsigned long childPower
;
3418 IOService
* theChild
;
3419 IOPMRequest
* childRequest
;
3420 uint32_t requestArg2
;
3423 PM_ASSERT_IN_GATE();
3424 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
3431 // Unless the child handles the notification immediately and returns
3432 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
3433 fHeadNotePendingAcks
++;
3434 theNub
->setAwaitingAck(true);
3436 requestArg2
= fHeadNoteFlags
;
3437 if (fHeadNotePowerState
< fCurrentPowerState
)
3438 requestArg2
|= kIOPMDomainPowerDrop
;
3440 requestType
= is_prechange
?
3441 kIOPMRequestTypePowerDomainWillChange
:
3442 kIOPMRequestTypePowerDomainDidChange
;
3444 childRequest
= acquirePMRequest( theChild
, requestType
);
3448 childRequest
->fArg0
= (void *) fHeadNotePowerArrayEntry
->outputPowerCharacter
;
3449 childRequest
->fArg1
= (void *) theNub
;
3450 childRequest
->fArg2
= (void *) requestArg2
;
3451 theChild
->submitPMRequest( childRequest
);
3452 ret
= IOPMWillAckLater
;
3456 ret
= IOPMAckImplied
;
3457 fHeadNotePendingAcks
--;
3458 theNub
->setAwaitingAck(false);
3459 childPower
= theChild
->currentPowerConsumption();
3460 if ( childPower
== kIOPMUnknown
)
3462 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
3464 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
3465 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
3469 theChild
->release();
3470 return (IOPMAckImplied
== ret
);
3474 // MARK: Power Change Initiated by Driver
3476 //*********************************************************************************
3477 // [private] OurChangeStart
3479 // Begin the processing of a power change initiated by us.
3480 //*********************************************************************************
3482 void IOService::OurChangeStart ( void )
3484 PM_ASSERT_IN_GATE();
3485 OUR_PMLog( kPMLogStartDeviceChange
, fHeadNotePowerState
, fCurrentPowerState
);
3487 // fMaxCapability is our maximum possible power state based on the current
3488 // power state of our parents. If we are trying to raise power beyond the
3489 // maximum, send an async request for more power to all parents.
3491 if (!IS_PM_ROOT() && (fMaxCapability
< fHeadNotePowerState
))
3493 fHeadNoteFlags
|= kIOPMNotDone
;
3494 requestDomainPower(fHeadNotePowerState
);
3499 // Redundant power changes skips to the end of the state machine.
3501 if (!fInitialChange
&& (fHeadNotePowerState
== fCurrentPowerState
))
3506 fInitialChange
= false;
3508 #if ROOT_DOMAIN_RUN_STATES
3509 // Change started, but may not complete...
3510 // Can be canceled (power drop) or deferred (power rise).
3512 getPMRootDomain()->handlePowerChangeStartForService(
3514 /* RD flags */ &fRootDomainState
,
3515 /* new pwr state */ fHeadNotePowerState
,
3516 /* change flags */ fHeadNoteFlags
);
3519 // Two separate paths, depending if power is being raised or lowered.
3520 // Lowering power is subject to approval by clients of this service.
3524 // Next machine state for a power drop.
3525 fMachineState
= kIOPM_OurChangeTellClientsPowerDown
;
3526 fDoNotPowerDown
= false;
3528 // Ask apps and kernel clients permission to lower power.
3529 fOutOfBandParameter
= kNotifyApps
;
3530 askChangeDown(fHeadNotePowerState
);
3534 // This service is raising power and parents are able to support the
3535 // new power state. However a parent may have already committed to
3536 // drop power, which might force this object to temporarily drop power.
3537 // This results in "oscillations" before the state machines converge
3538 // to a steady state.
3540 // To prevent this, a child must make a power reservation against all
3541 // parents before raising power. If the reservation fails, indicating
3542 // that the child will be unable to sustain the higher power state,
3543 // then the child will signal the parent to adjust power, and the child
3544 // will defer its power change.
3546 #if RESERVE_DOMAIN_POWER
3549 // Reserve parent power necessary to achieve fHeadNotePowerState.
3550 ret
= requestDomainPower( fHeadNotePowerState
, kReserveDomainPower
);
3551 if (ret
!= kIOReturnSuccess
)
3553 // Reservation failed, defer power rise.
3554 fHeadNoteFlags
|= kIOPMNotDone
;
3559 // Notify interested drivers and children.
3560 notifyAll( kIOPM_OurChangeSetPowerState
, kNotifyWillChange
);
3564 //*********************************************************************************
3566 struct IOPMRequestDomainPowerContext
{
3567 IOService
* child
; // the requesting child
3568 IOPMPowerFlags requestPowerFlags
; // power flags requested by child
3572 requestDomainPowerApplier(
3573 IORegistryEntry
* entry
,
3576 IOPowerConnection
* connection
;
3578 IOPMRequestDomainPowerContext
* context
;
3580 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)) == 0)
3582 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
3587 context
= (IOPMRequestDomainPowerContext
*) inContext
;
3589 if (connection
->parentKnowsState() && connection
->getReadyFlag())
3591 parent
->requestPowerDomainState(
3592 context
->requestPowerFlags
,
3600 //*********************************************************************************
3601 // [private] requestDomainPower
3602 //*********************************************************************************
3604 IOReturn
IOService::requestDomainPower(
3605 unsigned long ourPowerState
,
3606 IOOptionBits options
)
3608 const IOPMPowerState
* powerStateEntry
;
3609 IOPMPowerFlags requestPowerFlags
;
3610 unsigned long maxPowerState
;
3611 IOPMRequestDomainPowerContext context
;
3613 PM_ASSERT_IN_GATE();
3614 assert(ourPowerState
< fNumberOfPowerStates
);
3615 if (ourPowerState
>= fNumberOfPowerStates
)
3616 return kIOReturnBadArgument
;
3618 return kIOReturnSuccess
;
3620 // Fetch the input power flags for the requested power state.
3621 // Parent request is stated in terms of required power flags.
3623 powerStateEntry
= &fPowerStates
[ourPowerState
];
3624 requestPowerFlags
= powerStateEntry
->inputPowerRequirement
;
3626 if (powerStateEntry
->capabilityFlags
& (kIOPMChildClamp
| kIOPMPreventIdleSleep
))
3627 requestPowerFlags
|= kIOPMPreventIdleSleep
;
3628 if (powerStateEntry
->capabilityFlags
& (kIOPMChildClamp2
| kIOPMPreventSystemSleep
))
3629 requestPowerFlags
|= kIOPMPreventSystemSleep
;
3631 // Disregard the "previous request" for power reservation.
3633 if (((options
& kReserveDomainPower
) == 0) &&
3634 (fPreviousRequest
== requestPowerFlags
))
3636 // skip if domain already knows our requirements
3639 fPreviousRequest
= requestPowerFlags
;
3641 context
.child
= this;
3642 context
.requestPowerFlags
= requestPowerFlags
;
3643 fHeadNoteDomainTargetFlags
= 0;
3644 applyToParents(requestDomainPowerApplier
, &context
, gIOPowerPlane
);
3646 if (options
& kReserveDomainPower
)
3648 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
3649 fHeadNoteDomainTargetFlags
);
3651 if (maxPowerState
< fHeadNotePowerState
)
3653 PM_TRACE("%s: power desired %u:0x%x got %u:0x%x\n",
3655 (uint32_t) ourPowerState
, (uint32_t) requestPowerFlags
,
3656 (uint32_t) maxPowerState
, (uint32_t) fHeadNoteDomainTargetFlags
);
3657 return kIOReturnNoPower
;
3662 return kIOReturnSuccess
;
3665 //*********************************************************************************
3666 // [private] OurSyncStart
3667 //*********************************************************************************
3669 void IOService::OurSyncStart ( void )
3671 PM_ASSERT_IN_GATE();
3676 #if ROOT_DOMAIN_RUN_STATES
3677 getPMRootDomain()->handlePowerChangeStartForService(
3679 /* RD flags */ &fRootDomainState
,
3680 /* new pwr state */ fHeadNotePowerState
,
3681 /* change flags */ fHeadNoteFlags
);
3684 fMachineState
= kIOPM_SyncNotifyDidChange
;
3685 fDriverCallReason
= kDriverCallInformPreChange
;
3690 //*********************************************************************************
3691 // [private] OurChangeTellClientsPowerDown
3693 // All registered applications and kernel clients have positively acknowledged our
3694 // intention of lowering power. Here we notify them all that we will definitely
3695 // lower the power. If we don't have to wait for any of them to acknowledge, we
3696 // carry on by notifying interested drivers. Otherwise, we do wait.
3697 //*********************************************************************************
3699 void IOService::OurChangeTellClientsPowerDown ( void )
3701 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
3702 tellChangeDown1(fHeadNotePowerState
);
3705 //*********************************************************************************
3706 // [private] OurChangeTellPriorityClientsPowerDown
3708 // All registered applications and kernel clients have positively acknowledged our
3709 // intention of lowering power. Here we notify "priority" clients that we are
3710 // lowering power. If we don't have to wait for any of them to acknowledge, we
3711 // carry on by notifying interested drivers. Otherwise, we do wait.
3712 //*********************************************************************************
3714 void IOService::OurChangeTellPriorityClientsPowerDown ( void )
3716 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
3717 tellChangeDown2(fHeadNotePowerState
);
3720 //*********************************************************************************
3721 // [private] OurChangeNotifyInterestedDriversWillChange
3723 // All registered applications and kernel clients have acknowledged our notification
3724 // that we are lowering power. Here we notify interested drivers. If we don't have
3725 // to wait for any of them to acknowledge, we instruct our power driver to make the
3726 // change. Otherwise, we do wait.
3727 //*********************************************************************************
3729 void IOService::OurChangeNotifyInterestedDriversWillChange ( void )
3731 IOPMrootDomain
*rootDomain
;
3732 if ((rootDomain
= getPMRootDomain()) == this)
3734 rootDomain
->tracePoint(kIOPMTracePointSystemSleepDriversPhase
);
3737 notifyAll( kIOPM_OurChangeSetPowerState
, kNotifyWillChange
);
3740 //*********************************************************************************
3741 // [private] OurChangeSetPowerState
3743 // All interested drivers have acknowledged our pre-change notification of a power
3744 // change we initiated. Here we instruct our controlling driver to make
3745 // the change to the hardware. If it does so, we continue processing
3746 // (waiting for settle and notifying interested parties post-change.)
3747 // If it doesn't, we have to wait for it to acknowledge and then continue.
3748 //*********************************************************************************
3750 void IOService::OurChangeSetPowerState ( void )
3752 fNextMachineState
= kIOPM_OurChangeWaitForPowerSettle
;
3753 fMachineState
= kIOPM_DriverThreadCallDone
;
3754 fDriverCallReason
= kDriverCallSetPowerState
;
3756 if (notifyControllingDriver() == false)
3757 notifyControllingDriverDone();
3760 //*********************************************************************************
3761 // [private] OurChangeWaitForPowerSettle
3763 // Our controlling driver has changed power state on the hardware
3764 // during a power change we initiated. Wait for the driver specified
3765 // settle time to expire, before notifying interested parties post-change.
3766 //*********************************************************************************
3768 void IOService::OurChangeWaitForPowerSettle( void )
3770 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
3774 //*********************************************************************************
3775 // [private] OurChangeNotifyInterestedDriversDidChange
3777 // Power has settled on a power change we initiated. Here we notify
3778 // all our interested parties post-change. If they all acknowledge, we're
3779 // done with this change note, and we can start on the next one.
3780 // Otherwise we have to wait for acknowledgements and finish up later.
3781 //*********************************************************************************
3783 void IOService::OurChangeNotifyInterestedDriversDidChange ( void )
3785 notifyAll( kIOPM_OurChangeFinish
, kNotifyDidChange
);
3788 //*********************************************************************************
3789 // [private] OurChangeFinish
3791 // Power has settled on a power change we initiated, and
3792 // all our interested parties have acknowledged. We're
3793 // done with this change note, and we can start on the next one.
3794 //*********************************************************************************
3796 void IOService::OurChangeFinish ( void )
3802 // MARK: Power Change Initiated by Parent
3804 //*********************************************************************************
3805 // [private] ParentChangeStart
3807 // Here we begin the processing of a power change initiated by our parent.
3808 //*********************************************************************************
3810 IOReturn
IOService::ParentChangeStart ( void )
3812 PM_ASSERT_IN_GATE();
3813 OUR_PMLog( kPMLogStartParentChange
, fHeadNotePowerState
, fCurrentPowerState
);
3815 // Power domain is lowering power
3816 if ( fHeadNotePowerState
< fCurrentPowerState
)
3818 // TODO: redundant? See handlePowerDomainWillChangeTo()
3819 setParentInfo( fHeadNoteParentFlags
, fHeadNoteParentConnection
, true );
3821 #if ROOT_DOMAIN_RUN_STATES
3822 getPMRootDomain()->handlePowerChangeStartForService(
3824 /* RD flags */ &fRootDomainState
,
3825 /* new pwr state */ fHeadNotePowerState
,
3826 /* change flags */ fHeadNoteFlags
);
3829 // tell apps and kernel clients
3830 fInitialChange
= false;
3831 fMachineState
= kIOPM_ParentDownTellPriorityClientsPowerDown
;
3832 tellChangeDown1(fHeadNotePowerState
);
3833 return IOPMWillAckLater
;
3836 // Power domain is raising power
3837 if ( fHeadNotePowerState
> fCurrentPowerState
)
3839 if ( fDesiredPowerState
> fCurrentPowerState
)
3841 if ( fDesiredPowerState
< fHeadNotePowerState
)
3843 // We power up, but not all the way
3844 fHeadNotePowerState
= fDesiredPowerState
;
3845 fHeadNotePowerArrayEntry
= &fPowerStates
[fDesiredPowerState
];
3846 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
3849 // We don't need to change
3850 fHeadNotePowerState
= fCurrentPowerState
;
3851 fHeadNotePowerArrayEntry
= &fPowerStates
[fCurrentPowerState
];
3852 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
3856 if ( fHeadNoteFlags
& kIOPMDomainDidChange
)
3858 if ( fHeadNotePowerState
> fCurrentPowerState
)
3860 #if ROOT_DOMAIN_RUN_STATES
3861 getPMRootDomain()->handlePowerChangeStartForService(
3863 /* RD flags */ &fRootDomainState
,
3864 /* new pwr state */ fHeadNotePowerState
,
3865 /* change flags */ fHeadNoteFlags
);
3868 // Parent did change up - start our change up
3869 fInitialChange
= false;
3870 notifyAll( kIOPM_ParentUpSetPowerState
, kNotifyWillChange
);
3871 return IOPMWillAckLater
;
3873 else if (fHeadNoteFlags
& kIOPMSynchronize
)
3875 // We do not need to change power state, but notify
3876 // children to propagate tree synchronization.
3877 fMachineState
= kIOPM_SyncNotifyDidChange
;
3878 fDriverCallReason
= kDriverCallInformPreChange
;
3880 return IOPMWillAckLater
;
3885 return IOPMAckImplied
;
3888 //*********************************************************************************
3889 // [private] ParentDownTellPriorityClientsPowerDown
3891 // All applications and kernel clients have been notified of a power lowering
3892 // initiated by the parent and we had to wait for responses. Here
3893 // we notify any priority clients. If they all ack, we continue with the power change.
3894 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
3895 //*********************************************************************************
3897 void IOService::ParentDownTellPriorityClientsPowerDown ( void )
3899 fMachineState
= kIOPM_ParentDownNotifyInterestedDriversWillChange
;
3900 tellChangeDown2(fHeadNotePowerState
);
3903 //*********************************************************************************
3904 // [private] ParentDownNotifyInterestedDriversWillChange
3906 // All applications and kernel clients have been notified of a power lowering
3907 // initiated by the parent and we had to wait for their responses. Here we notify
3908 // any interested drivers and power domain children. If they all ack, we continue
3909 // with the power change.
3910 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
3911 //*********************************************************************************
3913 void IOService::ParentDownNotifyInterestedDriversWillChange ( void )
3915 IOPMrootDomain
*rootDomain
;
3916 if ((rootDomain
= getPMRootDomain()) == this)
3918 rootDomain
->tracePoint(kIOPMTracePointSystemSleepDriversPhase
);
3921 notifyAll( kIOPM_ParentDownSetPowerState
, kNotifyWillChange
);
3924 //*********************************************************************************
3925 // [private] ParentDownSetPowerState
3927 // We had to wait for it, but all parties have acknowledged our pre-change
3928 // notification of a power lowering initiated by the parent.
3929 // Here we instruct our controlling driver
3930 // to put the hardware in the state it needs to be in when the domain is
3931 // lowered. If it does so, we continue processing
3932 // (waiting for settle and acknowledging the parent.)
3933 // If it doesn't, we have to wait for it to acknowledge and then continue.
3934 //*********************************************************************************
3936 void IOService::ParentDownSetPowerState ( void )
3938 fNextMachineState
= kIOPM_ParentDownWaitForPowerSettle
;
3939 fMachineState
= kIOPM_DriverThreadCallDone
;
3940 fDriverCallReason
= kDriverCallSetPowerState
;
3942 if (notifyControllingDriver() == false)
3943 notifyControllingDriverDone();
3946 //*********************************************************************************
3947 // [private] ParentDownWaitForPowerSettle
3949 // Our controlling driver has changed power state on the hardware
3950 // during a power change initiated by our parent. We have had to wait
3951 // for acknowledgement from interested parties, or we have had to wait
3952 // for the controlling driver to change the state. Here we see if we need
3953 // to wait for power to settle before continuing. If not, we continue
3954 // processing (acknowledging our preparedness to the parent).
3955 // If so, we wait and continue later.
3956 //*********************************************************************************
3958 void IOService::ParentDownWaitForPowerSettle ( void )
3960 fMachineState
= kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange
;
3964 //*********************************************************************************
3965 // [private] ParentDownNotifyDidChangeAndAcknowledgeChange
3967 // Power has settled on a power change initiated by our parent. Here we
3968 // notify interested parties.
3969 //*********************************************************************************
3971 void IOService::ParentDownNotifyDidChangeAndAcknowledgeChange ( void )
3973 notifyAll( kIOPM_ParentAcknowledgePowerChange
, kNotifyDidChange
);
3976 //*********************************************************************************
3977 // [private] ParentAcknowledgePowerChange
3979 // We had to wait for it, but all parties have acknowledged our post-change
3980 // notification of a power change (either Up or Down) initiated by the parent.
3981 // Here we acknowledge the parent.
3982 //*********************************************************************************
3984 void IOService::ParentAcknowledgePowerChange ( void )
3986 IORegistryEntry
* nub
;
3989 nub
= fHeadNoteParentConnection
;
3992 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
3995 parent
->acknowledgePowerChange((IOService
*)nub
);
4001 //*********************************************************************************
4002 // [private] ParentUpSetPowerState
4004 // Our parent has informed us via powerStateDidChange that it has
4005 // raised the power in our power domain, and we have had to wait
4006 // for some interested party to acknowledge our notification.
4007 // Here we instruct our controlling
4008 // driver to program the hardware to take advantage of the higher domain
4009 // power. If it does so, we continue processing
4010 // (waiting for settle and notifying interested parties post-change.)
4011 // If it doesn't, we have to wait for it to acknowledge and then continue.
4012 //*********************************************************************************
4014 void IOService::ParentUpSetPowerState ( void )
4016 fNextMachineState
= kIOPM_ParentUpWaitForSettleTime
;
4017 fMachineState
= kIOPM_DriverThreadCallDone
;
4018 fDriverCallReason
= kDriverCallSetPowerState
;
4020 if (notifyControllingDriver() == false)
4021 notifyControllingDriverDone();
4024 //*********************************************************************************
4025 // [private] ParentUpWaitForSettleTime
4027 // Our controlling driver has changed power state on the hardware
4028 // during a power raise initiated by the parent, but we had to wait for it.
4029 // Here we see if we need to wait for power to settle before continuing.
4030 // If not, we continue processing (notifying interested parties post-change).
4031 // If so, we wait and continue later.
4032 //*********************************************************************************
4034 void IOService::ParentUpWaitForSettleTime ( void )
4036 fMachineState
= kIOPM_ParentUpNotifyInterestedDriversDidChange
;
4040 //*********************************************************************************
4041 // [private] ParentUpNotifyInterestedDriversDidChange
4043 // Power has settled on a power raise initiated by the parent.
4044 // Here we notify all our interested parties post-change. If they all acknowledge,
4045 // we're done with this change note, and we can start on the next one.
4046 // Otherwise we have to wait for acknowledgements and finish up later.
4047 //*********************************************************************************
4049 void IOService::ParentUpNotifyInterestedDriversDidChange ( void )
4051 notifyAll( kIOPM_ParentAcknowledgePowerChange
, kNotifyDidChange
);
4054 //*********************************************************************************
4055 // [private] all_done
4057 // A power change is complete, and the used post-change note is at
4058 // the head of the queue. Remove it and set myCurrentState to the result
4059 // of the change. Start up the next change in queue.
4060 //*********************************************************************************
4062 void IOService::all_done ( void )
4064 unsigned long previous_state
;
4066 #if ROOT_DOMAIN_RUN_STATES
4067 getPMRootDomain()->handlePowerChangeDoneForService(
4069 /* RD flags */ &fRootDomainState
,
4070 /* new pwr state */ fHeadNotePowerState
,
4071 /* change flags */ fHeadNoteFlags
);
4074 if ((fHeadNoteFlags
& kIOPMSynchronize
) &&
4075 ((fMachineState
== kIOPM_Finished
) || (fMachineState
== kIOPM_SyncFinish
)))
4077 // Sync operation and no power change occurred.
4078 // Do not inform driver and clients about this request completion,
4079 // except for the originator (root domain).
4081 if (getPMRequestType() == kIOPMRequestTypeSynchronizePowerTree
)
4083 powerChangeDone(fCurrentPowerState
);
4086 fMachineState
= kIOPM_Finished
;
4090 fMachineState
= kIOPM_Finished
;
4093 if ( fHeadNoteFlags
& kIOPMWeInitiated
)
4095 // could our driver switch to the new state?
4096 if ( !( fHeadNoteFlags
& kIOPMNotDone
) )
4098 // we changed, tell our parent
4099 requestDomainPower(fHeadNotePowerState
);
4101 // yes, did power raise?
4102 if ( fCurrentPowerState
< fHeadNotePowerState
)
4104 // yes, inform clients and apps
4105 tellChangeUp (fHeadNotePowerState
);
4107 previous_state
= fCurrentPowerState
;
4109 fCurrentPowerState
= fHeadNotePowerState
;
4111 fPMVars
->myCurrentState
= fCurrentPowerState
;
4113 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, 0);
4115 // inform subclass policy-maker
4116 if ((fLockedFlags
.PMStop
== false) && fParentsKnowState
)
4117 powerChangeDone(previous_state
);
4119 PM_DEBUG("%s::powerChangeDone() skipped\n", getName());
4123 // parent's power change
4124 if ( fHeadNoteFlags
& kIOPMParentInitiated
)
4126 if (((fHeadNoteFlags
& kIOPMDomainWillChange
) && (fCurrentPowerState
>= fHeadNotePowerState
)) ||
4127 ((fHeadNoteFlags
& kIOPMDomainDidChange
) && (fCurrentPowerState
< fHeadNotePowerState
)))
4130 if ( fCurrentPowerState
< fHeadNotePowerState
)
4132 // yes, inform clients and apps
4133 tellChangeUp (fHeadNotePowerState
);
4136 previous_state
= fCurrentPowerState
;
4137 fCurrentPowerState
= fHeadNotePowerState
;
4139 fPMVars
->myCurrentState
= fCurrentPowerState
;
4141 fMaxCapability
= fControllingDriver
->maxCapabilityForDomainState(fHeadNoteDomainFlags
);
4143 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, 0);
4145 // inform subclass policy-maker
4146 if ((fLockedFlags
.PMStop
== false) && fParentsKnowState
)
4147 powerChangeDone(previous_state
);
4149 PM_DEBUG("%s::powerChangeDone() skipped\n", getName());
4153 if (fCurrentPowerState
< fNumberOfPowerStates
)
4155 const IOPMPowerState
* powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4157 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4158 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4159 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4162 // When power rises enough to satisfy the tickle's desire for more power,
4163 // the condition preventing idle-timer from dropping power is removed.
4165 if (fCurrentPowerState
>= fIdleTimerMinPowerState
)
4167 fIdleTimerMinPowerState
= 0;
4171 //*********************************************************************************
4172 // [public] settleTimerExpired
4174 // Power has settled after our last change. Notify interested parties that
4175 // there is a new power state.
4176 //*********************************************************************************
4178 void IOService::settleTimerExpired ( void )
4183 //*********************************************************************************
4184 // settle_timer_expired
4186 // Holds a retain while the settle timer callout is in flight.
4187 //*********************************************************************************
4190 settle_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
4192 IOService
* me
= (IOService
*) arg0
;
4194 if (gIOPMWorkLoop
&& gIOPMReplyQueue
)
4196 gIOPMWorkLoop
->runAction(
4197 OSMemberFunctionCast(IOWorkLoop::Action
, me
, &IOService::settleTimerExpired
),
4199 gIOPMReplyQueue
->signalWorkAvailable();
4204 //*********************************************************************************
4205 // [private] startSettleTimer
4207 // Calculate a power-settling delay in microseconds and start a timer.
4208 //*********************************************************************************
4210 void IOService::startSettleTimer( void )
4212 AbsoluteTime deadline
;
4214 uint32_t settleTime
= 0;
4217 PM_ASSERT_IN_GATE();
4219 i
= fCurrentPowerState
;
4222 if ( fHeadNotePowerState
< fCurrentPowerState
)
4224 while ( i
> fHeadNotePowerState
)
4226 settleTime
+= (uint32_t) fPowerStates
[i
].settleDownTime
;
4232 if ( fHeadNotePowerState
> fCurrentPowerState
)
4234 while ( i
< fHeadNotePowerState
)
4236 settleTime
+= (uint32_t) fPowerStates
[i
+1].settleUpTime
;
4244 clock_interval_to_deadline(settleTime
, kMicrosecondScale
, &deadline
);
4245 pending
= thread_call_enter_delayed(fSettleTimer
, deadline
);
4246 if (pending
) release();
4250 //*********************************************************************************
4251 // [private] ackTimerTick
4253 // The acknowledgement timeout periodic timer has ticked.
4254 // If we are awaiting acks for a power change notification,
4255 // we decrement the timer word of each interested driver which hasn't acked.
4256 // If a timer word becomes zero, we pretend the driver aknowledged.
4257 // If we are waiting for the controlling driver to change the power
4258 // state of the hardware, we decrement its timer word, and if it becomes
4259 // zero, we pretend the driver acknowledged.
4261 // Returns true if the timer tick made it possible to advance to the next
4262 // machine state, false otherwise.
4263 //*********************************************************************************
4266 void IOService::ack_timer_ticked ( void )
4270 #endif /* !__LP64__ */
4272 bool IOService::ackTimerTick( void )
4274 IOPMinformee
* nextObject
;
4277 PM_ASSERT_IN_GATE();
4278 switch (fMachineState
) {
4279 case kIOPM_OurChangeWaitForPowerSettle
:
4280 case kIOPM_ParentDownWaitForPowerSettle
:
4281 case kIOPM_ParentUpWaitForSettleTime
:
4282 // are we waiting for controlling driver to acknowledge?
4283 if ( fDriverTimer
> 0 )
4285 // yes, decrement timer tick
4287 if ( fDriverTimer
== 0 )
4289 // controlling driver is tardy
4290 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
4291 OUR_PMLog(kPMLogCtrlDriverTardy
, 0, 0);
4292 setProperty(kIOPMTardyAckSPSKey
, kOSBooleanTrue
);
4293 PM_ERROR("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms\n",
4294 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
4296 if (gIOKitDebug
& kIOLogDebugPower
)
4298 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
4299 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
4303 // Unblock state machine and pretend driver has acked.
4307 // still waiting, set timer again
4313 case kIOPM_OurChangeSetPowerState
:
4314 case kIOPM_OurChangeFinish
:
4315 case kIOPM_ParentDownSetPowerState
:
4316 case kIOPM_ParentAcknowledgePowerChange
:
4317 case kIOPM_ParentUpSetPowerState
:
4318 case kIOPM_NotifyChildrenDone
:
4319 // are we waiting for interested parties to acknowledge?
4320 if ( fHeadNotePendingAcks
!= 0 )
4322 // yes, go through the list of interested drivers
4323 nextObject
= fInterestedDrivers
->firstInList();
4324 // and check each one
4325 while ( nextObject
!= NULL
)
4327 if ( nextObject
->timer
> 0 )
4329 nextObject
->timer
--;
4330 // this one should have acked by now
4331 if ( nextObject
->timer
== 0 )
4333 uint64_t nsec
= computeTimeDeltaNS(&nextObject
->startTime
);
4334 OUR_PMLog(kPMLogIntDriverTardy
, 0, 0);
4335 nextObject
->whatObject
->setProperty(kIOPMTardyAckPSCKey
, kOSBooleanTrue
);
4336 PM_ERROR("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) timed out after %d ms\n",
4337 nextObject
->whatObject
->getName(),
4338 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
4339 nextObject
->whatObject
, fName
, fCurrentPowerState
, fHeadNotePowerState
,
4342 // Pretend driver has acked.
4343 fHeadNotePendingAcks
--;
4346 nextObject
= fInterestedDrivers
->nextInList(nextObject
);
4349 // is that the last?
4350 if ( fHeadNotePendingAcks
== 0 )
4352 // yes, we can continue
4355 // no, set timer again
4361 case kIOPM_ParentDownTellPriorityClientsPowerDown
:
4362 case kIOPM_ParentDownNotifyInterestedDriversWillChange
:
4363 case kIOPM_OurChangeTellClientsPowerDown
:
4364 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
4365 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
4366 // apps didn't respond in time
4367 cleanClientResponses(true);
4368 OUR_PMLog(kPMLogClientTardy
, 0, 1);
4369 // tardy equates to approval
4374 PM_TRACE("%s: unexpected ack timer tick (state = %d)\n",
4375 getName(), fMachineState
);
4381 //*********************************************************************************
4382 // [private] start_ack_timer
4383 //*********************************************************************************
4385 void IOService::start_ack_timer ( void )
4387 start_ack_timer( ACK_TIMER_PERIOD
, kNanosecondScale
);
4390 void IOService::start_ack_timer ( UInt32 interval
, UInt32 scale
)
4392 AbsoluteTime deadline
;
4395 clock_interval_to_deadline(interval
, scale
, &deadline
);
4398 pending
= thread_call_enter_delayed(fAckTimer
, deadline
);
4399 if (pending
) release();
4402 //*********************************************************************************
4403 // [private] stop_ack_timer
4404 //*********************************************************************************
4406 void IOService::stop_ack_timer ( void )
4410 pending
= thread_call_cancel(fAckTimer
);
4411 if (pending
) release();
4414 //*********************************************************************************
4415 // [static] actionAckTimerExpired
4417 // Inside PM work loop's gate.
4418 //*********************************************************************************
4421 IOService::actionAckTimerExpired (
4423 void * arg0
, void * arg1
,
4424 void * arg2
, void * arg3
)
4426 IOService
* me
= (IOService
*) target
;
4429 // done will be true if the timer tick unblocks the machine state,
4430 // otherwise no need to signal the work loop.
4432 done
= me
->ackTimerTick();
4433 if (done
&& gIOPMReplyQueue
)
4434 gIOPMReplyQueue
->signalWorkAvailable();
4436 return kIOReturnSuccess
;
4439 //*********************************************************************************
4440 // ack_timer_expired
4442 // Thread call function. Holds a retain while the callout is in flight.
4443 //*********************************************************************************
4446 IOService::ack_timer_expired ( thread_call_param_t arg0
, thread_call_param_t arg1
)
4448 IOService
* me
= (IOService
*) arg0
;
4452 gIOPMWorkLoop
->runAction(&actionAckTimerExpired
, me
);
4457 //*********************************************************************************
4458 // [private] notifyControllingDriver
4459 //*********************************************************************************
4461 bool IOService::notifyControllingDriver ( void )
4463 DriverCallParam
* param
;
4464 unsigned long powerState
;
4466 PM_ASSERT_IN_GATE();
4467 assert( fDriverCallParamCount
== 0 );
4468 assert( fControllingDriver
);
4470 powerState
= fHeadNotePowerState
;
4472 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4475 param
= IONew(DriverCallParam
, 1);
4477 return false; // no memory
4479 fDriverCallParamPtr
= (void *) param
;
4480 fDriverCallParamSlots
= 1;
4483 param
->Target
= fControllingDriver
;
4484 fDriverCallParamCount
= 1;
4488 // Machine state for this object will stall waiting for a reply
4489 // from the callout thread.
4492 assert( fLockedFlags
.DriverCallBusy
== false );
4493 fLockedFlags
.DriverCallBusy
= true;
4495 thread_call_enter( fDriverCallEntry
);
4499 //*********************************************************************************
4500 // [private] notifyControllingDriverDone
4501 //*********************************************************************************
4503 void IOService::notifyControllingDriverDone( void )
4505 DriverCallParam
* param
;
4508 PM_ASSERT_IN_GATE();
4509 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4511 assert( fLockedFlags
.DriverCallBusy
== false );
4512 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
4516 assert(fDriverCallParamCount
== 1);
4518 // the return value from setPowerState()
4519 result
= param
->Result
;
4521 if ((result
== IOPMAckImplied
) || (result
< 0))
4523 // child return IOPMAckImplied
4526 else if (fDriverTimer
)
4528 assert(fDriverTimer
== -1);
4530 // Driver has not acked, and has returned a positive result.
4531 // Enforce a minimum permissible timeout value.
4532 // Make the min value large enough so timeout is less likely
4533 // to occur if a driver misinterpreted that the return value
4534 // should be in microsecond units. And make it large enough
4535 // to be noticeable if a driver neglects to ack.
4537 if (result
< kMinAckTimeoutTicks
)
4538 result
= kMinAckTimeoutTicks
;
4540 fDriverTimer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
4542 // else, child has already acked and driver_timer reset to 0.
4544 fDriverCallParamCount
= 0;
4548 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
4553 // Hop back to original machine state path.
4554 fMachineState
= fNextMachineState
;
4557 //*********************************************************************************
4558 // [public] askChangeDown
4560 // Ask registered applications and kernel clients if we can change to a lower
4563 // Subclass can override this to send a different message type. Parameter is
4564 // the destination state number.
4566 // Return true if we don't have to wait for acknowledgements
4567 //*********************************************************************************
4569 bool IOService::askChangeDown ( unsigned long stateNum
)
4571 return tellClientsWithResponse( kIOMessageCanDevicePowerOff
);
4574 //*********************************************************************************
4575 // [private] tellChangeDown1
4577 // Notify registered applications and kernel clients that we are definitely
4580 // Return true if we don't have to wait for acknowledgements
4581 //*********************************************************************************
4583 bool IOService::tellChangeDown1 ( unsigned long stateNum
)
4585 fOutOfBandParameter
= kNotifyApps
;
4586 return tellChangeDown(stateNum
);
4589 //*********************************************************************************
4590 // [private] tellChangeDown2
4592 // Notify priority clients that we are definitely dropping power.
4594 // Return true if we don't have to wait for acknowledgements
4595 //*********************************************************************************
4597 bool IOService::tellChangeDown2 ( unsigned long stateNum
)
4599 fOutOfBandParameter
= kNotifyPriority
;
4600 return tellChangeDown(stateNum
);
4603 //*********************************************************************************
4604 // [public] tellChangeDown
4606 // Notify registered applications and kernel clients that we are definitely
4609 // Subclass can override this to send a different message type. Parameter is
4610 // the destination state number.
4612 // Return true if we don't have to wait for acknowledgements
4613 //*********************************************************************************
4615 bool IOService::tellChangeDown ( unsigned long stateNum
)
4617 return tellClientsWithResponse( kIOMessageDeviceWillPowerOff
);
4620 //*********************************************************************************
4621 // cleanClientResponses
4623 //*********************************************************************************
4625 static void logAppTimeouts ( OSObject
* object
, void * arg
)
4627 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
4629 unsigned int clientIndex
;
4631 if (OSDynamicCast(_IOServiceInterestNotifier
, object
))
4633 // Discover the 'counter' value or index assigned to this client
4634 // when it was notified, by searching for the array index of the
4635 // client in an array holding the cached interested clients.
4637 clientIndex
= context
->notifyClients
->getNextIndexOfObject(object
, 0);
4639 if ((clientIndex
!= (unsigned int) -1) &&
4640 (flag
= context
->responseFlags
->getObject(clientIndex
)) &&
4641 (flag
!= kOSBooleanTrue
))
4643 OSString
* clientID
= 0;
4644 context
->us
->messageClient(context
->msgType
, object
, &clientID
);
4645 PM_ERROR(context
->errorLog
, clientID
? clientID
->getCStringNoCopy() : "");
4647 // TODO: record message type if possible
4648 IOService::getPMRootDomain()->pmStatsRecordApplicationResponse(
4649 gIOPMStatsApplicationResponseTimedOut
,
4650 clientID
? clientID
->getCStringNoCopy() : "",
4654 clientID
->release();
4659 void IOService::cleanClientResponses ( bool logErrors
)
4661 IOPMInterestContext context
;
4663 if (logErrors
&& fResponseArray
&& fNotifyClientArray
) {
4664 context
.responseFlags
= fResponseArray
;
4665 context
.notifyClients
= fNotifyClientArray
;
4666 context
.serialNumber
= fSerialNumber
;
4667 context
.counter
= 0;
4668 context
.msgType
= kIOMessageCopyClientID
;
4670 context
.maxTimeRequested
= 0;
4671 context
.stateNumber
= fHeadNotePowerState
;
4672 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
4673 context
.errorLog
= "PM notification timeout (%s)\n";
4675 switch ( fOutOfBandParameter
) {
4677 applyToInterested(gIOAppPowerStateInterest
, logAppTimeouts
, (void *) &context
);
4678 case kNotifyPriority
:
4686 // get rid of this stuff
4687 fResponseArray
->release();
4688 fResponseArray
= NULL
;
4690 if (fNotifyClientArray
)
4692 fNotifyClientArray
->release();
4693 fNotifyClientArray
= NULL
;
4699 //*********************************************************************************
4700 // [protected] tellClientsWithResponse
4702 // Notify registered applications and kernel clients that we are definitely
4705 // Return true if we don't have to wait for acknowledgements
4706 //*********************************************************************************
4708 bool IOService::tellClientsWithResponse (
4711 return tellClientsWithResponse( messageType
, 0 );
4714 bool IOService::tellClientsWithResponse (
4716 IOPMMessageFilter filter
)
4718 IOPMInterestContext context
;
4720 PM_ASSERT_IN_GATE();
4721 assert( fResponseArray
== NULL
);
4722 assert( fNotifyClientArray
== NULL
);
4724 fResponseArray
= OSArray::withCapacity( 1 );
4725 if (!fResponseArray
)
4728 fResponseArray
->setCapacityIncrement(8);
4731 context
.responseFlags
= fResponseArray
;
4732 context
.notifyClients
= 0;
4733 context
.serialNumber
= fSerialNumber
;
4734 context
.counter
= 0;
4735 context
.msgType
= messageType
;
4737 context
.maxTimeRequested
= 0;
4738 context
.stateNumber
= fHeadNotePowerState
;
4739 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
4740 context
.filterFunc
= filter
;
4742 switch ( fOutOfBandParameter
) {
4744 applyToInterested( gIOAppPowerStateInterest
,
4745 pmTellAppWithResponse
, (void *) &context
);
4746 fNotifyClientArray
= context
.notifyClients
;
4748 applyToInterested( gIOGeneralInterest
,
4749 pmTellClientWithResponse
, (void *) &context
);
4752 case kNotifyPriority
:
4753 applyToInterested( gIOPriorityPowerStateInterest
,
4754 pmTellClientWithResponse
, (void *) &context
);
4758 // do we have to wait for somebody?
4759 if ( !checkForDone() )
4761 OUR_PMLog(kPMLogStartAckTimer
, context
.maxTimeRequested
, 0);
4762 start_ack_timer( context
.maxTimeRequested
/ 1000, kMillisecondScale
);
4767 // everybody responded
4770 fResponseArray
->release();
4771 fResponseArray
= NULL
;
4773 if (fNotifyClientArray
)
4775 fNotifyClientArray
->release();
4776 fNotifyClientArray
= NULL
;
4782 //*********************************************************************************
4783 // [static private] pmTellAppWithResponse
4785 // We send a message to an application, and we expect a response, so we compute a
4786 // cookie we can identify the response with.
4787 //*********************************************************************************
4789 void IOService::pmTellAppWithResponse ( OSObject
* object
, void * arg
)
4791 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
4792 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
4796 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
4798 // object must be an _IOServiceInterestNotifier.
4802 // Lazily create app clients array.
4803 if (0 == context
->notifyClients
)
4805 context
->notifyClients
= OSArray::withCapacity( 32 );
4808 if (context
->filterFunc
&& !context
->filterFunc(object
, arg
))
4810 // ack - needed to match the counter index at logAppTimeouts().
4811 context
->responseFlags
->setObject(context
->counter
, kOSBooleanTrue
);
4812 if (context
->notifyClients
)
4813 context
->notifyClients
->setObject(context
->counter
, kOSBooleanTrue
);
4817 refcon
= ((context
->serialNumber
& 0xFFFF)<<16)
4818 + (context
->counter
& 0xFFFF);
4819 OUR_PMLog(kPMLogAppNotify
, context
->msgType
, refcon
);
4821 if (gIOKitDebug
& kIOLogDebugPower
)
4823 // Log client pid/name and associated index.
4824 OSString
* clientID
= 0;
4825 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
4826 PM_DEBUG("[Notify %u] message 0x%x to %s\n",
4827 (uint32_t) context
->counter
,
4829 clientID
? clientID
->getCStringNoCopy() : "");
4830 if (clientID
) clientID
->release();
4833 #if LOG_APP_RESPONSE_TIMES
4835 clock_get_uptime(&now
);
4836 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
4839 context
->responseFlags
->setObject(context
->counter
, num
);
4844 context
->responseFlags
->setObject(context
->counter
, kOSBooleanFalse
);
4846 if (context
->notifyClients
)
4847 context
->notifyClients
->setObject(context
->counter
, object
);
4849 context
->us
->messageClient(context
->msgType
, object
, (void *)refcon
);
4850 if ( context
->maxTimeRequested
< k30seconds
)
4852 context
->maxTimeRequested
= k30seconds
;
4859 //*********************************************************************************
4860 // [static private] pmTellClientWithResponse
4862 // We send a message to an in-kernel client, and we expect a response, so we compute a
4863 // cookie we can identify the response with.
4864 // If it doesn't understand the notification (it is not power-management savvy)
4865 // we won't wait for it to prepare for sleep. If it tells us via a return code
4866 // in the passed struct that it is currently ready, we won't wait for it to prepare.
4867 // If it tells us via the return code in the struct that it does need time, we will chill.
4868 //*********************************************************************************
4870 void IOService::pmTellClientWithResponse ( OSObject
* object
, void * arg
)
4872 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
4873 IOPowerStateChangeNotification notify
;
4878 if (context
->filterFunc
&& !context
->filterFunc(object
, arg
))
4881 refcon
= ((context
->serialNumber
& 0xFFFF)<<16) + (context
->counter
& 0xFFFF);
4882 context
->responseFlags
->setObject(context
->counter
, kOSBooleanFalse
);
4884 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
4885 if (gIOKitDebug
& kIOLogPower
) {
4886 OUR_PMLog(kPMLogClientNotify
, refcon
, (UInt32
) context
->msgType
);
4887 if (OSDynamicCast(IOService
, object
)) {
4888 const char *who
= ((IOService
*) object
)->getName();
4889 gPlatform
->PMLog(who
,
4890 kPMLogClientNotify
, * (UInt32
*) object
, (UInt64
) object
);
4891 } else if (OSDynamicCast(_IOServiceInterestNotifier
, object
)) {
4892 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
4893 OUR_PMLog(kPMLogClientNotify
, (UInt64
) n
->handler
, 0);
4897 notify
.powerRef
= (void *)refcon
;
4898 notify
.returnValue
= 0;
4899 notify
.stateNumber
= context
->stateNumber
;
4900 notify
.stateFlags
= context
->stateFlags
;
4901 retCode
= context
->us
->messageClient(context
->msgType
,object
,(void *)¬ify
);
4902 if ( retCode
== kIOReturnSuccess
)
4904 if ( notify
.returnValue
== 0 )
4906 // client doesn't want time to respond
4907 context
->responseFlags
->replaceObject(context
->counter
, kOSBooleanTrue
);
4908 OUR_PMLog(kPMLogClientAcknowledge
, refcon
, (UInt64
) object
);
4910 // it does want time, and it hasn't responded yet
4911 theFlag
= context
->responseFlags
->getObject(context
->counter
);
4912 if ( kOSBooleanTrue
!= theFlag
)
4914 // so note its time requirement
4915 if ( context
->maxTimeRequested
< notify
.returnValue
)
4917 context
->maxTimeRequested
= notify
.returnValue
;
4922 OUR_PMLog(kPMLogClientAcknowledge
, refcon
, 0);
4923 // not a client of ours
4924 // so we won't be waiting for response
4925 context
->responseFlags
->replaceObject(context
->counter
, kOSBooleanTrue
);
4930 //*********************************************************************************
4931 // [public] tellNoChangeDown
4933 // Notify registered applications and kernel clients that we are not
4936 // Subclass can override this to send a different message type. Parameter is
4937 // the aborted destination state number.
4938 //*********************************************************************************
4940 void IOService::tellNoChangeDown ( unsigned long )
4942 return tellClients( kIOMessageDeviceWillNotPowerOff
);
4945 //*********************************************************************************
4946 // [public] tellChangeUp
4948 // Notify registered applications and kernel clients that we are raising power.
4950 // Subclass can override this to send a different message type. Parameter is
4951 // the aborted destination state number.
4952 //*********************************************************************************
4954 void IOService::tellChangeUp ( unsigned long )
4956 return tellClients( kIOMessageDeviceHasPoweredOn
);
4959 //*********************************************************************************
4960 // [protected] tellClients
4962 // Notify registered applications and kernel clients of something.
4963 //*********************************************************************************
4965 void IOService::tellClients ( int messageType
)
4967 tellClients( messageType
, 0 );
4970 void IOService::tellClients ( int messageType
, IOPMMessageFilter filter
)
4972 IOPMInterestContext context
;
4974 context
.msgType
= messageType
;
4976 context
.stateNumber
= fHeadNotePowerState
;
4977 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
4978 context
.filterFunc
= filter
;
4980 applyToInterested( gIOPriorityPowerStateInterest
,
4981 tellKernelClientApplier
, (void *) &context
);
4983 applyToInterested( gIOAppPowerStateInterest
,
4984 tellAppClientApplier
, (void *) &context
);
4986 applyToInterested( gIOGeneralInterest
,
4987 tellKernelClientApplier
, (void *) &context
);
4990 //*********************************************************************************
4991 // [private] tellKernelClientApplier
4993 // Message a kernel client.
4994 //*********************************************************************************
4996 static void tellKernelClientApplier ( OSObject
* object
, void * arg
)
4998 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
4999 IOPowerStateChangeNotification notify
;
5001 if (context
->filterFunc
&& !context
->filterFunc(object
, arg
))
5004 notify
.powerRef
= (void *) 0;
5005 notify
.returnValue
= 0;
5006 notify
.stateNumber
= context
->stateNumber
;
5007 notify
.stateFlags
= context
->stateFlags
;
5009 context
->us
->messageClient(context
->msgType
, object
, ¬ify
);
5012 //*********************************************************************************
5013 // [private] tellAppClientApplier
5015 // Message a registered application.
5016 //*********************************************************************************
5018 static void tellAppClientApplier ( OSObject
* object
, void * arg
)
5020 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5022 if (context
->filterFunc
&& !context
->filterFunc(object
, arg
))
5025 context
->us
->messageClient(context
->msgType
, object
, 0);
5028 //*********************************************************************************
5029 // [private] checkForDone
5030 //*********************************************************************************
5032 bool IOService::checkForDone ( void )
5037 if ( fResponseArray
== NULL
)
5042 for ( i
= 0; ; i
++ )
5044 theFlag
= fResponseArray
->getObject(i
);
5045 if ( theFlag
== NULL
)
5049 if ( kOSBooleanTrue
!= theFlag
)
5057 //*********************************************************************************
5058 // [public] responseValid
5059 //*********************************************************************************
5061 bool IOService::responseValid ( unsigned long x
, int pid
)
5063 UInt16 serialComponent
;
5064 UInt16 ordinalComponent
;
5066 unsigned long refcon
= (unsigned long) x
;
5068 serialComponent
= (refcon
>> 16) & 0xFFFF;
5069 ordinalComponent
= (refcon
& 0xFFFF);
5071 if ( serialComponent
!= fSerialNumber
)
5076 if ( fResponseArray
== NULL
)
5081 theFlag
= fResponseArray
->getObject(ordinalComponent
);
5089 if ((num
= OSDynamicCast(OSNumber
, theFlag
)))
5091 #if LOG_APP_RESPONSE_TIMES
5096 clock_get_uptime(&now
);
5097 AbsoluteTime_to_scalar(&start
) = num
->unsigned64BitValue();
5098 SUB_ABSOLUTETIME(&now
, &start
);
5099 absolutetime_to_nanoseconds(now
, &nsec
);
5102 if (nsec
> LOG_APP_RESPONSE_TIMES
)
5104 OSString
* name
= IOCopyLogNameForPID(pid
);
5105 PM_DEBUG("PM response took %d ms (%s)\n", NS_TO_MS(nsec
),
5106 name
? name
->getCStringNoCopy() : "");
5108 if (nsec
> LOG_APP_RESPONSE_MSG_TRACER
)
5110 // TODO: populate the messageType argument
5111 getPMRootDomain()->pmStatsRecordApplicationResponse(
5112 gIOPMStatsApplicationResponseSlow
,
5113 name
? name
->getCStringNoCopy() : "", 0,
5114 NS_TO_MS(nsec
), pid
);
5121 theFlag
= kOSBooleanFalse
;
5124 if ( kOSBooleanFalse
== theFlag
)
5126 if ((gIOKitDebug
& kIOLogDebugPower
) &&
5127 (fOutOfBandParameter
== kNotifyApps
))
5129 PM_DEBUG("[Notify %u] acked\n", (uint32_t) ordinalComponent
);
5131 fResponseArray
->replaceObject(ordinalComponent
, kOSBooleanTrue
);
5137 //*********************************************************************************
5138 // [public] allowPowerChange
5140 // Our power state is about to lower, and we have notified applications
5141 // and kernel clients, and one of them has acknowledged. If this is the last to do
5142 // so, and all acknowledgements are positive, we continue with the power change.
5144 // We serialize this processing with timer expiration with a command gate on the
5145 // power management workloop, which the timer expiration is command gated to as well.
5146 //*********************************************************************************
5148 IOReturn
IOService::allowPowerChange ( unsigned long refcon
)
5150 IOPMRequest
* request
;
5155 return kIOReturnSuccess
;
5158 request
= acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange
);
5160 return kIOReturnNoMemory
;
5162 request
->fArg0
= (void *) refcon
;
5163 request
->fArg1
= (void *) proc_selfpid();
5164 request
->fArg2
= (void *) 0;
5165 submitPMRequest( request
);
5167 return kIOReturnSuccess
;
5171 IOReturn
IOService::serializedAllowPowerChange2 ( unsigned long refcon
)
5173 // [deprecated] public
5174 return kIOReturnUnsupported
;
5176 #endif /* !__LP64__ */
5178 //*********************************************************************************
5179 // [public] cancelPowerChange
5181 // Our power state is about to lower, and we have notified applications
5182 // and kernel clients, and one of them has vetoed the change. If this is the last
5183 // client to respond, we abandon the power change.
5185 // We serialize this processing with timer expiration with a command gate on the
5186 // power management workloop, which the timer expiration is command gated to as well.
5187 //*********************************************************************************
5189 IOReturn
IOService::cancelPowerChange ( unsigned long refcon
)
5191 IOPMRequest
* request
;
5197 return kIOReturnSuccess
;
5200 name
= IOCopyLogNameForPID(proc_selfpid());
5201 PM_ERROR("PM notification cancel (%s)\n", name
? name
->getCStringNoCopy() : "");
5203 request
= acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange
);
5208 return kIOReturnNoMemory
;
5211 request
->fArg0
= (void *) refcon
;
5212 request
->fArg1
= (void *) proc_selfpid();
5213 request
->fArg2
= (void *) name
;
5214 submitPMRequest( request
);
5216 return kIOReturnSuccess
;
5220 IOReturn
IOService::serializedCancelPowerChange2 ( unsigned long refcon
)
5222 // [deprecated] public
5223 return kIOReturnUnsupported
;
5226 //*********************************************************************************
5227 // PM_Clamp_Timer_Expired
5229 // called when clamp timer expires...set power state to 0.
5230 //*********************************************************************************
5232 void IOService::PM_Clamp_Timer_Expired ( void )
5236 //*********************************************************************************
5239 // Set to highest available power state for a minimum of duration milliseconds
5240 //*********************************************************************************
5242 void IOService::clampPowerOn ( unsigned long duration
)
5245 #endif /* !__LP64__ */
5247 //*********************************************************************************
5248 // [public] setPowerState
5250 // Does nothing here. This should be implemented in a subclass driver.
5251 //*********************************************************************************
5253 IOReturn
IOService::setPowerState (
5254 unsigned long powerStateOrdinal
, IOService
* whatDevice
)
5259 //*********************************************************************************
5260 // [public] maxCapabilityForDomainState
5262 // Finds the highest power state in the array whose input power
5263 // requirement is equal to the input parameter. Where a more intelligent
5264 // decision is possible, override this in the subclassed driver.
5265 //*********************************************************************************
5267 unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainState
)
5271 if (fNumberOfPowerStates
== 0 )
5275 for ( i
= fNumberOfPowerStates
- 1; i
>= 0; i
-- )
5277 if ( (domainState
& fPowerStates
[i
].inputPowerRequirement
) ==
5278 fPowerStates
[i
].inputPowerRequirement
)
5286 //*********************************************************************************
5287 // [public] initialPowerStateForDomainState
5289 // Finds the highest power state in the array whose input power
5290 // requirement is equal to the input parameter. Where a more intelligent
5291 // decision is possible, override this in the subclassed driver.
5292 //*********************************************************************************
5294 unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domainState
)
5298 if (fNumberOfPowerStates
== 0 )
5302 for ( i
= fNumberOfPowerStates
- 1; i
>= 0; i
-- )
5304 if ( (domainState
& fPowerStates
[i
].inputPowerRequirement
) ==
5305 fPowerStates
[i
].inputPowerRequirement
)
5313 //*********************************************************************************
5314 // [public] powerStateForDomainState
5316 // Finds the highest power state in the array whose input power
5317 // requirement is equal to the input parameter. Where a more intelligent
5318 // decision is possible, override this in the subclassed driver.
5319 //*********************************************************************************
5321 unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState
)
5325 if (fNumberOfPowerStates
== 0 )
5329 for ( i
= fNumberOfPowerStates
- 1; i
>= 0; i
-- )
5331 if ( (domainState
& fPowerStates
[i
].inputPowerRequirement
) ==
5332 fPowerStates
[i
].inputPowerRequirement
)
5341 //*********************************************************************************
5342 // [deprecated] didYouWakeSystem
5344 // Does nothing here. This should be implemented in a subclass driver.
5345 //*********************************************************************************
5347 bool IOService::didYouWakeSystem ( void )
5351 #endif /* !__LP64__ */
5353 //*********************************************************************************
5354 // [public] powerStateWillChangeTo
5356 // Does nothing here. This should be implemented in a subclass driver.
5357 //*********************************************************************************
5359 IOReturn
IOService::powerStateWillChangeTo ( IOPMPowerFlags
, unsigned long, IOService
* )
5361 return kIOPMAckImplied
;
5364 //*********************************************************************************
5365 // [public] powerStateDidChangeTo
5367 // Does nothing here. This should be implemented in a subclass driver.
5368 //*********************************************************************************
5370 IOReturn
IOService::powerStateDidChangeTo ( IOPMPowerFlags
, unsigned long, IOService
* )
5372 return kIOPMAckImplied
;
5375 //*********************************************************************************
5376 // [protected] powerChangeDone
5378 // Called from PM work loop thread.
5379 // Does nothing here. This should be implemented in a subclass policy-maker.
5380 //*********************************************************************************
5382 void IOService::powerChangeDone ( unsigned long )
5387 //*********************************************************************************
5388 // [deprecated] newTemperature
5390 // Does nothing here. This should be implemented in a subclass driver.
5391 //*********************************************************************************
5393 IOReturn
IOService::newTemperature ( long currentTemp
, IOService
* whichZone
)
5397 #endif /* !__LP64__ */
5399 //*********************************************************************************
5400 // [public] systemWillShutdown
5402 // System shutdown and restart notification.
5403 //*********************************************************************************
5405 void IOService::systemWillShutdown( IOOptionBits specifier
)
5407 IOPMrootDomain
* rootDomain
= IOService::getPMRootDomain();
5409 rootDomain
->acknowledgeSystemWillShutdown( this );
5412 //*********************************************************************************
5413 // [private static] acquirePMRequest
5414 //*********************************************************************************
5417 IOService::acquirePMRequest( IOService
* target
, IOOptionBits requestType
,
5418 IOPMRequest
* active
)
5420 IOPMRequest
* request
;
5424 request
= IOPMRequest::create();
5427 request
->init( target
, requestType
);
5430 IOPMRequest
* root
= active
->getRootRequest();
5431 if (root
) request
->attachRootRequest(root
);
5436 PM_ERROR("%s: No memory for PM request type 0x%x\n",
5437 target
->getName(), (uint32_t) requestType
);
5442 //*********************************************************************************
5443 // [private static] releasePMRequest
5444 //*********************************************************************************
5446 void IOService::releasePMRequest( IOPMRequest
* request
)
5455 //*********************************************************************************
5456 // [private] submitPMRequest
5457 //*********************************************************************************
5459 void IOService::submitPMRequest( IOPMRequest
* request
)
5462 assert( gIOPMReplyQueue
);
5463 assert( gIOPMRequestQueue
);
5465 PM_TRACE("[+ %02lx] %p [%p %s] %p %p %p\n",
5466 (long)request
->getType(), request
,
5467 request
->getTarget(), request
->getTarget()->getName(),
5468 request
->fArg0
, request
->fArg1
, request
->fArg2
);
5470 if (request
->isReplyType())
5471 gIOPMReplyQueue
->queuePMRequest( request
);
5473 gIOPMRequestQueue
->queuePMRequest( request
);
5476 void IOService::submitPMRequest( IOPMRequest
** requests
, IOItemCount count
)
5479 assert( count
> 0 );
5480 assert( gIOPMRequestQueue
);
5482 for (IOItemCount i
= 0; i
< count
; i
++)
5484 IOPMRequest
* req
= requests
[i
];
5485 PM_TRACE("[+ %02lx] %p [%p %s] %p %p %p\n",
5486 (long)req
->getType(), req
,
5487 req
->getTarget(), req
->getTarget()->getName(),
5488 req
->fArg0
, req
->fArg1
, req
->fArg2
);
5491 gIOPMRequestQueue
->queuePMRequestChain( requests
, count
);
5494 //*********************************************************************************
5495 // [private] servicePMRequestQueue
5496 //*********************************************************************************
5498 bool IOService::servicePMRequestQueue(
5499 IOPMRequest
* request
,
5500 IOPMRequestQueue
* queue
)
5502 // Calling PM methods without PMinit() is not allowed, fail the requests.
5506 PM_DEBUG("%s: PM not initialized\n", getName());
5510 // Create an IOPMWorkQueue on demand, when the initial PM request is
5515 // Allocate and attach an IOPMWorkQueue on demand to avoid taking
5516 // the work loop lock in PMinit(), which may deadlock with certain
5517 // drivers / families.
5519 fPMWorkQueue
= IOPMWorkQueue::create(
5521 /* Work */ OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
5522 &IOService::servicePMRequest
),
5523 /* Done */ OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
5524 &IOService::retirePMRequest
)
5528 (gIOPMWorkLoop
->addEventSource(fPMWorkQueue
) != kIOReturnSuccess
))
5530 PM_ERROR("%s: add PM work queue failed\n", getName());
5531 fPMWorkQueue
->release();
5537 PM_ERROR("%s: no PM work queue (type %02lx)\n",
5538 getName(), (long)request
->getType());
5543 fPMWorkQueue
->queuePMRequest(request
);
5544 return false; // do not signal more
5547 fAdjustPowerScheduled
= false;
5548 gIOPMFreeQueue
->queuePMRequest(request
);
5549 return false; // do not signal more
5552 //*********************************************************************************
5553 // [private] servicePMFreeQueue
5555 // Called by the request completion to recycle a completed request.
5556 //*********************************************************************************
5558 bool IOService::servicePMFreeQueue(
5559 IOPMRequest
* request
,
5560 IOPMCompletionQueue
* queue
)
5562 bool more
= request
->getNextRequest();
5563 IOPMRequest
* root
= request
->getRootRequest();
5565 if (root
&& (root
!= request
))
5568 releasePMRequest( request
);
5572 //*********************************************************************************
5573 // [private] retirePMRequest
5575 // Called by IOPMWorkQueue to retire a completed request.
5576 //*********************************************************************************
5578 bool IOService::retirePMRequest( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
5580 assert(request
&& queue
);
5582 PM_TRACE("[- %02x] %p [%p %s] State %d, Busy %d\n",
5583 request
->getType(), request
, this, getName(),
5584 fMachineState
, gIOPMBusyCount
);
5586 // Catch requests created by idleTimerExpired().
5588 if ((request
->getType() == kIOPMRequestTypeActivityTickle
) &&
5589 (request
->fArg1
== (void *) false))
5591 // Idle timer power drop request completed.
5592 // Restart the idle timer if deviceDesire can go lower, otherwise set
5593 // a flag so we know to restart idle timer when deviceDesire goes up.
5595 if (fDeviceDesire
> 0)
5597 fActivityTickleCount
= 0;
5598 clock_get_uptime(&fIdleTimerStartTime
);
5599 start_PM_idle_timer();
5602 fIdleTimerStopped
= true;
5605 gIOPMFreeQueue
->queuePMRequest( request
);
5609 //*********************************************************************************
5610 // [private] isPMBlocked
5612 // Check if machine state transition is blocked.
5613 //*********************************************************************************
5615 bool IOService::isPMBlocked ( IOPMRequest
* request
, int count
)
5620 if (kIOPM_Finished
== fMachineState
)
5623 if (kIOPM_DriverThreadCallDone
== fMachineState
)
5625 // 5 = kDriverCallInformPreChange
5626 // 6 = kDriverCallInformPostChange
5627 // 7 = kDriverCallSetPowerState
5628 if (fLockedFlags
.DriverCallBusy
) reason
= 5 + fDriverCallReason
;
5632 // Waiting on driver's setPowerState() timeout.
5638 // Child or interested driver acks pending.
5639 if (fHeadNotePendingAcks
)
5644 // Waiting on apps or priority power interest clients.
5650 // Waiting on settle timer expiration.
5657 fWaitReason
= reason
;
5663 PM_TRACE("[B %02x] %p [%p %s] State %d, Reason %d\n",
5664 request
->getType(), request
, this, getName(),
5665 fMachineState
, reason
);
5674 //*********************************************************************************
5675 // [private] servicePMRequest
5677 // Service a request from our work queue.
5678 //*********************************************************************************
5680 bool IOService::servicePMRequest( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
5685 assert(request
&& queue
);
5687 while (isPMBlocked(request
, loop
++) == false)
5689 PM_TRACE("[W %02x] %p [%p %s] State %d\n",
5690 request
->getType(), request
, this, getName(), fMachineState
);
5692 gIOPMRequest
= request
;
5694 // Every PM machine states must be handled in one of the cases below.
5696 switch ( fMachineState
)
5698 case kIOPM_Finished
:
5699 executePMRequest( request
);
5702 case kIOPM_OurChangeTellClientsPowerDown
:
5703 // our change, was it vetoed?
5704 if (!fDoNotPowerDown
)
5706 // no, we can continue
5707 OurChangeTellClientsPowerDown();
5711 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
5712 PM_ERROR("%s: idle cancel\n", fName
);
5713 // yes, rescind the warning
5714 tellNoChangeDown(fHeadNotePowerState
);
5715 // mark the change note un-actioned
5716 fHeadNoteFlags
|= kIOPMNotDone
;
5722 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
5723 // our change, should it be acted on still?
5724 if (fDoNotPowerDown
)
5726 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
5727 PM_ERROR("%s: idle revert\n", fName
);
5728 // no, tell clients we're back in the old state
5729 tellChangeUp(fCurrentPowerState
);
5730 // mark the change note un-actioned
5731 fHeadNoteFlags
|= kIOPMNotDone
;
5737 // yes, we can continue
5738 OurChangeTellPriorityClientsPowerDown();
5742 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
5743 OurChangeNotifyInterestedDriversWillChange();
5746 case kIOPM_OurChangeSetPowerState
:
5747 OurChangeSetPowerState();
5750 case kIOPM_OurChangeWaitForPowerSettle
:
5751 OurChangeWaitForPowerSettle();
5754 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
5755 OurChangeNotifyInterestedDriversDidChange();
5758 case kIOPM_OurChangeFinish
:
5762 case kIOPM_ParentDownTellPriorityClientsPowerDown
:
5763 ParentDownTellPriorityClientsPowerDown();
5766 case kIOPM_ParentDownNotifyInterestedDriversWillChange
:
5767 ParentDownNotifyInterestedDriversWillChange();
5770 case kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange
:
5771 ParentDownNotifyDidChangeAndAcknowledgeChange();
5774 case kIOPM_ParentDownSetPowerState
:
5775 ParentDownSetPowerState();
5778 case kIOPM_ParentDownWaitForPowerSettle
:
5779 ParentDownWaitForPowerSettle();
5782 case kIOPM_ParentAcknowledgePowerChange
:
5783 ParentAcknowledgePowerChange();
5786 case kIOPM_ParentUpSetPowerState
:
5787 ParentUpSetPowerState();
5790 case kIOPM_ParentUpWaitForSettleTime
:
5791 ParentUpWaitForSettleTime();
5794 case kIOPM_ParentUpNotifyInterestedDriversDidChange
:
5795 ParentUpNotifyInterestedDriversDidChange();
5798 case kIOPM_DriverThreadCallDone
:
5799 if (fDriverCallReason
== kDriverCallSetPowerState
)
5800 notifyControllingDriverDone();
5802 notifyInterestedDriversDone();
5805 case kIOPM_NotifyChildrenDone
:
5806 notifyChildrenDone();
5809 case kIOPM_SyncNotifyDidChange
:
5810 fMachineState
= kIOPM_SyncFinish
;
5811 fDriverCallReason
= kDriverCallInformPostChange
;
5815 case kIOPM_SyncFinish
:
5816 if (fHeadNoteFlags
& kIOPMParentInitiated
)
5817 ParentAcknowledgePowerChange();
5823 panic("servicePMWorkQueue: unknown machine state %x",
5829 if (fMachineState
== kIOPM_Finished
)
5831 //PM_TRACE("[%s] PM End: Request %p (type %02lx)\n",
5832 // getName(), request, request->getType());
5841 //*********************************************************************************
5842 // [private] executePMRequest
5843 //*********************************************************************************
5845 void IOService::executePMRequest( IOPMRequest
* request
)
5847 assert( kIOPM_Finished
== fMachineState
);
5849 switch (request
->getType())
5851 case kIOPMRequestTypePMStop
:
5852 handlePMstop( request
);
5855 case kIOPMRequestTypeAddPowerChild1
:
5856 addPowerChild1( request
);
5859 case kIOPMRequestTypeAddPowerChild2
:
5860 addPowerChild2( request
);
5863 case kIOPMRequestTypeAddPowerChild3
:
5864 addPowerChild3( request
);
5867 case kIOPMRequestTypeRegisterPowerDriver
:
5868 handleRegisterPowerDriver( request
);
5871 case kIOPMRequestTypeAdjustPowerState
:
5872 fAdjustPowerScheduled
= false;
5873 rebuildChildClampBits();
5877 case kIOPMRequestTypePowerDomainWillChange
:
5878 handlePowerDomainWillChangeTo( request
);
5881 case kIOPMRequestTypePowerDomainDidChange
:
5882 handlePowerDomainDidChangeTo( request
);
5885 case kIOPMRequestTypeRequestPowerState
:
5886 case kIOPMRequestTypeRequestPowerStateOverride
:
5887 handleRequestPowerState( request
);
5890 case kIOPMRequestTypePowerOverrideOnPriv
:
5891 case kIOPMRequestTypePowerOverrideOffPriv
:
5892 handlePowerOverrideChanged( request
);
5895 case kIOPMRequestTypeActivityTickle
:
5896 handleActivityTickle( request
);
5899 case kIOPMRequestTypeSynchronizePowerTree
:
5900 handleSynchronizePowerTree( request
);
5903 case kIOPMRequestTypeSetIdleTimerPeriod
:
5905 IOWorkLoop
* wl
= gIOPMWorkLoop
;
5906 fIdleTimerPeriod
= (uintptr_t) request
->fArg0
;
5908 if (wl
&& (false == fLockedFlags
.PMStop
) && (fIdleTimerPeriod
> 0))
5910 if ( NULL
== fIdleTimerEventSource
)
5912 IOTimerEventSource
* timerSrc
;
5914 timerSrc
= IOTimerEventSource::timerEventSource(
5916 OSMemberFunctionCast(IOTimerEventSource::Action
,
5917 this, &IOService::idleTimerExpired
));
5919 if (timerSrc
&& (wl
->addEventSource(timerSrc
) != kIOReturnSuccess
))
5921 timerSrc
->release();
5925 fIdleTimerEventSource
= timerSrc
;
5928 fActivityTickleCount
= 0;
5929 clock_get_uptime(&fIdleTimerStartTime
);
5930 start_PM_idle_timer();
5936 panic("executePMRequest: unknown request type %x", request
->getType());
5940 //*********************************************************************************
5941 // [private] servicePMReplyQueue
5942 //*********************************************************************************
5944 bool IOService::servicePMReplyQueue( IOPMRequest
* request
, IOPMRequestQueue
* queue
)
5948 assert( request
&& queue
);
5949 assert( request
->isReplyType() );
5951 PM_TRACE("[A %02x] %p [%p %s] State %d\n",
5952 request
->getType(), request
, this, getName(), fMachineState
);
5954 switch ( request
->getType() )
5956 case kIOPMRequestTypeAllowPowerChange
:
5957 case kIOPMRequestTypeCancelPowerChange
:
5958 // Check if we are expecting this response.
5959 if (responseValid((unsigned long) request
->fArg0
, (int)(long) request
->fArg1
))
5961 if (kIOPMRequestTypeCancelPowerChange
== request
->getType())
5963 OSString
* name
= (OSString
*) request
->fArg2
;
5964 getPMRootDomain()->pmStatsRecordApplicationResponse(
5965 gIOPMStatsApplicationResponseCancel
,
5966 name
? name
->getCStringNoCopy() : "", 0,
5967 0, (int)(uintptr_t) request
->fArg1
);
5969 fDoNotPowerDown
= true;
5975 if ( fResponseArray
)
5977 fResponseArray
->release();
5978 fResponseArray
= NULL
;
5980 if ( fNotifyClientArray
)
5982 fNotifyClientArray
->release();
5983 fNotifyClientArray
= NULL
;
5988 // OSString containing app name in Arg2 must be released.
5989 if (request
->getType() == kIOPMRequestTypeCancelPowerChange
)
5991 OSObject
* obj
= (OSObject
*) request
->fArg2
;
5992 if (obj
) obj
->release();
5996 case kIOPMRequestTypeAckPowerChange
:
5997 more
= handleAcknowledgePowerChange( request
);
6000 case kIOPMRequestTypeAckSetPowerState
:
6001 if (fDriverTimer
== -1)
6003 // driver acked while setPowerState() call is in-flight.
6004 // take this ack, return value from setPowerState() is irrelevant.
6005 OUR_PMLog(kPMLogDriverAcknowledgeSet
,
6006 (uintptr_t) this, fDriverTimer
);
6009 else if (fDriverTimer
> 0)
6011 // expected ack, stop the timer
6014 #if LOG_SETPOWER_TIMES
6015 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
6016 if (nsec
> LOG_SETPOWER_TIMES
)
6017 PM_DEBUG("%s::setPowerState(%p, %lu -> %lu) async took %d ms\n",
6018 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
6020 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (uintptr_t) this, fDriverTimer
);
6027 OUR_PMLog(kPMLogAcknowledgeErr4
, (uintptr_t) this, 0);
6031 case kIOPMRequestTypeInterestChanged
:
6032 handleInterestChanged( request
);
6036 case kIOPMRequestTypeIdleCancel
:
6037 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
)
6038 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
))
6040 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, 0);
6041 fDoNotPowerDown
= true;
6042 if (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
6043 cleanClientResponses(false);
6049 panic("servicePMReplyQueue: unknown reply type %x",
6050 request
->getType());
6053 releasePMRequest( request
);
6057 //*********************************************************************************
6058 // [private] assertPMThreadCall / deassertPMThreadCall
6059 //*********************************************************************************
6061 bool IOService::assertPMThreadCall( void )
6066 // PMfree() should only be called from IOService::free().
6067 // That makes it safe to touch IOServicePM state here.
6068 // Caller holds a retain and has checked target is on PM plane.
6071 if (fLockedFlags
.PMStop
)
6073 // PMstop() already issued - fail the assertion.
6078 // Increment assertion count to block PMstop(), and return true.
6079 fThreadAssertionCount
++;
6080 fThreadAssertionThread
= current_thread(); // only 1 caller
6086 void IOService::deassertPMThreadCall( void )
6089 assert(fThreadAssertionCount
> 0);
6090 if (fThreadAssertionCount
)
6091 fThreadAssertionCount
--;
6092 if (current_thread() == fThreadAssertionThread
)
6093 fThreadAssertionThread
= 0;
6094 if ((fThreadAssertionCount
== 0) && fLockedFlags
.PMStop
)
6096 // PMstop() is blocked waiting for assertion count to drop to zero.
6097 PM_LOCK_WAKEUP(&fThreadAssertionCount
);
6103 // MARK: IOPMRequest
6105 //*********************************************************************************
6106 // IOPMRequest Class
6108 // Requests from PM clients, and also used for inter-object messaging within PM.
6109 //*********************************************************************************
6111 OSDefineMetaClassAndStructors( IOPMRequest
, IOCommand
);
6113 IOPMRequest
* IOPMRequest::create( void )
6115 IOPMRequest
* me
= OSTypeAlloc(IOPMRequest
);
6116 if (me
&& !me
->init(0, kIOPMRequestTypeInvalid
))
6124 bool IOPMRequest::init( IOService
* target
, IOOptionBits type
)
6126 if (!IOCommand::init())
6131 fCompletionStatus
= kIOReturnSuccess
;
6139 void IOPMRequest::reset( void )
6141 assert( fWorkWaitCount
== 0 );
6142 assert( fFreeWaitCount
== 0 );
6144 detachNextRequest();
6145 detachRootRequest();
6147 fType
= kIOPMRequestTypeInvalid
;
6149 if (fCompletionAction
)
6151 fCompletionAction(fCompletionTarget
, fCompletionParam
, fCompletionStatus
);
6161 void IOPMRequest::attachNextRequest( IOPMRequest
* next
)
6165 // Postpone the execution of the next request after
6167 fRequestNext
= next
;
6168 fRequestNext
->fWorkWaitCount
++;
6169 #if LOG_REQUEST_ATTACH
6170 kprintf("Attached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
6171 this, (uint32_t) fType
, fRequestNext
,
6172 (uint32_t) fRequestNext
->fType
,
6173 (uint32_t) fRequestNext
->fWorkWaitCount
,
6174 fTarget
->getName());
6179 void IOPMRequest::detachNextRequest( void )
6183 assert(fRequestNext
->fWorkWaitCount
);
6184 if (fRequestNext
->fWorkWaitCount
)
6185 fRequestNext
->fWorkWaitCount
--;
6186 #if LOG_REQUEST_ATTACH
6187 kprintf("Detached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
6188 this, (uint32_t) fType
, fRequestNext
,
6189 (uint32_t) fRequestNext
->fType
,
6190 (uint32_t) fRequestNext
->fWorkWaitCount
,
6191 fTarget
->getName());
6197 void IOPMRequest::attachRootRequest( IOPMRequest
* root
)
6201 // Delay the completion of the root request after
6203 fRequestRoot
= root
;
6204 fRequestRoot
->fFreeWaitCount
++;
6205 #if LOG_REQUEST_ATTACH
6206 kprintf("Attached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
6207 this, (uint32_t) fType
, fRequestRoot
,
6208 (uint32_t) fRequestRoot
->fType
,
6209 (uint32_t) fRequestRoot
->fFreeWaitCount
,
6210 fTarget
->getName());
6215 void IOPMRequest::detachRootRequest( void )
6219 assert(fRequestRoot
->fFreeWaitCount
);
6220 if (fRequestRoot
->fFreeWaitCount
)
6221 fRequestRoot
->fFreeWaitCount
--;
6222 #if LOG_REQUEST_ATTACH
6223 kprintf("Detached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
6224 this, (uint32_t) fType
, fRequestRoot
,
6225 (uint32_t) fRequestRoot
->fType
,
6226 (uint32_t) fRequestRoot
->fFreeWaitCount
,
6227 fTarget
->getName());
6234 // MARK: IOPMRequestQueue
6236 //*********************************************************************************
6237 // IOPMRequestQueue Class
6239 // Global queues. As PM-aware drivers load and unload, their IOPMWorkQueue's are
6240 // created and deallocated. IOPMRequestQueue are created once and never released.
6241 //*********************************************************************************
6243 OSDefineMetaClassAndStructors( IOPMRequestQueue
, IOEventSource
);
6245 IOPMRequestQueue
* IOPMRequestQueue::create( IOService
* inOwner
, Action inAction
)
6247 IOPMRequestQueue
* me
= OSTypeAlloc(IOPMRequestQueue
);
6248 if (me
&& !me
->init(inOwner
, inAction
))
6256 bool IOPMRequestQueue::init( IOService
* inOwner
, Action inAction
)
6258 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
6261 queue_init(&fQueue
);
6262 fLock
= IOLockAlloc();
6263 return (fLock
!= 0);
6266 void IOPMRequestQueue::free( void )
6273 return IOEventSource::free();
6276 void IOPMRequestQueue::queuePMRequest( IOPMRequest
* request
)
6280 queue_enter(&fQueue
, request
, IOPMRequest
*, fCommandChain
);
6281 IOLockUnlock(fLock
);
6282 if (workLoop
) signalWorkAvailable();
6286 IOPMRequestQueue::queuePMRequestChain( IOPMRequest
** requests
, IOItemCount count
)
6290 assert(requests
&& count
);
6296 queue_enter(&fQueue
, next
, IOPMRequest
*, fCommandChain
);
6298 IOLockUnlock(fLock
);
6299 if (workLoop
) signalWorkAvailable();
6302 bool IOPMRequestQueue::checkForWork( void )
6304 Action dqAction
= (Action
) action
;
6305 IOPMRequest
* request
;
6309 IOLockLock( fLock
);
6311 while (!queue_empty(&fQueue
))
6313 queue_remove_first( &fQueue
, request
, IOPMRequest
*, fCommandChain
);
6314 IOLockUnlock( fLock
);
6315 target
= request
->getTarget();
6317 more
|= (*dqAction
)( target
, request
, this );
6318 IOLockLock( fLock
);
6321 IOLockUnlock( fLock
);
6325 void IOPMRequestQueue::signalWorkAvailable( void )
6327 IOEventSource::signalWorkAvailable();
6331 // MARK: IOPMWorkQueue
6333 //*********************************************************************************
6334 // IOPMWorkQueue Class
6336 // Every object in the power plane that has handled a PM request, will have an
6337 // instance of IOPMWorkQueue allocated for it.
6338 //*********************************************************************************
6340 OSDefineMetaClassAndStructors( IOPMWorkQueue
, IOEventSource
);
6343 IOPMWorkQueue::create( IOService
* inOwner
, Action work
, Action retire
)
6345 IOPMWorkQueue
* me
= OSTypeAlloc(IOPMWorkQueue
);
6346 if (me
&& !me
->init(inOwner
, work
, retire
))
6354 bool IOPMWorkQueue::init( IOService
* inOwner
, Action work
, Action retire
)
6356 if (!work
|| !retire
||
6357 !IOEventSource::init(inOwner
, (IOEventSourceAction
)0))
6360 queue_init(&fWorkQueue
);
6363 fRetireAction
= retire
;
6368 void IOPMWorkQueue::queuePMRequest( IOPMRequest
* request
)
6371 assert( onThread() );
6374 queue_enter(&fWorkQueue
, request
, IOPMRequest
*, fCommandChain
);
6378 bool IOPMWorkQueue::checkForWork( void )
6380 IOPMRequest
* request
;
6381 IOService
* target
= (IOService
*) owner
;
6384 while (!queue_empty(&fWorkQueue
))
6386 request
= (IOPMRequest
*) queue_first(&fWorkQueue
);
6387 assert(request
->getTarget() == target
);
6388 if (request
->isWorkBlocked()) break;
6389 done
= (*fWorkAction
)( target
, request
, this );
6392 assert(gIOPMBusyCount
> 0);
6393 if (gIOPMBusyCount
) gIOPMBusyCount
--;
6394 queue_remove_first(&fWorkQueue
, request
, IOPMRequest
*, fCommandChain
);
6395 (*fRetireAction
)( target
, request
, this );
6402 // MARK: IOPMCompletionQueue
6404 //*********************************************************************************
6405 // IOPMCompletionQueue Class
6406 //*********************************************************************************
6408 OSDefineMetaClassAndStructors( IOPMCompletionQueue
, IOEventSource
);
6410 IOPMCompletionQueue
* IOPMCompletionQueue::create( IOService
* inOwner
, Action inAction
)
6412 IOPMCompletionQueue
* me
= OSTypeAlloc(IOPMCompletionQueue
);
6413 if (me
&& !me
->init(inOwner
, inAction
))
6421 bool IOPMCompletionQueue::init( IOService
* inOwner
, Action inAction
)
6423 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
6426 queue_init(&fQueue
);
6430 void IOPMCompletionQueue::queuePMRequest( IOPMRequest
* request
)
6433 request
->detachNextRequest(); // unblocks next request
6434 queue_enter(&fQueue
, request
, IOPMRequest
*, fCommandChain
);
6435 if (workLoop
) signalWorkAvailable();
6438 bool IOPMCompletionQueue::checkForWork( void )
6440 Action dqAction
= (Action
) action
;
6441 IOPMRequest
* request
;
6444 queue_head_t tmpQueue
;
6446 queue_init(&tmpQueue
);
6448 while (!queue_empty(&fQueue
))
6450 queue_remove_first( &fQueue
, request
, IOPMRequest
*, fCommandChain
);
6451 if (request
->isFreeBlocked())
6453 queue_enter(&tmpQueue
, request
, IOPMRequest
*, fCommandChain
);
6456 target
= request
->getTarget();
6458 more
|= (*dqAction
)( target
, request
, this );
6461 queue_new_head(&tmpQueue
, &fQueue
, IOPMRequest
*, fCommandChain
);
6466 // MARK: IOServicePM
6468 OSDefineMetaClassAndStructors(IOServicePM
, OSObject
)
6470 //*********************************************************************************
6473 // Serialize IOServicePM for debugging.
6474 //*********************************************************************************
6477 setPMProperty( OSDictionary
* dict
, const char * key
, uint64_t value
)
6479 OSNumber
* num
= OSNumber::withNumber(value
, sizeof(value
) * 8);
6482 dict
->setObject(key
, num
);
6487 IOReturn
IOServicePM::gatedSerialize( OSSerialize
* s
)
6489 OSDictionary
* dict
;
6493 if (IdleTimerPeriod
)
6497 dict
= OSDictionary::withDictionary(
6498 PowerClients
, PowerClients
->getCount() + dictSize
);
6500 dict
= OSDictionary::withCapacity(dictSize
);
6504 setPMProperty(dict
, "CurrentPowerState", CurrentPowerState
);
6505 if (DesiredPowerState
!= CurrentPowerState
)
6506 setPMProperty(dict
, "DesiredPowerState", DesiredPowerState
);
6507 if (kIOPM_Finished
!= MachineState
)
6508 setPMProperty(dict
, "MachineState", MachineState
);
6509 if (DeviceOverrides
)
6510 dict
->setObject("PowerOverrideOn", kOSBooleanTrue
);
6512 if (IdleTimerPeriod
)
6518 clock_get_uptime(&now
);
6520 // The idle timer period in milliseconds.
6521 setPMProperty(dict
, "IdleTimerPeriod", IdleTimerPeriod
* 1000ULL);
6523 // The number of activity tickles recorded since device idle
6524 setPMProperty(dict
, "ActivityTickles", ActivityTickleCount
);
6526 if (AbsoluteTime_to_scalar(&DeviceActiveTimestamp
))
6528 // The number of milliseconds since the last activity tickle.
6530 SUB_ABSOLUTETIME(&delta
, &DeviceActiveTimestamp
);
6531 absolutetime_to_nanoseconds(delta
, &nsecs
);
6532 setPMProperty(dict
, "TimeSinceActivityTickle", NS_TO_MS(nsecs
));
6535 if (AbsoluteTime_to_scalar(&IdleTimerStartTime
))
6537 // The number of milliseconds since the last device idle.
6539 SUB_ABSOLUTETIME(&delta
, &IdleTimerStartTime
);
6540 absolutetime_to_nanoseconds(delta
, &nsecs
);
6541 setPMProperty(dict
, "TimeSinceDeviceIdle", NS_TO_MS(nsecs
));
6545 ok
= dict
->serialize(s
);
6549 return (ok
? kIOReturnSuccess
: kIOReturnNoMemory
);
6552 bool IOServicePM::serialize( OSSerialize
* s
) const
6554 IOReturn ret
= kIOReturnNotReady
;
6558 ret
= gIOPMWorkLoop
->runAction(
6559 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOServicePM::gatedSerialize
),
6560 (OSObject
*) this, (void *) s
);
6563 return (kIOReturnSuccess
== ret
);