]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOServicePM.cpp
fd150a4f64290e91816765fe434a652f47b606ff
[apple/xnu.git] / iokit / Kernel / IOServicePM.cpp
1 /*
2 * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 //#define IOASSERT 1
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>
39
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>
45
46 #include <sys/proc.h>
47
48 // Required for notification instrumentation
49 #include "IOServicePrivate.h"
50 #include "IOServicePMPrivate.h"
51 #include "IOKitKernelInternal.h"
52
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);
56
57 static uint64_t computeTimeDeltaNS( const AbsoluteTime * start )
58 {
59 AbsoluteTime now;
60 uint64_t nsec;
61
62 clock_get_uptime(&now);
63 SUB_ABSOLUTETIME(&now, start);
64 absolutetime_to_nanoseconds(now, &nsec);
65 return nsec;
66 }
67
68 #if PM_VARS_SUPPORT
69 OSDefineMetaClassAndStructors(IOPMprot, OSObject)
70 #endif
71
72 //*********************************************************************************
73 // Globals
74 //*********************************************************************************
75
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;
85
86 static const OSSymbol * gIOPMPowerClientDevice = 0;
87 static const OSSymbol * gIOPMPowerClientDriver = 0;
88 static const OSSymbol * gIOPMPowerClientChildProxy = 0;
89 static const OSSymbol * gIOPMPowerClientChildren = 0;
90
91 static uint32_t getPMRequestType( void )
92 {
93 uint32_t type = kIOPMRequestTypeInvalid;
94 if (gIOPMRequest)
95 type = gIOPMRequest->getType();
96 return type;
97 }
98
99 //*********************************************************************************
100 // Macros
101 //*********************************************************************************
102
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)
107
108 #define PM_CONNECT(x...)
109
110 #define PM_ASSERT_IN_GATE(x) \
111 do { \
112 assert(gIOPMWorkLoop->inGate()); \
113 } while(false)
114
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)
119
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"
126
127 #define OUR_PMLog(t, a, b) \
128 do { gPlatform->PMLog( fName, t, a, b); } while(0)
129
130 #define NS_TO_MS(nsec) ((int)((nsec) / 1000000ULL))
131
132 #if CONFIG_EMBEDDED
133 #define SUPPORT_IDLE_CANCEL 1
134 #endif
135
136 #define kNotifyWillChange (true)
137 #define kNotifyDidChange (false)
138
139 #define kIOPMPowerStateMax 0xFFFFFFFF
140
141 #define IS_PM_ROOT() (this == gIOPMRootNode)
142 #define IS_POWER_DROP (fHeadNotePowerState < fCurrentPowerState)
143 #define IS_POWER_RISE (fHeadNotePowerState > fCurrentPowerState)
144
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)
151
152 #define RESERVE_DOMAIN_POWER 1
153
154 enum {
155 kReserveDomainPower = 1
156 };
157
158 //*********************************************************************************
159 // PM machine states
160 //*********************************************************************************
161
162 enum {
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,
172 /* 10 not used */
173 kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange = 11,
174 kIOPM_ParentDownSetPowerState = 12,
175 kIOPM_ParentDownWaitForPowerSettle = 13,
176 kIOPM_ParentAcknowledgePowerChange = 14,
177 kIOPM_ParentUpSetPowerState = 15,
178 /* 16 not used */
179 kIOPM_ParentUpWaitForSettleTime = 17,
180 kIOPM_ParentUpNotifyInterestedDriversDidChange = 18,
181 /* 19 not used */
182 kIOPM_Finished = 20,
183 kIOPM_DriverThreadCallDone = 21,
184 kIOPM_NotifyChildrenDone = 22,
185 kIOPM_SyncNotifyDidChange = 23,
186 kIOPM_SyncFinish = 24
187 };
188
189
190 /*
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.
193
194 Many drivers implement their policy maker and power controller within the same
195 IOService object, but that is not required.
196
197 == Policy Maker ==
198 * Virtual IOService PM methods a "policy maker" may implement
199 * maxCapabilityForDomainState()
200 * initialPowerStateForDomainState()
201 * powerStateForDomainState()
202
203 * Virtual IOService PM methods a "policy maker" may CALL
204 * PMinit()
205
206 == Power Controller ==
207 * Virtual IOService PM methods a "power controller" may implement
208 * setPowerState()
209
210 * Virtual IOService PM methods a "power controller" may CALL
211 * joinPMtree()
212 * registerPowerDriver()
213
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
219 usable.
220 * The second kind of power state change is initiated by the power domain
221 parent.
222 The two are handled through different code paths.
223
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.
229 Example:
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.
240
241 == SelfInitiated ==
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
249 it has passed,
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.
255
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
259 state is reached.
260 -> Then all interested parties are notified that we are moving to that new
261 state.
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.
269
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
273 reached.
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
281 done.
282
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.
285 Examples:
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.
295
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
299 machine.
300
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
306 we're done.
307
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.
316
317 -> We start by notifying interested parties.
318 -> If they all acknowledge via return code, we can go on to state
319 "msSetPowerState".
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
331 expires, we go on.
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
334 new state.
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.
346
347 == 2. Parent Change Down ==
348 Start at Stage 2 of OurChange Down XXX gvdl
349
350 == 3. Change Up ==
351 Start at Stage 4 of OurChange Down XXX gvdl
352
353 Note all parent requested changes need to acknowledge the power has changed to the parent when done.
354 */
355
356 //*********************************************************************************
357 // [public] PMinit
358 //
359 // Initialize power management.
360 //*********************************************************************************
361
362 void IOService::PMinit ( void )
363 {
364 if ( !initialized )
365 {
366 if ( !gIOPMInitialized )
367 {
368 gPlatform = getPlatform();
369 gIOPMWorkLoop = IOWorkLoop::workLoop();
370 if (gIOPMWorkLoop)
371 {
372 gIOPMRequestQueue = IOPMRequestQueue::create(
373 this, OSMemberFunctionCast(IOPMRequestQueue::Action,
374 this, &IOService::servicePMRequestQueue));
375
376 gIOPMReplyQueue = IOPMRequestQueue::create(
377 this, OSMemberFunctionCast(IOPMRequestQueue::Action,
378 this, &IOService::servicePMReplyQueue));
379
380 gIOPMFreeQueue = IOPMCompletionQueue::create(
381 this, OSMemberFunctionCast(IOPMCompletionQueue::Action,
382 this, &IOService::servicePMFreeQueue));
383
384 if (gIOPMWorkLoop->addEventSource(gIOPMRequestQueue) !=
385 kIOReturnSuccess)
386 {
387 gIOPMRequestQueue->release();
388 gIOPMRequestQueue = 0;
389 }
390
391 if (gIOPMWorkLoop->addEventSource(gIOPMReplyQueue) !=
392 kIOReturnSuccess)
393 {
394 gIOPMReplyQueue->release();
395 gIOPMReplyQueue = 0;
396 }
397
398 if (gIOPMWorkLoop->addEventSource(gIOPMFreeQueue) !=
399 kIOReturnSuccess)
400 {
401 gIOPMFreeQueue->release();
402 gIOPMFreeQueue = 0;
403 }
404
405 gIOPMPowerClientDevice = OSSymbol::withCStringNoCopy( "DevicePowerState" );
406 gIOPMPowerClientDriver = OSSymbol::withCStringNoCopy( "DriverPowerState" );
407 gIOPMPowerClientChildProxy = OSSymbol::withCStringNoCopy( "ChildProxyPowerState" );
408 gIOPMPowerClientChildren = OSSymbol::withCStringNoCopy( "ChildrenPowerState" );
409 }
410
411 if (gIOPMRequestQueue && gIOPMReplyQueue && gIOPMFreeQueue)
412 gIOPMInitialized = true;
413 }
414 if (!gIOPMInitialized)
415 return;
416
417 pwrMgt = new IOServicePM;
418 pwrMgt->init();
419 setProperty(kPwrMgtKey, pwrMgt);
420
421 fPMLock = IOLockAlloc();
422 fInterestedDrivers = new IOPMinformeeList;
423 fInterestedDrivers->initialize();
424 fDesiredPowerState = 0;
425 fDeviceDesire = 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;
436 fPowerStates = NULL;
437 fNumberOfPowerStates = 0;
438 fCurrentPowerState = 0;
439 fParentsCurrentPowerFlags = 0;
440 fMaxCapability = 0;
441 fName = getName();
442 fParentsKnowState = false;
443 fSerialNumber = 0;
444 fResponseArray = NULL;
445 fNotifyClientArray = NULL;
446 fDoNotPowerDown = true;
447 fCurrentPowerConsumption = kIOPMUnknown;
448 fOverrideMaxPowerState = kIOPMPowerStateMax;
449
450 if (!gIOPMRootNode && (getParentEntry(gIOPowerPlane) == getRegistryRoot()))
451 {
452 gIOPMRootNode = this;
453 fParentsKnowState = true;
454 }
455
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);
463
464 #if PM_VARS_SUPPORT
465 IOPMprot * prot = new IOPMprot;
466 if (prot)
467 {
468 prot->init();
469 prot->ourName = fName;
470 prot->thePlatform = gPlatform;
471 fPMVars = prot;
472 pm_vars = prot;
473 }
474 #else
475 pm_vars = (void *) true;
476 #endif
477
478 initialized = true;
479 }
480 }
481
482 //*********************************************************************************
483 // [private] PMfree
484 //
485 // Free the data created by PMinit. Only called from IOService::free().
486 //*********************************************************************************
487
488 void IOService::PMfree ( void )
489 {
490 initialized = false;
491 pm_vars = 0;
492
493 if ( pwrMgt )
494 {
495 assert(fMachineState == kIOPM_Finished);
496 assert(fInsertInterestSet == NULL);
497 assert(fRemoveInterestSet == NULL);
498 assert(fNotifyChildArray == NULL);
499
500 if ( fIdleTimerEventSource != NULL ) {
501 fIdleTimerEventSource->disable();
502 gIOPMWorkLoop->removeEventSource(fIdleTimerEventSource);
503 fIdleTimerEventSource->release();
504 fIdleTimerEventSource = NULL;
505 }
506 if ( fSettleTimer ) {
507 thread_call_cancel(fSettleTimer);
508 thread_call_free(fSettleTimer);
509 fSettleTimer = NULL;
510 }
511 if ( fAckTimer ) {
512 thread_call_cancel(fAckTimer);
513 thread_call_free(fAckTimer);
514 fAckTimer = NULL;
515 }
516 if ( fDriverCallEntry ) {
517 thread_call_free(fDriverCallEntry);
518 fDriverCallEntry = NULL;
519 }
520 if ( fPMLock ) {
521 IOLockFree(fPMLock);
522 fPMLock = NULL;
523 }
524 if ( fActivityLock ) {
525 IOLockFree(fActivityLock);
526 fActivityLock = NULL;
527 }
528 if ( fInterestedDrivers ) {
529 fInterestedDrivers->release();
530 fInterestedDrivers = NULL;
531 }
532 if ( fPMWorkQueue ) {
533 gIOPMWorkLoop->removeEventSource(fPMWorkQueue);
534 fPMWorkQueue->release();
535 fPMWorkQueue = 0;
536 }
537 if (fDriverCallParamSlots && fDriverCallParamPtr) {
538 IODelete(fDriverCallParamPtr, DriverCallParam, fDriverCallParamSlots);
539 fDriverCallParamPtr = 0;
540 fDriverCallParamSlots = 0;
541 }
542 if ( fResponseArray ) {
543 fResponseArray->release();
544 fResponseArray = NULL;
545 }
546 if ( fNotifyClientArray ) {
547 fNotifyClientArray->release();
548 fNotifyClientArray = NULL;
549 }
550 if (fPowerStates && fNumberOfPowerStates) {
551 IODelete(fPowerStates, IOPMPowerState, fNumberOfPowerStates);
552 fNumberOfPowerStates = 0;
553 fPowerStates = NULL;
554 }
555 if (fPowerClients) {
556 fPowerClients->release();
557 fPowerClients = 0;
558 }
559
560 #if PM_VARS_SUPPORT
561 if (fPMVars)
562 {
563 fPMVars->release();
564 fPMVars = 0;
565 }
566 #endif
567
568 pwrMgt->release();
569 pwrMgt = 0;
570 }
571 }
572
573 //*********************************************************************************
574 // [public] joinPMtree
575 //
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.
581 //
582 // This may be the only "power management" method used in a nub,
583 // meaning it may not be initialized for power management.
584 //*********************************************************************************
585
586 void IOService::joinPMtree ( IOService * driver )
587 {
588 IOPlatformExpert * platform;
589
590 platform = getPlatform();
591 assert(platform != 0);
592 platform->PMRegisterDevice(this, driver);
593 }
594
595 #ifndef __LP64__
596 //*********************************************************************************
597 // [deprecated] youAreRoot
598 //
599 // Power Managment is informing us that we are the root power domain.
600 //*********************************************************************************
601
602 IOReturn IOService::youAreRoot ( void )
603 {
604 return IOPMNoErr;
605 }
606 #endif /* !__LP64__ */
607
608 //*********************************************************************************
609 // [public] PMstop
610 //
611 // Immediately stop driver callouts. Schedule an async stop request to detach
612 // from power plane.
613 //*********************************************************************************
614
615 void IOService::PMstop ( void )
616 {
617 IOPMRequest * request;
618
619 if (!initialized)
620 return;
621
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.
626
627 PM_LOCK();
628 fLockedFlags.PMStop = true;
629 if (fLockedFlags.DriverCallBusy)
630 {
631 PM_DEBUG("%s: PMstop() driver call busy\n", getName());
632 }
633 while (fThreadAssertionCount != 0)
634 {
635 if (current_thread() == fThreadAssertionThread)
636 {
637 PM_ERROR("%s: PMstop() called from PM thread call\n", getName());
638 break;
639 }
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);
644 }
645 PM_UNLOCK();
646
647 request = acquirePMRequest( this, kIOPMRequestTypePMStop );
648 if (request)
649 {
650 PM_TRACE("%s: %p PMstop\n", getName(), this);
651 submitPMRequest( request );
652 }
653 }
654
655 //*********************************************************************************
656 // [private] handlePMstop
657 //
658 // Disconnect the node from all parents and children in the power plane.
659 //*********************************************************************************
660
661 void IOService::handlePMstop ( IOPMRequest * request )
662 {
663 OSIterator * iter;
664 OSObject * next;
665 IOPowerConnection * connection;
666 IOService * theChild;
667 IOService * theParent;
668
669 PM_ASSERT_IN_GATE();
670 PM_TRACE("%s: %p %s start\n", getName(), this, __FUNCTION__);
671
672 // remove the property
673 removeProperty(kPwrMgtKey);
674
675 // detach parents
676 iter = getParentIterator(gIOPowerPlane);
677 if ( iter )
678 {
679 while ( (next = iter->getNextObject()) )
680 {
681 if ( (connection = OSDynamicCast(IOPowerConnection, next)) )
682 {
683 theParent = (IOService *)connection->copyParentEntry(gIOPowerPlane);
684 if ( theParent )
685 {
686 theParent->removePowerChild(connection);
687 theParent->release();
688 }
689 }
690 }
691 iter->release();
692 }
693
694 // detach IOConnections
695 detachAbove( gIOPowerPlane );
696
697 // no more power state changes
698 fParentsKnowState = false;
699
700 // detach children
701 iter = getChildIterator(gIOPowerPlane);
702 if ( iter )
703 {
704 while ( (next = iter->getNextObject()) )
705 {
706 if ( (connection = OSDynamicCast(IOPowerConnection, next)) )
707 {
708 theChild = ((IOService *)(connection->copyChildEntry(gIOPowerPlane)));
709 if ( theChild )
710 {
711 // detach nub from child
712 connection->detachFromChild(theChild, gIOPowerPlane);
713 theChild->release();
714 }
715 // detach us from nub
716 detachFromChild(connection, gIOPowerPlane);
717 }
718 }
719 iter->release();
720 }
721
722 // Remove all interested drivers from the list, including the power
723 // controlling driver.
724 //
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
728 // be freed.
729
730 if ( fInterestedDrivers )
731 {
732 IOPMinformeeList * list = fInterestedDrivers;
733 IOPMinformee * item;
734
735 PM_LOCK();
736 while ((item = list->firstInList()))
737 {
738 list->removeFromList(item->whatObject);
739 }
740 PM_UNLOCK();
741 }
742
743 // Tell idleTimerExpired() to ignore idle timer.
744 fIdleTimerPeriod = 0;
745 if (fIdleTimerEventSource)
746 fIdleTimerEventSource->disable();
747
748 PM_TRACE("%s: %p %s done\n", getName(), this, __FUNCTION__);
749 }
750
751 //*********************************************************************************
752 // [public] addPowerChild
753 //
754 // Power Management is informing us who our children are.
755 //*********************************************************************************
756
757 IOReturn IOService::addPowerChild ( IOService * child )
758 {
759 IOPowerConnection * connection = 0;
760 IOPMRequest * requests[3] = {0, 0, 0};
761 OSIterator * iter;
762 bool ok = true;
763
764 if (!child)
765 return kIOReturnBadArgument;
766
767 if (!initialized || !child->initialized)
768 return IOPMNotYetInitialized;
769
770 OUR_PMLog( kPMLogAddChild, (uintptr_t) child, 0 );
771
772 do {
773 // Is this child already one of our children?
774
775 iter = child->getParentIterator( gIOPowerPlane );
776 if ( iter )
777 {
778 IORegistryEntry * entry;
779 OSObject * next;
780
781 while ((next = iter->getNextObject()))
782 {
783 if ((entry = OSDynamicCast(IORegistryEntry, next)) &&
784 isChild(entry, gIOPowerPlane))
785 {
786 ok = false;
787 break;
788 }
789 }
790 iter->release();
791 }
792 if (!ok)
793 {
794 PM_DEBUG("%s: %s (%p) is already a child\n",
795 getName(), child->getName(), child);
796 break;
797 }
798
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.
804
805 connection = new IOPowerConnection;
806 if (!connection)
807 break;
808
809 // Create a chain of PM requests to perform the bottom-half
810 // work from the PM work loop.
811
812 requests[0] = acquirePMRequest(
813 /* target */ this,
814 /* type */ kIOPMRequestTypeAddPowerChild1 );
815
816 requests[1] = acquirePMRequest(
817 /* target */ child,
818 /* type */ kIOPMRequestTypeAddPowerChild2 );
819
820 requests[2] = acquirePMRequest(
821 /* target */ this,
822 /* type */ kIOPMRequestTypeAddPowerChild3 );
823
824 if (!requests[0] || !requests[1] || !requests[2])
825 break;
826
827 requests[0]->attachNextRequest( requests[1] );
828 requests[1]->attachNextRequest( requests[2] );
829
830 connection->init();
831 connection->start(this);
832 connection->setAwaitingAck(false);
833 connection->setReadyFlag(false);
834
835 attachToChild( connection, gIOPowerPlane );
836 connection->attachToChild( child, gIOPowerPlane );
837
838 // connection needs to be released
839 requests[0]->fArg0 = connection;
840 requests[1]->fArg0 = connection;
841 requests[2]->fArg0 = connection;
842
843 submitPMRequest( requests, 3 );
844 return kIOReturnSuccess;
845 }
846 while (false);
847
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]);
852
853 // Silent failure, to prevent platform drivers from adding the child
854 // to the root domain.
855
856 return kIOReturnSuccess;
857 }
858
859 //*********************************************************************************
860 // [private] addPowerChild1
861 //
862 // Step 1/3 of adding a power child. Called on the power parent.
863 //*********************************************************************************
864
865 void IOService::addPowerChild1 ( IOPMRequest * request )
866 {
867 unsigned long tempDesire = 0;
868
869 // Make us temporary usable before adding the child.
870
871 PM_ASSERT_IN_GATE();
872 OUR_PMLog( kPMLogMakeUsable, kPMLogMakeUsable, 0 );
873
874 if (fControllingDriver && inPlane(gIOPowerPlane) && fParentsKnowState)
875 {
876 tempDesire = fNumberOfPowerStates - 1;
877 }
878
879 if (tempDesire && (IS_PM_ROOT() || (fMaxCapability >= tempDesire)))
880 {
881 adjustPowerState(tempDesire);
882 }
883 }
884
885 //*********************************************************************************
886 // [private] addPowerChild2
887 //
888 // Step 2/3 of adding a power child. Called on the joining child.
889 // Execution blocked behind addPowerChild1.
890 //*********************************************************************************
891
892 void IOService::addPowerChild2 ( IOPMRequest * request )
893 {
894 IOPowerConnection * connection = (IOPowerConnection *) request->fArg0;
895 IOService * parent;
896 IOPMPowerFlags powerFlags;
897 bool knowsState;
898 unsigned long powerState;
899 unsigned long tempDesire;
900
901 PM_ASSERT_IN_GATE();
902 parent = (IOService *) connection->getParentEntry(gIOPowerPlane);
903
904 if (!parent || !inPlane(gIOPowerPlane))
905 {
906 PM_DEBUG("%s: addPowerChild2 not in power plane\n", getName());
907 return;
908 }
909
910 // Parent will be waiting for us to complete this stage.
911 // It is safe to directly access parent's vars.
912
913 knowsState = (parent->fPowerStates) && (parent->fParentsKnowState);
914 powerState = parent->fCurrentPowerState;
915
916 if (knowsState)
917 powerFlags = parent->fPowerStates[powerState].outputPowerCharacter;
918 else
919 powerFlags = 0;
920
921 // Set our power parent.
922
923 OUR_PMLog(kPMLogSetParent, knowsState, powerFlags);
924
925 setParentInfo( powerFlags, connection, knowsState );
926
927 connection->setReadyFlag(true);
928
929 if ( fControllingDriver && fParentsKnowState )
930 {
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);
936 }
937
938 #if ROOT_DOMAIN_RUN_STATES
939 getPMRootDomain()->tagPowerPlaneService(this, &fRootDomainState);
940 #endif
941 }
942
943 //*********************************************************************************
944 // [private] addPowerChild3
945 //
946 // Step 3/3 of adding a power child. Called on the parent.
947 // Execution blocked behind addPowerChild2.
948 //*********************************************************************************
949
950 void IOService::addPowerChild3 ( IOPMRequest * request )
951 {
952 IOPowerConnection * connection = (IOPowerConnection *) request->fArg0;
953 IOService * child;
954 IOPMrootDomain * rootDomain = getPMRootDomain();
955
956 PM_ASSERT_IN_GATE();
957 child = (IOService *) connection->getChildEntry(gIOPowerPlane);
958
959 if (child && inPlane(gIOPowerPlane))
960 {
961 if (child->getProperty("IOPMStrictTreeOrder"))
962 {
963 PM_DEBUG("%s: strict PM order enforced\n", getName());
964 fStrictTreeOrder = true;
965 }
966
967 if (rootDomain)
968 rootDomain->joinAggressiveness( child );
969 }
970 else
971 {
972 PM_DEBUG("%s: addPowerChild3 not in power plane\n", getName());
973 }
974
975 connection->release();
976 }
977
978 #ifndef __LP64__
979 //*********************************************************************************
980 // [deprecated] setPowerParent
981 //
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 //*********************************************************************************
987
988 IOReturn IOService::setPowerParent (
989 IOPowerConnection * theParent, bool stateKnown, IOPMPowerFlags powerFlags )
990 {
991 return kIOReturnUnsupported;
992 }
993 #endif /* !__LP64__ */
994
995 //*********************************************************************************
996 // [public] removePowerChild
997 //
998 // Called on a parent whose child is being removed by PMstop().
999 //*********************************************************************************
1000
1001 IOReturn IOService::removePowerChild ( IOPowerConnection * theNub )
1002 {
1003 IORegistryEntry * theChild;
1004
1005 PM_ASSERT_IN_GATE();
1006 OUR_PMLog( kPMLogRemoveChild, 0, 0 );
1007
1008 theNub->retain();
1009
1010 // detach nub from child
1011 theChild = theNub->copyChildEntry(gIOPowerPlane);
1012 if ( theChild )
1013 {
1014 theNub->detachFromChild(theChild, gIOPowerPlane);
1015 theChild->release();
1016 }
1017 // detach from the nub
1018 detachFromChild(theNub, gIOPowerPlane);
1019
1020 // Are we awaiting an ack from this child?
1021 if ( theNub->getAwaitingAck() )
1022 {
1023 // yes, pretend we got one
1024 theNub->setAwaitingAck(false);
1025 if (fHeadNotePendingAcks != 0 )
1026 {
1027 // that's one fewer ack to worry about
1028 fHeadNotePendingAcks--;
1029
1030 // is that the last?
1031 if ( fHeadNotePendingAcks == 0 )
1032 {
1033 stop_ack_timer();
1034 }
1035 }
1036 }
1037
1038 theNub->release();
1039
1040 // A child has gone away, re-scan children desires and clamp bits.
1041 // The fPendingAdjustPowerRequest helps to reduce redundant parent work.
1042
1043 if (!fAdjustPowerScheduled)
1044 {
1045 IOPMRequest * request;
1046 request = acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState );
1047 if (request)
1048 {
1049 submitPMRequest( request );
1050 fAdjustPowerScheduled = true;
1051 }
1052 }
1053
1054 return IOPMNoErr;
1055 }
1056
1057 //*********************************************************************************
1058 // [public] registerPowerDriver
1059 //
1060 // A driver has called us volunteering to control power to our device.
1061 //*********************************************************************************
1062
1063 IOReturn IOService::registerPowerDriver (
1064 IOService * powerDriver,
1065 IOPMPowerState * powerStates,
1066 unsigned long numberOfStates )
1067 {
1068 IOPMRequest * request;
1069 IOPMPowerState * powerStatesCopy = 0;
1070
1071 if (!initialized)
1072 return IOPMNotYetInitialized;
1073
1074 // Validate arguments.
1075 if (!powerStates || (numberOfStates < 2))
1076 {
1077 OUR_PMLog(kPMLogControllingDriverErr5, numberOfStates, 0);
1078 return kIOReturnBadArgument;
1079 }
1080
1081 if (!powerDriver || !powerDriver->initialized)
1082 {
1083 OUR_PMLog(kPMLogControllingDriverErr4, 0, 0);
1084 return kIOReturnBadArgument;
1085 }
1086
1087 if (powerStates[0].version != kIOPMPowerStateVersion1)
1088 {
1089 OUR_PMLog(kPMLogControllingDriverErr1, powerStates[0].version, 0);
1090 return kIOReturnBadArgument;
1091 }
1092
1093 do {
1094 // Make a copy of the supplied power state array.
1095 powerStatesCopy = IONew(IOPMPowerState, numberOfStates);
1096 if (!powerStatesCopy)
1097 break;
1098
1099 bcopy( powerStates, powerStatesCopy,
1100 sizeof(IOPMPowerState) * numberOfStates );
1101
1102 request = acquirePMRequest( this, kIOPMRequestTypeRegisterPowerDriver );
1103 if (!request)
1104 break;
1105
1106 powerDriver->retain();
1107 request->fArg0 = (void *) powerDriver;
1108 request->fArg1 = (void *) powerStatesCopy;
1109 request->fArg2 = (void *) numberOfStates;
1110
1111 submitPMRequest( request );
1112 return kIOReturnSuccess;
1113 }
1114 while (false);
1115
1116 if (powerStatesCopy)
1117 IODelete(powerStatesCopy, IOPMPowerState, numberOfStates);
1118 return kIOReturnNoMemory;
1119 }
1120
1121 //*********************************************************************************
1122 // [private] handleRegisterPowerDriver
1123 //*********************************************************************************
1124
1125 void IOService::handleRegisterPowerDriver ( IOPMRequest * request )
1126 {
1127 IOService * powerDriver = (IOService *) request->fArg0;
1128 IOPMPowerState * powerStates = (IOPMPowerState *) request->fArg1;
1129 unsigned long numberOfStates = (unsigned long) request->fArg2;
1130 unsigned long i;
1131 IOService * root;
1132 OSIterator * iter;
1133
1134 PM_ASSERT_IN_GATE();
1135 assert(powerStates);
1136 assert(powerDriver);
1137 assert(numberOfStates > 1);
1138
1139 if ( !fNumberOfPowerStates )
1140 {
1141 OUR_PMLog(kPMLogControllingDriver,
1142 (unsigned long) numberOfStates,
1143 (unsigned long) powerStates[0].version);
1144
1145 fPowerStates = powerStates;
1146 fNumberOfPowerStates = numberOfStates;
1147 fControllingDriver = powerDriver;
1148 fCurrentCapabilityFlags = fPowerStates[0].capabilityFlags;
1149
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;
1154 }
1155
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.
1160
1161 root = getPlatform()->getProvider();
1162 assert(root);
1163 if (!root ||
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)))))
1172 {
1173 if (fInterestedDrivers->findItem(powerDriver) == NULL)
1174 {
1175 PM_LOCK();
1176 fInterestedDrivers->appendNewInformee(powerDriver);
1177 PM_UNLOCK();
1178 }
1179 }
1180
1181 // Examine all existing power clients and perform limit check.
1182
1183 if (fPowerClients)
1184 {
1185 iter = OSCollectionIterator::withCollection(fPowerClients);
1186 if (iter)
1187 {
1188 const OSSymbol * client;
1189 while ((client = (const OSSymbol *) iter->getNextObject()))
1190 {
1191 uint32_t powerState = getPowerStateForClient(client);
1192 if (powerState >= numberOfStates)
1193 {
1194 updatePowerClient(client, numberOfStates - 1);
1195 }
1196 }
1197 iter->release();
1198 }
1199 }
1200
1201 if ( inPlane(gIOPowerPlane) && fParentsKnowState )
1202 {
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);
1208 }
1209 }
1210 else
1211 {
1212 OUR_PMLog(kPMLogControllingDriverErr2, numberOfStates, 0);
1213 IODelete(powerStates, IOPMPowerState, numberOfStates);
1214 }
1215
1216 powerDriver->release();
1217 }
1218
1219 //*********************************************************************************
1220 // [public] registerInterestedDriver
1221 //
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 //*********************************************************************************
1227
1228 IOPMPowerFlags IOService::registerInterestedDriver ( IOService * driver )
1229 {
1230 IOPMRequest * request;
1231 bool signal;
1232
1233 if (!initialized || !fInterestedDrivers)
1234 return IOPMNotPowerManaged;
1235
1236 PM_LOCK();
1237 signal = (!fInsertInterestSet && !fRemoveInterestSet);
1238 if (fInsertInterestSet == NULL)
1239 fInsertInterestSet = OSSet::withCapacity(4);
1240 if (fInsertInterestSet)
1241 fInsertInterestSet->setObject(driver);
1242 PM_UNLOCK();
1243
1244 if (signal)
1245 {
1246 request = acquirePMRequest( this, kIOPMRequestTypeInterestChanged );
1247 if (request)
1248 submitPMRequest( request );
1249 }
1250
1251 // This return value cannot be trusted, but return a value
1252 // for those clients that care.
1253
1254 OUR_PMLog(kPMLogInterestedDriver, kIOPMDeviceUsable, 2);
1255 return kIOPMDeviceUsable;
1256 }
1257
1258 //*********************************************************************************
1259 // [public] deRegisterInterestedDriver
1260 //*********************************************************************************
1261
1262 IOReturn IOService::deRegisterInterestedDriver ( IOService * driver )
1263 {
1264 IOPMinformeeList * list;
1265 IOPMinformee * item;
1266 IOPMRequest * request;
1267 bool signal;
1268
1269 if (!initialized || !fInterestedDrivers)
1270 return IOPMNotPowerManaged;
1271
1272 PM_LOCK();
1273 signal = (!fRemoveInterestSet && !fInsertInterestSet);
1274 if (fRemoveInterestSet == NULL)
1275 fRemoveInterestSet = OSSet::withCapacity(4);
1276 if (fRemoveInterestSet)
1277 {
1278 fRemoveInterestSet->setObject(driver);
1279
1280 list = fInterestedDrivers;
1281 item = list->findItem(driver);
1282 if (item && item->active)
1283 {
1284 item->active = false;
1285 }
1286 if (fLockedFlags.DriverCallBusy)
1287 PM_DEBUG("%s::deRegisterInterestedDriver() driver call busy\n", getName());
1288 }
1289 PM_UNLOCK();
1290
1291 if (signal)
1292 {
1293 request = acquirePMRequest( this, kIOPMRequestTypeInterestChanged );
1294 if (request)
1295 submitPMRequest( request );
1296 }
1297
1298 return IOPMNoErr;
1299 }
1300
1301 //*********************************************************************************
1302 // [private] handleInterestChanged
1303 //
1304 // Handle interest added or removed.
1305 //*********************************************************************************
1306
1307 void IOService::handleInterestChanged( IOPMRequest * request )
1308 {
1309 IOService * driver;
1310 IOPMinformee * informee;
1311 IOPMinformeeList * list = fInterestedDrivers;
1312
1313 PM_LOCK();
1314
1315 if (fInsertInterestSet)
1316 {
1317 while ((driver = (IOService *) fInsertInterestSet->getAnyObject()))
1318 {
1319 if ((list->findItem(driver) == NULL) &&
1320 (!fRemoveInterestSet ||
1321 !fRemoveInterestSet->containsObject(driver)))
1322 {
1323 informee = list->appendNewInformee(driver);
1324 }
1325 fInsertInterestSet->removeObject(driver);
1326 }
1327 fInsertInterestSet->release();
1328 fInsertInterestSet = 0;
1329 }
1330
1331 if (fRemoveInterestSet)
1332 {
1333 while ((driver = (IOService *) fRemoveInterestSet->getAnyObject()))
1334 {
1335 informee = list->findItem(driver);
1336 if (informee)
1337 {
1338 if (fHeadNotePendingAcks && informee->timer)
1339 {
1340 informee->timer = 0;
1341 fHeadNotePendingAcks--;
1342 }
1343 list->removeFromList(driver);
1344 }
1345 fRemoveInterestSet->removeObject(driver);
1346 }
1347 fRemoveInterestSet->release();
1348 fRemoveInterestSet = 0;
1349 }
1350
1351 PM_UNLOCK();
1352 }
1353
1354 //*********************************************************************************
1355 // [public] acknowledgePowerChange
1356 //
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
1361 // for.
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 //*********************************************************************************
1367
1368 IOReturn IOService::acknowledgePowerChange ( IOService * whichObject )
1369 {
1370 IOPMRequest * request;
1371
1372 if (!initialized)
1373 return IOPMNotYetInitialized;
1374 if (!whichObject)
1375 return kIOReturnBadArgument;
1376
1377 request = acquirePMRequest( this, kIOPMRequestTypeAckPowerChange );
1378 if (!request)
1379 return kIOReturnNoMemory;
1380
1381 whichObject->retain();
1382 request->fArg0 = whichObject;
1383
1384 submitPMRequest( request );
1385 return IOPMNoErr;
1386 }
1387
1388 //*********************************************************************************
1389 // [private] handleAcknowledgePowerChange
1390 //*********************************************************************************
1391
1392 bool IOService::handleAcknowledgePowerChange ( IOPMRequest * request )
1393 {
1394 IOPMinformee * informee;
1395 unsigned long childPower = kIOPMUnknown;
1396 IOService * theChild;
1397 IOService * whichObject;
1398 bool all_acked = false;
1399
1400 PM_ASSERT_IN_GATE();
1401 whichObject = (IOService *) request->fArg0;
1402 assert(whichObject);
1403
1404 // one of our interested drivers?
1405 informee = fInterestedDrivers->findItem( whichObject );
1406 if ( informee == NULL )
1407 {
1408 if ( !isChild(whichObject, gIOPowerPlane) )
1409 {
1410 OUR_PMLog(kPMLogAcknowledgeErr1, 0, 0);
1411 goto no_err;
1412 } else {
1413 OUR_PMLog(kPMLogChildAcknowledge, fHeadNotePendingAcks, 0);
1414 }
1415 } else {
1416 OUR_PMLog(kPMLogDriverAcknowledge, fHeadNotePendingAcks, 0);
1417 }
1418
1419 if ( fHeadNotePendingAcks != 0 )
1420 {
1421 assert(fPowerStates != NULL);
1422
1423 // yes, make sure we're expecting acks
1424 if ( informee != NULL )
1425 {
1426 // it's an interested driver
1427 // make sure we're expecting this ack
1428 if ( informee->timer != 0 )
1429 {
1430 #if LOG_SETPOWER_TIMES
1431 if (informee->timer > 0)
1432 {
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));
1440 }
1441 #endif
1442 // mark it acked
1443 informee->timer = 0;
1444 // that's one fewer to worry about
1445 fHeadNotePendingAcks--;
1446 } else {
1447 // this driver has already acked
1448 OUR_PMLog(kPMLogAcknowledgeErr2, 0, 0);
1449 }
1450 } else {
1451 // it's a child
1452 // make sure we're expecting this ack
1453 if ( ((IOPowerConnection *)whichObject)->getAwaitingAck() )
1454 {
1455 // that's one fewer to worry about
1456 fHeadNotePendingAcks--;
1457 ((IOPowerConnection *)whichObject)->setAwaitingAck(false);
1458 theChild = (IOService *)whichObject->copyChildEntry(gIOPowerPlane);
1459 if ( theChild )
1460 {
1461 childPower = theChild->currentPowerConsumption();
1462 theChild->release();
1463 }
1464 if ( childPower == kIOPMUnknown )
1465 {
1466 fHeadNotePowerArrayEntry->staticPower = kIOPMUnknown;
1467 } else {
1468 if (fHeadNotePowerArrayEntry->staticPower != kIOPMUnknown)
1469 {
1470 fHeadNotePowerArrayEntry->staticPower += childPower;
1471 }
1472 }
1473 }
1474 }
1475
1476 if ( fHeadNotePendingAcks == 0 ) {
1477 // yes, stop the timer
1478 stop_ack_timer();
1479 // and now we can continue
1480 all_acked = true;
1481 }
1482 } else {
1483 OUR_PMLog(kPMLogAcknowledgeErr3, 0, 0); // not expecting anybody to ack
1484 }
1485
1486 no_err:
1487 if (whichObject)
1488 whichObject->release();
1489
1490 return all_acked;
1491 }
1492
1493 //*********************************************************************************
1494 // [public] acknowledgeSetPowerState
1495 //
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 //*********************************************************************************
1500
1501 IOReturn IOService::acknowledgeSetPowerState ( void )
1502 {
1503 IOPMRequest * request;
1504
1505 if (!initialized)
1506 return IOPMNotYetInitialized;
1507
1508 request = acquirePMRequest( this, kIOPMRequestTypeAckSetPowerState );
1509 if (!request)
1510 return kIOReturnNoMemory;
1511
1512 submitPMRequest( request );
1513 return kIOReturnSuccess;
1514 }
1515
1516 //*********************************************************************************
1517 // [private] adjustPowerState
1518 //*********************************************************************************
1519
1520 void IOService::adjustPowerState ( uint32_t clamp )
1521 {
1522 PM_ASSERT_IN_GATE();
1523 computeDesiredState(clamp);
1524 if (fControllingDriver && fParentsKnowState && inPlane(gIOPowerPlane))
1525 {
1526 startPowerChange(
1527 /* flags */ kIOPMWeInitiated,
1528 /* power state */ fDesiredPowerState,
1529 /* domain flags */ 0,
1530 /* connection */ 0,
1531 /* parent flags */ 0);
1532 }
1533 }
1534
1535 //*********************************************************************************
1536 // [public] synchronizePowerTree
1537 //*********************************************************************************
1538
1539 IOReturn IOService::synchronizePowerTree ( void )
1540 {
1541 IOPMRequest * request_c;
1542 IOPMRequest * request_s;
1543
1544 if (this != getPMRootDomain())
1545 return kIOReturnBadArgument;
1546 if (!initialized)
1547 return kIOPMNotYetInitialized;
1548
1549 request_c = acquirePMRequest( this, kIOPMRequestTypeIdleCancel );
1550 request_s = acquirePMRequest( this, kIOPMRequestTypeSynchronizePowerTree );
1551
1552 if (!request_c || !request_s)
1553 goto error_no_memory;
1554
1555 request_c->attachNextRequest( request_s );
1556
1557 submitPMRequest(request_c);
1558 submitPMRequest(request_s);
1559
1560 return kIOReturnSuccess;
1561
1562 error_no_memory:
1563 if (request_c) releasePMRequest(request_c);
1564 if (request_s) releasePMRequest(request_s);
1565 return kIOReturnNoMemory;
1566 }
1567
1568 //*********************************************************************************
1569 // [private] handleSynchronizePowerTree
1570 //*********************************************************************************
1571
1572 void IOService::handleSynchronizePowerTree ( IOPMRequest * /*request*/ )
1573 {
1574 PM_ASSERT_IN_GATE();
1575 if (fControllingDriver && fParentsKnowState && inPlane(gIOPowerPlane) &&
1576 (fCurrentPowerState == fNumberOfPowerStates - 1))
1577 {
1578 startPowerChange(
1579 /* flags */ kIOPMWeInitiated | kIOPMSynchronize,
1580 /* power state */ fCurrentPowerState,
1581 /* domain flags */ 0,
1582 /* connection */ 0,
1583 /* parent flags */ 0);
1584 }
1585 }
1586
1587 #ifndef __LP64__
1588 //*********************************************************************************
1589 // [deprecated] powerDomainWillChangeTo
1590 //
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 //*********************************************************************************
1597
1598 IOReturn IOService::powerDomainWillChangeTo (
1599 IOPMPowerFlags newPowerFlags,
1600 IOPowerConnection * whichParent )
1601 {
1602 assert(false);
1603 return kIOReturnUnsupported;
1604 }
1605 #endif /* !__LP64__ */
1606
1607 //*********************************************************************************
1608 // [private] handlePowerDomainWillChangeTo
1609 //*********************************************************************************
1610
1611 void IOService::handlePowerDomainWillChangeTo ( IOPMRequest * request )
1612 {
1613 IOPMPowerFlags parentPowerFlags = (IOPMPowerFlags) request->fArg0;
1614 IOPowerConnection * whichParent = (IOPowerConnection *) request->fArg1;
1615 unsigned long parentChangeFlags = (unsigned long) request->fArg2;
1616 OSIterator * iter;
1617 OSObject * next;
1618 IOPowerConnection * connection;
1619 unsigned long newPowerState;
1620 unsigned long myChangeFlags;
1621 IOPMPowerFlags combinedPowerFlags;
1622 bool savedParentsKnowState;
1623 IOReturn result = IOPMAckImplied;
1624
1625 PM_ASSERT_IN_GATE();
1626 OUR_PMLog(kPMLogWillChange, parentPowerFlags, 0);
1627
1628 if (!inPlane(gIOPowerPlane) || !whichParent || !whichParent->getAwaitingAck())
1629 {
1630 PM_DEBUG("%s::%s not in power tree\n", getName(), __FUNCTION__);
1631 goto exit_no_ack;
1632 }
1633
1634 savedParentsKnowState = fParentsKnowState;
1635
1636 // Combine parents' output power flags.
1637
1638 combinedPowerFlags = 0;
1639
1640 iter = getParentIterator(gIOPowerPlane);
1641 if ( iter )
1642 {
1643 while ( (next = iter->getNextObject()) )
1644 {
1645 if ( (connection = OSDynamicCast(IOPowerConnection, next)) )
1646 {
1647 if ( connection == whichParent )
1648 combinedPowerFlags |= parentPowerFlags;
1649 else
1650 combinedPowerFlags |= connection->parentCurrentPowerFlags();
1651 }
1652 }
1653 iter->release();
1654 }
1655
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.
1658
1659 if ( fControllingDriver && !fInitialChange )
1660 {
1661 newPowerState = fControllingDriver->maxCapabilityForDomainState(
1662 combinedPowerFlags);
1663
1664 // Absorb parent's kIOPMSynchronize flag.
1665 myChangeFlags = kIOPMParentInitiated | kIOPMDomainWillChange |
1666 (parentChangeFlags & kIOPMSynchronize);
1667
1668 result = startPowerChange(
1669 /* flags */ myChangeFlags,
1670 /* power state */ newPowerState,
1671 /* domain flags */ combinedPowerFlags,
1672 /* connection */ whichParent,
1673 /* parent flags */ parentPowerFlags);
1674 }
1675
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.
1679
1680 if (parentChangeFlags & kIOPMDomainPowerDrop)
1681 {
1682 setParentInfo(parentPowerFlags, whichParent, true);
1683 }
1684
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.
1688
1689 if (IOPMAckImplied == result)
1690 {
1691 IOService * parent;
1692 parent = (IOService *) whichParent->copyParentEntry(gIOPowerPlane);
1693 assert(parent);
1694 if ( parent )
1695 {
1696 parent->acknowledgePowerChange( whichParent );
1697 parent->release();
1698 }
1699 }
1700
1701 exit_no_ack:
1702 // Drop the retain from notifyChild().
1703 if (whichParent) whichParent->release();
1704 }
1705
1706 #ifndef __LP64__
1707 //*********************************************************************************
1708 // [deprecated] powerDomainDidChangeTo
1709 //
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 //*********************************************************************************
1716
1717 IOReturn IOService::powerDomainDidChangeTo (
1718 IOPMPowerFlags newPowerFlags,
1719 IOPowerConnection * whichParent )
1720 {
1721 assert(false);
1722 return kIOReturnUnsupported;
1723 }
1724 #endif /* !__LP64__ */
1725
1726 //*********************************************************************************
1727 // [private] handlePowerDomainDidChangeTo
1728 //*********************************************************************************
1729
1730 void IOService::handlePowerDomainDidChangeTo ( IOPMRequest * request )
1731 {
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;
1740
1741 PM_ASSERT_IN_GATE();
1742 OUR_PMLog(kPMLogDidChange, parentPowerFlags, 0);
1743
1744 if (!inPlane(gIOPowerPlane) || !whichParent || !whichParent->getAwaitingAck())
1745 {
1746 PM_DEBUG("%s::%s not in power tree\n", getName(), __FUNCTION__);
1747 goto exit_no_ack;
1748 }
1749
1750 savedParentsKnowState = fParentsKnowState;
1751
1752 setParentInfo(parentPowerFlags, whichParent, true);
1753
1754 if ( fControllingDriver )
1755 {
1756 newPowerState = fControllingDriver->maxCapabilityForDomainState(
1757 fParentsCurrentPowerFlags);
1758
1759 if (fInitialChange)
1760 {
1761 initialDesire = fControllingDriver->initialPowerStateForDomainState(
1762 fParentsCurrentPowerFlags);
1763 computeDesiredState(initialDesire);
1764 }
1765
1766 // Absorb parent's kIOPMSynchronize flag.
1767 myChangeFlags = kIOPMParentInitiated | kIOPMDomainDidChange |
1768 (parentChangeFlags & kIOPMSynchronize);
1769
1770 result = startPowerChange(
1771 /* flags */ myChangeFlags,
1772 /* power state */ newPowerState,
1773 /* domain flags */ fParentsCurrentPowerFlags,
1774 /* connection */ whichParent,
1775 /* parent flags */ 0);
1776 }
1777
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.
1781
1782 if (IOPMAckImplied == result)
1783 {
1784 IOService * parent;
1785 parent = (IOService *) whichParent->copyParentEntry(gIOPowerPlane);
1786 assert(parent);
1787 if ( parent )
1788 {
1789 parent->acknowledgePowerChange( whichParent );
1790 parent->release();
1791 }
1792 }
1793
1794 // If the parent registers its power driver late, then this is the
1795 // first opportunity to tell our parent about our desire.
1796
1797 if (!savedParentsKnowState && fParentsKnowState)
1798 {
1799 PM_TRACE("%s::powerDomainDidChangeTo parentsKnowState = true\n",
1800 getName());
1801 requestDomainPower( fDesiredPowerState );
1802 }
1803
1804 exit_no_ack:
1805 // Drop the retain from notifyChild().
1806 if (whichParent) whichParent->release();
1807 }
1808
1809 //*********************************************************************************
1810 // [private] setParentInfo
1811 //
1812 // Set our connection data for one specific parent, and then combine all the parent
1813 // data together.
1814 //*********************************************************************************
1815
1816 void IOService::setParentInfo (
1817 IOPMPowerFlags newPowerFlags,
1818 IOPowerConnection * whichParent,
1819 bool knowsState )
1820 {
1821 OSIterator * iter;
1822 OSObject * next;
1823 IOPowerConnection * conn;
1824
1825 PM_ASSERT_IN_GATE();
1826
1827 // set our connection data
1828 whichParent->setParentCurrentPowerFlags(newPowerFlags);
1829 whichParent->setParentKnowsState(knowsState);
1830
1831 // recompute our parent info
1832 fParentsCurrentPowerFlags = 0;
1833 fParentsKnowState = true;
1834
1835 iter = getParentIterator(gIOPowerPlane);
1836 if ( iter )
1837 {
1838 while ( (next = iter->getNextObject()) )
1839 {
1840 if ( (conn = OSDynamicCast(IOPowerConnection, next)) )
1841 {
1842 fParentsKnowState &= conn->parentKnowsState();
1843 fParentsCurrentPowerFlags |= conn->parentCurrentPowerFlags();
1844 }
1845 }
1846 iter->release();
1847 }
1848 }
1849
1850 //*********************************************************************************
1851 // [private] rebuildChildClampBits
1852 //
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 //*********************************************************************************
1859
1860 void IOService::rebuildChildClampBits ( void )
1861 {
1862 unsigned long i;
1863 OSIterator * iter;
1864 OSObject * next;
1865 IOPowerConnection * connection;
1866 unsigned long powerState;
1867
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.
1870
1871 for ( i = 0; i < fNumberOfPowerStates; i++ )
1872 {
1873 fPowerStates[i].capabilityFlags &= ~(kIOPMChildClamp | kIOPMChildClamp2);
1874 }
1875
1876 if (!inPlane(gIOPowerPlane))
1877 return;
1878
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.
1882
1883 iter = getChildIterator(gIOPowerPlane);
1884 if ( iter )
1885 {
1886 while ( (next = iter->getNextObject()) )
1887 {
1888 if ( (connection = OSDynamicCast(IOPowerConnection, next)) )
1889 {
1890 if (connection->getReadyFlag() == false)
1891 {
1892 PM_CONNECT("[%s] %s: connection not ready\n",
1893 getName(), __FUNCTION__);
1894 continue;
1895 }
1896
1897 powerState = connection->getDesiredDomainState();
1898 if (powerState < fNumberOfPowerStates)
1899 {
1900 if ( connection->getPreventIdleSleepFlag() )
1901 fPowerStates[powerState].capabilityFlags |= kIOPMChildClamp;
1902 if ( connection->getPreventSystemSleepFlag() )
1903 fPowerStates[powerState].capabilityFlags |= kIOPMChildClamp2;
1904 }
1905 }
1906 }
1907 iter->release();
1908 }
1909 }
1910
1911 //*********************************************************************************
1912 // [public] requestPowerDomainState
1913 //
1914 // Called on a power parent when a child's power requirement changes.
1915 //*********************************************************************************
1916
1917 IOReturn IOService::requestPowerDomainState(
1918 IOPMPowerFlags childRequestPowerFlags,
1919 IOPowerConnection * childConnection,
1920 unsigned long specification )
1921 {
1922 unsigned long ps;
1923 IOPMPowerFlags outputPowerFlags;
1924 IOService * child;
1925 IOPMRequest * subRequest;
1926 bool preventIdle, preventSleep;
1927 bool adjustPower = false;
1928
1929 if (!initialized)
1930 return IOPMNotYetInitialized;
1931
1932 if (gIOPMWorkLoop->onThread() == false)
1933 {
1934 PM_DEBUG("%s::requestPowerDomainState\n", getName());
1935 return kIOReturnSuccess;
1936 }
1937
1938 OUR_PMLog(kPMLogRequestDomain, childRequestPowerFlags, specification);
1939
1940 if (!isChild(childConnection, gIOPowerPlane))
1941 return kIOReturnNotAttached;
1942
1943 if (!fControllingDriver || !fNumberOfPowerStates)
1944 return IOPMNotYetInitialized;
1945
1946 child = (IOService *) childConnection->getChildEntry(gIOPowerPlane);
1947 assert(child);
1948
1949 preventIdle = ((childRequestPowerFlags & kIOPMPreventIdleSleep) != 0);
1950 preventSleep = ((childRequestPowerFlags & kIOPMPreventSystemSleep) != 0);
1951 childRequestPowerFlags &= ~(kIOPMPreventIdleSleep | kIOPMPreventSystemSleep);
1952
1953 // Merge in the power flags contributed by this power parent
1954 // at its current or impending power state.
1955
1956 outputPowerFlags = fPowerStates[fCurrentPowerState].outputPowerCharacter;
1957 if ((fMachineState != kIOPM_Finished) && (getPMRootDomain() != this))
1958 {
1959 if (IS_POWER_DROP)
1960 {
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
1966 //
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.
1971 //
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.
1974
1975 if ((fMachineState == kIOPM_OurChangeTellClientsPowerDown) ||
1976 (fMachineState == kIOPM_OurChangeTellPriorityClientsPowerDown))
1977 {
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());
1982 }
1983 else
1984 {
1985 // Beyond cancellation point, report the impending state.
1986 outputPowerFlags =
1987 fPowerStates[fHeadNotePowerState].outputPowerCharacter;
1988 }
1989 }
1990 else
1991 {
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.
1999
2000 outputPowerFlags = childConnection->parentCurrentPowerFlags();
2001 }
2002 }
2003 child->fHeadNoteDomainTargetFlags |= outputPowerFlags;
2004
2005 // Map child's requested power flags to one of our power state.
2006
2007 for (ps = 0; ps < fNumberOfPowerStates; ps++)
2008 {
2009 if ((fPowerStates[ps].outputPowerCharacter & childRequestPowerFlags) ==
2010 (fOutputPowerCharacterFlags & childRequestPowerFlags))
2011 break;
2012 }
2013 if (ps >= fNumberOfPowerStates)
2014 {
2015 ps = 0; // should never happen
2016 }
2017
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.
2021
2022 if (!childConnection->childHasRequestedPower() ||
2023 (ps != childConnection->getDesiredDomainState()) ||
2024 (childConnection->getPreventIdleSleepFlag() != preventIdle) ||
2025 (childConnection->getPreventSystemSleepFlag() != preventSleep))
2026 adjustPower = true;
2027
2028 #if ENABLE_DEBUG_LOGS
2029 if (adjustPower)
2030 {
2031 PM_DEBUG("requestPowerDomainState[%s]: %s, init %d, %u->%u\n",
2032 getName(), child->getName(),
2033 !childConnection->childHasRequestedPower(),
2034 (uint32_t) childConnection->getDesiredDomainState(),
2035 (uint32_t) ps);
2036 }
2037 #endif
2038
2039 // Record the child's desires on the connection.
2040 #if SUPPORT_IDLE_CANCEL
2041 bool attemptCancel = (preventIdle && !childConnection->getPreventIdleSleepFlag());
2042 #endif
2043 childConnection->setChildHasRequestedPower();
2044 childConnection->setDesiredDomainState( ps );
2045 childConnection->setPreventIdleSleepFlag( preventIdle );
2046 childConnection->setPreventSystemSleepFlag( preventSleep );
2047
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.
2051
2052 if (adjustPower && !fDeviceOverrides &&
2053 (!fAdjustPowerScheduled || gIOPMRequest->getRootRequest()))
2054 {
2055 subRequest = acquirePMRequest(
2056 this, kIOPMRequestTypeAdjustPowerState, gIOPMRequest );
2057 if (subRequest)
2058 {
2059 submitPMRequest( subRequest );
2060 fAdjustPowerScheduled = true;
2061 }
2062 }
2063
2064 #if SUPPORT_IDLE_CANCEL
2065 if (attemptCancel)
2066 {
2067 subRequest = acquirePMRequest( this, kIOPMRequestTypeIdleCancel );
2068 if (subRequest)
2069 {
2070 submitPMRequest( subRequest );
2071 }
2072 }
2073 #endif
2074
2075 return kIOReturnSuccess;
2076 }
2077
2078 //*********************************************************************************
2079 // [public] temporaryPowerClampOn
2080 //
2081 // A power domain wants to clamp its power on till it has children which
2082 // will thendetermine the power domain state.
2083 //
2084 // We enter the highest state until addPowerChild is called.
2085 //*********************************************************************************
2086
2087 IOReturn IOService::temporaryPowerClampOn ( void )
2088 {
2089 return requestPowerState( gIOPMPowerClientChildProxy, kIOPMPowerStateMax );
2090 }
2091
2092 //*********************************************************************************
2093 // [public] makeUsable
2094 //
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.
2099 //
2100 // We treat this as a subclass object request to switch to the
2101 // highest power state.
2102 //*********************************************************************************
2103
2104 IOReturn IOService::makeUsable ( void )
2105 {
2106 OUR_PMLog(kPMLogMakeUsable, 0, 0);
2107 return requestPowerState( gIOPMPowerClientDevice, kIOPMPowerStateMax );
2108 }
2109
2110 //*********************************************************************************
2111 // [public] currentCapability
2112 //*********************************************************************************
2113
2114 IOPMPowerFlags IOService::currentCapability ( void )
2115 {
2116 if (!initialized)
2117 return IOPMNotPowerManaged;
2118
2119 return fCurrentCapabilityFlags;
2120 }
2121
2122 //*********************************************************************************
2123 // [public] changePowerStateTo
2124 //
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 //*********************************************************************************
2129
2130 IOReturn IOService::changePowerStateTo ( unsigned long ordinal )
2131 {
2132 OUR_PMLog(kPMLogChangeStateTo, ordinal, 0);
2133 return requestPowerState( gIOPMPowerClientDriver, ordinal );
2134 }
2135
2136 //*********************************************************************************
2137 // [protected] changePowerStateToPriv
2138 //
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 //*********************************************************************************
2143
2144 IOReturn IOService::changePowerStateToPriv ( unsigned long ordinal )
2145 {
2146 OUR_PMLog(kPMLogChangeStateToPriv, ordinal, 0);
2147 return requestPowerState( gIOPMPowerClientDevice, ordinal );
2148 }
2149
2150 //*********************************************************************************
2151 // [protected] changePowerStateWithOverrideTo
2152 //
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 //*********************************************************************************
2158
2159 IOReturn IOService::changePowerStateWithOverrideTo ( unsigned long ordinal )
2160 {
2161 IOPMRequest * request;
2162
2163 if (!initialized)
2164 return kIOPMNotYetInitialized;
2165
2166 OUR_PMLog(kPMLogChangeStateToPriv, ordinal, 0);
2167
2168 request = acquirePMRequest( this, kIOPMRequestTypeRequestPowerStateOverride );
2169 if (!request)
2170 return kIOReturnNoMemory;
2171
2172 gIOPMPowerClientDevice->retain();
2173 request->fArg0 = (void *) ordinal;
2174 request->fArg1 = (void *) gIOPMPowerClientDevice;
2175 request->fArg2 = 0;
2176 #if NOT_READY
2177 if (action)
2178 request->installCompletionAction( action, target, param );
2179 #endif
2180
2181 // Prevent needless downwards power transitions by clamping power
2182 // until the scheduled request is executed.
2183
2184 if (gIOPMWorkLoop->inGate() && (ordinal < fNumberOfPowerStates))
2185 {
2186 fTempClampPowerState = max(fTempClampPowerState, ordinal);
2187 fTempClampCount++;
2188 fOverrideMaxPowerState = ordinal;
2189 request->fArg2 = (void *) true;
2190 }
2191
2192 submitPMRequest( request );
2193 return IOPMNoErr;
2194 }
2195
2196 //*********************************************************************************
2197 // [private] requestPowerState
2198 //*********************************************************************************
2199
2200 IOReturn IOService::requestPowerState (
2201 const OSSymbol * client,
2202 uint32_t state )
2203 {
2204 IOPMRequest * request;
2205
2206 if (!client)
2207 return kIOReturnBadArgument;
2208 if (!initialized)
2209 return kIOPMNotYetInitialized;
2210
2211 request = acquirePMRequest( this, kIOPMRequestTypeRequestPowerState );
2212 if (!request)
2213 return kIOReturnNoMemory;
2214
2215 client->retain();
2216 request->fArg0 = (void *) state;
2217 request->fArg1 = (void *) client;
2218 request->fArg2 = 0;
2219 #if NOT_READY
2220 if (action)
2221 request->installCompletionAction( action, target, param );
2222 #endif
2223
2224 // Prevent needless downwards power transitions by clamping power
2225 // until the scheduled request is executed.
2226
2227 if (gIOPMWorkLoop->inGate() && (state < fNumberOfPowerStates))
2228 {
2229 fTempClampPowerState = max(fTempClampPowerState, state);
2230 fTempClampCount++;
2231 request->fArg2 = (void *) true;
2232 }
2233
2234 submitPMRequest( request );
2235 return IOPMNoErr;
2236 }
2237
2238 //*********************************************************************************
2239 // [private] handleRequestPowerState
2240 //*********************************************************************************
2241
2242 void IOService::handleRequestPowerState ( IOPMRequest * request )
2243 {
2244 const OSSymbol * client = (const OSSymbol *) request->fArg1;
2245 uint32_t state = (uint32_t)(uintptr_t) request->fArg0;
2246
2247 PM_ASSERT_IN_GATE();
2248 if (request->fArg2)
2249 {
2250 assert(fTempClampCount != 0);
2251 if (fTempClampCount) fTempClampCount--;
2252 if (!fTempClampCount) fTempClampPowerState = 0;
2253 }
2254
2255 if (fNumberOfPowerStates && (state >= fNumberOfPowerStates))
2256 state = fNumberOfPowerStates - 1;
2257
2258 // Override from changePowerStateWithOverrideTo() persists until
2259 // the next "device" power request, such as changePowerStateToPriv().
2260
2261 if ((getPMRequestType() != kIOPMRequestTypeRequestPowerStateOverride) &&
2262 (client == gIOPMPowerClientDevice))
2263 fOverrideMaxPowerState = kIOPMPowerStateMax;
2264
2265 if ((state == 0) &&
2266 (client != gIOPMPowerClientDevice) &&
2267 (client != gIOPMPowerClientDriver) &&
2268 (client != gIOPMPowerClientChildProxy))
2269 removePowerClient(client);
2270 else
2271 updatePowerClient(client, state);
2272
2273 adjustPowerState();
2274 client->release();
2275 }
2276
2277 //*********************************************************************************
2278 // [private] Helper functions to update/remove power clients.
2279 //*********************************************************************************
2280
2281 void IOService::updatePowerClient( const OSSymbol * client, uint32_t powerState )
2282 {
2283 if (!fPowerClients)
2284 fPowerClients = OSDictionary::withCapacity(4);
2285 if (fPowerClients && client)
2286 {
2287 OSNumber * num = (OSNumber *) fPowerClients->getObject(client);
2288 if (num)
2289 num->setValue(powerState);
2290 else
2291 {
2292 num = OSNumber::withNumber(powerState, 32);
2293 if (num)
2294 {
2295 fPowerClients->setObject(client, num);
2296 num->release();
2297 }
2298 }
2299 }
2300 }
2301
2302 void IOService::removePowerClient( const OSSymbol * client )
2303 {
2304 if (fPowerClients && client)
2305 fPowerClients->removeObject(client);
2306 }
2307
2308 uint32_t IOService::getPowerStateForClient( const OSSymbol * client )
2309 {
2310 uint32_t powerState = 0;
2311
2312 if (fPowerClients && client)
2313 {
2314 OSNumber * num = (OSNumber *) fPowerClients->getObject(client);
2315 if (num) powerState = num->unsigned32BitValue();
2316 }
2317 return powerState;
2318 }
2319
2320 //*********************************************************************************
2321 // [private] computeDesiredState
2322 //*********************************************************************************
2323
2324 void IOService::computeDesiredState ( unsigned long localClamp )
2325 {
2326 OSIterator * iter;
2327 OSObject * next;
2328 IOPowerConnection * connection;
2329 uint32_t desiredState = 0;
2330 uint32_t newPowerState = 0;
2331 bool hasChildren = false;
2332
2333 // Desired power state is always 0 without a controlling driver.
2334
2335 if (!fNumberOfPowerStates)
2336 {
2337 fDesiredPowerState = 0;
2338 //PM_DEBUG("%s::%s no controlling driver\n", getName(), __FUNCTION__);
2339 return;
2340 }
2341
2342 // Examine the children's desired power state.
2343
2344 iter = getChildIterator(gIOPowerPlane);
2345 if (iter)
2346 {
2347 while ((next = iter->getNextObject()))
2348 {
2349 if ((connection = OSDynamicCast(IOPowerConnection, next)))
2350 {
2351 if (connection->getReadyFlag() == false)
2352 {
2353 PM_CONNECT("[%s] %s: connection not ready\n",
2354 getName(), __FUNCTION__);
2355 continue;
2356 }
2357 if (connection->childHasRequestedPower())
2358 hasChildren = true;
2359 if (connection->getDesiredDomainState() > desiredState)
2360 desiredState = connection->getDesiredDomainState();
2361 }
2362 }
2363 iter->release();
2364 }
2365 if (hasChildren)
2366 updatePowerClient(gIOPMPowerClientChildren, desiredState);
2367 else
2368 removePowerClient(gIOPMPowerClientChildren);
2369
2370 // Iterate through all power clients to determine the min power state.
2371
2372 iter = OSCollectionIterator::withCollection(fPowerClients);
2373 if (iter)
2374 {
2375 const OSSymbol * client;
2376 while ((client = (const OSSymbol *) iter->getNextObject()))
2377 {
2378 // Ignore child and driver when override is in effect.
2379 if ((fDeviceOverrides ||
2380 (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride)) &&
2381 ((client == gIOPMPowerClientChildren) ||
2382 (client == gIOPMPowerClientDriver)))
2383 continue;
2384
2385 // Ignore child proxy when children are present.
2386 if (hasChildren && (client == gIOPMPowerClientChildProxy))
2387 continue;
2388
2389 desiredState = getPowerStateForClient(client);
2390 assert(desiredState < fNumberOfPowerStates);
2391 PM_TRACE(" %u %s\n",
2392 desiredState, client->getCStringNoCopy());
2393
2394 newPowerState = max(newPowerState, desiredState);
2395
2396 if (client == gIOPMPowerClientDevice)
2397 fDeviceDesire = desiredState;
2398 }
2399 iter->release();
2400 }
2401
2402 // Factor in the temporary power desires.
2403
2404 newPowerState = max(newPowerState, localClamp);
2405 newPowerState = max(newPowerState, fTempClampPowerState);
2406
2407 // Limit check against max power override.
2408
2409 newPowerState = min(newPowerState, fOverrideMaxPowerState);
2410
2411 // Limit check against number of power states.
2412
2413 if (newPowerState >= fNumberOfPowerStates)
2414 newPowerState = fNumberOfPowerStates - 1;
2415
2416 fDesiredPowerState = newPowerState;
2417
2418 PM_TRACE(" temp %u, clamp %u, current %u, new %u\n",
2419 (uint32_t) localClamp, (uint32_t) fTempClampPowerState,
2420 (uint32_t) fCurrentPowerState, newPowerState);
2421
2422 // Restart idle timer if stopped and device desire has increased.
2423
2424 if (fDeviceDesire && fIdleTimerStopped)
2425 {
2426 fIdleTimerStopped = false;
2427 fActivityTickleCount = 0;
2428 clock_get_uptime(&fIdleTimerStartTime);
2429 start_PM_idle_timer();
2430 }
2431
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.
2437
2438 if ((getPMRequestType() != kIOPMRequestTypeActivityTickle) &&
2439 (fActivityTicklePowerState != -1))
2440 {
2441 IOLockLock(fActivityLock);
2442 fActivityTicklePowerState = -1;
2443 IOLockUnlock(fActivityLock);
2444 }
2445 }
2446
2447 //*********************************************************************************
2448 // [public] currentPowerConsumption
2449 //
2450 //*********************************************************************************
2451
2452 unsigned long IOService::currentPowerConsumption ( void )
2453 {
2454 if (!initialized)
2455 return kIOPMUnknown;
2456
2457 return fCurrentPowerConsumption;
2458 }
2459
2460 //*********************************************************************************
2461 // [deprecated] getPMworkloop
2462 //*********************************************************************************
2463
2464 IOWorkLoop * IOService::getPMworkloop ( void )
2465 {
2466 return gIOPMWorkLoop;
2467 }
2468
2469 //*********************************************************************************
2470 // [public] activityTickle
2471 //
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 //*********************************************************************************
2478
2479 bool IOService::activityTickle ( unsigned long type, unsigned long stateNumber )
2480 {
2481 IOPMRequest * request;
2482 bool noPowerChange = true;
2483
2484 if ( initialized && stateNumber && (type == kIOPMSuperclassPolicy1) )
2485 {
2486 IOLockLock(fActivityLock);
2487
2488 // Record device activity for the idle timer handler.
2489
2490 fDeviceActive = true;
2491 fActivityTickleCount++;
2492 clock_get_uptime(&fDeviceActiveTimestamp);
2493
2494 #if ROOT_DOMAIN_RUN_STATES
2495 if (fCurrentPowerState == 0)
2496 getPMRootDomain()->handleActivityTickleForService(this);
2497 #endif
2498
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.
2502
2503 if (fActivityTicklePowerState < (long)stateNumber)
2504 {
2505 fActivityTicklePowerState = stateNumber;
2506 noPowerChange = false;
2507
2508 request = acquirePMRequest( this, kIOPMRequestTypeActivityTickle );
2509 if (request)
2510 {
2511 request->fArg0 = (void *) stateNumber; // power state
2512 request->fArg1 = (void *) true; // power rise
2513 submitPMRequest(request);
2514 }
2515 }
2516
2517 IOLockUnlock(fActivityLock);
2518 }
2519
2520 // Returns false if the activityTickle might cause a transition to a
2521 // higher powered state, true otherwise.
2522
2523 return noPowerChange;
2524 }
2525
2526 //*********************************************************************************
2527 // [private] handleActivityTickle
2528 //*********************************************************************************
2529
2530 void IOService::handleActivityTickle ( IOPMRequest * request )
2531 {
2532 uint32_t ticklePowerState = (uint32_t)(uintptr_t) request->fArg0;
2533 bool adjustPower = false;
2534
2535 PM_ASSERT_IN_GATE();
2536 if (request->fArg1)
2537 {
2538 // Power rise from activity tickle.
2539 if ((ticklePowerState > fDeviceDesire) &&
2540 (ticklePowerState < fNumberOfPowerStates))
2541 {
2542 fIdleTimerMinPowerState = ticklePowerState;
2543 adjustPower = true;
2544 }
2545 }
2546 else if (fDeviceDesire > fIdleTimerMinPowerState)
2547 {
2548 // Power drop due to idle timer expiration.
2549 // Do not allow idle timer to reduce power below tickle power.
2550 ticklePowerState = fDeviceDesire - 1;
2551 adjustPower = true;
2552 }
2553
2554 if (adjustPower)
2555 {
2556 updatePowerClient(gIOPMPowerClientDevice, ticklePowerState);
2557 adjustPowerState();
2558 }
2559 }
2560
2561 //*********************************************************************************
2562 // [public] setIdleTimerPeriod
2563 //
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,
2567 // start the timer.
2568 //*********************************************************************************
2569
2570 IOReturn IOService::setIdleTimerPeriod ( unsigned long period )
2571 {
2572 if (!initialized)
2573 return IOPMNotYetInitialized;
2574
2575 OUR_PMLog(kPMLogSetIdleTimerPeriod, period, 0);
2576
2577 IOPMRequest * request =
2578 acquirePMRequest( this, kIOPMRequestTypeSetIdleTimerPeriod );
2579 if (!request)
2580 return kIOReturnNoMemory;
2581
2582 request->fArg0 = (void *) period;
2583 submitPMRequest( request );
2584
2585 return IOPMNoErr;
2586 }
2587
2588 //******************************************************************************
2589 // [public] nextIdleTimeout
2590 //
2591 // Returns how many "seconds from now" the device should idle into its
2592 // next lowest power state.
2593 //******************************************************************************
2594
2595 SInt32 IOService::nextIdleTimeout(
2596 AbsoluteTime currentTime,
2597 AbsoluteTime lastActivity,
2598 unsigned int powerState)
2599 {
2600 AbsoluteTime delta;
2601 UInt64 delta_ns;
2602 SInt32 delta_secs;
2603 SInt32 delay_secs;
2604
2605 // Calculate time difference using funky macro from clock.h.
2606 delta = currentTime;
2607 SUB_ABSOLUTETIME(&delta, &lastActivity);
2608
2609 // Figure it in seconds.
2610 absolutetime_to_nanoseconds(delta, &delta_ns);
2611 delta_secs = (SInt32)(delta_ns / NSEC_PER_SEC);
2612
2613 // Be paranoid about delta somehow exceeding timer period.
2614 if (delta_secs < (int) fIdleTimerPeriod)
2615 delay_secs = (int) fIdleTimerPeriod - delta_secs;
2616 else
2617 delay_secs = (int) fIdleTimerPeriod;
2618
2619 return (SInt32)delay_secs;
2620 }
2621
2622 //******************************************************************************
2623 // [public] start_PM_idle_timer
2624 //
2625 // The parameter is a pointer to us. Use it to call our timeout method.
2626 //******************************************************************************
2627
2628 void IOService::start_PM_idle_timer ( void )
2629 {
2630 static const int maxTimeout = 100000;
2631 static const int minTimeout = 1;
2632 AbsoluteTime uptime;
2633 SInt32 idle_in = 0;
2634
2635 if (!initialized || !fIdleTimerPeriod || !fIdleTimerEventSource)
2636 return;
2637
2638 IOLockLock(fActivityLock);
2639
2640 clock_get_uptime(&uptime);
2641
2642 // Subclasses may modify idle sleep algorithm
2643 idle_in = nextIdleTimeout(uptime, fDeviceActiveTimestamp, fCurrentPowerState);
2644
2645 // Check for out-of range responses
2646 if (idle_in > maxTimeout)
2647 {
2648 // use standard implementation
2649 idle_in = IOService::nextIdleTimeout(uptime,
2650 fDeviceActiveTimestamp,
2651 fCurrentPowerState);
2652 } else if (idle_in < minTimeout) {
2653 idle_in = fIdleTimerPeriod;
2654 }
2655
2656 IOLockUnlock(fActivityLock);
2657
2658 fIdleTimerEventSource->setTimeout(idle_in, NSEC_PER_SEC);
2659 }
2660
2661 //*********************************************************************************
2662 // [private] idleTimerExpired
2663 //
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 //*********************************************************************************
2668
2669 void IOService::idleTimerExpired( IOTimerEventSource * )
2670 {
2671 IOPMRequest * request;
2672 bool restartTimer = true;
2673
2674 if ( !initialized || !fIdleTimerPeriod || fLockedFlags.PMStop )
2675 return;
2676
2677 IOLockLock(fActivityLock);
2678
2679 // Check for device activity (tickles) over last timer period.
2680
2681 if (fDeviceActive)
2682 {
2683 // Device was active - do not drop power, restart timer.
2684 fDeviceActive = false;
2685 }
2686 else
2687 {
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.
2692
2693 if (fActivityTicklePowerState > 0)
2694 {
2695 fActivityTicklePowerState--;
2696 }
2697
2698 request = acquirePMRequest( this, kIOPMRequestTypeActivityTickle );
2699 if (request)
2700 {
2701 request->fArg0 = (void *) 0; // power state (irrelevant)
2702 request->fArg1 = (void *) false; // power drop
2703 submitPMRequest( request );
2704
2705 // Do not restart timer until after the tickle request has been
2706 // processed.
2707
2708 restartTimer = false;
2709 }
2710 }
2711
2712 IOLockUnlock(fActivityLock);
2713
2714 if (restartTimer)
2715 start_PM_idle_timer();
2716 }
2717
2718 #ifndef __LP64__
2719 //*********************************************************************************
2720 // [deprecated] PM_idle_timer_expiration
2721 //*********************************************************************************
2722
2723 void IOService::PM_idle_timer_expiration ( void )
2724 {
2725 }
2726
2727 //*********************************************************************************
2728 // [deprecated] command_received
2729 //*********************************************************************************
2730
2731 void IOService::command_received ( void *statePtr , void *, void * , void * )
2732 {
2733 }
2734 #endif /* !__LP64__ */
2735
2736 //*********************************************************************************
2737 // [public] setAggressiveness
2738 //
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 //*********************************************************************************
2742
2743 IOReturn IOService::setAggressiveness ( unsigned long type, unsigned long newLevel )
2744 {
2745 return kIOReturnSuccess;
2746 }
2747
2748 //*********************************************************************************
2749 // [public] getAggressiveness
2750 //
2751 // Called by the user client.
2752 //*********************************************************************************
2753
2754 IOReturn IOService::getAggressiveness ( unsigned long type, unsigned long * currentLevel )
2755 {
2756 IOPMrootDomain * rootDomain = getPMRootDomain();
2757
2758 if (!rootDomain)
2759 return kIOReturnNotReady;
2760
2761 return rootDomain->getAggressiveness( type, currentLevel );
2762 }
2763
2764 //*********************************************************************************
2765 // [public] getPowerState
2766 //
2767 //*********************************************************************************
2768
2769 UInt32 IOService::getPowerState ( void )
2770 {
2771 if (!initialized)
2772 return 0;
2773
2774 return fCurrentPowerState;
2775 }
2776
2777 #ifndef __LP64__
2778 //*********************************************************************************
2779 // [deprecated] systemWake
2780 //
2781 // Pass this to all power domain children. All those which are
2782 // power domains will pass it on to their children, etc.
2783 //*********************************************************************************
2784
2785 IOReturn IOService::systemWake ( void )
2786 {
2787 OSIterator * iter;
2788 OSObject * next;
2789 IOPowerConnection * connection;
2790 IOService * theChild;
2791
2792 iter = getChildIterator(gIOPowerPlane);
2793 if ( iter )
2794 {
2795 while ( (next = iter->getNextObject()) )
2796 {
2797 if ( (connection = OSDynamicCast(IOPowerConnection, next)) )
2798 {
2799 if (connection->getReadyFlag() == false)
2800 {
2801 PM_CONNECT("[%s] %s: connection not ready\n",
2802 getName(), __FUNCTION__);
2803 continue;
2804 }
2805
2806 theChild = (IOService *)connection->copyChildEntry(gIOPowerPlane);
2807 if ( theChild )
2808 {
2809 theChild->systemWake();
2810 theChild->release();
2811 }
2812 }
2813 }
2814 iter->release();
2815 }
2816
2817 if ( fControllingDriver != NULL )
2818 {
2819 if ( fControllingDriver->didYouWakeSystem() )
2820 {
2821 makeUsable();
2822 }
2823 }
2824
2825 return IOPMNoErr;
2826 }
2827
2828 //*********************************************************************************
2829 // [deprecated] temperatureCriticalForZone
2830 //*********************************************************************************
2831
2832 IOReturn IOService::temperatureCriticalForZone ( IOService * whichZone )
2833 {
2834 IOService * theParent;
2835 IOService * theNub;
2836
2837 OUR_PMLog(kPMLogCriticalTemp, 0, 0);
2838
2839 if ( inPlane(gIOPowerPlane) && !IS_PM_ROOT() )
2840 {
2841 theNub = (IOService *)copyParentEntry(gIOPowerPlane);
2842 if ( theNub )
2843 {
2844 theParent = (IOService *)theNub->copyParentEntry(gIOPowerPlane);
2845 theNub->release();
2846 if ( theParent )
2847 {
2848 theParent->temperatureCriticalForZone(whichZone);
2849 theParent->release();
2850 }
2851 }
2852 }
2853 return IOPMNoErr;
2854 }
2855 #endif /* !__LP64__ */
2856
2857 //*********************************************************************************
2858 // [protected] powerOverrideOnPriv
2859 //*********************************************************************************
2860
2861 IOReturn IOService::powerOverrideOnPriv ( void )
2862 {
2863 IOPMRequest * request;
2864
2865 if (!initialized)
2866 return IOPMNotYetInitialized;
2867
2868 if (gIOPMWorkLoop->inGate())
2869 {
2870 fDeviceOverrides = true;
2871 return IOPMNoErr;
2872 }
2873
2874 request = acquirePMRequest( this, kIOPMRequestTypePowerOverrideOnPriv );
2875 if (!request)
2876 return kIOReturnNoMemory;
2877
2878 submitPMRequest( request );
2879 return IOPMNoErr;
2880 }
2881
2882 //*********************************************************************************
2883 // [protected] powerOverrideOffPriv
2884 //*********************************************************************************
2885
2886 IOReturn IOService::powerOverrideOffPriv ( void )
2887 {
2888 IOPMRequest * request;
2889
2890 if (!initialized)
2891 return IOPMNotYetInitialized;
2892
2893 if (gIOPMWorkLoop->inGate())
2894 {
2895 fDeviceOverrides = false;
2896 return IOPMNoErr;
2897 }
2898
2899 request = acquirePMRequest( this, kIOPMRequestTypePowerOverrideOffPriv );
2900 if (!request)
2901 return kIOReturnNoMemory;
2902
2903 submitPMRequest( request );
2904 return IOPMNoErr;
2905 }
2906
2907 //*********************************************************************************
2908 // [private] handlePowerOverrideChanged
2909 //*********************************************************************************
2910
2911 void IOService::handlePowerOverrideChanged ( IOPMRequest * request )
2912 {
2913 PM_ASSERT_IN_GATE();
2914 if (request->getType() == kIOPMRequestTypePowerOverrideOnPriv)
2915 {
2916 OUR_PMLog(kPMLogOverrideOn, 0, 0);
2917 fDeviceOverrides = true;
2918 }
2919 else
2920 {
2921 OUR_PMLog(kPMLogOverrideOff, 0, 0);
2922 fDeviceOverrides = false;
2923 }
2924
2925 adjustPowerState();
2926 }
2927
2928 //*********************************************************************************
2929 // [private] startPowerChange
2930 //*********************************************************************************
2931
2932 IOReturn IOService::startPowerChange (
2933 unsigned long changeFlags,
2934 unsigned long powerState,
2935 unsigned long domainFlags,
2936 IOPowerConnection * parentConnection,
2937 unsigned long parentFlags )
2938 {
2939 PM_ASSERT_IN_GATE();
2940 assert( fMachineState == kIOPM_Finished );
2941 assert( powerState < fNumberOfPowerStates );
2942
2943 if (powerState >= fNumberOfPowerStates)
2944 return IOPMAckImplied;
2945
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);
2951 #endif
2952
2953 // Initialize the change note.
2954
2955 fHeadNoteFlags = changeFlags;
2956 fHeadNotePowerState = powerState;
2957 fHeadNotePowerArrayEntry = &fPowerStates[ powerState ];
2958 fHeadNoteParentConnection = NULL;
2959
2960 if (changeFlags & kIOPMWeInitiated)
2961 {
2962 if (changeFlags & kIOPMSynchronize)
2963 OurSyncStart();
2964 else
2965 OurChangeStart();
2966 return 0;
2967 }
2968 else
2969 {
2970 assert(changeFlags & kIOPMParentInitiated);
2971 fHeadNoteDomainFlags = domainFlags;
2972 fHeadNoteParentFlags = parentFlags;
2973 fHeadNoteParentConnection = parentConnection;
2974 return ParentChangeStart();
2975 }
2976 }
2977
2978 //*********************************************************************************
2979 // [private] notifyInterestedDrivers
2980 //*********************************************************************************
2981
2982 bool IOService::notifyInterestedDrivers ( void )
2983 {
2984 IOPMinformee * informee;
2985 IOPMinformeeList * list = fInterestedDrivers;
2986 DriverCallParam * param;
2987 IOItemCount count;
2988
2989 PM_ASSERT_IN_GATE();
2990 assert( fDriverCallParamCount == 0 );
2991 assert( fHeadNotePendingAcks == 0 );
2992
2993 fHeadNotePendingAcks = 0;
2994
2995 count = list->numberOfItems();
2996 if (!count)
2997 goto done; // no interested drivers
2998
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()
3002 // responses.
3003
3004 param = (DriverCallParam *) fDriverCallParamPtr;
3005 if (count > fDriverCallParamSlots)
3006 {
3007 if (fDriverCallParamSlots)
3008 {
3009 assert(fDriverCallParamPtr);
3010 IODelete(fDriverCallParamPtr, DriverCallParam, fDriverCallParamSlots);
3011 fDriverCallParamPtr = 0;
3012 fDriverCallParamSlots = 0;
3013 }
3014
3015 param = IONew(DriverCallParam, count);
3016 if (!param)
3017 goto done; // no memory
3018
3019 fDriverCallParamPtr = (void *) param;
3020 fDriverCallParamSlots = count;
3021 }
3022
3023 informee = list->firstInList();
3024 assert(informee);
3025 for (IOItemCount i = 0; i < count; i++)
3026 {
3027 informee->timer = -1;
3028 param[i].Target = informee;
3029 informee->retain();
3030 informee = list->nextInList( informee );
3031 }
3032
3033 fDriverCallParamCount = count;
3034 fHeadNotePendingAcks = count;
3035
3036 // Machine state will be blocked pending callout thread completion.
3037
3038 PM_LOCK();
3039 assert( fLockedFlags.DriverCallBusy == false );
3040 fLockedFlags.DriverCallBusy = true;
3041 PM_UNLOCK();
3042 thread_call_enter( fDriverCallEntry );
3043 return true;
3044
3045 done:
3046 // no interested drivers or did not schedule callout thread due to error.
3047 return false;
3048 }
3049
3050 //*********************************************************************************
3051 // [private] notifyInterestedDriversDone
3052 //*********************************************************************************
3053
3054 void IOService::notifyInterestedDriversDone ( void )
3055 {
3056 IOPMinformee * informee;
3057 IOItemCount count;
3058 DriverCallParam * param;
3059 IOReturn result;
3060
3061 PM_ASSERT_IN_GATE();
3062 param = (DriverCallParam *) fDriverCallParamPtr;
3063 count = fDriverCallParamCount;
3064
3065 assert( fLockedFlags.DriverCallBusy == false );
3066 assert( fMachineState == kIOPM_DriverThreadCallDone );
3067
3068 if (param && count)
3069 {
3070 for (IOItemCount i = 0; i < count; i++, param++)
3071 {
3072 informee = (IOPMinformee *) param->Target;
3073 result = param->Result;
3074
3075 if ((result == IOPMAckImplied) || (result < 0))
3076 {
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.
3081
3082 if (fHeadNotePendingAcks && informee->timer)
3083 fHeadNotePendingAcks--;
3084
3085 informee->timer = 0;
3086 }
3087 else if (informee->timer)
3088 {
3089 assert(informee->timer == -1);
3090
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.
3097
3098 if (result < kMinAckTimeoutTicks)
3099 result = kMinAckTimeoutTicks;
3100
3101 informee->timer = (result / (ACK_TIMER_PERIOD / ns_per_us)) + 1;
3102 }
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.
3107
3108 informee->release();
3109 }
3110
3111 fDriverCallParamCount = 0;
3112
3113 if ( fHeadNotePendingAcks )
3114 {
3115 OUR_PMLog(kPMLogStartAckTimer, 0, 0);
3116 start_ack_timer();
3117 }
3118 }
3119
3120 // Hop back to original machine state path (from notifyAll)
3121 fMachineState = fNextMachineState;
3122
3123 notifyChildren();
3124 }
3125
3126 //*********************************************************************************
3127 // [private] notifyChildren
3128 //*********************************************************************************
3129
3130 void IOService::notifyChildren ( void )
3131 {
3132 OSIterator * iter;
3133 OSObject * next;
3134 IOPowerConnection * connection;
3135 OSArray * children = 0;
3136
3137 if (fStrictTreeOrder)
3138 children = OSArray::withCapacity(8);
3139
3140 // Sum child power consumption in notifyChild()
3141 fHeadNotePowerArrayEntry->staticPower = 0;
3142
3143 iter = getChildIterator(gIOPowerPlane);
3144 if ( iter )
3145 {
3146 while ((next = iter->getNextObject()))
3147 {
3148 if ((connection = OSDynamicCast(IOPowerConnection, next)))
3149 {
3150 if (connection->getReadyFlag() == false)
3151 {
3152 PM_CONNECT("[%s] %s: connection not ready\n",
3153 getName(), __FUNCTION__);
3154 continue;
3155 }
3156
3157 if (children)
3158 children->setObject( connection );
3159 else
3160 notifyChild( connection,
3161 fDriverCallReason == kDriverCallInformPreChange );
3162 }
3163 }
3164 iter->release();
3165 }
3166
3167 if (children)
3168 {
3169 if (children->getCount() == 0)
3170 {
3171 children->release();
3172 children = 0;
3173 }
3174 else
3175 {
3176 assert(fNotifyChildArray == 0);
3177 fNotifyChildArray = children;
3178 fNextMachineState = fMachineState;
3179 fMachineState = kIOPM_NotifyChildrenDone;
3180 }
3181 }
3182 }
3183
3184 //*********************************************************************************
3185 // [private] notifyChildrenDone
3186 //*********************************************************************************
3187
3188 void IOService::notifyChildrenDone ( void )
3189 {
3190 PM_ASSERT_IN_GATE();
3191 assert(fNotifyChildArray);
3192 assert(fMachineState == kIOPM_NotifyChildrenDone);
3193
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.
3200 //
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.
3203
3204 if (fNotifyChildArray->getCount())
3205 {
3206 IOPowerConnection * connection;
3207 connection = (IOPowerConnection *) fNotifyChildArray->getObject(0);
3208 fNotifyChildArray->removeObject(0);
3209 notifyChild( connection, fDriverCallReason == kDriverCallInformPreChange );
3210 }
3211 else
3212 {
3213 fNotifyChildArray->release();
3214 fNotifyChildArray = 0;
3215 fMachineState = fNextMachineState;
3216 }
3217 }
3218
3219 //*********************************************************************************
3220 // [private] notifyAll
3221 //*********************************************************************************
3222
3223 IOReturn IOService::notifyAll ( int nextMachineState, bool is_prechange )
3224 {
3225 // Save the next machine_state to be restored by notifyInterestedDriversDone()
3226
3227 PM_ASSERT_IN_GATE();
3228 fNextMachineState = nextMachineState;
3229 fMachineState = kIOPM_DriverThreadCallDone;
3230 fDriverCallReason = is_prechange ?
3231 kDriverCallInformPreChange : kDriverCallInformPostChange;
3232
3233 if (!notifyInterestedDrivers())
3234 notifyInterestedDriversDone();
3235
3236 return IOPMWillAckLater;
3237 }
3238
3239 //*********************************************************************************
3240 // [private, static] pmDriverCallout
3241 //
3242 // Thread call context
3243 //*********************************************************************************
3244
3245 IOReturn IOService::actionDriverCalloutDone (
3246 OSObject * target,
3247 void * arg0, void * arg1,
3248 void * arg2, void * arg3 )
3249 {
3250 IOServicePM * pwrMgt = (IOServicePM *) arg0;
3251
3252 PM_LOCK();
3253 fLockedFlags.DriverCallBusy = false;
3254 PM_UNLOCK();
3255
3256 if (gIOPMReplyQueue)
3257 gIOPMReplyQueue->signalWorkAvailable();
3258
3259 return kIOReturnSuccess;
3260 }
3261
3262 void IOService::pmDriverCallout ( IOService * from )
3263 {
3264 assert(from);
3265 switch (from->fDriverCallReason)
3266 {
3267 case kDriverCallSetPowerState:
3268 from->driverSetPowerState();
3269 break;
3270
3271 case kDriverCallInformPreChange:
3272 case kDriverCallInformPostChange:
3273 from->driverInformPowerChange();
3274 break;
3275
3276 default:
3277 panic("IOService::pmDriverCallout bad machine state %x",
3278 from->fDriverCallReason);
3279 }
3280
3281 gIOPMWorkLoop->runAction(actionDriverCalloutDone,
3282 /* target */ from,
3283 /* arg0 */ (void *) from->pwrMgt );
3284 }
3285
3286 //*********************************************************************************
3287 // [private] driverSetPowerState
3288 //
3289 // Thread call context
3290 //*********************************************************************************
3291
3292 void IOService::driverSetPowerState ( void )
3293 {
3294 IOService * driver;
3295 unsigned long powerState;
3296 DriverCallParam * param;
3297 IOReturn result;
3298 AbsoluteTime end;
3299
3300 assert( fLockedFlags.DriverCallBusy == true );
3301 param = (DriverCallParam *) fDriverCallParamPtr;
3302 assert( param );
3303 assert( fDriverCallParamCount == 1 );
3304
3305 driver = fControllingDriver;
3306 powerState = fHeadNotePowerState;
3307
3308 if (fLockedFlags.PMStop == false)
3309 {
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);
3315
3316 #if LOG_SETPOWER_TIMES
3317 if ((result == IOPMAckImplied) || (result < 0))
3318 {
3319 uint64_t nsec;
3320
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));
3326 }
3327 #endif
3328 }
3329 else
3330 result = kIOPMAckImplied;
3331
3332 param->Result = result;
3333 }
3334
3335 //*********************************************************************************
3336 // [private] driverInformPowerChange
3337 //
3338 // Thread call context
3339 //*********************************************************************************
3340
3341 void IOService::driverInformPowerChange ( void )
3342 {
3343 IOItemCount count;
3344 IOPMinformee * informee;
3345 IOService * driver;
3346 IOReturn result;
3347 IOPMPowerFlags powerFlags;
3348 unsigned long powerState;
3349 DriverCallParam * param;
3350 AbsoluteTime end;
3351
3352 assert( fLockedFlags.DriverCallBusy == true );
3353 param = (DriverCallParam *) fDriverCallParamPtr;
3354 count = fDriverCallParamCount;
3355 assert( count && param );
3356
3357 powerFlags = fHeadNotePowerArrayEntry->capabilityFlags;
3358 powerState = fHeadNotePowerState;
3359
3360 for (IOItemCount i = 0; i < count; i++)
3361 {
3362 informee = (IOPMinformee *) param->Target;
3363 driver = informee->whatObject;
3364
3365 if ((fLockedFlags.PMStop == false) && informee->active)
3366 {
3367 if (fDriverCallReason == kDriverCallInformPreChange)
3368 {
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);
3374 }
3375 else
3376 {
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);
3382 }
3383
3384 #if LOG_SETPOWER_TIMES
3385 if ((result == IOPMAckImplied) || (result < 0))
3386 {
3387 uint64_t nsec;
3388
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",
3393 driver->getName(),
3394 (fDriverCallReason == kDriverCallInformPreChange) ? "Will" : "Did",
3395 driver, fName, fCurrentPowerState, powerState, NS_TO_MS(nsec));
3396 }
3397 #endif
3398 }
3399 else
3400 result = kIOPMAckImplied;
3401
3402 param->Result = result;
3403 param++;
3404 }
3405 }
3406
3407 //*********************************************************************************
3408 // [private] notifyChild
3409 //
3410 // Notify a power domain child of an upcoming power change.
3411 // If the object acknowledges the current change, we return TRUE.
3412 //*********************************************************************************
3413
3414 bool IOService::notifyChild ( IOPowerConnection * theNub, bool is_prechange )
3415 {
3416 IOReturn ret = IOPMAckImplied;
3417 unsigned long childPower;
3418 IOService * theChild;
3419 IOPMRequest * childRequest;
3420 uint32_t requestArg2;
3421 int requestType;
3422
3423 PM_ASSERT_IN_GATE();
3424 theChild = (IOService *)(theNub->copyChildEntry(gIOPowerPlane));
3425 if (!theChild)
3426 {
3427 assert(false);
3428 return true;
3429 }
3430
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);
3435
3436 requestArg2 = fHeadNoteFlags;
3437 if (fHeadNotePowerState < fCurrentPowerState)
3438 requestArg2 |= kIOPMDomainPowerDrop;
3439
3440 requestType = is_prechange ?
3441 kIOPMRequestTypePowerDomainWillChange :
3442 kIOPMRequestTypePowerDomainDidChange;
3443
3444 childRequest = acquirePMRequest( theChild, requestType );
3445 if (childRequest)
3446 {
3447 theNub->retain();
3448 childRequest->fArg0 = (void *) fHeadNotePowerArrayEntry->outputPowerCharacter;
3449 childRequest->fArg1 = (void *) theNub;
3450 childRequest->fArg2 = (void *) requestArg2;
3451 theChild->submitPMRequest( childRequest );
3452 ret = IOPMWillAckLater;
3453 }
3454 else
3455 {
3456 ret = IOPMAckImplied;
3457 fHeadNotePendingAcks--;
3458 theNub->setAwaitingAck(false);
3459 childPower = theChild->currentPowerConsumption();
3460 if ( childPower == kIOPMUnknown )
3461 {
3462 fHeadNotePowerArrayEntry->staticPower = kIOPMUnknown;
3463 } else {
3464 if (fHeadNotePowerArrayEntry->staticPower != kIOPMUnknown )
3465 fHeadNotePowerArrayEntry->staticPower += childPower;
3466 }
3467 }
3468
3469 theChild->release();
3470 return (IOPMAckImplied == ret);
3471 }
3472
3473 // MARK: -
3474 // MARK: Power Change Initiated by Driver
3475
3476 //*********************************************************************************
3477 // [private] OurChangeStart
3478 //
3479 // Begin the processing of a power change initiated by us.
3480 //*********************************************************************************
3481
3482 void IOService::OurChangeStart ( void )
3483 {
3484 PM_ASSERT_IN_GATE();
3485 OUR_PMLog( kPMLogStartDeviceChange, fHeadNotePowerState, fCurrentPowerState );
3486
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.
3490
3491 if (!IS_PM_ROOT() && (fMaxCapability < fHeadNotePowerState))
3492 {
3493 fHeadNoteFlags |= kIOPMNotDone;
3494 requestDomainPower(fHeadNotePowerState);
3495 OurChangeFinish();
3496 return;
3497 }
3498
3499 // Redundant power changes skips to the end of the state machine.
3500
3501 if (!fInitialChange && (fHeadNotePowerState == fCurrentPowerState))
3502 {
3503 OurChangeFinish();
3504 return;
3505 }
3506 fInitialChange = false;
3507
3508 #if ROOT_DOMAIN_RUN_STATES
3509 // Change started, but may not complete...
3510 // Can be canceled (power drop) or deferred (power rise).
3511
3512 getPMRootDomain()->handlePowerChangeStartForService(
3513 /* service */ this,
3514 /* RD flags */ &fRootDomainState,
3515 /* new pwr state */ fHeadNotePowerState,
3516 /* change flags */ fHeadNoteFlags );
3517 #endif
3518
3519 // Two separate paths, depending if power is being raised or lowered.
3520 // Lowering power is subject to approval by clients of this service.
3521
3522 if (IS_POWER_DROP)
3523 {
3524 // Next machine state for a power drop.
3525 fMachineState = kIOPM_OurChangeTellClientsPowerDown;
3526 fDoNotPowerDown = false;
3527
3528 // Ask apps and kernel clients permission to lower power.
3529 fOutOfBandParameter = kNotifyApps;
3530 askChangeDown(fHeadNotePowerState);
3531 }
3532 else
3533 {
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.
3539 //
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.
3545
3546 #if RESERVE_DOMAIN_POWER
3547 IOReturn ret;
3548
3549 // Reserve parent power necessary to achieve fHeadNotePowerState.
3550 ret = requestDomainPower( fHeadNotePowerState, kReserveDomainPower );
3551 if (ret != kIOReturnSuccess)
3552 {
3553 // Reservation failed, defer power rise.
3554 fHeadNoteFlags |= kIOPMNotDone;
3555 OurChangeFinish();
3556 return;
3557 }
3558 #endif
3559 // Notify interested drivers and children.
3560 notifyAll( kIOPM_OurChangeSetPowerState, kNotifyWillChange );
3561 }
3562 }
3563
3564 //*********************************************************************************
3565
3566 struct IOPMRequestDomainPowerContext {
3567 IOService * child; // the requesting child
3568 IOPMPowerFlags requestPowerFlags; // power flags requested by child
3569 };
3570
3571 static void
3572 requestDomainPowerApplier(
3573 IORegistryEntry * entry,
3574 void * inContext )
3575 {
3576 IOPowerConnection * connection;
3577 IOService * parent;
3578 IOPMRequestDomainPowerContext * context;
3579
3580 if ((connection = OSDynamicCast(IOPowerConnection, entry)) == 0)
3581 return;
3582 parent = (IOService *) connection->copyParentEntry(gIOPowerPlane);
3583 if (!parent)
3584 return;
3585
3586 assert(inContext);
3587 context = (IOPMRequestDomainPowerContext *) inContext;
3588
3589 if (connection->parentKnowsState() && connection->getReadyFlag())
3590 {
3591 parent->requestPowerDomainState(
3592 context->requestPowerFlags,
3593 connection,
3594 IOPMLowestState);
3595 }
3596
3597 parent->release();
3598 }
3599
3600 //*********************************************************************************
3601 // [private] requestDomainPower
3602 //*********************************************************************************
3603
3604 IOReturn IOService::requestDomainPower(
3605 unsigned long ourPowerState,
3606 IOOptionBits options )
3607 {
3608 const IOPMPowerState * powerStateEntry;
3609 IOPMPowerFlags requestPowerFlags;
3610 unsigned long maxPowerState;
3611 IOPMRequestDomainPowerContext context;
3612
3613 PM_ASSERT_IN_GATE();
3614 assert(ourPowerState < fNumberOfPowerStates);
3615 if (ourPowerState >= fNumberOfPowerStates)
3616 return kIOReturnBadArgument;
3617 if (IS_PM_ROOT())
3618 return kIOReturnSuccess;
3619
3620 // Fetch the input power flags for the requested power state.
3621 // Parent request is stated in terms of required power flags.
3622
3623 powerStateEntry = &fPowerStates[ourPowerState];
3624 requestPowerFlags = powerStateEntry->inputPowerRequirement;
3625
3626 if (powerStateEntry->capabilityFlags & (kIOPMChildClamp | kIOPMPreventIdleSleep))
3627 requestPowerFlags |= kIOPMPreventIdleSleep;
3628 if (powerStateEntry->capabilityFlags & (kIOPMChildClamp2 | kIOPMPreventSystemSleep))
3629 requestPowerFlags |= kIOPMPreventSystemSleep;
3630
3631 // Disregard the "previous request" for power reservation.
3632
3633 if (((options & kReserveDomainPower) == 0) &&
3634 (fPreviousRequest == requestPowerFlags))
3635 {
3636 // skip if domain already knows our requirements
3637 goto done;
3638 }
3639 fPreviousRequest = requestPowerFlags;
3640
3641 context.child = this;
3642 context.requestPowerFlags = requestPowerFlags;
3643 fHeadNoteDomainTargetFlags = 0;
3644 applyToParents(requestDomainPowerApplier, &context, gIOPowerPlane);
3645
3646 if (options & kReserveDomainPower)
3647 {
3648 maxPowerState = fControllingDriver->maxCapabilityForDomainState(
3649 fHeadNoteDomainTargetFlags );
3650
3651 if (maxPowerState < fHeadNotePowerState)
3652 {
3653 PM_TRACE("%s: power desired %u:0x%x got %u:0x%x\n",
3654 getName(),
3655 (uint32_t) ourPowerState, (uint32_t) requestPowerFlags,
3656 (uint32_t) maxPowerState, (uint32_t) fHeadNoteDomainTargetFlags);
3657 return kIOReturnNoPower;
3658 }
3659 }
3660
3661 done:
3662 return kIOReturnSuccess;
3663 }
3664
3665 //*********************************************************************************
3666 // [private] OurSyncStart
3667 //*********************************************************************************
3668
3669 void IOService::OurSyncStart ( void )
3670 {
3671 PM_ASSERT_IN_GATE();
3672
3673 if (fInitialChange)
3674 return;
3675
3676 #if ROOT_DOMAIN_RUN_STATES
3677 getPMRootDomain()->handlePowerChangeStartForService(
3678 /* service */ this,
3679 /* RD flags */ &fRootDomainState,
3680 /* new pwr state */ fHeadNotePowerState,
3681 /* change flags */ fHeadNoteFlags );
3682 #endif
3683
3684 fMachineState = kIOPM_SyncNotifyDidChange;
3685 fDriverCallReason = kDriverCallInformPreChange;
3686
3687 notifyChildren();
3688 }
3689
3690 //*********************************************************************************
3691 // [private] OurChangeTellClientsPowerDown
3692 //
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 //*********************************************************************************
3698
3699 void IOService::OurChangeTellClientsPowerDown ( void )
3700 {
3701 fMachineState = kIOPM_OurChangeTellPriorityClientsPowerDown;
3702 tellChangeDown1(fHeadNotePowerState);
3703 }
3704
3705 //*********************************************************************************
3706 // [private] OurChangeTellPriorityClientsPowerDown
3707 //
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 //*********************************************************************************
3713
3714 void IOService::OurChangeTellPriorityClientsPowerDown ( void )
3715 {
3716 fMachineState = kIOPM_OurChangeNotifyInterestedDriversWillChange;
3717 tellChangeDown2(fHeadNotePowerState);
3718 }
3719
3720 //*********************************************************************************
3721 // [private] OurChangeNotifyInterestedDriversWillChange
3722 //
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 //*********************************************************************************
3728
3729 void IOService::OurChangeNotifyInterestedDriversWillChange ( void )
3730 {
3731 IOPMrootDomain *rootDomain;
3732 if ((rootDomain = getPMRootDomain()) == this)
3733 {
3734 rootDomain->tracePoint(kIOPMTracePointSystemSleepDriversPhase);
3735 }
3736
3737 notifyAll( kIOPM_OurChangeSetPowerState, kNotifyWillChange );
3738 }
3739
3740 //*********************************************************************************
3741 // [private] OurChangeSetPowerState
3742 //
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 //*********************************************************************************
3749
3750 void IOService::OurChangeSetPowerState ( void )
3751 {
3752 fNextMachineState = kIOPM_OurChangeWaitForPowerSettle;
3753 fMachineState = kIOPM_DriverThreadCallDone;
3754 fDriverCallReason = kDriverCallSetPowerState;
3755
3756 if (notifyControllingDriver() == false)
3757 notifyControllingDriverDone();
3758 }
3759
3760 //*********************************************************************************
3761 // [private] OurChangeWaitForPowerSettle
3762 //
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 //*********************************************************************************
3767
3768 void IOService::OurChangeWaitForPowerSettle( void )
3769 {
3770 fMachineState = kIOPM_OurChangeNotifyInterestedDriversDidChange;
3771 startSettleTimer();
3772 }
3773
3774 //*********************************************************************************
3775 // [private] OurChangeNotifyInterestedDriversDidChange
3776 //
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 //*********************************************************************************
3782
3783 void IOService::OurChangeNotifyInterestedDriversDidChange ( void )
3784 {
3785 notifyAll( kIOPM_OurChangeFinish, kNotifyDidChange );
3786 }
3787
3788 //*********************************************************************************
3789 // [private] OurChangeFinish
3790 //
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 //*********************************************************************************
3795
3796 void IOService::OurChangeFinish ( void )
3797 {
3798 all_done();
3799 }
3800
3801 // MARK: -
3802 // MARK: Power Change Initiated by Parent
3803
3804 //*********************************************************************************
3805 // [private] ParentChangeStart
3806 //
3807 // Here we begin the processing of a power change initiated by our parent.
3808 //*********************************************************************************
3809
3810 IOReturn IOService::ParentChangeStart ( void )
3811 {
3812 PM_ASSERT_IN_GATE();
3813 OUR_PMLog( kPMLogStartParentChange, fHeadNotePowerState, fCurrentPowerState );
3814
3815 // Power domain is lowering power
3816 if ( fHeadNotePowerState < fCurrentPowerState )
3817 {
3818 // TODO: redundant? See handlePowerDomainWillChangeTo()
3819 setParentInfo( fHeadNoteParentFlags, fHeadNoteParentConnection, true );
3820
3821 #if ROOT_DOMAIN_RUN_STATES
3822 getPMRootDomain()->handlePowerChangeStartForService(
3823 /* service */ this,
3824 /* RD flags */ &fRootDomainState,
3825 /* new pwr state */ fHeadNotePowerState,
3826 /* change flags */ fHeadNoteFlags );
3827 #endif
3828
3829 // tell apps and kernel clients
3830 fInitialChange = false;
3831 fMachineState = kIOPM_ParentDownTellPriorityClientsPowerDown;
3832 tellChangeDown1(fHeadNotePowerState);
3833 return IOPMWillAckLater;
3834 }
3835
3836 // Power domain is raising power
3837 if ( fHeadNotePowerState > fCurrentPowerState )
3838 {
3839 if ( fDesiredPowerState > fCurrentPowerState )
3840 {
3841 if ( fDesiredPowerState < fHeadNotePowerState )
3842 {
3843 // We power up, but not all the way
3844 fHeadNotePowerState = fDesiredPowerState;
3845 fHeadNotePowerArrayEntry = &fPowerStates[fDesiredPowerState];
3846 OUR_PMLog(kPMLogAmendParentChange, fHeadNotePowerState, 0);
3847 }
3848 } else {
3849 // We don't need to change
3850 fHeadNotePowerState = fCurrentPowerState;
3851 fHeadNotePowerArrayEntry = &fPowerStates[fCurrentPowerState];
3852 OUR_PMLog(kPMLogAmendParentChange, fHeadNotePowerState, 0);
3853 }
3854 }
3855
3856 if ( fHeadNoteFlags & kIOPMDomainDidChange )
3857 {
3858 if ( fHeadNotePowerState > fCurrentPowerState )
3859 {
3860 #if ROOT_DOMAIN_RUN_STATES
3861 getPMRootDomain()->handlePowerChangeStartForService(
3862 /* service */ this,
3863 /* RD flags */ &fRootDomainState,
3864 /* new pwr state */ fHeadNotePowerState,
3865 /* change flags */ fHeadNoteFlags );
3866 #endif
3867
3868 // Parent did change up - start our change up
3869 fInitialChange = false;
3870 notifyAll( kIOPM_ParentUpSetPowerState, kNotifyWillChange );
3871 return IOPMWillAckLater;
3872 }
3873 else if (fHeadNoteFlags & kIOPMSynchronize)
3874 {
3875 // We do not need to change power state, but notify
3876 // children to propagate tree synchronization.
3877 fMachineState = kIOPM_SyncNotifyDidChange;
3878 fDriverCallReason = kDriverCallInformPreChange;
3879 notifyChildren();
3880 return IOPMWillAckLater;
3881 }
3882 }
3883
3884 all_done();
3885 return IOPMAckImplied;
3886 }
3887
3888 //*********************************************************************************
3889 // [private] ParentDownTellPriorityClientsPowerDown
3890 //
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 //*********************************************************************************
3896
3897 void IOService::ParentDownTellPriorityClientsPowerDown ( void )
3898 {
3899 fMachineState = kIOPM_ParentDownNotifyInterestedDriversWillChange;
3900 tellChangeDown2(fHeadNotePowerState);
3901 }
3902
3903 //*********************************************************************************
3904 // [private] ParentDownNotifyInterestedDriversWillChange
3905 //
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 //*********************************************************************************
3912
3913 void IOService::ParentDownNotifyInterestedDriversWillChange ( void )
3914 {
3915 IOPMrootDomain *rootDomain;
3916 if ((rootDomain = getPMRootDomain()) == this)
3917 {
3918 rootDomain->tracePoint(kIOPMTracePointSystemSleepDriversPhase);
3919 }
3920
3921 notifyAll( kIOPM_ParentDownSetPowerState, kNotifyWillChange );
3922 }
3923
3924 //*********************************************************************************
3925 // [private] ParentDownSetPowerState
3926 //
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 //*********************************************************************************
3935
3936 void IOService::ParentDownSetPowerState ( void )
3937 {
3938 fNextMachineState = kIOPM_ParentDownWaitForPowerSettle;
3939 fMachineState = kIOPM_DriverThreadCallDone;
3940 fDriverCallReason = kDriverCallSetPowerState;
3941
3942 if (notifyControllingDriver() == false)
3943 notifyControllingDriverDone();
3944 }
3945
3946 //*********************************************************************************
3947 // [private] ParentDownWaitForPowerSettle
3948 //
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 //*********************************************************************************
3957
3958 void IOService::ParentDownWaitForPowerSettle ( void )
3959 {
3960 fMachineState = kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange;
3961 startSettleTimer();
3962 }
3963
3964 //*********************************************************************************
3965 // [private] ParentDownNotifyDidChangeAndAcknowledgeChange
3966 //
3967 // Power has settled on a power change initiated by our parent. Here we
3968 // notify interested parties.
3969 //*********************************************************************************
3970
3971 void IOService::ParentDownNotifyDidChangeAndAcknowledgeChange ( void )
3972 {
3973 notifyAll( kIOPM_ParentAcknowledgePowerChange, kNotifyDidChange );
3974 }
3975
3976 //*********************************************************************************
3977 // [private] ParentAcknowledgePowerChange
3978 //
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 //*********************************************************************************
3983
3984 void IOService::ParentAcknowledgePowerChange ( void )
3985 {
3986 IORegistryEntry * nub;
3987 IOService * parent;
3988
3989 nub = fHeadNoteParentConnection;
3990 nub->retain();
3991 all_done();
3992 parent = (IOService *)nub->copyParentEntry(gIOPowerPlane);
3993 if ( parent )
3994 {
3995 parent->acknowledgePowerChange((IOService *)nub);
3996 parent->release();
3997 }
3998 nub->release();
3999 }
4000
4001 //*********************************************************************************
4002 // [private] ParentUpSetPowerState
4003 //
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 //*********************************************************************************
4013
4014 void IOService::ParentUpSetPowerState ( void )
4015 {
4016 fNextMachineState = kIOPM_ParentUpWaitForSettleTime;
4017 fMachineState = kIOPM_DriverThreadCallDone;
4018 fDriverCallReason = kDriverCallSetPowerState;
4019
4020 if (notifyControllingDriver() == false)
4021 notifyControllingDriverDone();
4022 }
4023
4024 //*********************************************************************************
4025 // [private] ParentUpWaitForSettleTime
4026 //
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 //*********************************************************************************
4033
4034 void IOService::ParentUpWaitForSettleTime ( void )
4035 {
4036 fMachineState = kIOPM_ParentUpNotifyInterestedDriversDidChange;
4037 startSettleTimer();
4038 }
4039
4040 //*********************************************************************************
4041 // [private] ParentUpNotifyInterestedDriversDidChange
4042 //
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 //*********************************************************************************
4048
4049 void IOService::ParentUpNotifyInterestedDriversDidChange ( void )
4050 {
4051 notifyAll( kIOPM_ParentAcknowledgePowerChange, kNotifyDidChange );
4052 }
4053
4054 //*********************************************************************************
4055 // [private] all_done
4056 //
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 //*********************************************************************************
4061
4062 void IOService::all_done ( void )
4063 {
4064 unsigned long previous_state;
4065
4066 #if ROOT_DOMAIN_RUN_STATES
4067 getPMRootDomain()->handlePowerChangeDoneForService(
4068 /* service */ this,
4069 /* RD flags */ &fRootDomainState,
4070 /* new pwr state */ fHeadNotePowerState,
4071 /* change flags */ fHeadNoteFlags );
4072 #endif
4073
4074 if ((fHeadNoteFlags & kIOPMSynchronize) &&
4075 ((fMachineState == kIOPM_Finished) || (fMachineState == kIOPM_SyncFinish)))
4076 {
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).
4080
4081 if (getPMRequestType() == kIOPMRequestTypeSynchronizePowerTree)
4082 {
4083 powerChangeDone(fCurrentPowerState);
4084 }
4085
4086 fMachineState = kIOPM_Finished;
4087 return;
4088 }
4089
4090 fMachineState = kIOPM_Finished;
4091
4092 // our power change
4093 if ( fHeadNoteFlags & kIOPMWeInitiated )
4094 {
4095 // could our driver switch to the new state?
4096 if ( !( fHeadNoteFlags & kIOPMNotDone) )
4097 {
4098 // we changed, tell our parent
4099 requestDomainPower(fHeadNotePowerState);
4100
4101 // yes, did power raise?
4102 if ( fCurrentPowerState < fHeadNotePowerState )
4103 {
4104 // yes, inform clients and apps
4105 tellChangeUp (fHeadNotePowerState);
4106 }
4107 previous_state = fCurrentPowerState;
4108 // either way
4109 fCurrentPowerState = fHeadNotePowerState;
4110 #if PM_VARS_SUPPORT
4111 fPMVars->myCurrentState = fCurrentPowerState;
4112 #endif
4113 OUR_PMLog(kPMLogChangeDone, fCurrentPowerState, 0);
4114
4115 // inform subclass policy-maker
4116 if ((fLockedFlags.PMStop == false) && fParentsKnowState)
4117 powerChangeDone(previous_state);
4118 else
4119 PM_DEBUG("%s::powerChangeDone() skipped\n", getName());
4120 }
4121 }
4122
4123 // parent's power change
4124 if ( fHeadNoteFlags & kIOPMParentInitiated)
4125 {
4126 if (((fHeadNoteFlags & kIOPMDomainWillChange) && (fCurrentPowerState >= fHeadNotePowerState)) ||
4127 ((fHeadNoteFlags & kIOPMDomainDidChange) && (fCurrentPowerState < fHeadNotePowerState)))
4128 {
4129 // did power raise?
4130 if ( fCurrentPowerState < fHeadNotePowerState )
4131 {
4132 // yes, inform clients and apps
4133 tellChangeUp (fHeadNotePowerState);
4134 }
4135 // either way
4136 previous_state = fCurrentPowerState;
4137 fCurrentPowerState = fHeadNotePowerState;
4138 #if PM_VARS_SUPPORT
4139 fPMVars->myCurrentState = fCurrentPowerState;
4140 #endif
4141 fMaxCapability = fControllingDriver->maxCapabilityForDomainState(fHeadNoteDomainFlags);
4142
4143 OUR_PMLog(kPMLogChangeDone, fCurrentPowerState, 0);
4144
4145 // inform subclass policy-maker
4146 if ((fLockedFlags.PMStop == false) && fParentsKnowState)
4147 powerChangeDone(previous_state);
4148 else
4149 PM_DEBUG("%s::powerChangeDone() skipped\n", getName());
4150 }
4151 }
4152
4153 if (fCurrentPowerState < fNumberOfPowerStates)
4154 {
4155 const IOPMPowerState * powerStatePtr = &fPowerStates[fCurrentPowerState];
4156
4157 fCurrentCapabilityFlags = powerStatePtr->capabilityFlags;
4158 if (fCurrentCapabilityFlags & kIOPMStaticPowerValid)
4159 fCurrentPowerConsumption = powerStatePtr->staticPower;
4160 }
4161
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.
4164
4165 if (fCurrentPowerState >= fIdleTimerMinPowerState)
4166 {
4167 fIdleTimerMinPowerState = 0;
4168 }
4169 }
4170
4171 //*********************************************************************************
4172 // [public] settleTimerExpired
4173 //
4174 // Power has settled after our last change. Notify interested parties that
4175 // there is a new power state.
4176 //*********************************************************************************
4177
4178 void IOService::settleTimerExpired ( void )
4179 {
4180 fSettleTimeUS = 0;
4181 }
4182
4183 //*********************************************************************************
4184 // settle_timer_expired
4185 //
4186 // Holds a retain while the settle timer callout is in flight.
4187 //*********************************************************************************
4188
4189 static void
4190 settle_timer_expired( thread_call_param_t arg0, thread_call_param_t arg1 )
4191 {
4192 IOService * me = (IOService *) arg0;
4193
4194 if (gIOPMWorkLoop && gIOPMReplyQueue)
4195 {
4196 gIOPMWorkLoop->runAction(
4197 OSMemberFunctionCast(IOWorkLoop::Action, me, &IOService::settleTimerExpired),
4198 me);
4199 gIOPMReplyQueue->signalWorkAvailable();
4200 }
4201 me->release();
4202 }
4203
4204 //*********************************************************************************
4205 // [private] startSettleTimer
4206 //
4207 // Calculate a power-settling delay in microseconds and start a timer.
4208 //*********************************************************************************
4209
4210 void IOService::startSettleTimer( void )
4211 {
4212 AbsoluteTime deadline;
4213 unsigned long i;
4214 uint32_t settleTime = 0;
4215 boolean_t pending;
4216
4217 PM_ASSERT_IN_GATE();
4218
4219 i = fCurrentPowerState;
4220
4221 // lowering power
4222 if ( fHeadNotePowerState < fCurrentPowerState )
4223 {
4224 while ( i > fHeadNotePowerState )
4225 {
4226 settleTime += (uint32_t) fPowerStates[i].settleDownTime;
4227 i--;
4228 }
4229 }
4230
4231 // raising power
4232 if ( fHeadNotePowerState > fCurrentPowerState )
4233 {
4234 while ( i < fHeadNotePowerState )
4235 {
4236 settleTime += (uint32_t) fPowerStates[i+1].settleUpTime;
4237 i++;
4238 }
4239 }
4240
4241 if (settleTime)
4242 {
4243 retain();
4244 clock_interval_to_deadline(settleTime, kMicrosecondScale, &deadline);
4245 pending = thread_call_enter_delayed(fSettleTimer, deadline);
4246 if (pending) release();
4247 }
4248 }
4249
4250 //*********************************************************************************
4251 // [private] ackTimerTick
4252 //
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.
4260 //
4261 // Returns true if the timer tick made it possible to advance to the next
4262 // machine state, false otherwise.
4263 //*********************************************************************************
4264
4265 #ifndef __LP64__
4266 void IOService::ack_timer_ticked ( void )
4267 {
4268 assert(false);
4269 }
4270 #endif /* !__LP64__ */
4271
4272 bool IOService::ackTimerTick( void )
4273 {
4274 IOPMinformee * nextObject;
4275 bool done = false;
4276
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 )
4284 {
4285 // yes, decrement timer tick
4286 fDriverTimer--;
4287 if ( fDriverTimer == 0 )
4288 {
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));
4295
4296 if (gIOKitDebug & kIOLogDebugPower)
4297 {
4298 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
4299 fName, this, fCurrentPowerState, fHeadNotePowerState, NS_TO_MS(nsec));
4300 }
4301 else
4302 {
4303 // Unblock state machine and pretend driver has acked.
4304 done = true;
4305 }
4306 } else {
4307 // still waiting, set timer again
4308 start_ack_timer();
4309 }
4310 }
4311 break;
4312
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 )
4321 {
4322 // yes, go through the list of interested drivers
4323 nextObject = fInterestedDrivers->firstInList();
4324 // and check each one
4325 while ( nextObject != NULL )
4326 {
4327 if ( nextObject->timer > 0 )
4328 {
4329 nextObject->timer--;
4330 // this one should have acked by now
4331 if ( nextObject->timer == 0 )
4332 {
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,
4340 NS_TO_MS(nsec));
4341
4342 // Pretend driver has acked.
4343 fHeadNotePendingAcks--;
4344 }
4345 }
4346 nextObject = fInterestedDrivers->nextInList(nextObject);
4347 }
4348
4349 // is that the last?
4350 if ( fHeadNotePendingAcks == 0 )
4351 {
4352 // yes, we can continue
4353 done = true;
4354 } else {
4355 // no, set timer again
4356 start_ack_timer();
4357 }
4358 }
4359 break;
4360
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
4370 done = true;
4371 break;
4372
4373 default:
4374 PM_TRACE("%s: unexpected ack timer tick (state = %d)\n",
4375 getName(), fMachineState);
4376 break;
4377 }
4378 return done;
4379 }
4380
4381 //*********************************************************************************
4382 // [private] start_ack_timer
4383 //*********************************************************************************
4384
4385 void IOService::start_ack_timer ( void )
4386 {
4387 start_ack_timer( ACK_TIMER_PERIOD, kNanosecondScale );
4388 }
4389
4390 void IOService::start_ack_timer ( UInt32 interval, UInt32 scale )
4391 {
4392 AbsoluteTime deadline;
4393 boolean_t pending;
4394
4395 clock_interval_to_deadline(interval, scale, &deadline);
4396
4397 retain();
4398 pending = thread_call_enter_delayed(fAckTimer, deadline);
4399 if (pending) release();
4400 }
4401
4402 //*********************************************************************************
4403 // [private] stop_ack_timer
4404 //*********************************************************************************
4405
4406 void IOService::stop_ack_timer ( void )
4407 {
4408 boolean_t pending;
4409
4410 pending = thread_call_cancel(fAckTimer);
4411 if (pending) release();
4412 }
4413
4414 //*********************************************************************************
4415 // [static] actionAckTimerExpired
4416 //
4417 // Inside PM work loop's gate.
4418 //*********************************************************************************
4419
4420 IOReturn
4421 IOService::actionAckTimerExpired (
4422 OSObject * target,
4423 void * arg0, void * arg1,
4424 void * arg2, void * arg3 )
4425 {
4426 IOService * me = (IOService *) target;
4427 bool done;
4428
4429 // done will be true if the timer tick unblocks the machine state,
4430 // otherwise no need to signal the work loop.
4431
4432 done = me->ackTimerTick();
4433 if (done && gIOPMReplyQueue)
4434 gIOPMReplyQueue->signalWorkAvailable();
4435
4436 return kIOReturnSuccess;
4437 }
4438
4439 //*********************************************************************************
4440 // ack_timer_expired
4441 //
4442 // Thread call function. Holds a retain while the callout is in flight.
4443 //*********************************************************************************
4444
4445 void
4446 IOService::ack_timer_expired ( thread_call_param_t arg0, thread_call_param_t arg1 )
4447 {
4448 IOService * me = (IOService *) arg0;
4449
4450 if (gIOPMWorkLoop)
4451 {
4452 gIOPMWorkLoop->runAction(&actionAckTimerExpired, me);
4453 }
4454 me->release();
4455 }
4456
4457 //*********************************************************************************
4458 // [private] notifyControllingDriver
4459 //*********************************************************************************
4460
4461 bool IOService::notifyControllingDriver ( void )
4462 {
4463 DriverCallParam * param;
4464 unsigned long powerState;
4465
4466 PM_ASSERT_IN_GATE();
4467 assert( fDriverCallParamCount == 0 );
4468 assert( fControllingDriver );
4469
4470 powerState = fHeadNotePowerState;
4471
4472 param = (DriverCallParam *) fDriverCallParamPtr;
4473 if (!param)
4474 {
4475 param = IONew(DriverCallParam, 1);
4476 if (!param)
4477 return false; // no memory
4478
4479 fDriverCallParamPtr = (void *) param;
4480 fDriverCallParamSlots = 1;
4481 }
4482
4483 param->Target = fControllingDriver;
4484 fDriverCallParamCount = 1;
4485
4486 fDriverTimer = -1;
4487
4488 // Machine state for this object will stall waiting for a reply
4489 // from the callout thread.
4490
4491 PM_LOCK();
4492 assert( fLockedFlags.DriverCallBusy == false );
4493 fLockedFlags.DriverCallBusy = true;
4494 PM_UNLOCK();
4495 thread_call_enter( fDriverCallEntry );
4496 return true;
4497 }
4498
4499 //*********************************************************************************
4500 // [private] notifyControllingDriverDone
4501 //*********************************************************************************
4502
4503 void IOService::notifyControllingDriverDone( void )
4504 {
4505 DriverCallParam * param;
4506 IOReturn result;
4507
4508 PM_ASSERT_IN_GATE();
4509 param = (DriverCallParam *) fDriverCallParamPtr;
4510
4511 assert( fLockedFlags.DriverCallBusy == false );
4512 assert( fMachineState == kIOPM_DriverThreadCallDone );
4513
4514 if (param)
4515 {
4516 assert(fDriverCallParamCount == 1);
4517
4518 // the return value from setPowerState()
4519 result = param->Result;
4520
4521 if ((result == IOPMAckImplied) || (result < 0))
4522 {
4523 // child return IOPMAckImplied
4524 fDriverTimer = 0;
4525 }
4526 else if (fDriverTimer)
4527 {
4528 assert(fDriverTimer == -1);
4529
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.
4536
4537 if (result < kMinAckTimeoutTicks)
4538 result = kMinAckTimeoutTicks;
4539
4540 fDriverTimer = (result / (ACK_TIMER_PERIOD / ns_per_us)) + 1;
4541 }
4542 // else, child has already acked and driver_timer reset to 0.
4543
4544 fDriverCallParamCount = 0;
4545
4546 if ( fDriverTimer )
4547 {
4548 OUR_PMLog(kPMLogStartAckTimer, 0, 0);
4549 start_ack_timer();
4550 }
4551 }
4552
4553 // Hop back to original machine state path.
4554 fMachineState = fNextMachineState;
4555 }
4556
4557 //*********************************************************************************
4558 // [public] askChangeDown
4559 //
4560 // Ask registered applications and kernel clients if we can change to a lower
4561 // power state.
4562 //
4563 // Subclass can override this to send a different message type. Parameter is
4564 // the destination state number.
4565 //
4566 // Return true if we don't have to wait for acknowledgements
4567 //*********************************************************************************
4568
4569 bool IOService::askChangeDown ( unsigned long stateNum )
4570 {
4571 return tellClientsWithResponse( kIOMessageCanDevicePowerOff );
4572 }
4573
4574 //*********************************************************************************
4575 // [private] tellChangeDown1
4576 //
4577 // Notify registered applications and kernel clients that we are definitely
4578 // dropping power.
4579 //
4580 // Return true if we don't have to wait for acknowledgements
4581 //*********************************************************************************
4582
4583 bool IOService::tellChangeDown1 ( unsigned long stateNum )
4584 {
4585 fOutOfBandParameter = kNotifyApps;
4586 return tellChangeDown(stateNum);
4587 }
4588
4589 //*********************************************************************************
4590 // [private] tellChangeDown2
4591 //
4592 // Notify priority clients that we are definitely dropping power.
4593 //
4594 // Return true if we don't have to wait for acknowledgements
4595 //*********************************************************************************
4596
4597 bool IOService::tellChangeDown2 ( unsigned long stateNum )
4598 {
4599 fOutOfBandParameter = kNotifyPriority;
4600 return tellChangeDown(stateNum);
4601 }
4602
4603 //*********************************************************************************
4604 // [public] tellChangeDown
4605 //
4606 // Notify registered applications and kernel clients that we are definitely
4607 // dropping power.
4608 //
4609 // Subclass can override this to send a different message type. Parameter is
4610 // the destination state number.
4611 //
4612 // Return true if we don't have to wait for acknowledgements
4613 //*********************************************************************************
4614
4615 bool IOService::tellChangeDown ( unsigned long stateNum )
4616 {
4617 return tellClientsWithResponse( kIOMessageDeviceWillPowerOff );
4618 }
4619
4620 //*********************************************************************************
4621 // cleanClientResponses
4622 //
4623 //*********************************************************************************
4624
4625 static void logAppTimeouts ( OSObject * object, void * arg )
4626 {
4627 IOPMInterestContext * context = (IOPMInterestContext *) arg;
4628 OSObject * flag;
4629 unsigned int clientIndex;
4630
4631 if (OSDynamicCast(_IOServiceInterestNotifier, object))
4632 {
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.
4636
4637 clientIndex = context->notifyClients->getNextIndexOfObject(object, 0);
4638
4639 if ((clientIndex != (unsigned int) -1) &&
4640 (flag = context->responseFlags->getObject(clientIndex)) &&
4641 (flag != kOSBooleanTrue))
4642 {
4643 OSString * clientID = 0;
4644 context->us->messageClient(context->msgType, object, &clientID);
4645 PM_ERROR(context->errorLog, clientID ? clientID->getCStringNoCopy() : "");
4646
4647 // TODO: record message type if possible
4648 IOService::getPMRootDomain()->pmStatsRecordApplicationResponse(
4649 gIOPMStatsApplicationResponseTimedOut,
4650 clientID ? clientID->getCStringNoCopy() : "",
4651 0, (30*1000), -1);
4652
4653 if (clientID)
4654 clientID->release();
4655 }
4656 }
4657 }
4658
4659 void IOService::cleanClientResponses ( bool logErrors )
4660 {
4661 IOPMInterestContext context;
4662
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;
4669 context.us = this;
4670 context.maxTimeRequested = 0;
4671 context.stateNumber = fHeadNotePowerState;
4672 context.stateFlags = fHeadNotePowerArrayEntry->capabilityFlags;
4673 context.errorLog = "PM notification timeout (%s)\n";
4674
4675 switch ( fOutOfBandParameter ) {
4676 case kNotifyApps:
4677 applyToInterested(gIOAppPowerStateInterest, logAppTimeouts, (void *) &context);
4678 case kNotifyPriority:
4679 default:
4680 break;
4681 }
4682 }
4683
4684 if (fResponseArray)
4685 {
4686 // get rid of this stuff
4687 fResponseArray->release();
4688 fResponseArray = NULL;
4689 }
4690 if (fNotifyClientArray)
4691 {
4692 fNotifyClientArray->release();
4693 fNotifyClientArray = NULL;
4694 }
4695
4696 return;
4697 }
4698
4699 //*********************************************************************************
4700 // [protected] tellClientsWithResponse
4701 //
4702 // Notify registered applications and kernel clients that we are definitely
4703 // dropping power.
4704 //
4705 // Return true if we don't have to wait for acknowledgements
4706 //*********************************************************************************
4707
4708 bool IOService::tellClientsWithResponse (
4709 int messageType )
4710 {
4711 return tellClientsWithResponse( messageType, 0 );
4712 }
4713
4714 bool IOService::tellClientsWithResponse (
4715 int messageType,
4716 IOPMMessageFilter filter )
4717 {
4718 IOPMInterestContext context;
4719
4720 PM_ASSERT_IN_GATE();
4721 assert( fResponseArray == NULL );
4722 assert( fNotifyClientArray == NULL );
4723
4724 fResponseArray = OSArray::withCapacity( 1 );
4725 if (!fResponseArray)
4726 goto exit;
4727
4728 fResponseArray->setCapacityIncrement(8);
4729 fSerialNumber += 1;
4730
4731 context.responseFlags = fResponseArray;
4732 context.notifyClients = 0;
4733 context.serialNumber = fSerialNumber;
4734 context.counter = 0;
4735 context.msgType = messageType;
4736 context.us = this;
4737 context.maxTimeRequested = 0;
4738 context.stateNumber = fHeadNotePowerState;
4739 context.stateFlags = fHeadNotePowerArrayEntry->capabilityFlags;
4740 context.filterFunc = filter;
4741
4742 switch ( fOutOfBandParameter ) {
4743 case kNotifyApps:
4744 applyToInterested( gIOAppPowerStateInterest,
4745 pmTellAppWithResponse, (void *) &context );
4746 fNotifyClientArray = context.notifyClients;
4747
4748 applyToInterested( gIOGeneralInterest,
4749 pmTellClientWithResponse, (void *) &context );
4750 break;
4751
4752 case kNotifyPriority:
4753 applyToInterested( gIOPriorityPowerStateInterest,
4754 pmTellClientWithResponse, (void *) &context );
4755 break;
4756 }
4757
4758 // do we have to wait for somebody?
4759 if ( !checkForDone() )
4760 {
4761 OUR_PMLog(kPMLogStartAckTimer, context.maxTimeRequested, 0);
4762 start_ack_timer( context.maxTimeRequested / 1000, kMillisecondScale );
4763 return false;
4764 }
4765
4766 exit:
4767 // everybody responded
4768 if (fResponseArray)
4769 {
4770 fResponseArray->release();
4771 fResponseArray = NULL;
4772 }
4773 if (fNotifyClientArray)
4774 {
4775 fNotifyClientArray->release();
4776 fNotifyClientArray = NULL;
4777 }
4778
4779 return true;
4780 }
4781
4782 //*********************************************************************************
4783 // [static private] pmTellAppWithResponse
4784 //
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 //*********************************************************************************
4788
4789 void IOService::pmTellAppWithResponse ( OSObject * object, void * arg )
4790 {
4791 IOPMInterestContext * context = (IOPMInterestContext *) arg;
4792 IOServicePM * pwrMgt = context->us->pwrMgt;
4793 AbsoluteTime now;
4794 UInt32 refcon;
4795
4796 if (!OSDynamicCast(_IOServiceInterestNotifier, object))
4797 {
4798 // object must be an _IOServiceInterestNotifier.
4799 return;
4800 }
4801
4802 // Lazily create app clients array.
4803 if (0 == context->notifyClients)
4804 {
4805 context->notifyClients = OSArray::withCapacity( 32 );
4806 }
4807
4808 if (context->filterFunc && !context->filterFunc(object, arg))
4809 {
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);
4814 }
4815 else
4816 {
4817 refcon = ((context->serialNumber & 0xFFFF)<<16)
4818 + (context->counter & 0xFFFF);
4819 OUR_PMLog(kPMLogAppNotify, context->msgType, refcon);
4820
4821 if (gIOKitDebug & kIOLogDebugPower)
4822 {
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,
4828 context->msgType,
4829 clientID ? clientID->getCStringNoCopy() : "");
4830 if (clientID) clientID->release();
4831 }
4832
4833 #if LOG_APP_RESPONSE_TIMES
4834 OSNumber * num;
4835 clock_get_uptime(&now);
4836 num = OSNumber::withNumber(AbsoluteTime_to_scalar(&now), sizeof(uint64_t) * 8);
4837 if (num)
4838 {
4839 context->responseFlags->setObject(context->counter, num);
4840 num->release();
4841 }
4842 else
4843 #endif
4844 context->responseFlags->setObject(context->counter, kOSBooleanFalse);
4845
4846 if (context->notifyClients)
4847 context->notifyClients->setObject(context->counter, object);
4848
4849 context->us->messageClient(context->msgType, object, (void *)refcon);
4850 if ( context->maxTimeRequested < k30seconds )
4851 {
4852 context->maxTimeRequested = k30seconds;
4853 }
4854 }
4855
4856 context->counter++;
4857 }
4858
4859 //*********************************************************************************
4860 // [static private] pmTellClientWithResponse
4861 //
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 //*********************************************************************************
4869
4870 void IOService::pmTellClientWithResponse ( OSObject * object, void * arg )
4871 {
4872 IOPMInterestContext * context = (IOPMInterestContext *) arg;
4873 IOPowerStateChangeNotification notify;
4874 UInt32 refcon;
4875 IOReturn retCode;
4876 OSObject * theFlag;
4877
4878 if (context->filterFunc && !context->filterFunc(object, arg))
4879 return;
4880
4881 refcon = ((context->serialNumber & 0xFFFF)<<16) + (context->counter & 0xFFFF);
4882 context->responseFlags->setObject(context->counter, kOSBooleanFalse);
4883
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);
4894 }
4895 }
4896
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 *)&notify);
4902 if ( retCode == kIOReturnSuccess )
4903 {
4904 if ( notify.returnValue == 0 )
4905 {
4906 // client doesn't want time to respond
4907 context->responseFlags->replaceObject(context->counter, kOSBooleanTrue);
4908 OUR_PMLog(kPMLogClientAcknowledge, refcon, (UInt64) object);
4909 } else {
4910 // it does want time, and it hasn't responded yet
4911 theFlag = context->responseFlags->getObject(context->counter);
4912 if ( kOSBooleanTrue != theFlag )
4913 {
4914 // so note its time requirement
4915 if ( context->maxTimeRequested < notify.returnValue )
4916 {
4917 context->maxTimeRequested = notify.returnValue;
4918 }
4919 }
4920 }
4921 } else {
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);
4926 }
4927 context->counter++;
4928 }
4929
4930 //*********************************************************************************
4931 // [public] tellNoChangeDown
4932 //
4933 // Notify registered applications and kernel clients that we are not
4934 // dropping power.
4935 //
4936 // Subclass can override this to send a different message type. Parameter is
4937 // the aborted destination state number.
4938 //*********************************************************************************
4939
4940 void IOService::tellNoChangeDown ( unsigned long )
4941 {
4942 return tellClients( kIOMessageDeviceWillNotPowerOff );
4943 }
4944
4945 //*********************************************************************************
4946 // [public] tellChangeUp
4947 //
4948 // Notify registered applications and kernel clients that we are raising power.
4949 //
4950 // Subclass can override this to send a different message type. Parameter is
4951 // the aborted destination state number.
4952 //*********************************************************************************
4953
4954 void IOService::tellChangeUp ( unsigned long )
4955 {
4956 return tellClients( kIOMessageDeviceHasPoweredOn );
4957 }
4958
4959 //*********************************************************************************
4960 // [protected] tellClients
4961 //
4962 // Notify registered applications and kernel clients of something.
4963 //*********************************************************************************
4964
4965 void IOService::tellClients ( int messageType )
4966 {
4967 tellClients( messageType, 0 );
4968 }
4969
4970 void IOService::tellClients ( int messageType, IOPMMessageFilter filter )
4971 {
4972 IOPMInterestContext context;
4973
4974 context.msgType = messageType;
4975 context.us = this;
4976 context.stateNumber = fHeadNotePowerState;
4977 context.stateFlags = fHeadNotePowerArrayEntry->capabilityFlags;
4978 context.filterFunc = filter;
4979
4980 applyToInterested( gIOPriorityPowerStateInterest,
4981 tellKernelClientApplier, (void *) &context );
4982
4983 applyToInterested( gIOAppPowerStateInterest,
4984 tellAppClientApplier, (void *) &context );
4985
4986 applyToInterested( gIOGeneralInterest,
4987 tellKernelClientApplier, (void *) &context );
4988 }
4989
4990 //*********************************************************************************
4991 // [private] tellKernelClientApplier
4992 //
4993 // Message a kernel client.
4994 //*********************************************************************************
4995
4996 static void tellKernelClientApplier ( OSObject * object, void * arg )
4997 {
4998 IOPMInterestContext * context = (IOPMInterestContext *) arg;
4999 IOPowerStateChangeNotification notify;
5000
5001 if (context->filterFunc && !context->filterFunc(object, arg))
5002 return;
5003
5004 notify.powerRef = (void *) 0;
5005 notify.returnValue = 0;
5006 notify.stateNumber = context->stateNumber;
5007 notify.stateFlags = context->stateFlags;
5008
5009 context->us->messageClient(context->msgType, object, &notify);
5010 }
5011
5012 //*********************************************************************************
5013 // [private] tellAppClientApplier
5014 //
5015 // Message a registered application.
5016 //*********************************************************************************
5017
5018 static void tellAppClientApplier ( OSObject * object, void * arg )
5019 {
5020 IOPMInterestContext * context = (IOPMInterestContext *) arg;
5021
5022 if (context->filterFunc && !context->filterFunc(object, arg))
5023 return;
5024
5025 context->us->messageClient(context->msgType, object, 0);
5026 }
5027
5028 //*********************************************************************************
5029 // [private] checkForDone
5030 //*********************************************************************************
5031
5032 bool IOService::checkForDone ( void )
5033 {
5034 int i = 0;
5035 OSObject * theFlag;
5036
5037 if ( fResponseArray == NULL )
5038 {
5039 return true;
5040 }
5041
5042 for ( i = 0; ; i++ )
5043 {
5044 theFlag = fResponseArray->getObject(i);
5045 if ( theFlag == NULL )
5046 {
5047 break;
5048 }
5049 if ( kOSBooleanTrue != theFlag )
5050 {
5051 return false;
5052 }
5053 }
5054 return true;
5055 }
5056
5057 //*********************************************************************************
5058 // [public] responseValid
5059 //*********************************************************************************
5060
5061 bool IOService::responseValid ( unsigned long x, int pid )
5062 {
5063 UInt16 serialComponent;
5064 UInt16 ordinalComponent;
5065 OSObject * theFlag;
5066 unsigned long refcon = (unsigned long) x;
5067
5068 serialComponent = (refcon >> 16) & 0xFFFF;
5069 ordinalComponent = (refcon & 0xFFFF);
5070
5071 if ( serialComponent != fSerialNumber )
5072 {
5073 return false;
5074 }
5075
5076 if ( fResponseArray == NULL )
5077 {
5078 return false;
5079 }
5080
5081 theFlag = fResponseArray->getObject(ordinalComponent);
5082
5083 if ( theFlag == 0 )
5084 {
5085 return false;
5086 }
5087
5088 OSNumber * num;
5089 if ((num = OSDynamicCast(OSNumber, theFlag)))
5090 {
5091 #if LOG_APP_RESPONSE_TIMES
5092 AbsoluteTime now;
5093 AbsoluteTime start;
5094 uint64_t nsec;
5095
5096 clock_get_uptime(&now);
5097 AbsoluteTime_to_scalar(&start) = num->unsigned64BitValue();
5098 SUB_ABSOLUTETIME(&now, &start);
5099 absolutetime_to_nanoseconds(now, &nsec);
5100
5101 // > 100 ms
5102 if (nsec > LOG_APP_RESPONSE_TIMES)
5103 {
5104 OSString * name = IOCopyLogNameForPID(pid);
5105 PM_DEBUG("PM response took %d ms (%s)\n", NS_TO_MS(nsec),
5106 name ? name->getCStringNoCopy() : "");
5107
5108 if (nsec > LOG_APP_RESPONSE_MSG_TRACER)
5109 {
5110 // TODO: populate the messageType argument
5111 getPMRootDomain()->pmStatsRecordApplicationResponse(
5112 gIOPMStatsApplicationResponseSlow,
5113 name ? name->getCStringNoCopy() : "", 0,
5114 NS_TO_MS(nsec), pid);
5115 }
5116
5117 if (name)
5118 name->release();
5119 }
5120 #endif
5121 theFlag = kOSBooleanFalse;
5122 }
5123
5124 if ( kOSBooleanFalse == theFlag )
5125 {
5126 if ((gIOKitDebug & kIOLogDebugPower) &&
5127 (fOutOfBandParameter == kNotifyApps))
5128 {
5129 PM_DEBUG("[Notify %u] acked\n", (uint32_t) ordinalComponent);
5130 }
5131 fResponseArray->replaceObject(ordinalComponent, kOSBooleanTrue);
5132 }
5133
5134 return true;
5135 }
5136
5137 //*********************************************************************************
5138 // [public] allowPowerChange
5139 //
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.
5143 //
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 //*********************************************************************************
5147
5148 IOReturn IOService::allowPowerChange ( unsigned long refcon )
5149 {
5150 IOPMRequest * request;
5151
5152 if ( !initialized )
5153 {
5154 // we're unloading
5155 return kIOReturnSuccess;
5156 }
5157
5158 request = acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange );
5159 if (!request)
5160 return kIOReturnNoMemory;
5161
5162 request->fArg0 = (void *) refcon;
5163 request->fArg1 = (void *) proc_selfpid();
5164 request->fArg2 = (void *) 0;
5165 submitPMRequest( request );
5166
5167 return kIOReturnSuccess;
5168 }
5169
5170 #ifndef __LP64__
5171 IOReturn IOService::serializedAllowPowerChange2 ( unsigned long refcon )
5172 {
5173 // [deprecated] public
5174 return kIOReturnUnsupported;
5175 }
5176 #endif /* !__LP64__ */
5177
5178 //*********************************************************************************
5179 // [public] cancelPowerChange
5180 //
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.
5184 //
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 //*********************************************************************************
5188
5189 IOReturn IOService::cancelPowerChange ( unsigned long refcon )
5190 {
5191 IOPMRequest * request;
5192 OSString * name;
5193
5194 if ( !initialized )
5195 {
5196 // we're unloading
5197 return kIOReturnSuccess;
5198 }
5199
5200 name = IOCopyLogNameForPID(proc_selfpid());
5201 PM_ERROR("PM notification cancel (%s)\n", name ? name->getCStringNoCopy() : "");
5202
5203 request = acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange );
5204 if (!request)
5205 {
5206 if (name)
5207 name->release();
5208 return kIOReturnNoMemory;
5209 }
5210
5211 request->fArg0 = (void *) refcon;
5212 request->fArg1 = (void *) proc_selfpid();
5213 request->fArg2 = (void *) name;
5214 submitPMRequest( request );
5215
5216 return kIOReturnSuccess;
5217 }
5218
5219 #ifndef __LP64__
5220 IOReturn IOService::serializedCancelPowerChange2 ( unsigned long refcon )
5221 {
5222 // [deprecated] public
5223 return kIOReturnUnsupported;
5224 }
5225
5226 //*********************************************************************************
5227 // PM_Clamp_Timer_Expired
5228 //
5229 // called when clamp timer expires...set power state to 0.
5230 //*********************************************************************************
5231
5232 void IOService::PM_Clamp_Timer_Expired ( void )
5233 {
5234 }
5235
5236 //*********************************************************************************
5237 // clampPowerOn
5238 //
5239 // Set to highest available power state for a minimum of duration milliseconds
5240 //*********************************************************************************
5241
5242 void IOService::clampPowerOn ( unsigned long duration )
5243 {
5244 }
5245 #endif /* !__LP64__ */
5246
5247 //*********************************************************************************
5248 // [public] setPowerState
5249 //
5250 // Does nothing here. This should be implemented in a subclass driver.
5251 //*********************************************************************************
5252
5253 IOReturn IOService::setPowerState (
5254 unsigned long powerStateOrdinal, IOService * whatDevice )
5255 {
5256 return IOPMNoErr;
5257 }
5258
5259 //*********************************************************************************
5260 // [public] maxCapabilityForDomainState
5261 //
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 //*********************************************************************************
5266
5267 unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainState )
5268 {
5269 int i;
5270
5271 if (fNumberOfPowerStates == 0 )
5272 {
5273 return 0;
5274 }
5275 for ( i = fNumberOfPowerStates - 1; i >= 0; i-- )
5276 {
5277 if ( (domainState & fPowerStates[i].inputPowerRequirement) ==
5278 fPowerStates[i].inputPowerRequirement )
5279 {
5280 return i;
5281 }
5282 }
5283 return 0;
5284 }
5285
5286 //*********************************************************************************
5287 // [public] initialPowerStateForDomainState
5288 //
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 //*********************************************************************************
5293
5294 unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domainState )
5295 {
5296 int i;
5297
5298 if (fNumberOfPowerStates == 0 )
5299 {
5300 return 0;
5301 }
5302 for ( i = fNumberOfPowerStates - 1; i >= 0; i-- )
5303 {
5304 if ( (domainState & fPowerStates[i].inputPowerRequirement) ==
5305 fPowerStates[i].inputPowerRequirement )
5306 {
5307 return i;
5308 }
5309 }
5310 return 0;
5311 }
5312
5313 //*********************************************************************************
5314 // [public] powerStateForDomainState
5315 //
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 //*********************************************************************************
5320
5321 unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState )
5322 {
5323 int i;
5324
5325 if (fNumberOfPowerStates == 0 )
5326 {
5327 return 0;
5328 }
5329 for ( i = fNumberOfPowerStates - 1; i >= 0; i-- )
5330 {
5331 if ( (domainState & fPowerStates[i].inputPowerRequirement) ==
5332 fPowerStates[i].inputPowerRequirement )
5333 {
5334 return i;
5335 }
5336 }
5337 return 0;
5338 }
5339
5340 #ifndef __LP64__
5341 //*********************************************************************************
5342 // [deprecated] didYouWakeSystem
5343 //
5344 // Does nothing here. This should be implemented in a subclass driver.
5345 //*********************************************************************************
5346
5347 bool IOService::didYouWakeSystem ( void )
5348 {
5349 return false;
5350 }
5351 #endif /* !__LP64__ */
5352
5353 //*********************************************************************************
5354 // [public] powerStateWillChangeTo
5355 //
5356 // Does nothing here. This should be implemented in a subclass driver.
5357 //*********************************************************************************
5358
5359 IOReturn IOService::powerStateWillChangeTo ( IOPMPowerFlags, unsigned long, IOService * )
5360 {
5361 return kIOPMAckImplied;
5362 }
5363
5364 //*********************************************************************************
5365 // [public] powerStateDidChangeTo
5366 //
5367 // Does nothing here. This should be implemented in a subclass driver.
5368 //*********************************************************************************
5369
5370 IOReturn IOService::powerStateDidChangeTo ( IOPMPowerFlags, unsigned long, IOService * )
5371 {
5372 return kIOPMAckImplied;
5373 }
5374
5375 //*********************************************************************************
5376 // [protected] powerChangeDone
5377 //
5378 // Called from PM work loop thread.
5379 // Does nothing here. This should be implemented in a subclass policy-maker.
5380 //*********************************************************************************
5381
5382 void IOService::powerChangeDone ( unsigned long )
5383 {
5384 }
5385
5386 #ifndef __LP64__
5387 //*********************************************************************************
5388 // [deprecated] newTemperature
5389 //
5390 // Does nothing here. This should be implemented in a subclass driver.
5391 //*********************************************************************************
5392
5393 IOReturn IOService::newTemperature ( long currentTemp, IOService * whichZone )
5394 {
5395 return IOPMNoErr;
5396 }
5397 #endif /* !__LP64__ */
5398
5399 //*********************************************************************************
5400 // [public] systemWillShutdown
5401 //
5402 // System shutdown and restart notification.
5403 //*********************************************************************************
5404
5405 void IOService::systemWillShutdown( IOOptionBits specifier )
5406 {
5407 IOPMrootDomain * rootDomain = IOService::getPMRootDomain();
5408 if (rootDomain)
5409 rootDomain->acknowledgeSystemWillShutdown( this );
5410 }
5411
5412 //*********************************************************************************
5413 // [private static] acquirePMRequest
5414 //*********************************************************************************
5415
5416 IOPMRequest *
5417 IOService::acquirePMRequest( IOService * target, IOOptionBits requestType,
5418 IOPMRequest * active )
5419 {
5420 IOPMRequest * request;
5421
5422 assert(target);
5423
5424 request = IOPMRequest::create();
5425 if (request)
5426 {
5427 request->init( target, requestType );
5428 if (active)
5429 {
5430 IOPMRequest * root = active->getRootRequest();
5431 if (root) request->attachRootRequest(root);
5432 }
5433 }
5434 else
5435 {
5436 PM_ERROR("%s: No memory for PM request type 0x%x\n",
5437 target->getName(), (uint32_t) requestType);
5438 }
5439 return request;
5440 }
5441
5442 //*********************************************************************************
5443 // [private static] releasePMRequest
5444 //*********************************************************************************
5445
5446 void IOService::releasePMRequest( IOPMRequest * request )
5447 {
5448 if (request)
5449 {
5450 request->reset();
5451 request->release();
5452 }
5453 }
5454
5455 //*********************************************************************************
5456 // [private] submitPMRequest
5457 //*********************************************************************************
5458
5459 void IOService::submitPMRequest( IOPMRequest * request )
5460 {
5461 assert( request );
5462 assert( gIOPMReplyQueue );
5463 assert( gIOPMRequestQueue );
5464
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);
5469
5470 if (request->isReplyType())
5471 gIOPMReplyQueue->queuePMRequest( request );
5472 else
5473 gIOPMRequestQueue->queuePMRequest( request );
5474 }
5475
5476 void IOService::submitPMRequest( IOPMRequest ** requests, IOItemCount count )
5477 {
5478 assert( requests );
5479 assert( count > 0 );
5480 assert( gIOPMRequestQueue );
5481
5482 for (IOItemCount i = 0; i < count; i++)
5483 {
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);
5489 }
5490
5491 gIOPMRequestQueue->queuePMRequestChain( requests, count );
5492 }
5493
5494 //*********************************************************************************
5495 // [private] servicePMRequestQueue
5496 //*********************************************************************************
5497
5498 bool IOService::servicePMRequestQueue(
5499 IOPMRequest * request,
5500 IOPMRequestQueue * queue )
5501 {
5502 // Calling PM methods without PMinit() is not allowed, fail the requests.
5503
5504 if (!initialized)
5505 {
5506 PM_DEBUG("%s: PM not initialized\n", getName());
5507 goto done;
5508 }
5509
5510 // Create an IOPMWorkQueue on demand, when the initial PM request is
5511 // received.
5512
5513 if (!fPMWorkQueue)
5514 {
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.
5518
5519 fPMWorkQueue = IOPMWorkQueue::create(
5520 /* target */ this,
5521 /* Work */ OSMemberFunctionCast(IOPMWorkQueue::Action, this,
5522 &IOService::servicePMRequest),
5523 /* Done */ OSMemberFunctionCast(IOPMWorkQueue::Action, this,
5524 &IOService::retirePMRequest)
5525 );
5526
5527 if (fPMWorkQueue &&
5528 (gIOPMWorkLoop->addEventSource(fPMWorkQueue) != kIOReturnSuccess))
5529 {
5530 PM_ERROR("%s: add PM work queue failed\n", getName());
5531 fPMWorkQueue->release();
5532 fPMWorkQueue = 0;
5533 }
5534
5535 if (!fPMWorkQueue)
5536 {
5537 PM_ERROR("%s: no PM work queue (type %02lx)\n",
5538 getName(), (long)request->getType());
5539 goto done;
5540 }
5541 }
5542
5543 fPMWorkQueue->queuePMRequest(request);
5544 return false; // do not signal more
5545
5546 done:
5547 fAdjustPowerScheduled = false;
5548 gIOPMFreeQueue->queuePMRequest(request);
5549 return false; // do not signal more
5550 }
5551
5552 //*********************************************************************************
5553 // [private] servicePMFreeQueue
5554 //
5555 // Called by the request completion to recycle a completed request.
5556 //*********************************************************************************
5557
5558 bool IOService::servicePMFreeQueue(
5559 IOPMRequest * request,
5560 IOPMCompletionQueue * queue )
5561 {
5562 bool more = request->getNextRequest();
5563 IOPMRequest * root = request->getRootRequest();
5564
5565 if (root && (root != request))
5566 more = true;
5567
5568 releasePMRequest( request );
5569 return more;
5570 }
5571
5572 //*********************************************************************************
5573 // [private] retirePMRequest
5574 //
5575 // Called by IOPMWorkQueue to retire a completed request.
5576 //*********************************************************************************
5577
5578 bool IOService::retirePMRequest( IOPMRequest * request, IOPMWorkQueue * queue )
5579 {
5580 assert(request && queue);
5581
5582 PM_TRACE("[- %02x] %p [%p %s] State %d, Busy %d\n",
5583 request->getType(), request, this, getName(),
5584 fMachineState, gIOPMBusyCount);
5585
5586 // Catch requests created by idleTimerExpired().
5587
5588 if ((request->getType() == kIOPMRequestTypeActivityTickle) &&
5589 (request->fArg1 == (void *) false))
5590 {
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.
5594
5595 if (fDeviceDesire > 0)
5596 {
5597 fActivityTickleCount = 0;
5598 clock_get_uptime(&fIdleTimerStartTime);
5599 start_PM_idle_timer();
5600 }
5601 else
5602 fIdleTimerStopped = true;
5603 }
5604
5605 gIOPMFreeQueue->queuePMRequest( request );
5606 return true;
5607 }
5608
5609 //*********************************************************************************
5610 // [private] isPMBlocked
5611 //
5612 // Check if machine state transition is blocked.
5613 //*********************************************************************************
5614
5615 bool IOService::isPMBlocked ( IOPMRequest * request, int count )
5616 {
5617 int reason = 0;
5618
5619 do {
5620 if (kIOPM_Finished == fMachineState)
5621 break;
5622
5623 if (kIOPM_DriverThreadCallDone == fMachineState)
5624 {
5625 // 5 = kDriverCallInformPreChange
5626 // 6 = kDriverCallInformPostChange
5627 // 7 = kDriverCallSetPowerState
5628 if (fLockedFlags.DriverCallBusy) reason = 5 + fDriverCallReason;
5629 break;
5630 }
5631
5632 // Waiting on driver's setPowerState() timeout.
5633 if (fDriverTimer)
5634 {
5635 reason = 1; break;
5636 }
5637
5638 // Child or interested driver acks pending.
5639 if (fHeadNotePendingAcks)
5640 {
5641 reason = 2; break;
5642 }
5643
5644 // Waiting on apps or priority power interest clients.
5645 if (fResponseArray)
5646 {
5647 reason = 3; break;
5648 }
5649
5650 // Waiting on settle timer expiration.
5651 if (fSettleTimeUS)
5652 {
5653 reason = 4; break;
5654 }
5655 } while (false);
5656
5657 fWaitReason = reason;
5658
5659 if (reason)
5660 {
5661 if (count)
5662 {
5663 PM_TRACE("[B %02x] %p [%p %s] State %d, Reason %d\n",
5664 request->getType(), request, this, getName(),
5665 fMachineState, reason);
5666 }
5667
5668 return true;
5669 }
5670
5671 return false;
5672 }
5673
5674 //*********************************************************************************
5675 // [private] servicePMRequest
5676 //
5677 // Service a request from our work queue.
5678 //*********************************************************************************
5679
5680 bool IOService::servicePMRequest( IOPMRequest * request, IOPMWorkQueue * queue )
5681 {
5682 bool done = false;
5683 int loop = 0;
5684
5685 assert(request && queue);
5686
5687 while (isPMBlocked(request, loop++) == false)
5688 {
5689 PM_TRACE("[W %02x] %p [%p %s] State %d\n",
5690 request->getType(), request, this, getName(), fMachineState);
5691
5692 gIOPMRequest = request;
5693
5694 // Every PM machine states must be handled in one of the cases below.
5695
5696 switch ( fMachineState )
5697 {
5698 case kIOPM_Finished:
5699 executePMRequest( request );
5700 break;
5701
5702 case kIOPM_OurChangeTellClientsPowerDown:
5703 // our change, was it vetoed?
5704 if (!fDoNotPowerDown)
5705 {
5706 // no, we can continue
5707 OurChangeTellClientsPowerDown();
5708 }
5709 else
5710 {
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;
5717 // and we're done
5718 all_done();
5719 }
5720 break;
5721
5722 case kIOPM_OurChangeTellPriorityClientsPowerDown:
5723 // our change, should it be acted on still?
5724 if (fDoNotPowerDown)
5725 {
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;
5732 // and we're done
5733 all_done();
5734 }
5735 else
5736 {
5737 // yes, we can continue
5738 OurChangeTellPriorityClientsPowerDown();
5739 }
5740 break;
5741
5742 case kIOPM_OurChangeNotifyInterestedDriversWillChange:
5743 OurChangeNotifyInterestedDriversWillChange();
5744 break;
5745
5746 case kIOPM_OurChangeSetPowerState:
5747 OurChangeSetPowerState();
5748 break;
5749
5750 case kIOPM_OurChangeWaitForPowerSettle:
5751 OurChangeWaitForPowerSettle();
5752 break;
5753
5754 case kIOPM_OurChangeNotifyInterestedDriversDidChange:
5755 OurChangeNotifyInterestedDriversDidChange();
5756 break;
5757
5758 case kIOPM_OurChangeFinish:
5759 OurChangeFinish();
5760 break;
5761
5762 case kIOPM_ParentDownTellPriorityClientsPowerDown:
5763 ParentDownTellPriorityClientsPowerDown();
5764 break;
5765
5766 case kIOPM_ParentDownNotifyInterestedDriversWillChange:
5767 ParentDownNotifyInterestedDriversWillChange();
5768 break;
5769
5770 case kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange:
5771 ParentDownNotifyDidChangeAndAcknowledgeChange();
5772 break;
5773
5774 case kIOPM_ParentDownSetPowerState:
5775 ParentDownSetPowerState();
5776 break;
5777
5778 case kIOPM_ParentDownWaitForPowerSettle:
5779 ParentDownWaitForPowerSettle();
5780 break;
5781
5782 case kIOPM_ParentAcknowledgePowerChange:
5783 ParentAcknowledgePowerChange();
5784 break;
5785
5786 case kIOPM_ParentUpSetPowerState:
5787 ParentUpSetPowerState();
5788 break;
5789
5790 case kIOPM_ParentUpWaitForSettleTime:
5791 ParentUpWaitForSettleTime();
5792 break;
5793
5794 case kIOPM_ParentUpNotifyInterestedDriversDidChange:
5795 ParentUpNotifyInterestedDriversDidChange();
5796 break;
5797
5798 case kIOPM_DriverThreadCallDone:
5799 if (fDriverCallReason == kDriverCallSetPowerState)
5800 notifyControllingDriverDone();
5801 else
5802 notifyInterestedDriversDone();
5803 break;
5804
5805 case kIOPM_NotifyChildrenDone:
5806 notifyChildrenDone();
5807 break;
5808
5809 case kIOPM_SyncNotifyDidChange:
5810 fMachineState = kIOPM_SyncFinish;
5811 fDriverCallReason = kDriverCallInformPostChange;
5812 notifyChildren();
5813 break;
5814
5815 case kIOPM_SyncFinish:
5816 if (fHeadNoteFlags & kIOPMParentInitiated)
5817 ParentAcknowledgePowerChange();
5818 else
5819 OurChangeFinish();
5820 break;
5821
5822 default:
5823 panic("servicePMWorkQueue: unknown machine state %x",
5824 fMachineState);
5825 }
5826
5827 gIOPMRequest = 0;
5828
5829 if (fMachineState == kIOPM_Finished)
5830 {
5831 //PM_TRACE("[%s] PM End: Request %p (type %02lx)\n",
5832 // getName(), request, request->getType());
5833 done = true;
5834 break;
5835 }
5836 }
5837
5838 return done;
5839 }
5840
5841 //*********************************************************************************
5842 // [private] executePMRequest
5843 //*********************************************************************************
5844
5845 void IOService::executePMRequest( IOPMRequest * request )
5846 {
5847 assert( kIOPM_Finished == fMachineState );
5848
5849 switch (request->getType())
5850 {
5851 case kIOPMRequestTypePMStop:
5852 handlePMstop( request );
5853 break;
5854
5855 case kIOPMRequestTypeAddPowerChild1:
5856 addPowerChild1( request );
5857 break;
5858
5859 case kIOPMRequestTypeAddPowerChild2:
5860 addPowerChild2( request );
5861 break;
5862
5863 case kIOPMRequestTypeAddPowerChild3:
5864 addPowerChild3( request );
5865 break;
5866
5867 case kIOPMRequestTypeRegisterPowerDriver:
5868 handleRegisterPowerDriver( request );
5869 break;
5870
5871 case kIOPMRequestTypeAdjustPowerState:
5872 fAdjustPowerScheduled = false;
5873 rebuildChildClampBits();
5874 adjustPowerState();
5875 break;
5876
5877 case kIOPMRequestTypePowerDomainWillChange:
5878 handlePowerDomainWillChangeTo( request );
5879 break;
5880
5881 case kIOPMRequestTypePowerDomainDidChange:
5882 handlePowerDomainDidChangeTo( request );
5883 break;
5884
5885 case kIOPMRequestTypeRequestPowerState:
5886 case kIOPMRequestTypeRequestPowerStateOverride:
5887 handleRequestPowerState( request );
5888 break;
5889
5890 case kIOPMRequestTypePowerOverrideOnPriv:
5891 case kIOPMRequestTypePowerOverrideOffPriv:
5892 handlePowerOverrideChanged( request );
5893 break;
5894
5895 case kIOPMRequestTypeActivityTickle:
5896 handleActivityTickle( request );
5897 break;
5898
5899 case kIOPMRequestTypeSynchronizePowerTree:
5900 handleSynchronizePowerTree( request );
5901 break;
5902
5903 case kIOPMRequestTypeSetIdleTimerPeriod:
5904 {
5905 IOWorkLoop * wl = gIOPMWorkLoop;
5906 fIdleTimerPeriod = (uintptr_t) request->fArg0;
5907
5908 if (wl && (false == fLockedFlags.PMStop) && (fIdleTimerPeriod > 0))
5909 {
5910 if ( NULL == fIdleTimerEventSource )
5911 {
5912 IOTimerEventSource * timerSrc;
5913
5914 timerSrc = IOTimerEventSource::timerEventSource(
5915 this,
5916 OSMemberFunctionCast(IOTimerEventSource::Action,
5917 this, &IOService::idleTimerExpired));
5918
5919 if (timerSrc && (wl->addEventSource(timerSrc) != kIOReturnSuccess))
5920 {
5921 timerSrc->release();
5922 timerSrc = 0;
5923 }
5924
5925 fIdleTimerEventSource = timerSrc;
5926 }
5927
5928 fActivityTickleCount = 0;
5929 clock_get_uptime(&fIdleTimerStartTime);
5930 start_PM_idle_timer();
5931 }
5932 }
5933 break;
5934
5935 default:
5936 panic("executePMRequest: unknown request type %x", request->getType());
5937 }
5938 }
5939
5940 //*********************************************************************************
5941 // [private] servicePMReplyQueue
5942 //*********************************************************************************
5943
5944 bool IOService::servicePMReplyQueue( IOPMRequest * request, IOPMRequestQueue * queue )
5945 {
5946 bool more = false;
5947
5948 assert( request && queue );
5949 assert( request->isReplyType() );
5950
5951 PM_TRACE("[A %02x] %p [%p %s] State %d\n",
5952 request->getType(), request, this, getName(), fMachineState);
5953
5954 switch ( request->getType() )
5955 {
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))
5960 {
5961 if (kIOPMRequestTypeCancelPowerChange == request->getType())
5962 {
5963 OSString * name = (OSString *) request->fArg2;
5964 getPMRootDomain()->pmStatsRecordApplicationResponse(
5965 gIOPMStatsApplicationResponseCancel,
5966 name ? name->getCStringNoCopy() : "", 0,
5967 0, (int)(uintptr_t) request->fArg1);
5968
5969 fDoNotPowerDown = true;
5970 }
5971
5972 if (checkForDone())
5973 {
5974 stop_ack_timer();
5975 if ( fResponseArray )
5976 {
5977 fResponseArray->release();
5978 fResponseArray = NULL;
5979 }
5980 if ( fNotifyClientArray )
5981 {
5982 fNotifyClientArray->release();
5983 fNotifyClientArray = NULL;
5984 }
5985 more = true;
5986 }
5987 }
5988 // OSString containing app name in Arg2 must be released.
5989 if (request->getType() == kIOPMRequestTypeCancelPowerChange)
5990 {
5991 OSObject * obj = (OSObject *) request->fArg2;
5992 if (obj) obj->release();
5993 }
5994 break;
5995
5996 case kIOPMRequestTypeAckPowerChange:
5997 more = handleAcknowledgePowerChange( request );
5998 break;
5999
6000 case kIOPMRequestTypeAckSetPowerState:
6001 if (fDriverTimer == -1)
6002 {
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);
6007 fDriverTimer = 0;
6008 }
6009 else if (fDriverTimer > 0)
6010 {
6011 // expected ack, stop the timer
6012 stop_ack_timer();
6013
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));
6019 #endif
6020 OUR_PMLog(kPMLogDriverAcknowledgeSet, (uintptr_t) this, fDriverTimer);
6021 fDriverTimer = 0;
6022 more = true;
6023 }
6024 else
6025 {
6026 // unexpected ack
6027 OUR_PMLog(kPMLogAcknowledgeErr4, (uintptr_t) this, 0);
6028 }
6029 break;
6030
6031 case kIOPMRequestTypeInterestChanged:
6032 handleInterestChanged( request );
6033 more = true;
6034 break;
6035
6036 case kIOPMRequestTypeIdleCancel:
6037 if ((fMachineState == kIOPM_OurChangeTellClientsPowerDown)
6038 || (fMachineState == kIOPM_OurChangeTellPriorityClientsPowerDown))
6039 {
6040 OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, 0);
6041 fDoNotPowerDown = true;
6042 if (fMachineState == kIOPM_OurChangeTellPriorityClientsPowerDown)
6043 cleanClientResponses(false);
6044 more = true;
6045 }
6046 break;
6047
6048 default:
6049 panic("servicePMReplyQueue: unknown reply type %x",
6050 request->getType());
6051 }
6052
6053 releasePMRequest( request );
6054 return more;
6055 }
6056
6057 //*********************************************************************************
6058 // [private] assertPMThreadCall / deassertPMThreadCall
6059 //*********************************************************************************
6060
6061 bool IOService::assertPMThreadCall( void )
6062 {
6063 if (!initialized)
6064 return false;
6065
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.
6069
6070 PM_LOCK();
6071 if (fLockedFlags.PMStop)
6072 {
6073 // PMstop() already issued - fail the assertion.
6074 PM_UNLOCK();
6075 return false;
6076 }
6077
6078 // Increment assertion count to block PMstop(), and return true.
6079 fThreadAssertionCount++;
6080 fThreadAssertionThread = current_thread(); // only 1 caller
6081 PM_UNLOCK();
6082
6083 return true;
6084 }
6085
6086 void IOService::deassertPMThreadCall( void )
6087 {
6088 PM_LOCK();
6089 assert(fThreadAssertionCount > 0);
6090 if (fThreadAssertionCount)
6091 fThreadAssertionCount--;
6092 if (current_thread() == fThreadAssertionThread)
6093 fThreadAssertionThread = 0;
6094 if ((fThreadAssertionCount == 0) && fLockedFlags.PMStop)
6095 {
6096 // PMstop() is blocked waiting for assertion count to drop to zero.
6097 PM_LOCK_WAKEUP(&fThreadAssertionCount);
6098 }
6099 PM_UNLOCK();
6100 }
6101
6102 // MARK: -
6103 // MARK: IOPMRequest
6104
6105 //*********************************************************************************
6106 // IOPMRequest Class
6107 //
6108 // Requests from PM clients, and also used for inter-object messaging within PM.
6109 //*********************************************************************************
6110
6111 OSDefineMetaClassAndStructors( IOPMRequest, IOCommand );
6112
6113 IOPMRequest * IOPMRequest::create( void )
6114 {
6115 IOPMRequest * me = OSTypeAlloc(IOPMRequest);
6116 if (me && !me->init(0, kIOPMRequestTypeInvalid))
6117 {
6118 me->release();
6119 me = 0;
6120 }
6121 return me;
6122 }
6123
6124 bool IOPMRequest::init( IOService * target, IOOptionBits type )
6125 {
6126 if (!IOCommand::init())
6127 return false;
6128
6129 fType = type;
6130 fTarget = target;
6131 fCompletionStatus = kIOReturnSuccess;
6132
6133 if (fTarget)
6134 fTarget->retain();
6135
6136 return true;
6137 }
6138
6139 void IOPMRequest::reset( void )
6140 {
6141 assert( fWorkWaitCount == 0 );
6142 assert( fFreeWaitCount == 0 );
6143
6144 detachNextRequest();
6145 detachRootRequest();
6146
6147 fType = kIOPMRequestTypeInvalid;
6148
6149 if (fCompletionAction)
6150 {
6151 fCompletionAction(fCompletionTarget, fCompletionParam, fCompletionStatus);
6152 }
6153
6154 if (fTarget)
6155 {
6156 fTarget->release();
6157 fTarget = 0;
6158 }
6159 }
6160
6161 void IOPMRequest::attachNextRequest( IOPMRequest * next )
6162 {
6163 if (!fRequestNext)
6164 {
6165 // Postpone the execution of the next request after
6166 // this request.
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());
6175 #endif
6176 }
6177 }
6178
6179 void IOPMRequest::detachNextRequest( void )
6180 {
6181 if (fRequestNext)
6182 {
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());
6192 #endif
6193 fRequestNext = 0;
6194 }
6195 }
6196
6197 void IOPMRequest::attachRootRequest( IOPMRequest * root )
6198 {
6199 if (!fRequestRoot)
6200 {
6201 // Delay the completion of the root request after
6202 // this request.
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());
6211 #endif
6212 }
6213 }
6214
6215 void IOPMRequest::detachRootRequest( void )
6216 {
6217 if (fRequestRoot)
6218 {
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());
6228 #endif
6229 fRequestRoot = 0;
6230 }
6231 }
6232
6233 // MARK: -
6234 // MARK: IOPMRequestQueue
6235
6236 //*********************************************************************************
6237 // IOPMRequestQueue Class
6238 //
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 //*********************************************************************************
6242
6243 OSDefineMetaClassAndStructors( IOPMRequestQueue, IOEventSource );
6244
6245 IOPMRequestQueue * IOPMRequestQueue::create( IOService * inOwner, Action inAction )
6246 {
6247 IOPMRequestQueue * me = OSTypeAlloc(IOPMRequestQueue);
6248 if (me && !me->init(inOwner, inAction))
6249 {
6250 me->release();
6251 me = 0;
6252 }
6253 return me;
6254 }
6255
6256 bool IOPMRequestQueue::init( IOService * inOwner, Action inAction )
6257 {
6258 if (!inAction || !IOEventSource::init(inOwner, (IOEventSourceAction)inAction))
6259 return false;
6260
6261 queue_init(&fQueue);
6262 fLock = IOLockAlloc();
6263 return (fLock != 0);
6264 }
6265
6266 void IOPMRequestQueue::free( void )
6267 {
6268 if (fLock)
6269 {
6270 IOLockFree(fLock);
6271 fLock = 0;
6272 }
6273 return IOEventSource::free();
6274 }
6275
6276 void IOPMRequestQueue::queuePMRequest( IOPMRequest * request )
6277 {
6278 assert(request);
6279 IOLockLock(fLock);
6280 queue_enter(&fQueue, request, IOPMRequest *, fCommandChain);
6281 IOLockUnlock(fLock);
6282 if (workLoop) signalWorkAvailable();
6283 }
6284
6285 void
6286 IOPMRequestQueue::queuePMRequestChain( IOPMRequest ** requests, IOItemCount count )
6287 {
6288 IOPMRequest * next;
6289
6290 assert(requests && count);
6291 IOLockLock(fLock);
6292 while (count--)
6293 {
6294 next = *requests;
6295 requests++;
6296 queue_enter(&fQueue, next, IOPMRequest *, fCommandChain);
6297 }
6298 IOLockUnlock(fLock);
6299 if (workLoop) signalWorkAvailable();
6300 }
6301
6302 bool IOPMRequestQueue::checkForWork( void )
6303 {
6304 Action dqAction = (Action) action;
6305 IOPMRequest * request;
6306 IOService * target;
6307 bool more = false;
6308
6309 IOLockLock( fLock );
6310
6311 while (!queue_empty(&fQueue))
6312 {
6313 queue_remove_first( &fQueue, request, IOPMRequest *, fCommandChain );
6314 IOLockUnlock( fLock );
6315 target = request->getTarget();
6316 assert(target);
6317 more |= (*dqAction)( target, request, this );
6318 IOLockLock( fLock );
6319 }
6320
6321 IOLockUnlock( fLock );
6322 return more;
6323 }
6324
6325 void IOPMRequestQueue::signalWorkAvailable( void )
6326 {
6327 IOEventSource::signalWorkAvailable();
6328 }
6329
6330 // MARK: -
6331 // MARK: IOPMWorkQueue
6332
6333 //*********************************************************************************
6334 // IOPMWorkQueue Class
6335 //
6336 // Every object in the power plane that has handled a PM request, will have an
6337 // instance of IOPMWorkQueue allocated for it.
6338 //*********************************************************************************
6339
6340 OSDefineMetaClassAndStructors( IOPMWorkQueue, IOEventSource );
6341
6342 IOPMWorkQueue *
6343 IOPMWorkQueue::create( IOService * inOwner, Action work, Action retire )
6344 {
6345 IOPMWorkQueue * me = OSTypeAlloc(IOPMWorkQueue);
6346 if (me && !me->init(inOwner, work, retire))
6347 {
6348 me->release();
6349 me = 0;
6350 }
6351 return me;
6352 }
6353
6354 bool IOPMWorkQueue::init( IOService * inOwner, Action work, Action retire )
6355 {
6356 if (!work || !retire ||
6357 !IOEventSource::init(inOwner, (IOEventSourceAction)0))
6358 return false;
6359
6360 queue_init(&fWorkQueue);
6361
6362 fWorkAction = work;
6363 fRetireAction = retire;
6364
6365 return true;
6366 }
6367
6368 void IOPMWorkQueue::queuePMRequest( IOPMRequest * request )
6369 {
6370 assert( request );
6371 assert( onThread() );
6372
6373 gIOPMBusyCount++;
6374 queue_enter(&fWorkQueue, request, IOPMRequest *, fCommandChain);
6375 checkForWork();
6376 }
6377
6378 bool IOPMWorkQueue::checkForWork( void )
6379 {
6380 IOPMRequest * request;
6381 IOService * target = (IOService *) owner;
6382 bool done;
6383
6384 while (!queue_empty(&fWorkQueue))
6385 {
6386 request = (IOPMRequest *) queue_first(&fWorkQueue);
6387 assert(request->getTarget() == target);
6388 if (request->isWorkBlocked()) break;
6389 done = (*fWorkAction)( target, request, this );
6390 if (!done) break;
6391
6392 assert(gIOPMBusyCount > 0);
6393 if (gIOPMBusyCount) gIOPMBusyCount--;
6394 queue_remove_first(&fWorkQueue, request, IOPMRequest *, fCommandChain);
6395 (*fRetireAction)( target, request, this );
6396 }
6397
6398 return false;
6399 }
6400
6401 // MARK: -
6402 // MARK: IOPMCompletionQueue
6403
6404 //*********************************************************************************
6405 // IOPMCompletionQueue Class
6406 //*********************************************************************************
6407
6408 OSDefineMetaClassAndStructors( IOPMCompletionQueue, IOEventSource );
6409
6410 IOPMCompletionQueue * IOPMCompletionQueue::create( IOService * inOwner, Action inAction )
6411 {
6412 IOPMCompletionQueue * me = OSTypeAlloc(IOPMCompletionQueue);
6413 if (me && !me->init(inOwner, inAction))
6414 {
6415 me->release();
6416 me = 0;
6417 }
6418 return me;
6419 }
6420
6421 bool IOPMCompletionQueue::init( IOService * inOwner, Action inAction )
6422 {
6423 if (!inAction || !IOEventSource::init(inOwner, (IOEventSourceAction)inAction))
6424 return false;
6425
6426 queue_init(&fQueue);
6427 return true;
6428 }
6429
6430 void IOPMCompletionQueue::queuePMRequest( IOPMRequest * request )
6431 {
6432 assert(request);
6433 request->detachNextRequest(); // unblocks next request
6434 queue_enter(&fQueue, request, IOPMRequest *, fCommandChain);
6435 if (workLoop) signalWorkAvailable();
6436 }
6437
6438 bool IOPMCompletionQueue::checkForWork( void )
6439 {
6440 Action dqAction = (Action) action;
6441 IOPMRequest * request;
6442 IOService * target;
6443 bool more = false;
6444 queue_head_t tmpQueue;
6445
6446 queue_init(&tmpQueue);
6447
6448 while (!queue_empty(&fQueue))
6449 {
6450 queue_remove_first( &fQueue, request, IOPMRequest *, fCommandChain );
6451 if (request->isFreeBlocked())
6452 {
6453 queue_enter(&tmpQueue, request, IOPMRequest *, fCommandChain);
6454 continue;
6455 }
6456 target = request->getTarget();
6457 assert(target);
6458 more |= (*dqAction)( target, request, this );
6459 }
6460
6461 queue_new_head(&tmpQueue, &fQueue, IOPMRequest *, fCommandChain);
6462 return more;
6463 }
6464
6465 // MARK: -
6466 // MARK: IOServicePM
6467
6468 OSDefineMetaClassAndStructors(IOServicePM, OSObject)
6469
6470 //*********************************************************************************
6471 // serialize
6472 //
6473 // Serialize IOServicePM for debugging.
6474 //*********************************************************************************
6475
6476 static void
6477 setPMProperty( OSDictionary * dict, const char * key, uint64_t value )
6478 {
6479 OSNumber * num = OSNumber::withNumber(value, sizeof(value) * 8);
6480 if (num)
6481 {
6482 dict->setObject(key, num);
6483 num->release();
6484 }
6485 }
6486
6487 IOReturn IOServicePM::gatedSerialize( OSSerialize * s )
6488 {
6489 OSDictionary * dict;
6490 bool ok = false;
6491 int dictSize = 4;
6492
6493 if (IdleTimerPeriod)
6494 dictSize += 4;
6495
6496 if (PowerClients)
6497 dict = OSDictionary::withDictionary(
6498 PowerClients, PowerClients->getCount() + dictSize);
6499 else
6500 dict = OSDictionary::withCapacity(dictSize);
6501
6502 if (dict)
6503 {
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);
6511
6512 if (IdleTimerPeriod)
6513 {
6514 AbsoluteTime now;
6515 AbsoluteTime delta;
6516 uint64_t nsecs;
6517
6518 clock_get_uptime(&now);
6519
6520 // The idle timer period in milliseconds.
6521 setPMProperty(dict, "IdleTimerPeriod", IdleTimerPeriod * 1000ULL);
6522
6523 // The number of activity tickles recorded since device idle
6524 setPMProperty(dict, "ActivityTickles", ActivityTickleCount);
6525
6526 if (AbsoluteTime_to_scalar(&DeviceActiveTimestamp))
6527 {
6528 // The number of milliseconds since the last activity tickle.
6529 delta = now;
6530 SUB_ABSOLUTETIME(&delta, &DeviceActiveTimestamp);
6531 absolutetime_to_nanoseconds(delta, &nsecs);
6532 setPMProperty(dict, "TimeSinceActivityTickle", NS_TO_MS(nsecs));
6533 }
6534
6535 if (AbsoluteTime_to_scalar(&IdleTimerStartTime))
6536 {
6537 // The number of milliseconds since the last device idle.
6538 delta = now;
6539 SUB_ABSOLUTETIME(&delta, &IdleTimerStartTime);
6540 absolutetime_to_nanoseconds(delta, &nsecs);
6541 setPMProperty(dict, "TimeSinceDeviceIdle", NS_TO_MS(nsecs));
6542 }
6543 }
6544
6545 ok = dict->serialize(s);
6546 dict->release();
6547 }
6548
6549 return (ok ? kIOReturnSuccess : kIOReturnNoMemory);
6550 }
6551
6552 bool IOServicePM::serialize( OSSerialize * s ) const
6553 {
6554 IOReturn ret = kIOReturnNotReady;
6555
6556 if (gIOPMWorkLoop)
6557 {
6558 ret = gIOPMWorkLoop->runAction(
6559 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOServicePM::gatedSerialize),
6560 (OSObject *) this, (void *) s);
6561 }
6562
6563 return (kIOReturnSuccess == ret);
6564 }