]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOServicePM.cpp
4d35ed45bbf100807893416aaa16e58a92e842e3
[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 //#undef IOASSERT
30 //#define IOASSERT 1
31
32 #include <IOKit/assert.h>
33 #include <IOKit/IOKitDebug.h>
34 #include <IOKit/IOLib.h>
35 #include <IOKit/IOMessage.h>
36 #include <IOKit/IOPlatformExpert.h>
37 #include <IOKit/IOService.h>
38 #include <IOKit/IOEventSource.h>
39 #include <IOKit/IOWorkLoop.h>
40 #include <IOKit/IOCommand.h>
41 #include <IOKit/IOTimeStamp.h>
42
43 #include <IOKit/pwr_mgt/IOPMlog.h>
44 #include <IOKit/pwr_mgt/IOPMinformee.h>
45 #include <IOKit/pwr_mgt/IOPMinformeeList.h>
46 #include <IOKit/pwr_mgt/IOPowerConnection.h>
47 #include <IOKit/pwr_mgt/RootDomain.h>
48 #include <IOKit/pwr_mgt/IOPMPrivate.h>
49
50 #include <sys/proc.h>
51 #include <sys/proc_internal.h>
52 #include <libkern/OSDebug.h>
53
54 // Required for notification instrumentation
55 #include "IOServicePrivate.h"
56 #include "IOServicePMPrivate.h"
57 #include "IOKitKernelInternal.h"
58
59 static void settle_timer_expired(thread_call_param_t, thread_call_param_t);
60 static void idle_timer_expired(thread_call_param_t, thread_call_param_t);
61 static void tellKernelClientApplier(OSObject * object, void * arg);
62 static void tellAppClientApplier(OSObject * object, void * arg);
63
64 static uint64_t computeTimeDeltaNS( const AbsoluteTime * start )
65 {
66 AbsoluteTime now;
67 uint64_t nsec;
68
69 clock_get_uptime(&now);
70 SUB_ABSOLUTETIME(&now, start);
71 absolutetime_to_nanoseconds(now, &nsec);
72 return nsec;
73 }
74
75 #if PM_VARS_SUPPORT
76 OSDefineMetaClassAndStructors(IOPMprot, OSObject)
77 #endif
78
79 // Container class for recording system power events
80 OSDefineMetaClassAndStructors( PMEventDetails, OSObject );
81
82 //******************************************************************************
83 // Globals
84 //******************************************************************************
85
86 static bool gIOPMInitialized = false;
87 static uint32_t gIOPMBusyCount = 0;
88 static uint32_t gIOPMWorkCount = 0;
89 static uint32_t gIOPMTickleGeneration = 0;
90 static IOWorkLoop * gIOPMWorkLoop = 0;
91 static IOPMRequestQueue * gIOPMRequestQueue = 0;
92 static IOPMRequestQueue * gIOPMReplyQueue = 0;
93 static IOPMWorkQueue * gIOPMWorkQueue = 0;
94 static IOPMCompletionQueue * gIOPMFreeQueue = 0;
95 static IOPMRequest * gIOPMRequest = 0;
96 static IOService * gIOPMRootNode = 0;
97 static IOPlatformExpert * gPlatform = 0;
98
99 static const OSSymbol * gIOPMPowerClientDevice = 0;
100 static const OSSymbol * gIOPMPowerClientDriver = 0;
101 static const OSSymbol * gIOPMPowerClientChildProxy = 0;
102 static const OSSymbol * gIOPMPowerClientChildren = 0;
103
104 static const OSSymbol * gIOPMPowerClientAdvisoryTickle = 0;
105 static bool gIOPMAdvisoryTickleEnabled = true;
106
107 static uint32_t getPMRequestType( void )
108 {
109 uint32_t type = kIOPMRequestTypeInvalid;
110 if (gIOPMRequest)
111 type = gIOPMRequest->getType();
112 return type;
113 }
114
115 //******************************************************************************
116 // Macros
117 //******************************************************************************
118
119 #define PM_ERROR(x...) do { kprintf(x); IOLog(x); } while (false)
120 #define PM_LOG(x...) do { kprintf(x); } while (false)
121
122 #define PM_LOG1(x...) do { \
123 if (kIOLogDebugPower & gIOKitDebug) \
124 kprintf(x); } while (false)
125
126 #define PM_LOG2(x...) do { \
127 if (kIOLogDebugPower & gIOKitDebug) \
128 kprintf(x); } while (false)
129
130 #if 0
131 #define PM_LOG3(x...) do { kprintf(x); } while (false)
132 #else
133 #define PM_LOG3(x...)
134 #endif
135
136 #define RD_LOG(x...) do { \
137 if ((kIOLogPMRootDomain & gIOKitDebug) && \
138 (getPMRootDomain() == this)) \
139 kprintf("PMRD: " x); } while (false)
140
141 #define PM_ASSERT_IN_GATE(x) \
142 do { \
143 assert(gIOPMWorkLoop->inGate()); \
144 } while(false)
145
146 #define PM_LOCK() IOLockLock(fPMLock)
147 #define PM_UNLOCK() IOLockUnlock(fPMLock)
148 #define PM_LOCK_SLEEP(event, dl) IOLockSleepDeadline(fPMLock, event, dl, THREAD_UNINT)
149 #define PM_LOCK_WAKEUP(event) IOLockWakeup(fPMLock, event, false)
150
151 #define ns_per_us 1000
152 #define k30Seconds (30*1000000)
153 #define kMinAckTimeoutTicks (10*1000000)
154 #define kIOPMTardyAckSPSKey "IOPMTardyAckSetPowerState"
155 #define kIOPMTardyAckPSCKey "IOPMTardyAckPowerStateChange"
156 #define kPwrMgtKey "IOPowerManagement"
157
158 #define OUR_PMLog(t, a, b) do { \
159 if (gIOKitDebug & kIOLogPower) \
160 pwrMgt->pmPrint(t, a, b); \
161 if (gIOKitTrace & kIOTracePowerMgmt) \
162 pwrMgt->pmTrace(t, a, b); \
163 } while(0)
164
165 #define NS_TO_MS(nsec) ((int)((nsec) / 1000000ULL))
166 #define NS_TO_US(nsec) ((int)((nsec) / 1000ULL))
167
168 #if CONFIG_EMBEDDED
169 #define SUPPORT_IDLE_CANCEL 1
170 #endif
171
172 #define kIOPMPowerStateMax 0xFFFFFFFF
173 #define kInvalidTicklePowerState (-1)
174
175 #define kNoTickleCancelWindow (60ULL * 1000ULL * 1000ULL * 1000ULL)
176
177 #define IS_PM_ROOT (this == gIOPMRootNode)
178 #define IS_ROOT_DOMAIN (getPMRootDomain() == this)
179 #define IS_POWER_DROP (fHeadNotePowerState < fCurrentPowerState)
180 #define IS_POWER_RISE (fHeadNotePowerState > fCurrentPowerState)
181
182 // log setPowerStates longer than (ns):
183 #define LOG_SETPOWER_TIMES (50ULL * 1000ULL * 1000ULL)
184 // log app responses longer than (ns):
185 #define LOG_APP_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
186 // use message tracer to log messages longer than (ns):
187 #define LOG_APP_RESPONSE_MSG_TRACER (3 * 1000ULL * 1000ULL * 1000ULL)
188
189 enum {
190 kReserveDomainPower = 1
191 };
192
193 #define MS_PUSH(n) \
194 do { assert(kIOPM_BadMachineState == fSavedMachineState); \
195 assert(kIOPM_BadMachineState != n); \
196 fSavedMachineState = n; } while (false)
197
198 #define MS_POP() \
199 do { assert(kIOPM_BadMachineState != fSavedMachineState); \
200 fMachineState = fSavedMachineState; \
201 fSavedMachineState = kIOPM_BadMachineState; } while (false)
202
203 #define PM_ACTION_0(a) \
204 do { if (fPMActions.a) { \
205 (fPMActions.a)(fPMActions.target, this, &fPMActions); } \
206 } while (false)
207
208 #define PM_ACTION_2(a, x, y) \
209 do { if (fPMActions.a) { \
210 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y); } \
211 } while (false)
212
213 static OSNumber * copyClientIDForNotification(
214 OSObject *object,
215 IOPMInterestContext *context);
216
217 static void logClientIDForNotification(
218 OSObject *object,
219 IOPMInterestContext *context,
220 const char *logString);
221
222 //*********************************************************************************
223 // PM machine states
224 //
225 // Check kgmacros after modifying machine states.
226 //*********************************************************************************
227
228 enum {
229 kIOPM_Finished = 0,
230
231 kIOPM_OurChangeTellClientsPowerDown = 1,
232 kIOPM_OurChangeTellPriorityClientsPowerDown = 2,
233 kIOPM_OurChangeNotifyInterestedDriversWillChange = 3,
234 kIOPM_OurChangeSetPowerState = 4,
235 kIOPM_OurChangeWaitForPowerSettle = 5,
236 kIOPM_OurChangeNotifyInterestedDriversDidChange = 6,
237 kIOPM_OurChangeTellCapabilityDidChange = 7,
238 kIOPM_OurChangeFinish = 8,
239
240 kIOPM_ParentChangeTellPriorityClientsPowerDown = 10,
241 kIOPM_ParentChangeNotifyInterestedDriversWillChange = 11,
242 kIOPM_ParentChangeSetPowerState = 12,
243 kIOPM_ParentChangeWaitForPowerSettle = 13,
244 kIOPM_ParentChangeNotifyInterestedDriversDidChange = 14,
245 kIOPM_ParentChangeTellCapabilityDidChange = 15,
246 kIOPM_ParentChangeAcknowledgePowerChange = 16,
247
248 kIOPM_NotifyChildrenStart = 17,
249 kIOPM_NotifyChildrenOrdered = 18,
250 kIOPM_NotifyChildrenDelayed = 19,
251 kIOPM_SyncTellClientsPowerDown = 20,
252 kIOPM_SyncTellPriorityClientsPowerDown = 21,
253 kIOPM_SyncNotifyWillChange = 22,
254 kIOPM_SyncNotifyDidChange = 23,
255 kIOPM_SyncTellCapabilityDidChange = 24,
256 kIOPM_SyncFinish = 25,
257 kIOPM_TellCapabilityChangeDone = 26,
258 kIOPM_DriverThreadCallDone = 27,
259
260 kIOPM_BadMachineState = 0xFFFFFFFF
261 };
262
263
264 /*
265 Power Management defines a few roles that drivers can play in their own,
266 and other drivers', power management. We briefly define those here.
267
268 Many drivers implement their policy maker and power controller within the same
269 IOService object, but that is not required.
270
271 == Policy Maker ==
272 * Virtual IOService PM methods a "policy maker" may implement
273 * maxCapabilityForDomainState()
274 * initialPowerStateForDomainState()
275 * powerStateForDomainState()
276
277 * Virtual IOService PM methods a "policy maker" may CALL
278 * PMinit()
279
280 == Power Controller ==
281 * Virtual IOService PM methods a "power controller" may implement
282 * setPowerState()
283
284 * Virtual IOService PM methods a "power controller" may CALL
285 * joinPMtree()
286 * registerPowerDriver()
287
288 =======================
289 There are two different kinds of power state changes.
290 * One is initiated by a subclassed device object which has either decided
291 to change power state, or its controlling driver has suggested it, or
292 some other driver wants to use the idle device and has asked it to become
293 usable.
294 * The second kind of power state change is initiated by the power domain
295 parent.
296 The two are handled through different code paths.
297
298 We maintain a queue of "change notifications," or change notes.
299 * Usually the queue is empty.
300 * When it isn't, usually there is one change note in it
301 * It's possible to have more than one power state change pending at one
302 time, so a queue is implemented.
303 Example:
304 * The subclass device decides it's idle and initiates a change to a lower
305 power state. This causes interested parties to be notified, but they
306 don't all acknowledge right away. This causes the change note to sit
307 in the queue until all the acks are received. During this time, the
308 device decides it isn't idle anymore and wants to raise power back up
309 again. This change can't be started, however, because the previous one
310 isn't complete yet, so the second one waits in the queue. During this
311 time, the parent decides to lower or raise the power state of the entire
312 power domain and notifies the device, and that notification goes into
313 the queue, too, and can't be actioned until the others are.
314
315 == SelfInitiated ==
316 This is how a power change initiated by the subclass device is handled:
317 -> First, all interested parties are notified of the change via their
318 powerStateWillChangeTo method. If they all don't acknowledge via return
319 code, then we have to wait. If they do, or when they finally all
320 acknowledge via our acknowledgePowerChange method, then we can continue.
321 -> We call the controlling driver, instructing it to change to the new state
322 -> Then we wait for power to settle. If there is no settling-time, or after
323 it has passed,
324 -> we notify interested parties again, this time via their
325 powerStateDidChangeTo methods.
326 -> When they have all acked, we're done.
327 If we lowered power and don't need the power domain to be in its current power
328 state, we suggest to the parent that it lower the power domain state.
329
330 == PowerDomainDownInitiated ==
331 How a change to a lower power domain state initiated by the parent is handled:
332 -> First, we figure out what power state we will be in when the new domain
333 state is reached.
334 -> Then all interested parties are notified that we are moving to that new
335 state.
336 -> When they have acknowledged, we call the controlling driver to assume
337 that state and we wait for power to settle.
338 -> Then we acknowledge our preparedness to our parent. When all its
339 interested parties have acknowledged,
340 -> it lowers power and then notifies its interested parties again.
341 -> When we get this call, we notify our interested parties that the power
342 state has changed, and when they have all acknowledged, we're done.
343
344 == PowerDomainUpInitiated ==
345 How a change to a higher power domain state initiated by the parent is handled:
346 -> We figure out what power state we will be in when the new domain state is
347 reached.
348 -> If it is different from our current state we acknowledge the parent.
349 -> When all the parent's interested parties have acknowledged, it raises
350 power in the domain and waits for power to settle.
351 -> Then it notifies everyone that the new state has been reached.
352 -> When we get this call, we call the controlling driver, instructing it to
353 assume the new state, and wait for power to settle.
354 -> Then we notify our interested parties. When they all acknowledge we are
355 done.
356
357 In either of the two power domain state cases above, it is possible that we
358 will not be changing state even though the domain is.
359 Examples:
360 * A change to a lower domain state may not affect us because we are already
361 in a low enough state,
362 * We will not take advantage of a change to a higher domain state, because
363 we have no need of the higher power. In such cases, there is nothing to
364 do but acknowledge the parent. So when the parent calls our
365 powerDomainWillChange method, and we decide that we will not be changing
366 state, we merely acknowledge the parent, via return code, and wait.
367 When the parent subsequently calls powerStateDidChange, we acknowledge again
368 via return code, and the change is complete.
369
370 == 4 Paths Through State Machine ==
371 Power state changes are processed in a state machine, and since there are four
372 varieties of power state changes, there are four major paths through the state
373 machine.
374
375 == 5. No Need To change ==
376 The fourth is nearly trivial. In this path, the parent is changing the domain
377 state, but we are not changing the device state. The change starts when the
378 parent calls powerDomainWillChange. All we do is acknowledge the parent. When
379 the parent calls powerStateDidChange, we acknowledge the parent again, and
380 we're done.
381
382 == 1. OurChange Down == XXX gvdl
383 The first is fairly simple. It starts:
384 * when a power domain child calls requestPowerDomainState and we decide to
385 change power states to accomodate the child,
386 * or if our power-controlling driver calls changePowerStateTo,
387 * or if some other driver which is using our device calls makeUsable,
388 * or if a subclassed object calls changePowerStateToPriv.
389 These are all power changes initiated by us, not forced upon us by the parent.
390
391 -> We start by notifying interested parties.
392 -> If they all acknowledge via return code, we can go on to state
393 "msSetPowerState".
394 -> Otherwise, we start the ack timer and wait for the stragglers to
395 acknowlege by calling acknowledgePowerChange.
396 -> We move on to state "msSetPowerState" when all the
397 stragglers have acknowledged, or when the ack timer expires on
398 all those which didn't acknowledge.
399 In "msSetPowerState" we call the power-controlling driver to change the
400 power state of the hardware.
401 -> If it returns saying it has done so, we go on to state
402 "msWaitForPowerSettle".
403 -> Otherwise, we have to wait for it, so we set the ack timer and wait.
404 -> When it calls acknowledgeSetPowerState, or when the ack timer
405 expires, we go on.
406 In "msWaitForPowerSettle", we look in the power state array to see if
407 there is any settle time required when changing from our current state to the
408 new state.
409 -> If not, we go right away to "msNotifyInterestedDriversDidChange".
410 -> Otherwise, we set the settle timer and wait. When it expires, we move on.
411 In "msNotifyInterestedDriversDidChange" state, we notify all our
412 interested parties via their powerStateDidChange methods that we have finished
413 changing power state.
414 -> If they all acknowledge via return code, we move on to "msFinish".
415 -> Otherwise we set the ack timer and wait. When they have all
416 acknowledged, or when the ack timer has expired for those that didn't,
417 we move on to "msFinish".
418 In "msFinish" we remove the used change note from the head of the queue
419 and start the next one if one exists.
420
421 == 2. Parent Change Down ==
422 Start at Stage 2 of OurChange Down XXX gvdl
423
424 == 3. Change Up ==
425 Start at Stage 4 of OurChange Down XXX gvdl
426
427 Note all parent requested changes need to acknowledge the power has changed to the parent when done.
428 */
429
430 //*********************************************************************************
431 // [public] PMinit
432 //
433 // Initialize power management.
434 //*********************************************************************************
435
436 void IOService::PMinit ( void )
437 {
438 if ( !initialized )
439 {
440 if ( !gIOPMInitialized )
441 {
442 gPlatform = getPlatform();
443 gIOPMWorkLoop = IOWorkLoop::workLoop();
444 if (gIOPMWorkLoop)
445 {
446 gIOPMRequestQueue = IOPMRequestQueue::create(
447 this, OSMemberFunctionCast(IOPMRequestQueue::Action,
448 this, &IOService::servicePMRequestQueue));
449
450 gIOPMReplyQueue = IOPMRequestQueue::create(
451 this, OSMemberFunctionCast(IOPMRequestQueue::Action,
452 this, &IOService::servicePMReplyQueue));
453
454 gIOPMWorkQueue = IOPMWorkQueue::create(
455 this,
456 OSMemberFunctionCast(IOPMWorkQueue::Action, this,
457 &IOService::servicePMRequest),
458 OSMemberFunctionCast(IOPMWorkQueue::Action, this,
459 &IOService::retirePMRequest));
460
461 gIOPMFreeQueue = IOPMCompletionQueue::create(
462 this, OSMemberFunctionCast(IOPMCompletionQueue::Action,
463 this, &IOService::servicePMFreeQueue));
464
465 if (gIOPMWorkLoop->addEventSource(gIOPMRequestQueue) !=
466 kIOReturnSuccess)
467 {
468 gIOPMRequestQueue->release();
469 gIOPMRequestQueue = 0;
470 }
471
472 if (gIOPMWorkLoop->addEventSource(gIOPMReplyQueue) !=
473 kIOReturnSuccess)
474 {
475 gIOPMReplyQueue->release();
476 gIOPMReplyQueue = 0;
477 }
478
479 if (gIOPMWorkLoop->addEventSource(gIOPMWorkQueue) !=
480 kIOReturnSuccess)
481 {
482 gIOPMWorkQueue->release();
483 gIOPMWorkQueue = 0;
484 }
485
486 if (gIOPMWorkLoop->addEventSource(gIOPMFreeQueue) !=
487 kIOReturnSuccess)
488 {
489 gIOPMFreeQueue->release();
490 gIOPMFreeQueue = 0;
491 }
492
493 gIOPMPowerClientDevice =
494 OSSymbol::withCStringNoCopy( "DevicePowerState" );
495
496 gIOPMPowerClientDriver =
497 OSSymbol::withCStringNoCopy( "DriverPowerState" );
498
499 gIOPMPowerClientChildProxy =
500 OSSymbol::withCStringNoCopy( "ChildProxyPowerState" );
501
502 gIOPMPowerClientChildren =
503 OSSymbol::withCStringNoCopy( "ChildrenPowerState" );
504
505 gIOPMPowerClientAdvisoryTickle =
506 OSSymbol::withCStringNoCopy( "AdvisoryTicklePowerState" );
507 }
508
509 if (gIOPMRequestQueue && gIOPMReplyQueue && gIOPMFreeQueue)
510 gIOPMInitialized = true;
511 }
512 if (!gIOPMInitialized)
513 return;
514
515 pwrMgt = new IOServicePM;
516 pwrMgt->init();
517 setProperty(kPwrMgtKey, pwrMgt);
518
519 queue_init(&pwrMgt->WorkChain);
520 queue_init(&pwrMgt->RequestHead);
521 queue_init(&pwrMgt->PMDriverCallQueue);
522
523 fOwner = this;
524 fPMLock = IOLockAlloc();
525 fInterestedDrivers = new IOPMinformeeList;
526 fInterestedDrivers->initialize();
527 fDesiredPowerState = 0;
528 fDeviceDesire = 0;
529 fInitialPowerChange = true;
530 fInitialSetPowerState = true;
531 fPreviousRequestPowerFlags = 0;
532 fDeviceOverrideEnabled = false;
533 fMachineState = kIOPM_Finished;
534 fSavedMachineState = kIOPM_BadMachineState;
535 fIdleTimerMinPowerState = 0;
536 fActivityLock = IOLockAlloc();
537 fStrictTreeOrder = false;
538 fActivityTicklePowerState = kInvalidTicklePowerState;
539 fAdvisoryTicklePowerState = kInvalidTicklePowerState;
540 fControllingDriver = NULL;
541 fPowerStates = NULL;
542 fNumberOfPowerStates = 0;
543 fCurrentPowerState = 0;
544 fParentsCurrentPowerFlags = 0;
545 fMaxPowerState = 0;
546 fName = getName();
547 fParentsKnowState = false;
548 fSerialNumber = 0;
549 fResponseArray = NULL;
550 fNotifyClientArray = NULL;
551 fCurrentPowerConsumption = kIOPMUnknown;
552 fOverrideMaxPowerState = kIOPMPowerStateMax;
553
554 if (!gIOPMRootNode && (getParentEntry(gIOPowerPlane) == getRegistryRoot()))
555 {
556 gIOPMRootNode = this;
557 fParentsKnowState = true;
558 }
559 else if (getProperty(kIOPMResetPowerStateOnWakeKey) == kOSBooleanTrue)
560 {
561 fResetPowerStateOnWake = true;
562 }
563
564 fAckTimer = thread_call_allocate(
565 &IOService::ack_timer_expired, (thread_call_param_t)this);
566 fSettleTimer = thread_call_allocate(
567 &settle_timer_expired, (thread_call_param_t)this);
568 fIdleTimer = thread_call_allocate(
569 &idle_timer_expired, (thread_call_param_t)this);
570 fDriverCallEntry = thread_call_allocate(
571 (thread_call_func_t) &IOService::pmDriverCallout, this);
572 assert(fDriverCallEntry);
573
574 // Check for powerChangeDone override.
575 if (OSMemberFunctionCast(void (*)(void),
576 getResourceService(), &IOService::powerChangeDone) !=
577 OSMemberFunctionCast(void (*)(void),
578 this, &IOService::powerChangeDone))
579 {
580 fPCDFunctionOverride = true;
581 }
582
583 #if PM_VARS_SUPPORT
584 IOPMprot * prot = new IOPMprot;
585 if (prot)
586 {
587 prot->init();
588 prot->ourName = fName;
589 prot->thePlatform = gPlatform;
590 fPMVars = prot;
591 pm_vars = prot;
592 }
593 #else
594 pm_vars = (void *) (uintptr_t) true;
595 #endif
596
597 initialized = true;
598 }
599 }
600
601 //*********************************************************************************
602 // [private] PMfree
603 //
604 // Free the data created by PMinit. Only called from IOService::free().
605 //*********************************************************************************
606
607 void IOService::PMfree ( void )
608 {
609 initialized = false;
610 pm_vars = 0;
611
612 if ( pwrMgt )
613 {
614 assert(fMachineState == kIOPM_Finished);
615 assert(fInsertInterestSet == NULL);
616 assert(fRemoveInterestSet == NULL);
617 assert(fNotifyChildArray == NULL);
618 assert(queue_empty(&pwrMgt->RequestHead));
619 assert(queue_empty(&fPMDriverCallQueue));
620
621 if ( fSettleTimer ) {
622 thread_call_cancel(fSettleTimer);
623 thread_call_free(fSettleTimer);
624 fSettleTimer = NULL;
625 }
626 if ( fAckTimer ) {
627 thread_call_cancel(fAckTimer);
628 thread_call_free(fAckTimer);
629 fAckTimer = NULL;
630 }
631 if ( fIdleTimer ) {
632 thread_call_cancel(fIdleTimer);
633 thread_call_free(fIdleTimer);
634 fIdleTimer = NULL;
635 }
636 if ( fDriverCallEntry ) {
637 thread_call_free(fDriverCallEntry);
638 fDriverCallEntry = NULL;
639 }
640 if ( fPMLock ) {
641 IOLockFree(fPMLock);
642 fPMLock = NULL;
643 }
644 if ( fActivityLock ) {
645 IOLockFree(fActivityLock);
646 fActivityLock = NULL;
647 }
648 if ( fInterestedDrivers ) {
649 fInterestedDrivers->release();
650 fInterestedDrivers = NULL;
651 }
652 if (fDriverCallParamSlots && fDriverCallParamPtr) {
653 IODelete(fDriverCallParamPtr, DriverCallParam, fDriverCallParamSlots);
654 fDriverCallParamPtr = 0;
655 fDriverCallParamSlots = 0;
656 }
657 if ( fResponseArray ) {
658 fResponseArray->release();
659 fResponseArray = NULL;
660 }
661 if ( fNotifyClientArray ) {
662 fNotifyClientArray->release();
663 fNotifyClientArray = NULL;
664 }
665 if (fPowerStates && fNumberOfPowerStates) {
666 IODelete(fPowerStates, IOPMPSEntry, fNumberOfPowerStates);
667 fNumberOfPowerStates = 0;
668 fPowerStates = NULL;
669 }
670 if (fPowerClients) {
671 fPowerClients->release();
672 fPowerClients = 0;
673 }
674
675 #if PM_VARS_SUPPORT
676 if (fPMVars)
677 {
678 fPMVars->release();
679 fPMVars = 0;
680 }
681 #endif
682
683 pwrMgt->release();
684 pwrMgt = 0;
685 }
686 }
687
688 void IOService::PMDebug( uint32_t event, uintptr_t param1, uintptr_t param2 )
689 {
690 OUR_PMLog(event, param1, param2);
691 }
692
693 //*********************************************************************************
694 // [public] joinPMtree
695 //
696 // A policy-maker calls its nub here when initializing, to be attached into
697 // the power management hierarchy. The default function is to call the
698 // platform expert, which knows how to do it. This method is overridden
699 // by a nub subclass which may either know how to do it, or may need to
700 // take other action.
701 //
702 // This may be the only "power management" method used in a nub,
703 // meaning it may not be initialized for power management.
704 //*********************************************************************************
705
706 void IOService::joinPMtree ( IOService * driver )
707 {
708 IOPlatformExpert * platform;
709
710 platform = getPlatform();
711 assert(platform != 0);
712 platform->PMRegisterDevice(this, driver);
713 }
714
715 #ifndef __LP64__
716 //*********************************************************************************
717 // [deprecated] youAreRoot
718 //
719 // Power Managment is informing us that we are the root power domain.
720 //*********************************************************************************
721
722 IOReturn IOService::youAreRoot ( void )
723 {
724 return IOPMNoErr;
725 }
726 #endif /* !__LP64__ */
727
728 //*********************************************************************************
729 // [public] PMstop
730 //
731 // Immediately stop driver callouts. Schedule an async stop request to detach
732 // from power plane.
733 //*********************************************************************************
734
735 void IOService::PMstop ( void )
736 {
737 IOPMRequest * request;
738
739 if (!initialized)
740 return;
741
742 PM_LOCK();
743
744 if (fLockedFlags.PMStop)
745 {
746 PM_LOG2("%s: PMstop() already stopped\n", fName);
747 PM_UNLOCK();
748 return;
749 }
750
751 // Inhibit future driver calls.
752 fLockedFlags.PMStop = true;
753
754 // Wait for all prior driver calls to finish.
755 waitForPMDriverCall();
756
757 PM_UNLOCK();
758
759 // The rest of the work is performed async.
760 request = acquirePMRequest( this, kIOPMRequestTypePMStop );
761 if (request)
762 {
763 PM_LOG2("%s: %p PMstop\n", getName(), this);
764 submitPMRequest( request );
765 }
766 }
767
768 //*********************************************************************************
769 // [private] handlePMstop
770 //
771 // Disconnect the node from all parents and children in the power plane.
772 //*********************************************************************************
773
774 void IOService::handlePMstop ( IOPMRequest * request )
775 {
776 OSIterator * iter;
777 OSObject * next;
778 IOPowerConnection * connection;
779 IOService * theChild;
780 IOService * theParent;
781
782 PM_ASSERT_IN_GATE();
783 PM_LOG2("%s: %p %s start\n", getName(), this, __FUNCTION__);
784
785 // remove driver from prevent system sleep lists
786 getPMRootDomain()->updatePreventIdleSleepList(this, false);
787 getPMRootDomain()->updatePreventSystemSleepList(this, false);
788
789 // remove the property
790 removeProperty(kPwrMgtKey);
791
792 // detach parents
793 iter = getParentIterator(gIOPowerPlane);
794 if ( iter )
795 {
796 while ( (next = iter->getNextObject()) )
797 {
798 if ( (connection = OSDynamicCast(IOPowerConnection, next)) )
799 {
800 theParent = (IOService *)connection->copyParentEntry(gIOPowerPlane);
801 if ( theParent )
802 {
803 theParent->removePowerChild(connection);
804 theParent->release();
805 }
806 }
807 }
808 iter->release();
809 }
810
811 // detach IOConnections
812 detachAbove( gIOPowerPlane );
813
814 // no more power state changes
815 fParentsKnowState = false;
816
817 // detach children
818 iter = getChildIterator(gIOPowerPlane);
819 if ( iter )
820 {
821 while ( (next = iter->getNextObject()) )
822 {
823 if ( (connection = OSDynamicCast(IOPowerConnection, next)) )
824 {
825 theChild = ((IOService *)(connection->copyChildEntry(gIOPowerPlane)));
826 if ( theChild )
827 {
828 // detach nub from child
829 connection->detachFromChild(theChild, gIOPowerPlane);
830 theChild->release();
831 }
832 // detach us from nub
833 detachFromChild(connection, gIOPowerPlane);
834 }
835 }
836 iter->release();
837 }
838
839 // Remove all interested drivers from the list, including the power
840 // controlling driver.
841 //
842 // Usually, the controlling driver and the policy-maker functionality
843 // are implemented by the same object, and without the deregistration,
844 // the object will be holding an extra retain on itself, and cannot
845 // be freed.
846
847 if ( fInterestedDrivers )
848 {
849 IOPMinformeeList * list = fInterestedDrivers;
850 IOPMinformee * item;
851
852 PM_LOCK();
853 while ((item = list->firstInList()))
854 {
855 list->removeFromList(item->whatObject);
856 }
857 PM_UNLOCK();
858 }
859
860 // Clear idle period to prevent idleTimerExpired() from servicing
861 // idle timer expirations.
862
863 fIdleTimerPeriod = 0;
864 if (fIdleTimer && thread_call_cancel(fIdleTimer))
865 release();
866
867 PM_LOG2("%s: %p %s done\n", getName(), this, __FUNCTION__);
868 }
869
870 //*********************************************************************************
871 // [public] addPowerChild
872 //
873 // Power Management is informing us who our children are.
874 //*********************************************************************************
875
876 IOReturn IOService::addPowerChild ( IOService * child )
877 {
878 IOPowerConnection * connection = 0;
879 IOPMRequest * requests[3] = {0, 0, 0};
880 OSIterator * iter;
881 bool ok = true;
882
883 if (!child)
884 return kIOReturnBadArgument;
885
886 if (!initialized || !child->initialized)
887 return IOPMNotYetInitialized;
888
889 OUR_PMLog( kPMLogAddChild, (uintptr_t) child, 0 );
890
891 do {
892 // Is this child already one of our children?
893
894 iter = child->getParentIterator( gIOPowerPlane );
895 if ( iter )
896 {
897 IORegistryEntry * entry;
898 OSObject * next;
899
900 while ((next = iter->getNextObject()))
901 {
902 if ((entry = OSDynamicCast(IORegistryEntry, next)) &&
903 isChild(entry, gIOPowerPlane))
904 {
905 ok = false;
906 break;
907 }
908 }
909 iter->release();
910 }
911 if (!ok)
912 {
913 PM_LOG("%s: %s (%p) is already a child\n",
914 getName(), child->getName(), child);
915 break;
916 }
917
918 // Add the child to the power plane immediately, but the
919 // joining connection is marked as not ready.
920 // We want the child to appear in the power plane before
921 // returning to the caller, but don't want the caller to
922 // block on the PM work loop.
923
924 connection = new IOPowerConnection;
925 if (!connection)
926 break;
927
928 // Create a chain of PM requests to perform the bottom-half
929 // work from the PM work loop.
930
931 requests[0] = acquirePMRequest(
932 /* target */ this,
933 /* type */ kIOPMRequestTypeAddPowerChild1 );
934
935 requests[1] = acquirePMRequest(
936 /* target */ child,
937 /* type */ kIOPMRequestTypeAddPowerChild2 );
938
939 requests[2] = acquirePMRequest(
940 /* target */ this,
941 /* type */ kIOPMRequestTypeAddPowerChild3 );
942
943 if (!requests[0] || !requests[1] || !requests[2])
944 break;
945
946 requests[0]->attachNextRequest( requests[1] );
947 requests[1]->attachNextRequest( requests[2] );
948
949 connection->init();
950 connection->start(this);
951 connection->setAwaitingAck(false);
952 connection->setReadyFlag(false);
953
954 attachToChild( connection, gIOPowerPlane );
955 connection->attachToChild( child, gIOPowerPlane );
956
957 // connection needs to be released
958 requests[0]->fArg0 = connection;
959 requests[1]->fArg0 = connection;
960 requests[2]->fArg0 = connection;
961
962 submitPMRequest( requests, 3 );
963 return kIOReturnSuccess;
964 }
965 while (false);
966
967 if (connection) connection->release();
968 if (requests[0]) releasePMRequest(requests[0]);
969 if (requests[1]) releasePMRequest(requests[1]);
970 if (requests[2]) releasePMRequest(requests[2]);
971
972 // Silent failure, to prevent platform drivers from adding the child
973 // to the root domain.
974
975 return kIOReturnSuccess;
976 }
977
978 //*********************************************************************************
979 // [private] addPowerChild1
980 //
981 // Step 1/3 of adding a power child. Called on the power parent.
982 //*********************************************************************************
983
984 void IOService::addPowerChild1 ( IOPMRequest * request )
985 {
986 unsigned long tempDesire = 0;
987
988 // Make us temporary usable before adding the child.
989
990 PM_ASSERT_IN_GATE();
991 OUR_PMLog( kPMLogMakeUsable, kPMLogMakeUsable, 0 );
992
993 if (fControllingDriver && inPlane(gIOPowerPlane) && fParentsKnowState)
994 {
995 tempDesire = fNumberOfPowerStates - 1;
996 }
997
998 if (tempDesire && (IS_PM_ROOT || (fMaxPowerState >= tempDesire)))
999 {
1000 adjustPowerState(tempDesire);
1001 }
1002 }
1003
1004 //*********************************************************************************
1005 // [private] addPowerChild2
1006 //
1007 // Step 2/3 of adding a power child. Called on the joining child.
1008 // Execution blocked behind addPowerChild1.
1009 //*********************************************************************************
1010
1011 void IOService::addPowerChild2 ( IOPMRequest * request )
1012 {
1013 IOPowerConnection * connection = (IOPowerConnection *) request->fArg0;
1014 IOService * parent;
1015 IOPMPowerFlags powerFlags;
1016 bool knowsState;
1017 unsigned long powerState;
1018 unsigned long tempDesire;
1019
1020 PM_ASSERT_IN_GATE();
1021 parent = (IOService *) connection->getParentEntry(gIOPowerPlane);
1022
1023 if (!parent || !inPlane(gIOPowerPlane))
1024 {
1025 PM_LOG("%s: addPowerChild2 not in power plane\n", getName());
1026 return;
1027 }
1028
1029 // Parent will be waiting for us to complete this stage.
1030 // It is safe to directly access parent's vars.
1031
1032 knowsState = (parent->fPowerStates) && (parent->fParentsKnowState);
1033 powerState = parent->fCurrentPowerState;
1034
1035 if (knowsState)
1036 powerFlags = parent->fPowerStates[powerState].outputPowerFlags;
1037 else
1038 powerFlags = 0;
1039
1040 // Set our power parent.
1041
1042 OUR_PMLog(kPMLogSetParent, knowsState, powerFlags);
1043
1044 setParentInfo( powerFlags, connection, knowsState );
1045
1046 connection->setReadyFlag(true);
1047
1048 if ( fControllingDriver && fParentsKnowState )
1049 {
1050 fMaxPowerState = fControllingDriver->maxCapabilityForDomainState(fParentsCurrentPowerFlags);
1051 // initially change into the state we are already in
1052 tempDesire = fControllingDriver->initialPowerStateForDomainState(fParentsCurrentPowerFlags);
1053 fPreviousRequestPowerFlags = (IOPMPowerFlags)(-1);
1054 adjustPowerState(tempDesire);
1055 }
1056
1057 getPMRootDomain()->tagPowerPlaneService(this, &fPMActions);
1058 }
1059
1060 //*********************************************************************************
1061 // [private] addPowerChild3
1062 //
1063 // Step 3/3 of adding a power child. Called on the parent.
1064 // Execution blocked behind addPowerChild2.
1065 //*********************************************************************************
1066
1067 void IOService::addPowerChild3 ( IOPMRequest * request )
1068 {
1069 IOPowerConnection * connection = (IOPowerConnection *) request->fArg0;
1070 IOService * child;
1071 IOPMrootDomain * rootDomain = getPMRootDomain();
1072
1073 PM_ASSERT_IN_GATE();
1074 child = (IOService *) connection->getChildEntry(gIOPowerPlane);
1075
1076 if (child && inPlane(gIOPowerPlane))
1077 {
1078 if ((this != rootDomain) && child->getProperty("IOPMStrictTreeOrder"))
1079 {
1080 PM_LOG1("%s: strict PM order enforced\n", getName());
1081 fStrictTreeOrder = true;
1082 }
1083
1084 if (rootDomain)
1085 rootDomain->joinAggressiveness( child );
1086 }
1087 else
1088 {
1089 PM_LOG("%s: addPowerChild3 not in power plane\n", getName());
1090 }
1091
1092 connection->release();
1093 }
1094
1095 #ifndef __LP64__
1096 //*********************************************************************************
1097 // [deprecated] setPowerParent
1098 //
1099 // Power Management is informing us who our parent is.
1100 // If we have a controlling driver, find out, given our newly-informed
1101 // power domain state, what state it would be in, and then tell it
1102 // to assume that state.
1103 //*********************************************************************************
1104
1105 IOReturn IOService::setPowerParent (
1106 IOPowerConnection * theParent, bool stateKnown, IOPMPowerFlags powerFlags )
1107 {
1108 return kIOReturnUnsupported;
1109 }
1110 #endif /* !__LP64__ */
1111
1112 //*********************************************************************************
1113 // [public] removePowerChild
1114 //
1115 // Called on a parent whose child is being removed by PMstop().
1116 //*********************************************************************************
1117
1118 IOReturn IOService::removePowerChild ( IOPowerConnection * theNub )
1119 {
1120 IORegistryEntry * theChild;
1121
1122 PM_ASSERT_IN_GATE();
1123 OUR_PMLog( kPMLogRemoveChild, 0, 0 );
1124
1125 theNub->retain();
1126
1127 // detach nub from child
1128 theChild = theNub->copyChildEntry(gIOPowerPlane);
1129 if ( theChild )
1130 {
1131 theNub->detachFromChild(theChild, gIOPowerPlane);
1132 theChild->release();
1133 }
1134 // detach from the nub
1135 detachFromChild(theNub, gIOPowerPlane);
1136
1137 // Are we awaiting an ack from this child?
1138 if ( theNub->getAwaitingAck() )
1139 {
1140 // yes, pretend we got one
1141 theNub->setAwaitingAck(false);
1142 if (fHeadNotePendingAcks != 0 )
1143 {
1144 // that's one fewer ack to worry about
1145 fHeadNotePendingAcks--;
1146
1147 // is that the last?
1148 if ( fHeadNotePendingAcks == 0 )
1149 {
1150 stop_ack_timer();
1151
1152 // Request unblocked, work queue
1153 // should re-scan all busy requests.
1154 gIOPMWorkQueue->incrementProducerCount();
1155 }
1156 }
1157 }
1158
1159 theNub->release();
1160
1161 // A child has gone away, re-scan children desires and clamp bits.
1162 // The fPendingAdjustPowerRequest helps to reduce redundant parent work.
1163
1164 if (!fAdjustPowerScheduled)
1165 {
1166 IOPMRequest * request;
1167 request = acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState );
1168 if (request)
1169 {
1170 submitPMRequest( request );
1171 fAdjustPowerScheduled = true;
1172 }
1173 }
1174
1175 return IOPMNoErr;
1176 }
1177
1178 //*********************************************************************************
1179 // [public] registerPowerDriver
1180 //
1181 // A driver has called us volunteering to control power to our device.
1182 //*********************************************************************************
1183
1184 IOReturn IOService::registerPowerDriver (
1185 IOService * powerDriver,
1186 IOPMPowerState * powerStates,
1187 unsigned long numberOfStates )
1188 {
1189 IOPMRequest * request;
1190 IOPMPSEntry * powerStatesCopy = 0;
1191
1192 if (!initialized)
1193 return IOPMNotYetInitialized;
1194
1195 // Validate arguments.
1196 if (!powerStates || (numberOfStates < 2))
1197 {
1198 OUR_PMLog(kPMLogControllingDriverErr5, numberOfStates, 0);
1199 return kIOReturnBadArgument;
1200 }
1201
1202 if (!powerDriver || !powerDriver->initialized)
1203 {
1204 OUR_PMLog(kPMLogControllingDriverErr4, 0, 0);
1205 return kIOReturnBadArgument;
1206 }
1207
1208 if (powerStates[0].version != kIOPMPowerStateVersion1)
1209 {
1210 OUR_PMLog(kPMLogControllingDriverErr1, powerStates[0].version, 0);
1211 return kIOReturnBadArgument;
1212 }
1213
1214 do {
1215 // Make a copy of the supplied power state array.
1216 powerStatesCopy = IONew(IOPMPSEntry, numberOfStates);
1217 if (!powerStatesCopy)
1218 break;
1219
1220 for (uint32_t i = 0; i < numberOfStates; i++)
1221 {
1222 powerStatesCopy[i].capabilityFlags = powerStates[i].capabilityFlags;
1223 powerStatesCopy[i].outputPowerFlags = powerStates[i].outputPowerCharacter;
1224 powerStatesCopy[i].inputPowerFlags = powerStates[i].inputPowerRequirement;
1225 powerStatesCopy[i].staticPower = powerStates[i].staticPower;
1226 powerStatesCopy[i].settleUpTime = powerStates[i].settleUpTime;
1227 powerStatesCopy[i].settleDownTime = powerStates[i].settleDownTime;
1228 }
1229
1230 request = acquirePMRequest( this, kIOPMRequestTypeRegisterPowerDriver );
1231 if (!request)
1232 break;
1233
1234 powerDriver->retain();
1235 request->fArg0 = (void *) powerDriver;
1236 request->fArg1 = (void *) powerStatesCopy;
1237 request->fArg2 = (void *) numberOfStates;
1238
1239 submitPMRequest( request );
1240 return kIOReturnSuccess;
1241 }
1242 while (false);
1243
1244 if (powerStatesCopy)
1245 IODelete(powerStatesCopy, IOPMPSEntry, numberOfStates);
1246 return kIOReturnNoMemory;
1247 }
1248
1249 //*********************************************************************************
1250 // [private] handleRegisterPowerDriver
1251 //*********************************************************************************
1252
1253 void IOService::handleRegisterPowerDriver ( IOPMRequest * request )
1254 {
1255 IOService * powerDriver = (IOService *) request->fArg0;
1256 IOPMPSEntry * powerStates = (IOPMPSEntry *) request->fArg1;
1257 unsigned long numberOfStates = (unsigned long) request->fArg2;
1258 unsigned long i;
1259 IOService * root;
1260 OSIterator * iter;
1261
1262 PM_ASSERT_IN_GATE();
1263 assert(powerStates);
1264 assert(powerDriver);
1265 assert(numberOfStates > 1);
1266
1267 if ( !fNumberOfPowerStates )
1268 {
1269 OUR_PMLog(kPMLogControllingDriver,
1270 (unsigned long) numberOfStates,
1271 (unsigned long) kIOPMPowerStateVersion1);
1272
1273 fPowerStates = powerStates;
1274 fNumberOfPowerStates = numberOfStates;
1275 fControllingDriver = powerDriver;
1276 fCurrentCapabilityFlags = fPowerStates[0].capabilityFlags;
1277
1278 // make a mask of all the character bits we know about
1279 fOutputPowerCharacterFlags = 0;
1280 for ( i = 0; i < numberOfStates; i++ ) {
1281 fOutputPowerCharacterFlags |= fPowerStates[i].outputPowerFlags;
1282 if (!fDeviceUsablePowerState &&
1283 (fPowerStates[i].capabilityFlags & IOPMDeviceUsable))
1284 {
1285 // The minimum power state that the device is usable
1286 fDeviceUsablePowerState = i;
1287 }
1288 }
1289
1290 // Register powerDriver as interested, unless already done.
1291 // We don't want to register the default implementation since
1292 // it does nothing. One ramification of not always registering
1293 // is the one fewer retain count held.
1294
1295 root = getPlatform()->getProvider();
1296 assert(root);
1297 if (!root ||
1298 ((OSMemberFunctionCast(void (*)(void),
1299 root, &IOService::powerStateDidChangeTo)) !=
1300 ((OSMemberFunctionCast(void (*)(void),
1301 this, &IOService::powerStateDidChangeTo)))) ||
1302 ((OSMemberFunctionCast(void (*)(void),
1303 root, &IOService::powerStateWillChangeTo)) !=
1304 ((OSMemberFunctionCast(void (*)(void),
1305 this, &IOService::powerStateWillChangeTo)))))
1306 {
1307 if (fInterestedDrivers->findItem(powerDriver) == NULL)
1308 {
1309 PM_LOCK();
1310 fInterestedDrivers->appendNewInformee(powerDriver);
1311 PM_UNLOCK();
1312 }
1313 }
1314
1315 // Examine all existing power clients and perform limit check.
1316
1317 if (fPowerClients)
1318 {
1319 iter = OSCollectionIterator::withCollection(fPowerClients);
1320 if (iter)
1321 {
1322 const OSSymbol * client;
1323 while ((client = (const OSSymbol *) iter->getNextObject()))
1324 {
1325 uint32_t powerState = getPowerStateForClient(client);
1326 if (powerState >= numberOfStates)
1327 {
1328 updatePowerClient(client, numberOfStates - 1);
1329 }
1330 }
1331 iter->release();
1332 }
1333 }
1334
1335 if ( inPlane(gIOPowerPlane) && fParentsKnowState )
1336 {
1337 unsigned long tempDesire;
1338 fMaxPowerState = fControllingDriver->maxCapabilityForDomainState(fParentsCurrentPowerFlags);
1339 // initially change into the state we are already in
1340 tempDesire = fControllingDriver->initialPowerStateForDomainState(fParentsCurrentPowerFlags);
1341 adjustPowerState(tempDesire);
1342 }
1343 }
1344 else
1345 {
1346 OUR_PMLog(kPMLogControllingDriverErr2, numberOfStates, 0);
1347 IODelete(powerStates, IOPMPSEntry, numberOfStates);
1348 }
1349
1350 powerDriver->release();
1351 }
1352
1353 //*********************************************************************************
1354 // [public] registerInterestedDriver
1355 //
1356 // Add the caller to our list of interested drivers and return our current
1357 // power state. If we don't have a power-controlling driver yet, we will
1358 // call this interested driver again later when we do get a driver and find
1359 // out what the current power state of the device is.
1360 //*********************************************************************************
1361
1362 IOPMPowerFlags IOService::registerInterestedDriver ( IOService * driver )
1363 {
1364 IOPMRequest * request;
1365 bool signal;
1366
1367 if (!driver || !initialized || !fInterestedDrivers)
1368 return 0;
1369
1370 PM_LOCK();
1371 signal = (!fInsertInterestSet && !fRemoveInterestSet);
1372 if (fInsertInterestSet == NULL)
1373 fInsertInterestSet = OSSet::withCapacity(4);
1374 if (fInsertInterestSet)
1375 {
1376 fInsertInterestSet->setObject(driver);
1377 if (fRemoveInterestSet)
1378 fRemoveInterestSet->removeObject(driver);
1379 }
1380 PM_UNLOCK();
1381
1382 if (signal)
1383 {
1384 request = acquirePMRequest( this, kIOPMRequestTypeInterestChanged );
1385 if (request)
1386 submitPMRequest( request );
1387 }
1388
1389 // This return value cannot be trusted, but return a value
1390 // for those clients that care.
1391
1392 OUR_PMLog(kPMLogInterestedDriver, kIOPMDeviceUsable, 2);
1393 return kIOPMDeviceUsable;
1394 }
1395
1396 //*********************************************************************************
1397 // [public] deRegisterInterestedDriver
1398 //*********************************************************************************
1399
1400 IOReturn IOService::deRegisterInterestedDriver ( IOService * driver )
1401 {
1402 IOPMinformeeList * list;
1403 IOPMinformee * item;
1404 IOPMRequest * request;
1405 bool signal;
1406
1407 if (!driver)
1408 return kIOReturnBadArgument;
1409 if (!initialized || !fInterestedDrivers)
1410 return IOPMNotPowerManaged;
1411
1412 PM_LOCK();
1413 signal = (!fRemoveInterestSet && !fInsertInterestSet);
1414 if (fRemoveInterestSet == NULL)
1415 fRemoveInterestSet = OSSet::withCapacity(4);
1416 if (fRemoveInterestSet)
1417 {
1418 fRemoveInterestSet->setObject(driver);
1419 if (fInsertInterestSet)
1420 fInsertInterestSet->removeObject(driver);
1421
1422 list = fInterestedDrivers;
1423 item = list->findItem(driver);
1424 if (item && item->active)
1425 {
1426 item->active = false;
1427 waitForPMDriverCall( driver );
1428 }
1429 }
1430 PM_UNLOCK();
1431
1432 if (signal)
1433 {
1434 request = acquirePMRequest( this, kIOPMRequestTypeInterestChanged );
1435 if (request)
1436 submitPMRequest( request );
1437 }
1438
1439 return IOPMNoErr;
1440 }
1441
1442 //*********************************************************************************
1443 // [private] handleInterestChanged
1444 //
1445 // Handle interest added or removed.
1446 //*********************************************************************************
1447
1448 void IOService::handleInterestChanged( IOPMRequest * request )
1449 {
1450 IOService * driver;
1451 IOPMinformee * informee;
1452 IOPMinformeeList * list = fInterestedDrivers;
1453
1454 PM_LOCK();
1455
1456 if (fInsertInterestSet)
1457 {
1458 while ((driver = (IOService *) fInsertInterestSet->getAnyObject()))
1459 {
1460 if (list->findItem(driver) == NULL)
1461 {
1462 informee = list->appendNewInformee(driver);
1463 }
1464 fInsertInterestSet->removeObject(driver);
1465 }
1466 fInsertInterestSet->release();
1467 fInsertInterestSet = 0;
1468 }
1469
1470 if (fRemoveInterestSet)
1471 {
1472 while ((driver = (IOService *) fRemoveInterestSet->getAnyObject()))
1473 {
1474 informee = list->findItem(driver);
1475 if (informee)
1476 {
1477 // Clean-up async interest acknowledgement
1478 if (fHeadNotePendingAcks && informee->timer)
1479 {
1480 informee->timer = 0;
1481 fHeadNotePendingAcks--;
1482 }
1483 list->removeFromList(driver);
1484 }
1485 fRemoveInterestSet->removeObject(driver);
1486 }
1487 fRemoveInterestSet->release();
1488 fRemoveInterestSet = 0;
1489 }
1490
1491 PM_UNLOCK();
1492 }
1493
1494 //*********************************************************************************
1495 // [public] acknowledgePowerChange
1496 //
1497 // After we notified one of the interested drivers or a power-domain child
1498 // of an impending change in power, it has called to say it is now
1499 // prepared for the change. If this object is the last to
1500 // acknowledge this change, we take whatever action we have been waiting
1501 // for.
1502 // That may include acknowledging to our parent. In this case, we do it
1503 // last of all to insure that this doesn't cause the parent to call us some-
1504 // where else and alter data we are relying on here (like the very existance
1505 // of a "current change note".)
1506 //*********************************************************************************
1507
1508 IOReturn IOService::acknowledgePowerChange ( IOService * whichObject )
1509 {
1510 IOPMRequest * request;
1511
1512 if (!initialized)
1513 return IOPMNotYetInitialized;
1514 if (!whichObject)
1515 return kIOReturnBadArgument;
1516
1517 request = acquirePMRequest( this, kIOPMRequestTypeAckPowerChange );
1518 if (!request)
1519 return kIOReturnNoMemory;
1520
1521 whichObject->retain();
1522 request->fArg0 = whichObject;
1523
1524 submitPMRequest( request );
1525 return IOPMNoErr;
1526 }
1527
1528 //*********************************************************************************
1529 // [private] handleAcknowledgePowerChange
1530 //*********************************************************************************
1531
1532 bool IOService::handleAcknowledgePowerChange ( IOPMRequest * request )
1533 {
1534 IOPMinformee * informee;
1535 unsigned long childPower = kIOPMUnknown;
1536 IOService * theChild;
1537 IOService * whichObject;
1538 bool all_acked = false;
1539
1540 PM_ASSERT_IN_GATE();
1541 whichObject = (IOService *) request->fArg0;
1542 assert(whichObject);
1543
1544 // one of our interested drivers?
1545 informee = fInterestedDrivers->findItem( whichObject );
1546 if ( informee == NULL )
1547 {
1548 if ( !isChild(whichObject, gIOPowerPlane) )
1549 {
1550 OUR_PMLog(kPMLogAcknowledgeErr1, 0, 0);
1551 goto no_err;
1552 } else {
1553 OUR_PMLog(kPMLogChildAcknowledge, fHeadNotePendingAcks, 0);
1554 }
1555 } else {
1556 OUR_PMLog(kPMLogDriverAcknowledge, fHeadNotePendingAcks, 0);
1557 }
1558
1559 if ( fHeadNotePendingAcks != 0 )
1560 {
1561 assert(fPowerStates != NULL);
1562
1563 // yes, make sure we're expecting acks
1564 if ( informee != NULL )
1565 {
1566 // it's an interested driver
1567 // make sure we're expecting this ack
1568 if ( informee->timer != 0 )
1569 {
1570 #if LOG_SETPOWER_TIMES
1571 if (informee->timer > 0)
1572 {
1573 uint64_t nsec = computeTimeDeltaNS(&informee->startTime);
1574 if (nsec > LOG_SETPOWER_TIMES)
1575 PM_LOG("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) async took %d ms\n",
1576 informee->whatObject->getName(),
1577 (fDriverCallReason == kDriverCallInformPreChange) ? "Will" : "Did",
1578 informee->whatObject,
1579 fName, fCurrentPowerState, fHeadNotePowerState, NS_TO_US(nsec));
1580
1581 uint16_t logType = (fDriverCallReason == kDriverCallInformPreChange)
1582 ? kIOPMEventTypePSWillChangeTo
1583 : kIOPMEventTypePSDidChangeTo;
1584
1585 PMEventDetails *details = PMEventDetails::eventDetails(
1586 logType,
1587 fName,
1588 (uintptr_t)this,
1589 informee->whatObject->getName(),
1590 0, 0, 0,
1591 NS_TO_MS(nsec));
1592
1593 getPMRootDomain()->recordAndReleasePMEventGated( details );
1594 }
1595 #endif
1596 // mark it acked
1597 informee->timer = 0;
1598 // that's one fewer to worry about
1599 fHeadNotePendingAcks--;
1600 } else {
1601 // this driver has already acked
1602 OUR_PMLog(kPMLogAcknowledgeErr2, 0, 0);
1603 }
1604 } else {
1605 // it's a child
1606 // make sure we're expecting this ack
1607 if ( ((IOPowerConnection *)whichObject)->getAwaitingAck() )
1608 {
1609 // that's one fewer to worry about
1610 fHeadNotePendingAcks--;
1611 ((IOPowerConnection *)whichObject)->setAwaitingAck(false);
1612 theChild = (IOService *)whichObject->copyChildEntry(gIOPowerPlane);
1613 if ( theChild )
1614 {
1615 childPower = theChild->currentPowerConsumption();
1616 theChild->release();
1617 }
1618 if ( childPower == kIOPMUnknown )
1619 {
1620 fHeadNotePowerArrayEntry->staticPower = kIOPMUnknown;
1621 } else {
1622 if (fHeadNotePowerArrayEntry->staticPower != kIOPMUnknown)
1623 {
1624 fHeadNotePowerArrayEntry->staticPower += childPower;
1625 }
1626 }
1627 }
1628 }
1629
1630 if ( fHeadNotePendingAcks == 0 ) {
1631 // yes, stop the timer
1632 stop_ack_timer();
1633 // and now we can continue
1634 all_acked = true;
1635 }
1636 } else {
1637 OUR_PMLog(kPMLogAcknowledgeErr3, 0, 0); // not expecting anybody to ack
1638 }
1639
1640 no_err:
1641 if (whichObject)
1642 whichObject->release();
1643
1644 return all_acked;
1645 }
1646
1647 //*********************************************************************************
1648 // [public] acknowledgeSetPowerState
1649 //
1650 // After we instructed our controlling driver to change power states,
1651 // it has called to say it has finished doing so.
1652 // We continue to process the power state change.
1653 //*********************************************************************************
1654
1655 IOReturn IOService::acknowledgeSetPowerState ( void )
1656 {
1657 IOPMRequest * request;
1658
1659 if (!initialized)
1660 return IOPMNotYetInitialized;
1661
1662 request = acquirePMRequest( this, kIOPMRequestTypeAckSetPowerState );
1663 if (!request)
1664 return kIOReturnNoMemory;
1665
1666 submitPMRequest( request );
1667 return kIOReturnSuccess;
1668 }
1669
1670 //*********************************************************************************
1671 // [private] adjustPowerState
1672 //*********************************************************************************
1673
1674 void IOService::adjustPowerState ( uint32_t clamp )
1675 {
1676 PM_ASSERT_IN_GATE();
1677 computeDesiredState(clamp, false);
1678 if (fControllingDriver && fParentsKnowState && inPlane(gIOPowerPlane))
1679 {
1680 IOPMPowerChangeFlags changeFlags = kIOPMSelfInitiated;
1681
1682 // Indicate that children desires must be ignored, and do not ask
1683 // apps for permission to drop power. This is used by root domain
1684 // for demand sleep.
1685
1686 if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride)
1687 changeFlags |= (kIOPMIgnoreChildren | kIOPMSkipAskPowerDown);
1688
1689 startPowerChange(
1690 /* flags */ changeFlags,
1691 /* power state */ fDesiredPowerState,
1692 /* domain flags */ 0,
1693 /* connection */ 0,
1694 /* parent flags */ 0);
1695 }
1696 }
1697
1698 //*********************************************************************************
1699 // [public] synchronizePowerTree
1700 //*********************************************************************************
1701
1702 IOReturn IOService::synchronizePowerTree (
1703 IOOptionBits options,
1704 IOService * notifyRoot )
1705 {
1706 IOPMRequest * request_c = 0;
1707 IOPMRequest * request_s;
1708
1709 if (this != getPMRootDomain())
1710 return kIOReturnBadArgument;
1711 if (!initialized)
1712 return kIOPMNotYetInitialized;
1713
1714 if (notifyRoot)
1715 {
1716 IOPMRequest * nr;
1717
1718 // Cancels don't need to be synchronized.
1719 nr = acquirePMRequest(notifyRoot, kIOPMRequestTypeChildNotifyDelayCancel);
1720 if (nr) submitPMRequest(nr);
1721 nr = acquirePMRequest(getPMRootDomain(), kIOPMRequestTypeChildNotifyDelayCancel);
1722 if (nr) submitPMRequest(nr);
1723 }
1724
1725 request_s = acquirePMRequest( this, kIOPMRequestTypeSynchronizePowerTree );
1726 if (!request_s)
1727 goto error_no_memory;
1728
1729 if (options & kIOPMSyncCancelPowerDown)
1730 request_c = acquirePMRequest( this, kIOPMRequestTypeIdleCancel );
1731 if (request_c)
1732 {
1733 request_c->attachNextRequest( request_s );
1734 submitPMRequest(request_c);
1735 }
1736
1737 request_s->fArg0 = (void *)(uintptr_t) options;
1738 submitPMRequest(request_s);
1739
1740 return kIOReturnSuccess;
1741
1742 error_no_memory:
1743 if (request_c) releasePMRequest(request_c);
1744 if (request_s) releasePMRequest(request_s);
1745 return kIOReturnNoMemory;
1746 }
1747
1748 //*********************************************************************************
1749 // [private] handleSynchronizePowerTree
1750 //*********************************************************************************
1751
1752 void IOService::handleSynchronizePowerTree ( IOPMRequest * request )
1753 {
1754 PM_ASSERT_IN_GATE();
1755 if (fControllingDriver && fParentsKnowState && inPlane(gIOPowerPlane) &&
1756 (fCurrentPowerState == fNumberOfPowerStates - 1))
1757 {
1758 IOOptionBits options = (uintptr_t) request->fArg0;
1759
1760 startPowerChange(
1761 /* flags */ kIOPMSelfInitiated | kIOPMSynchronize |
1762 (options & kIOPMSyncNoChildNotify),
1763 /* power state */ fCurrentPowerState,
1764 /* domain flags */ 0,
1765 /* connection */ 0,
1766 /* parent flags */ 0);
1767 }
1768 }
1769
1770 #ifndef __LP64__
1771 //*********************************************************************************
1772 // [deprecated] powerDomainWillChangeTo
1773 //
1774 // Called by the power-hierarchy parent notifying of a new power state
1775 // in the power domain.
1776 // We enqueue a parent power-change to our queue of power changes.
1777 // This may or may not cause us to change power, depending on what
1778 // kind of change is occuring in the domain.
1779 //*********************************************************************************
1780
1781 IOReturn IOService::powerDomainWillChangeTo (
1782 IOPMPowerFlags newPowerFlags,
1783 IOPowerConnection * whichParent )
1784 {
1785 assert(false);
1786 return kIOReturnUnsupported;
1787 }
1788 #endif /* !__LP64__ */
1789
1790 //*********************************************************************************
1791 // [private] handlePowerDomainWillChangeTo
1792 //*********************************************************************************
1793
1794 void IOService::handlePowerDomainWillChangeTo ( IOPMRequest * request )
1795 {
1796 IOPMPowerFlags parentPowerFlags = (IOPMPowerFlags) request->fArg0;
1797 IOPowerConnection * whichParent = (IOPowerConnection *) request->fArg1;
1798 IOPMPowerChangeFlags parentChangeFlags = (IOPMPowerChangeFlags)(uintptr_t) request->fArg2;
1799 IOPMPowerChangeFlags myChangeFlags;
1800 OSIterator * iter;
1801 OSObject * next;
1802 IOPowerConnection * connection;
1803 IOPMPowerStateIndex maxPowerState;
1804 IOPMPowerFlags combinedPowerFlags;
1805 bool savedParentsKnowState;
1806 IOReturn result = IOPMAckImplied;
1807
1808 PM_ASSERT_IN_GATE();
1809 OUR_PMLog(kPMLogWillChange, parentPowerFlags, 0);
1810
1811 if (!inPlane(gIOPowerPlane) || !whichParent || !whichParent->getAwaitingAck())
1812 {
1813 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__);
1814 goto exit_no_ack;
1815 }
1816
1817 savedParentsKnowState = fParentsKnowState;
1818
1819 // Combine parents' output power flags.
1820
1821 combinedPowerFlags = 0;
1822
1823 iter = getParentIterator(gIOPowerPlane);
1824 if ( iter )
1825 {
1826 while ( (next = iter->getNextObject()) )
1827 {
1828 if ( (connection = OSDynamicCast(IOPowerConnection, next)) )
1829 {
1830 if ( connection == whichParent )
1831 combinedPowerFlags |= parentPowerFlags;
1832 else
1833 combinedPowerFlags |= connection->parentCurrentPowerFlags();
1834 }
1835 }
1836 iter->release();
1837 }
1838
1839 // If our initial change has yet to occur, then defer the power change
1840 // until after the power domain has completed its power transition.
1841
1842 if ( fControllingDriver && !fInitialPowerChange )
1843 {
1844 maxPowerState = fControllingDriver->maxCapabilityForDomainState(
1845 combinedPowerFlags);
1846
1847 // Use kIOPMSynchronize below instead of kIOPMRootBroadcastFlags
1848 // to avoid propagating the root change flags if any service must
1849 // change power state due to root's will-change notification.
1850 // Root does not change power state for kIOPMSynchronize.
1851
1852 myChangeFlags = kIOPMParentInitiated | kIOPMDomainWillChange |
1853 (parentChangeFlags & kIOPMSynchronize);
1854
1855 result = startPowerChange(
1856 /* flags */ myChangeFlags,
1857 /* power state */ maxPowerState,
1858 /* domain flags */ combinedPowerFlags,
1859 /* connection */ whichParent,
1860 /* parent flags */ parentPowerFlags);
1861 }
1862
1863 // If parent is dropping power, immediately update the parent's
1864 // capability flags. Any future merging of parent(s) combined
1865 // power flags should account for this power drop.
1866
1867 if (parentChangeFlags & kIOPMDomainPowerDrop)
1868 {
1869 setParentInfo(parentPowerFlags, whichParent, true);
1870 }
1871
1872 // Parent is expecting an ACK from us. If we did not embark on a state
1873 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1874 // still required to issue an ACK to our parent.
1875
1876 if (IOPMAckImplied == result)
1877 {
1878 IOService * parent;
1879 parent = (IOService *) whichParent->copyParentEntry(gIOPowerPlane);
1880 assert(parent);
1881 if ( parent )
1882 {
1883 parent->acknowledgePowerChange( whichParent );
1884 parent->release();
1885 }
1886 }
1887
1888 exit_no_ack:
1889 // Drop the retain from notifyChild().
1890 if (whichParent) whichParent->release();
1891 }
1892
1893 #ifndef __LP64__
1894 //*********************************************************************************
1895 // [deprecated] powerDomainDidChangeTo
1896 //
1897 // Called by the power-hierarchy parent after the power state of the power domain
1898 // has settled at a new level.
1899 // We enqueue a parent power-change to our queue of power changes.
1900 // This may or may not cause us to change power, depending on what
1901 // kind of change is occuring in the domain.
1902 //*********************************************************************************
1903
1904 IOReturn IOService::powerDomainDidChangeTo (
1905 IOPMPowerFlags newPowerFlags,
1906 IOPowerConnection * whichParent )
1907 {
1908 assert(false);
1909 return kIOReturnUnsupported;
1910 }
1911 #endif /* !__LP64__ */
1912
1913 //*********************************************************************************
1914 // [private] handlePowerDomainDidChangeTo
1915 //*********************************************************************************
1916
1917 void IOService::handlePowerDomainDidChangeTo ( IOPMRequest * request )
1918 {
1919 IOPMPowerFlags parentPowerFlags = (IOPMPowerFlags) request->fArg0;
1920 IOPowerConnection * whichParent = (IOPowerConnection *) request->fArg1;
1921 IOPMPowerChangeFlags parentChangeFlags = (IOPMPowerChangeFlags)(uintptr_t) request->fArg2;
1922 IOPMPowerChangeFlags myChangeFlags;
1923 IOPMPowerStateIndex maxPowerState;
1924 IOPMPowerStateIndex initialDesire = 0;
1925 bool computeDesire = false;
1926 bool desireChanged = false;
1927 bool savedParentsKnowState;
1928 IOReturn result = IOPMAckImplied;
1929
1930 PM_ASSERT_IN_GATE();
1931 OUR_PMLog(kPMLogDidChange, parentPowerFlags, 0);
1932
1933 if (!inPlane(gIOPowerPlane) || !whichParent || !whichParent->getAwaitingAck())
1934 {
1935 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__);
1936 goto exit_no_ack;
1937 }
1938
1939 savedParentsKnowState = fParentsKnowState;
1940
1941 setParentInfo(parentPowerFlags, whichParent, true);
1942
1943 if ( fControllingDriver )
1944 {
1945 maxPowerState = fControllingDriver->maxCapabilityForDomainState(
1946 fParentsCurrentPowerFlags);
1947
1948 if (fInitialPowerChange)
1949 {
1950 computeDesire = true;
1951 initialDesire = fControllingDriver->initialPowerStateForDomainState(
1952 fParentsCurrentPowerFlags);
1953 }
1954 else if (parentChangeFlags & kIOPMRootChangeUp)
1955 {
1956 if (fAdvisoryTickleUsed)
1957 {
1958 // On system wake, re-compute the desired power state since
1959 // gIOPMAdvisoryTickleEnabled will change for a full wake,
1960 // which is an input to computeDesiredState(). This is not
1961 // necessary for a dark wake because powerChangeDone() will
1962 // handle the dark to full wake case, but it does no harm.
1963
1964 desireChanged = true;
1965 }
1966
1967 if (fResetPowerStateOnWake)
1968 {
1969 // Query the driver for the desired power state on system wake.
1970 // Default implementation returns the lowest power state.
1971
1972 IOPMPowerStateIndex wakePowerState =
1973 fControllingDriver->initialPowerStateForDomainState(
1974 kIOPMRootDomainState | kIOPMPowerOn );
1975
1976 // fDesiredPowerState was adjusted before going to sleep
1977 // with fDeviceDesire at min.
1978
1979 if (wakePowerState > fDesiredPowerState)
1980 {
1981 // Must schedule a power adjustment if we changed the
1982 // device desire. That will update the desired domain
1983 // power on the parent power connection and ping the
1984 // power parent if necessary.
1985
1986 updatePowerClient(gIOPMPowerClientDevice, wakePowerState);
1987 desireChanged = true;
1988 }
1989 }
1990 }
1991
1992 if (computeDesire || desireChanged)
1993 computeDesiredState(initialDesire, false);
1994
1995 // Absorb and propagate parent's broadcast flags
1996 myChangeFlags = kIOPMParentInitiated | kIOPMDomainDidChange |
1997 (parentChangeFlags & kIOPMRootBroadcastFlags);
1998
1999 result = startPowerChange(
2000 /* flags */ myChangeFlags,
2001 /* power state */ maxPowerState,
2002 /* domain flags */ fParentsCurrentPowerFlags,
2003 /* connection */ whichParent,
2004 /* parent flags */ 0);
2005 }
2006
2007 // Parent is expecting an ACK from us. If we did not embark on a state
2008 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
2009 // still required to issue an ACK to our parent.
2010
2011 if (IOPMAckImplied == result)
2012 {
2013 IOService * parent;
2014 parent = (IOService *) whichParent->copyParentEntry(gIOPowerPlane);
2015 assert(parent);
2016 if ( parent )
2017 {
2018 parent->acknowledgePowerChange( whichParent );
2019 parent->release();
2020 }
2021 }
2022
2023 // If the parent registers its power driver late, then this is the
2024 // first opportunity to tell our parent about our desire. Or if the
2025 // child's desire changed during a parent change notify.
2026
2027 if ((!savedParentsKnowState && fParentsKnowState) || desireChanged)
2028 {
2029 PM_LOG1("%s::powerDomainDidChangeTo parentsKnowState %d\n",
2030 getName(), fParentsKnowState);
2031 requestDomainPower( fDesiredPowerState );
2032 }
2033
2034 exit_no_ack:
2035 // Drop the retain from notifyChild().
2036 if (whichParent) whichParent->release();
2037 }
2038
2039 //*********************************************************************************
2040 // [private] setParentInfo
2041 //
2042 // Set our connection data for one specific parent, and then combine all the parent
2043 // data together.
2044 //*********************************************************************************
2045
2046 void IOService::setParentInfo (
2047 IOPMPowerFlags newPowerFlags,
2048 IOPowerConnection * whichParent,
2049 bool knowsState )
2050 {
2051 OSIterator * iter;
2052 OSObject * next;
2053 IOPowerConnection * conn;
2054
2055 PM_ASSERT_IN_GATE();
2056
2057 // set our connection data
2058 whichParent->setParentCurrentPowerFlags(newPowerFlags);
2059 whichParent->setParentKnowsState(knowsState);
2060
2061 // recompute our parent info
2062 fParentsCurrentPowerFlags = 0;
2063 fParentsKnowState = true;
2064
2065 iter = getParentIterator(gIOPowerPlane);
2066 if ( iter )
2067 {
2068 while ( (next = iter->getNextObject()) )
2069 {
2070 if ( (conn = OSDynamicCast(IOPowerConnection, next)) )
2071 {
2072 fParentsKnowState &= conn->parentKnowsState();
2073 fParentsCurrentPowerFlags |= conn->parentCurrentPowerFlags();
2074 }
2075 }
2076 iter->release();
2077 }
2078 }
2079
2080 //******************************************************************************
2081 // [private] trackSystemSleepPreventers
2082 //******************************************************************************
2083
2084 void IOService::trackSystemSleepPreventers(
2085 IOPMPowerStateIndex oldPowerState,
2086 IOPMPowerStateIndex newPowerState,
2087 IOPMPowerChangeFlags changeFlags __unused )
2088 {
2089 IOPMPowerFlags oldCapability, newCapability;
2090
2091 oldCapability = fPowerStates[oldPowerState].capabilityFlags &
2092 (kIOPMPreventIdleSleep | kIOPMPreventSystemSleep);
2093 newCapability = fPowerStates[newPowerState].capabilityFlags &
2094 (kIOPMPreventIdleSleep | kIOPMPreventSystemSleep);
2095
2096 if (fHeadNoteChangeFlags & kIOPMInitialPowerChange)
2097 oldCapability = 0;
2098 if (oldCapability == newCapability)
2099 return;
2100
2101 if ((oldCapability ^ newCapability) & kIOPMPreventIdleSleep)
2102 {
2103 #if SUPPORT_IDLE_CANCEL
2104 if ((oldCapability & kIOPMPreventIdleSleep) == 0)
2105 {
2106 IOPMRequest * cancelRequest;
2107
2108 cancelRequest = acquirePMRequest( getPMRootDomain(), kIOPMRequestTypeIdleCancel );
2109 if (cancelRequest)
2110 {
2111 submitPMRequest( cancelRequest );
2112 }
2113 }
2114 #endif
2115
2116 getPMRootDomain()->updatePreventIdleSleepList(this,
2117 ((oldCapability & kIOPMPreventIdleSleep) == 0));
2118 }
2119
2120 if ((oldCapability ^ newCapability) & kIOPMPreventSystemSleep)
2121 {
2122
2123 getPMRootDomain()->updatePreventSystemSleepList(this,
2124 ((oldCapability & kIOPMPreventSystemSleep) == 0));
2125 }
2126 }
2127
2128 //*********************************************************************************
2129 // [public] requestPowerDomainState
2130 //
2131 // Called on a power parent when a child's power requirement changes.
2132 //*********************************************************************************
2133
2134 IOReturn IOService::requestPowerDomainState(
2135 IOPMPowerFlags childRequestPowerFlags,
2136 IOPowerConnection * childConnection,
2137 unsigned long specification )
2138 {
2139 IOPMPowerStateIndex ps;
2140 IOPMPowerFlags outputPowerFlags;
2141 IOService * child;
2142 IOPMRequest * subRequest;
2143 bool adjustPower = false;
2144
2145 if (!initialized)
2146 return IOPMNotYetInitialized;
2147
2148 if (gIOPMWorkLoop->onThread() == false)
2149 {
2150 PM_LOG("%s::requestPowerDomainState\n", getName());
2151 return kIOReturnSuccess;
2152 }
2153
2154 OUR_PMLog(kPMLogRequestDomain, childRequestPowerFlags, specification);
2155
2156 if (!isChild(childConnection, gIOPowerPlane))
2157 return kIOReturnNotAttached;
2158
2159 if (!fControllingDriver || !fNumberOfPowerStates)
2160 return kIOReturnNotReady;
2161
2162 child = (IOService *) childConnection->getChildEntry(gIOPowerPlane);
2163 assert(child);
2164
2165 // Merge in the power flags contributed by this power parent
2166 // at its current or impending power state.
2167
2168 outputPowerFlags = fPowerStates[fCurrentPowerState].outputPowerFlags;
2169 if (fMachineState != kIOPM_Finished)
2170 {
2171 if (IS_POWER_DROP && !IS_ROOT_DOMAIN)
2172 {
2173 // Use the lower power state when dropping power.
2174 // Must be careful since a power drop can be canceled
2175 // from the following states:
2176 // - kIOPM_OurChangeTellClientsPowerDown
2177 // - kIOPM_OurChangeTellPriorityClientsPowerDown
2178 //
2179 // The child must not wait for this parent to raise power
2180 // if the power drop was cancelled. The solution is to cancel
2181 // the power drop if possible, then schedule an adjustment to
2182 // re-evaluate the parent's power state.
2183 //
2184 // Root domain is excluded to avoid idle sleep issues. And permit
2185 // root domain children to pop up when system is going to sleep.
2186
2187 if ((fMachineState == kIOPM_OurChangeTellClientsPowerDown) ||
2188 (fMachineState == kIOPM_OurChangeTellPriorityClientsPowerDown))
2189 {
2190 fDoNotPowerDown = true; // cancel power drop
2191 adjustPower = true; // schedule an adjustment
2192 PM_LOG1("%s: power drop cancelled in state %u by %s\n",
2193 getName(), fMachineState, child->getName());
2194 }
2195 else
2196 {
2197 // Beyond cancellation point, report the impending state.
2198 outputPowerFlags =
2199 fPowerStates[fHeadNotePowerState].outputPowerFlags;
2200 }
2201 }
2202 else if (IS_POWER_RISE)
2203 {
2204 // When raising power, must report the output power flags from
2205 // child's perspective. A child power request may arrive while
2206 // parent is transitioning upwards. If a request arrives after
2207 // setParentInfo() has already recorded the output power flags
2208 // for the next power state, then using the power supplied by
2209 // fCurrentPowerState is incorrect, and might cause the child
2210 // to wait when it should not.
2211
2212 outputPowerFlags = childConnection->parentCurrentPowerFlags();
2213 }
2214 }
2215 child->fHeadNoteDomainTargetFlags |= outputPowerFlags;
2216
2217 // Map child's requested power flags to one of our power state.
2218
2219 for (ps = 0; ps < fNumberOfPowerStates; ps++)
2220 {
2221 if ((fPowerStates[ps].outputPowerFlags & childRequestPowerFlags) ==
2222 (fOutputPowerCharacterFlags & childRequestPowerFlags))
2223 break;
2224 }
2225 if (ps >= fNumberOfPowerStates)
2226 {
2227 ps = 0; // should never happen
2228 }
2229
2230 // Conditions that warrants a power adjustment on this parent.
2231 // Adjust power will also propagate any changes to the child's
2232 // prevent idle/sleep flags towards the root domain.
2233
2234 if (!childConnection->childHasRequestedPower() ||
2235 (ps != childConnection->getDesiredDomainState()))
2236 adjustPower = true;
2237
2238 #if ENABLE_DEBUG_LOGS
2239 if (adjustPower)
2240 {
2241 PM_LOG("requestPowerDomainState[%s]: %s, init %d, %u->%u\n",
2242 getName(), child->getName(),
2243 !childConnection->childHasRequestedPower(),
2244 (uint32_t) childConnection->getDesiredDomainState(),
2245 (uint32_t) ps);
2246 }
2247 #endif
2248
2249 // Record the child's desires on the connection.
2250 childConnection->setChildHasRequestedPower();
2251 childConnection->setDesiredDomainState( ps );
2252
2253 // Schedule a request to re-evaluate all children desires and
2254 // adjust power state. Submit a request if one wasn't pending,
2255 // or if the current request is part of a call tree.
2256
2257 if (adjustPower && !fDeviceOverrideEnabled &&
2258 (!fAdjustPowerScheduled || gIOPMRequest->getRootRequest()))
2259 {
2260 subRequest = acquirePMRequest(
2261 this, kIOPMRequestTypeAdjustPowerState, gIOPMRequest );
2262 if (subRequest)
2263 {
2264 submitPMRequest( subRequest );
2265 fAdjustPowerScheduled = true;
2266 }
2267 }
2268
2269 return kIOReturnSuccess;
2270 }
2271
2272 //*********************************************************************************
2273 // [public] temporaryPowerClampOn
2274 //
2275 // A power domain wants to clamp its power on till it has children which
2276 // will thendetermine the power domain state.
2277 //
2278 // We enter the highest state until addPowerChild is called.
2279 //*********************************************************************************
2280
2281 IOReturn IOService::temporaryPowerClampOn ( void )
2282 {
2283 return requestPowerState( gIOPMPowerClientChildProxy, kIOPMPowerStateMax );
2284 }
2285
2286 //*********************************************************************************
2287 // [public] makeUsable
2288 //
2289 // Some client of our device is asking that we become usable. Although
2290 // this has not come from a subclassed device object, treat it exactly
2291 // as if it had. In this way, subsequent requests for lower power from
2292 // a subclassed device object will pre-empt this request.
2293 //
2294 // We treat this as a subclass object request to switch to the
2295 // highest power state.
2296 //*********************************************************************************
2297
2298 IOReturn IOService::makeUsable ( void )
2299 {
2300 OUR_PMLog(kPMLogMakeUsable, 0, 0);
2301 return requestPowerState( gIOPMPowerClientDevice, kIOPMPowerStateMax );
2302 }
2303
2304 //*********************************************************************************
2305 // [public] currentCapability
2306 //*********************************************************************************
2307
2308 IOPMPowerFlags IOService::currentCapability ( void )
2309 {
2310 if (!initialized)
2311 return IOPMNotPowerManaged;
2312
2313 return fCurrentCapabilityFlags;
2314 }
2315
2316 //*********************************************************************************
2317 // [public] changePowerStateTo
2318 //
2319 // Called by our power-controlling driver to change power state. The new desired
2320 // power state is computed and compared against the current power state. If those
2321 // power states differ, then a power state change is initiated.
2322 //*********************************************************************************
2323
2324 IOReturn IOService::changePowerStateTo ( unsigned long ordinal )
2325 {
2326 OUR_PMLog(kPMLogChangeStateTo, ordinal, 0);
2327 return requestPowerState( gIOPMPowerClientDriver, ordinal );
2328 }
2329
2330 //*********************************************************************************
2331 // [protected] changePowerStateToPriv
2332 //
2333 // Called by our driver subclass to change power state. The new desired power
2334 // state is computed and compared against the current power state. If those
2335 // power states differ, then a power state change is initiated.
2336 //*********************************************************************************
2337
2338 IOReturn IOService::changePowerStateToPriv ( unsigned long ordinal )
2339 {
2340 OUR_PMLog(kPMLogChangeStateToPriv, ordinal, 0);
2341 return requestPowerState( gIOPMPowerClientDevice, ordinal );
2342 }
2343
2344 //*********************************************************************************
2345 // [protected] changePowerStateWithOverrideTo
2346 //
2347 // Called by our driver subclass to change power state. The new desired power
2348 // state is computed and compared against the current power state. If those
2349 // power states differ, then a power state change is initiated.
2350 // Override enforced - Children and Driver desires are ignored.
2351 //*********************************************************************************
2352
2353 IOReturn IOService::changePowerStateWithOverrideTo ( unsigned long ordinal )
2354 {
2355 IOPMRequest * request;
2356
2357 if (!initialized)
2358 return kIOPMNotYetInitialized;
2359
2360 OUR_PMLog(kPMLogChangeStateToPriv, ordinal, 0);
2361
2362 request = acquirePMRequest( this, kIOPMRequestTypeRequestPowerStateOverride );
2363 if (!request)
2364 return kIOReturnNoMemory;
2365
2366 gIOPMPowerClientDevice->retain();
2367 request->fArg0 = (void *) ordinal;
2368 request->fArg1 = (void *) gIOPMPowerClientDevice;
2369 request->fArg2 = 0;
2370 #if NOT_READY
2371 if (action)
2372 request->installCompletionAction( action, target, param );
2373 #endif
2374
2375 // Prevent needless downwards power transitions by clamping power
2376 // until the scheduled request is executed.
2377
2378 if (gIOPMWorkLoop->inGate() && (ordinal < fNumberOfPowerStates))
2379 {
2380 fTempClampPowerState = max(fTempClampPowerState, ordinal);
2381 fTempClampCount++;
2382 fOverrideMaxPowerState = ordinal;
2383 request->fArg2 = (void *) (uintptr_t) true;
2384 }
2385
2386 submitPMRequest( request );
2387 return IOPMNoErr;
2388 }
2389
2390 //*********************************************************************************
2391 // [private] requestPowerState
2392 //*********************************************************************************
2393
2394 IOReturn IOService::requestPowerState (
2395 const OSSymbol * client,
2396 uint32_t state )
2397 {
2398 IOPMRequest * request;
2399
2400 if (!client)
2401 return kIOReturnBadArgument;
2402 if (!initialized)
2403 return kIOPMNotYetInitialized;
2404
2405 request = acquirePMRequest( this, kIOPMRequestTypeRequestPowerState );
2406 if (!request)
2407 return kIOReturnNoMemory;
2408
2409 client->retain();
2410 request->fArg0 = (void *) state;
2411 request->fArg1 = (void *) client;
2412 request->fArg2 = 0;
2413 #if NOT_READY
2414 if (action)
2415 request->installCompletionAction( action, target, param );
2416 #endif
2417
2418 // Prevent needless downwards power transitions by clamping power
2419 // until the scheduled request is executed.
2420
2421 if (gIOPMWorkLoop->inGate() && (state < fNumberOfPowerStates))
2422 {
2423 fTempClampPowerState = max(fTempClampPowerState, state);
2424 fTempClampCount++;
2425 request->fArg2 = (void *) (uintptr_t) true;
2426 }
2427
2428 submitPMRequest( request );
2429 return IOPMNoErr;
2430 }
2431
2432 //*********************************************************************************
2433 // [private] handleRequestPowerState
2434 //*********************************************************************************
2435
2436 void IOService::handleRequestPowerState ( IOPMRequest * request )
2437 {
2438 const OSSymbol * client = (const OSSymbol *) request->fArg1;
2439 uint32_t state = (uint32_t)(uintptr_t) request->fArg0;
2440
2441 PM_ASSERT_IN_GATE();
2442 if (request->fArg2)
2443 {
2444 assert(fTempClampCount != 0);
2445 if (fTempClampCount) fTempClampCount--;
2446 if (!fTempClampCount) fTempClampPowerState = 0;
2447 }
2448
2449 if (fNumberOfPowerStates && (state >= fNumberOfPowerStates))
2450 state = fNumberOfPowerStates - 1;
2451
2452 // The power suppression due to changePowerStateWithOverrideTo() expires
2453 // upon the next "device" power request - changePowerStateToPriv().
2454
2455 if ((getPMRequestType() != kIOPMRequestTypeRequestPowerStateOverride) &&
2456 (client == gIOPMPowerClientDevice))
2457 fOverrideMaxPowerState = kIOPMPowerStateMax;
2458
2459 if ((state == 0) &&
2460 (client != gIOPMPowerClientDevice) &&
2461 (client != gIOPMPowerClientDriver) &&
2462 (client != gIOPMPowerClientChildProxy))
2463 removePowerClient(client);
2464 else
2465 updatePowerClient(client, state);
2466
2467 adjustPowerState();
2468 client->release();
2469 }
2470
2471 //*********************************************************************************
2472 // [private] Helper functions to update/remove power clients.
2473 //*********************************************************************************
2474
2475 void IOService::updatePowerClient( const OSSymbol * client, uint32_t powerState )
2476 {
2477 if (!fPowerClients)
2478 fPowerClients = OSDictionary::withCapacity(4);
2479 if (fPowerClients && client)
2480 {
2481 OSNumber * num = (OSNumber *) fPowerClients->getObject(client);
2482 if (num)
2483 num->setValue(powerState);
2484 else
2485 {
2486 num = OSNumber::withNumber(powerState, 32);
2487 if (num)
2488 {
2489 fPowerClients->setObject(client, num);
2490 num->release();
2491 }
2492 }
2493 }
2494 }
2495
2496 void IOService::removePowerClient( const OSSymbol * client )
2497 {
2498 if (fPowerClients && client)
2499 fPowerClients->removeObject(client);
2500 }
2501
2502 uint32_t IOService::getPowerStateForClient( const OSSymbol * client )
2503 {
2504 uint32_t powerState = 0;
2505
2506 if (fPowerClients && client)
2507 {
2508 OSNumber * num = (OSNumber *) fPowerClients->getObject(client);
2509 if (num) powerState = num->unsigned32BitValue();
2510 }
2511 return powerState;
2512 }
2513
2514 //*********************************************************************************
2515 // [protected] powerOverrideOnPriv
2516 //*********************************************************************************
2517
2518 IOReturn IOService::powerOverrideOnPriv ( void )
2519 {
2520 IOPMRequest * request;
2521
2522 if (!initialized)
2523 return IOPMNotYetInitialized;
2524
2525 if (gIOPMWorkLoop->inGate())
2526 {
2527 fDeviceOverrideEnabled = true;
2528 return IOPMNoErr;
2529 }
2530
2531 request = acquirePMRequest( this, kIOPMRequestTypePowerOverrideOnPriv );
2532 if (!request)
2533 return kIOReturnNoMemory;
2534
2535 submitPMRequest( request );
2536 return IOPMNoErr;
2537 }
2538
2539 //*********************************************************************************
2540 // [protected] powerOverrideOffPriv
2541 //*********************************************************************************
2542
2543 IOReturn IOService::powerOverrideOffPriv ( void )
2544 {
2545 IOPMRequest * request;
2546
2547 if (!initialized)
2548 return IOPMNotYetInitialized;
2549
2550 if (gIOPMWorkLoop->inGate())
2551 {
2552 fDeviceOverrideEnabled = false;
2553 return IOPMNoErr;
2554 }
2555
2556 request = acquirePMRequest( this, kIOPMRequestTypePowerOverrideOffPriv );
2557 if (!request)
2558 return kIOReturnNoMemory;
2559
2560 submitPMRequest( request );
2561 return IOPMNoErr;
2562 }
2563
2564 //*********************************************************************************
2565 // [private] handlePowerOverrideChanged
2566 //*********************************************************************************
2567
2568 void IOService::handlePowerOverrideChanged ( IOPMRequest * request )
2569 {
2570 PM_ASSERT_IN_GATE();
2571 if (request->getType() == kIOPMRequestTypePowerOverrideOnPriv)
2572 {
2573 OUR_PMLog(kPMLogOverrideOn, 0, 0);
2574 fDeviceOverrideEnabled = true;
2575 }
2576 else
2577 {
2578 OUR_PMLog(kPMLogOverrideOff, 0, 0);
2579 fDeviceOverrideEnabled = false;
2580 }
2581
2582 adjustPowerState();
2583 }
2584
2585 //*********************************************************************************
2586 // [private] computeDesiredState
2587 //*********************************************************************************
2588
2589 void IOService::computeDesiredState( unsigned long localClamp, bool computeOnly )
2590 {
2591 OSIterator * iter;
2592 OSObject * next;
2593 IOPowerConnection * connection;
2594 uint32_t desiredState = 0;
2595 uint32_t newPowerState = 0;
2596 bool hasChildren = false;
2597
2598 // Desired power state is always 0 without a controlling driver.
2599
2600 if (!fNumberOfPowerStates)
2601 {
2602 fDesiredPowerState = 0;
2603 //PM_LOG("%s::%s no controlling driver\n", getName(), __FUNCTION__);
2604 return;
2605 }
2606
2607 // Examine the children's desired power state.
2608
2609 iter = getChildIterator(gIOPowerPlane);
2610 if (iter)
2611 {
2612 while ((next = iter->getNextObject()))
2613 {
2614 if ((connection = OSDynamicCast(IOPowerConnection, next)))
2615 {
2616 if (connection->getReadyFlag() == false)
2617 {
2618 PM_LOG3("[%s] %s: connection not ready\n",
2619 getName(), __FUNCTION__);
2620 continue;
2621 }
2622 if (connection->childHasRequestedPower())
2623 hasChildren = true;
2624 if (connection->getDesiredDomainState() > desiredState)
2625 desiredState = connection->getDesiredDomainState();
2626 }
2627 }
2628 iter->release();
2629 }
2630 if (hasChildren)
2631 updatePowerClient(gIOPMPowerClientChildren, desiredState);
2632 else
2633 removePowerClient(gIOPMPowerClientChildren);
2634
2635 // Iterate through all power clients to determine the min power state.
2636
2637 iter = OSCollectionIterator::withCollection(fPowerClients);
2638 if (iter)
2639 {
2640 const OSSymbol * client;
2641 while ((client = (const OSSymbol *) iter->getNextObject()))
2642 {
2643 // Ignore child and driver when override is in effect.
2644 if ((fDeviceOverrideEnabled ||
2645 (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride)) &&
2646 ((client == gIOPMPowerClientChildren) ||
2647 (client == gIOPMPowerClientDriver)))
2648 continue;
2649
2650 // Ignore child proxy when children are present.
2651 if (hasChildren && (client == gIOPMPowerClientChildProxy))
2652 continue;
2653
2654 // Advisory tickles are irrelevant unless system is in full wake
2655 if (client == gIOPMPowerClientAdvisoryTickle &&
2656 !gIOPMAdvisoryTickleEnabled)
2657 continue;
2658
2659 desiredState = getPowerStateForClient(client);
2660 assert(desiredState < fNumberOfPowerStates);
2661 PM_LOG1(" %u %s\n",
2662 desiredState, client->getCStringNoCopy());
2663
2664 newPowerState = max(newPowerState, desiredState);
2665
2666 if (client == gIOPMPowerClientDevice)
2667 fDeviceDesire = desiredState;
2668 }
2669 iter->release();
2670 }
2671
2672 // Factor in the temporary power desires.
2673
2674 newPowerState = max(newPowerState, localClamp);
2675 newPowerState = max(newPowerState, fTempClampPowerState);
2676
2677 // Limit check against max power override.
2678
2679 newPowerState = min(newPowerState, fOverrideMaxPowerState);
2680
2681 // Limit check against number of power states.
2682
2683 if (newPowerState >= fNumberOfPowerStates)
2684 newPowerState = fNumberOfPowerStates - 1;
2685
2686 fDesiredPowerState = newPowerState;
2687
2688 PM_LOG1(" temp %u, clamp %u, current %u, new %u\n",
2689 (uint32_t) localClamp, (uint32_t) fTempClampPowerState,
2690 (uint32_t) fCurrentPowerState, newPowerState);
2691
2692 if (!computeOnly)
2693 {
2694 // Restart idle timer if possible when device desire has increased.
2695 // Or if an advisory desire exists.
2696
2697 if (fIdleTimerPeriod && fIdleTimerStopped)
2698 {
2699 restartIdleTimer();
2700 }
2701
2702 // Invalidate cached tickle power state when desires change, and not
2703 // due to a tickle request. In case the driver has requested a lower
2704 // power state, but the tickle is caching a higher power state which
2705 // will drop future tickles until the cached value is lowered or in-
2706 // validated. The invalidation must occur before the power transition
2707 // to avoid dropping a necessary tickle.
2708
2709 if ((getPMRequestType() != kIOPMRequestTypeActivityTickle) &&
2710 (fActivityTicklePowerState != kInvalidTicklePowerState))
2711 {
2712 IOLockLock(fActivityLock);
2713 fActivityTicklePowerState = kInvalidTicklePowerState;
2714 IOLockUnlock(fActivityLock);
2715 }
2716 }
2717 }
2718
2719 //*********************************************************************************
2720 // [public] currentPowerConsumption
2721 //
2722 //*********************************************************************************
2723
2724 unsigned long IOService::currentPowerConsumption ( void )
2725 {
2726 if (!initialized)
2727 return kIOPMUnknown;
2728
2729 return fCurrentPowerConsumption;
2730 }
2731
2732 //*********************************************************************************
2733 // [deprecated] getPMworkloop
2734 //*********************************************************************************
2735
2736 IOWorkLoop * IOService::getPMworkloop ( void )
2737 {
2738 return gIOPMWorkLoop;
2739 }
2740
2741 #if NOT_YET
2742
2743 //*********************************************************************************
2744 // Power Parent/Children Applier
2745 //*********************************************************************************
2746
2747 static void
2748 applyToPowerChildren(
2749 IOService * service,
2750 IOServiceApplierFunction applier,
2751 void * context,
2752 IOOptionBits options )
2753 {
2754 PM_ASSERT_IN_GATE();
2755
2756 IORegistryEntry * entry;
2757 IORegistryIterator * iter;
2758 IOPowerConnection * connection;
2759 IOService * child;
2760
2761 iter = IORegistryIterator::iterateOver(service, gIOPowerPlane, options);
2762 if (iter)
2763 {
2764 while ((entry = iter->getNextObject()))
2765 {
2766 // Get child of IOPowerConnection objects
2767 if ((connection = OSDynamicCast(IOPowerConnection, entry)))
2768 {
2769 child = (IOService *) connection->copyChildEntry(gIOPowerPlane);
2770 if (child)
2771 {
2772 (*applier)(child, context);
2773 child->release();
2774 }
2775 }
2776 }
2777 iter->release();
2778 }
2779 }
2780
2781 static void
2782 applyToPowerParent(
2783 IOService * service,
2784 IOServiceApplierFunction applier,
2785 void * context,
2786 IOOptionBits options )
2787 {
2788 PM_ASSERT_IN_GATE();
2789
2790 IORegistryEntry * entry;
2791 IORegistryIterator * iter;
2792 IOPowerConnection * connection;
2793 IOService * parent;
2794
2795 iter = IORegistryIterator::iterateOver(service, gIOPowerPlane,
2796 options | kIORegistryIterateParents);
2797 if (iter)
2798 {
2799 while ((entry = iter->getNextObject()))
2800 {
2801 // Get child of IOPowerConnection objects
2802 if ((connection = OSDynamicCast(IOPowerConnection, entry)))
2803 {
2804 parent = (IOService *) connection->copyParentEntry(gIOPowerPlane);
2805 if (parent)
2806 {
2807 (*applier)(parent, context);
2808 parent->release();
2809 }
2810 }
2811 }
2812 iter->release();
2813 }
2814 }
2815
2816 #endif /* NOT_YET */
2817
2818 // MARK: -
2819 // MARK: Activity Tickle & Idle Timer
2820
2821 void IOService::setAdvisoryTickleEnable( bool enable )
2822 {
2823 gIOPMAdvisoryTickleEnabled = enable;
2824 }
2825
2826 //*********************************************************************************
2827 // [public] activityTickle
2828 //
2829 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
2830 // flag to be set, and the device state checked. If the device has been
2831 // powered down, it is powered up again.
2832 // The tickle with parameter kIOPMSubclassPolicy is ignored here and
2833 // should be intercepted by a subclass.
2834 //*********************************************************************************
2835
2836 bool IOService::activityTickle ( unsigned long type, unsigned long stateNumber )
2837 {
2838 IOPMRequest * request;
2839 bool noPowerChange = true;
2840 uint32_t tickleFlags;
2841
2842 if (!initialized)
2843 return true; // no power change
2844
2845 if ((type == kIOPMSuperclassPolicy1) && stateNumber)
2846 {
2847 IOLockLock(fActivityLock);
2848
2849 // Record device activity for the idle timer handler.
2850
2851 fDeviceWasActive = true;
2852 fActivityTickleCount++;
2853 clock_get_uptime(&fDeviceActiveTimestamp);
2854
2855 PM_ACTION_0(actionActivityTickle);
2856
2857 // Record the last tickle power state.
2858 // This helps to filter out redundant tickles as
2859 // this function may be called from the data path.
2860
2861 if (fActivityTicklePowerState < (int)stateNumber)
2862 {
2863 fActivityTicklePowerState = stateNumber;
2864 noPowerChange = false;
2865
2866 tickleFlags = kTickleTypeActivity | kTickleTypePowerRise;
2867 request = acquirePMRequest( this, kIOPMRequestTypeActivityTickle );
2868 if (request)
2869 {
2870 request->fArg0 = (void *) stateNumber;
2871 request->fArg1 = (void *) tickleFlags;
2872 request->fArg2 = (void *) gIOPMTickleGeneration;
2873 submitPMRequest(request);
2874 }
2875 }
2876
2877 IOLockUnlock(fActivityLock);
2878 }
2879
2880 else if ((type == kIOPMActivityTickleTypeAdvisory) &&
2881 ((stateNumber = fDeviceUsablePowerState)))
2882 {
2883 IOLockLock(fActivityLock);
2884
2885 fAdvisoryTickled = true;
2886
2887 if (fAdvisoryTicklePowerState != (int)stateNumber)
2888 {
2889 fAdvisoryTicklePowerState = stateNumber;
2890 noPowerChange = false;
2891
2892 tickleFlags = kTickleTypeAdvisory | kTickleTypePowerRise;
2893 request = acquirePMRequest( this, kIOPMRequestTypeActivityTickle );
2894 if (request)
2895 {
2896 request->fArg0 = (void *) stateNumber;
2897 request->fArg1 = (void *) tickleFlags;
2898 request->fArg2 = (void *) gIOPMTickleGeneration;
2899 submitPMRequest(request);
2900 }
2901 }
2902
2903 IOLockUnlock(fActivityLock);
2904 }
2905
2906 // Returns false if the activityTickle might cause a transition to a
2907 // higher powered state, true otherwise.
2908
2909 return noPowerChange;
2910 }
2911
2912 //*********************************************************************************
2913 // [private] handleActivityTickle
2914 //*********************************************************************************
2915
2916 void IOService::handleActivityTickle ( IOPMRequest * request )
2917 {
2918 uint32_t ticklePowerState = (uint32_t)(uintptr_t) request->fArg0;
2919 uint32_t tickleFlags = (uint32_t)(uintptr_t) request->fArg1;
2920 uint32_t tickleGeneration = (uint32_t)(uintptr_t) request->fArg2;
2921 bool adjustPower = false;
2922
2923 PM_ASSERT_IN_GATE();
2924 if (fResetPowerStateOnWake && (tickleGeneration != gIOPMTickleGeneration))
2925 {
2926 // Drivers that don't want power restored on wake will drop any
2927 // tickles that pre-dates the current system wake. The model is
2928 // that each wake is a fresh start, with power state depressed
2929 // until a new tickle or an explicit power up request from the
2930 // driver. It is possible for the PM work loop to enter the
2931 // system sleep path with tickle requests queued.
2932
2933 return;
2934 }
2935
2936 if (tickleFlags & kTickleTypeActivity)
2937 {
2938 if (tickleFlags & kTickleTypePowerRise)
2939 {
2940 if ((ticklePowerState > fDeviceDesire) &&
2941 (ticklePowerState < fNumberOfPowerStates))
2942 {
2943 fIdleTimerMinPowerState = ticklePowerState;
2944 updatePowerClient(gIOPMPowerClientDevice, ticklePowerState);
2945 adjustPower = true;
2946 }
2947 }
2948 else if (fDeviceDesire > fIdleTimerMinPowerState)
2949 {
2950 // Power drop due to idle timer expiration.
2951 // Do not allow idle timer to reduce power below tickle power.
2952 // This prevents the idle timer from decreasing the device desire
2953 // to zero and cancelling the effect of a pre-sleep tickle when
2954 // system wakes up to doze state, while the device is unable to
2955 // raise its power state to satisfy the tickle.
2956
2957 ticklePowerState = fDeviceDesire - 1;
2958 updatePowerClient(gIOPMPowerClientDevice, ticklePowerState);
2959 adjustPower = true;
2960 }
2961 }
2962 else // advisory tickle
2963 {
2964 if (tickleFlags & kTickleTypePowerRise)
2965 {
2966 if ((ticklePowerState == fDeviceUsablePowerState) &&
2967 (ticklePowerState < fNumberOfPowerStates))
2968 {
2969 updatePowerClient(gIOPMPowerClientAdvisoryTickle, ticklePowerState);
2970 fHasAdvisoryDesire = true;
2971 fAdvisoryTickleUsed = true;
2972 adjustPower = true;
2973 }
2974 else
2975 {
2976 IOLockLock(fActivityLock);
2977 fAdvisoryTicklePowerState = kInvalidTicklePowerState;
2978 IOLockUnlock(fActivityLock);
2979 }
2980 }
2981 else if (fHasAdvisoryDesire)
2982 {
2983 removePowerClient(gIOPMPowerClientAdvisoryTickle);
2984 fHasAdvisoryDesire = false;
2985 adjustPower = true;
2986 }
2987 }
2988
2989 if (adjustPower)
2990 {
2991 adjustPowerState();
2992 }
2993 }
2994
2995 //******************************************************************************
2996 // [public] setIdleTimerPeriod
2997 //
2998 // A subclass policy-maker is using our standard idleness detection service.
2999 // Start the idle timer. Period is in seconds.
3000 //******************************************************************************
3001
3002 IOReturn IOService::setIdleTimerPeriod ( unsigned long period )
3003 {
3004 if (!initialized)
3005 return IOPMNotYetInitialized;
3006
3007 OUR_PMLog(kPMLogSetIdleTimerPeriod, period, fIdleTimerPeriod);
3008
3009 IOPMRequest * request =
3010 acquirePMRequest( this, kIOPMRequestTypeSetIdleTimerPeriod );
3011 if (!request)
3012 return kIOReturnNoMemory;
3013
3014 request->fArg0 = (void *) period;
3015 submitPMRequest( request );
3016
3017 return kIOReturnSuccess;
3018 }
3019
3020 IOReturn IOService::setIgnoreIdleTimer( bool ignore )
3021 {
3022 if (!initialized)
3023 return IOPMNotYetInitialized;
3024
3025 OUR_PMLog(kIOPMRequestTypeIgnoreIdleTimer, ignore, 0);
3026
3027 IOPMRequest * request =
3028 acquirePMRequest( this, kIOPMRequestTypeIgnoreIdleTimer );
3029 if (!request)
3030 return kIOReturnNoMemory;
3031
3032 request->fArg0 = (void *) ignore;
3033 submitPMRequest( request );
3034
3035 return kIOReturnSuccess;
3036 }
3037
3038 //******************************************************************************
3039 // [public] nextIdleTimeout
3040 //
3041 // Returns how many "seconds from now" the device should idle into its
3042 // next lowest power state.
3043 //******************************************************************************
3044
3045 SInt32 IOService::nextIdleTimeout(
3046 AbsoluteTime currentTime,
3047 AbsoluteTime lastActivity,
3048 unsigned int powerState)
3049 {
3050 AbsoluteTime delta;
3051 UInt64 delta_ns;
3052 SInt32 delta_secs;
3053 SInt32 delay_secs;
3054
3055 // Calculate time difference using funky macro from clock.h.
3056 delta = currentTime;
3057 SUB_ABSOLUTETIME(&delta, &lastActivity);
3058
3059 // Figure it in seconds.
3060 absolutetime_to_nanoseconds(delta, &delta_ns);
3061 delta_secs = (SInt32)(delta_ns / NSEC_PER_SEC);
3062
3063 // Be paranoid about delta somehow exceeding timer period.
3064 if (delta_secs < (int) fIdleTimerPeriod)
3065 delay_secs = (int) fIdleTimerPeriod - delta_secs;
3066 else
3067 delay_secs = (int) fIdleTimerPeriod;
3068
3069 return (SInt32)delay_secs;
3070 }
3071
3072 //*********************************************************************************
3073 // [public] start_PM_idle_timer
3074 //*********************************************************************************
3075
3076 void IOService::start_PM_idle_timer ( void )
3077 {
3078 static const int maxTimeout = 100000;
3079 static const int minTimeout = 1;
3080 AbsoluteTime uptime, deadline;
3081 SInt32 idle_in = 0;
3082 boolean_t pending;
3083
3084 if (!initialized || !fIdleTimerPeriod)
3085 return;
3086
3087 IOLockLock(fActivityLock);
3088
3089 clock_get_uptime(&uptime);
3090
3091 // Subclasses may modify idle sleep algorithm
3092 idle_in = nextIdleTimeout(uptime, fDeviceActiveTimestamp, fCurrentPowerState);
3093
3094 // Check for out-of range responses
3095 if (idle_in > maxTimeout)
3096 {
3097 // use standard implementation
3098 idle_in = IOService::nextIdleTimeout(uptime,
3099 fDeviceActiveTimestamp,
3100 fCurrentPowerState);
3101 } else if (idle_in < minTimeout) {
3102 idle_in = fIdleTimerPeriod;
3103 }
3104
3105 IOLockUnlock(fActivityLock);
3106
3107 retain();
3108 clock_interval_to_absolutetime_interval(idle_in, kSecondScale, &deadline);
3109 ADD_ABSOLUTETIME(&deadline, &uptime);
3110 pending = thread_call_enter_delayed(fIdleTimer, deadline);
3111 if (pending) release();
3112 }
3113
3114 //*********************************************************************************
3115 // [private] restartIdleTimer
3116 //*********************************************************************************
3117
3118 void IOService::restartIdleTimer( void )
3119 {
3120 if (fDeviceDesire != 0)
3121 {
3122 fIdleTimerStopped = false;
3123 fActivityTickleCount = 0;
3124 clock_get_uptime(&fIdleTimerStartTime);
3125 start_PM_idle_timer();
3126 }
3127 else if (fHasAdvisoryDesire)
3128 {
3129 fIdleTimerStopped = false;
3130 start_PM_idle_timer();
3131 }
3132 else
3133 {
3134 fIdleTimerStopped = true;
3135 }
3136 }
3137
3138 //*********************************************************************************
3139 // idle_timer_expired
3140 //*********************************************************************************
3141
3142 static void
3143 idle_timer_expired (
3144 thread_call_param_t arg0, thread_call_param_t arg1 )
3145 {
3146 IOService * me = (IOService *) arg0;
3147
3148 if (gIOPMWorkLoop)
3149 gIOPMWorkLoop->runAction(
3150 OSMemberFunctionCast(IOWorkLoop::Action, me,
3151 &IOService::idleTimerExpired),
3152 me);
3153
3154 me->release();
3155 }
3156
3157 //*********************************************************************************
3158 // [private] idleTimerExpired
3159 //
3160 // The idle timer has expired. If there has been activity since the last
3161 // expiration, just restart the timer and return. If there has not been
3162 // activity, switch to the next lower power state and restart the timer.
3163 //*********************************************************************************
3164
3165 void IOService::idleTimerExpired( void )
3166 {
3167 IOPMRequest * request;
3168 bool restartTimer = true;
3169 uint32_t tickleFlags;
3170
3171 if ( !initialized || !fIdleTimerPeriod || fIdleTimerStopped ||
3172 fLockedFlags.PMStop )
3173 return;
3174
3175 IOLockLock(fActivityLock);
3176
3177 // Check for device activity (tickles) over last timer period.
3178
3179 if (fDeviceWasActive)
3180 {
3181 // Device was active - do not drop power, restart timer.
3182 fDeviceWasActive = false;
3183 }
3184 else if (!fIdleTimerIgnored)
3185 {
3186 // No device activity - drop power state by one level.
3187 // Decrement the cached tickle power state when possible.
3188 // This value may be (-1) before activityTickle() is called,
3189 // but the power drop request must be issued regardless.
3190
3191 if (fActivityTicklePowerState > 0)
3192 fActivityTicklePowerState--;
3193
3194 tickleFlags = kTickleTypeActivity | kTickleTypePowerDrop;
3195 request = acquirePMRequest( this, kIOPMRequestTypeActivityTickle );
3196 if (request)
3197 {
3198 request->fArg0 = (void *) 0; // irrelevant
3199 request->fArg1 = (void *) tickleFlags;
3200 request->fArg2 = (void *) gIOPMTickleGeneration;
3201 submitPMRequest( request );
3202
3203 // Do not restart timer until after the tickle request has been
3204 // processed.
3205
3206 restartTimer = false;
3207 }
3208 }
3209
3210 if (fAdvisoryTickled)
3211 {
3212 fAdvisoryTickled = false;
3213 }
3214 else if (fHasAdvisoryDesire)
3215 {
3216 // Want new tickles to turn into pm request after we drop the lock
3217 fAdvisoryTicklePowerState = kInvalidTicklePowerState;
3218
3219 tickleFlags = kTickleTypeAdvisory | kTickleTypePowerDrop;
3220 request = acquirePMRequest( this, kIOPMRequestTypeActivityTickle );
3221 if (request)
3222 {
3223 request->fArg0 = (void *) 0; // irrelevant
3224 request->fArg1 = (void *) tickleFlags;
3225 request->fArg2 = (void *) gIOPMTickleGeneration;
3226 submitPMRequest( request );
3227
3228 // Do not restart timer until after the tickle request has been
3229 // processed.
3230
3231 restartTimer = false;
3232 }
3233 }
3234
3235 IOLockUnlock(fActivityLock);
3236
3237 if (restartTimer)
3238 start_PM_idle_timer();
3239 }
3240
3241 #ifndef __LP64__
3242 //*********************************************************************************
3243 // [deprecated] PM_idle_timer_expiration
3244 //*********************************************************************************
3245
3246 void IOService::PM_idle_timer_expiration ( void )
3247 {
3248 }
3249
3250 //*********************************************************************************
3251 // [deprecated] command_received
3252 //*********************************************************************************
3253
3254 void IOService::command_received ( void *statePtr , void *, void * , void * )
3255 {
3256 }
3257 #endif /* !__LP64__ */
3258
3259 //*********************************************************************************
3260 // [public] setAggressiveness
3261 //
3262 // Pass on the input parameters to all power domain children. All those which are
3263 // power domains will pass it on to their children, etc.
3264 //*********************************************************************************
3265
3266 IOReturn IOService::setAggressiveness ( unsigned long type, unsigned long newLevel )
3267 {
3268 return kIOReturnSuccess;
3269 }
3270
3271 //*********************************************************************************
3272 // [public] getAggressiveness
3273 //
3274 // Called by the user client.
3275 //*********************************************************************************
3276
3277 IOReturn IOService::getAggressiveness ( unsigned long type, unsigned long * currentLevel )
3278 {
3279 IOPMrootDomain * rootDomain = getPMRootDomain();
3280
3281 if (!rootDomain)
3282 return kIOReturnNotReady;
3283
3284 return rootDomain->getAggressiveness( type, currentLevel );
3285 }
3286
3287 //*********************************************************************************
3288 // [public] getPowerState
3289 //
3290 //*********************************************************************************
3291
3292 UInt32 IOService::getPowerState ( void )
3293 {
3294 if (!initialized)
3295 return 0;
3296
3297 return fCurrentPowerState;
3298 }
3299
3300 #ifndef __LP64__
3301 //*********************************************************************************
3302 // [deprecated] systemWake
3303 //
3304 // Pass this to all power domain children. All those which are
3305 // power domains will pass it on to their children, etc.
3306 //*********************************************************************************
3307
3308 IOReturn IOService::systemWake ( void )
3309 {
3310 OSIterator * iter;
3311 OSObject * next;
3312 IOPowerConnection * connection;
3313 IOService * theChild;
3314
3315 iter = getChildIterator(gIOPowerPlane);
3316 if ( iter )
3317 {
3318 while ( (next = iter->getNextObject()) )
3319 {
3320 if ( (connection = OSDynamicCast(IOPowerConnection, next)) )
3321 {
3322 if (connection->getReadyFlag() == false)
3323 {
3324 PM_LOG3("[%s] %s: connection not ready\n",
3325 getName(), __FUNCTION__);
3326 continue;
3327 }
3328
3329 theChild = (IOService *)connection->copyChildEntry(gIOPowerPlane);
3330 if ( theChild )
3331 {
3332 theChild->systemWake();
3333 theChild->release();
3334 }
3335 }
3336 }
3337 iter->release();
3338 }
3339
3340 if ( fControllingDriver != NULL )
3341 {
3342 if ( fControllingDriver->didYouWakeSystem() )
3343 {
3344 makeUsable();
3345 }
3346 }
3347
3348 return IOPMNoErr;
3349 }
3350
3351 //*********************************************************************************
3352 // [deprecated] temperatureCriticalForZone
3353 //*********************************************************************************
3354
3355 IOReturn IOService::temperatureCriticalForZone ( IOService * whichZone )
3356 {
3357 IOService * theParent;
3358 IOService * theNub;
3359
3360 OUR_PMLog(kPMLogCriticalTemp, 0, 0);
3361
3362 if ( inPlane(gIOPowerPlane) && !IS_PM_ROOT )
3363 {
3364 theNub = (IOService *)copyParentEntry(gIOPowerPlane);
3365 if ( theNub )
3366 {
3367 theParent = (IOService *)theNub->copyParentEntry(gIOPowerPlane);
3368 theNub->release();
3369 if ( theParent )
3370 {
3371 theParent->temperatureCriticalForZone(whichZone);
3372 theParent->release();
3373 }
3374 }
3375 }
3376 return IOPMNoErr;
3377 }
3378 #endif /* !__LP64__ */
3379
3380 // MARK: -
3381 // MARK: Power Change (Common)
3382
3383 //*********************************************************************************
3384 // [private] startPowerChange
3385 //
3386 // All power state changes starts here.
3387 //*********************************************************************************
3388
3389 IOReturn IOService::startPowerChange(
3390 IOPMPowerChangeFlags changeFlags,
3391 IOPMPowerStateIndex powerState,
3392 IOPMPowerFlags domainFlags,
3393 IOPowerConnection * parentConnection,
3394 IOPMPowerFlags parentFlags )
3395 {
3396 PM_ASSERT_IN_GATE();
3397 assert( fMachineState == kIOPM_Finished );
3398 assert( powerState < fNumberOfPowerStates );
3399
3400 if (powerState >= fNumberOfPowerStates)
3401 return IOPMAckImplied;
3402
3403 fIsPreChange = true;
3404 PM_ACTION_2(actionPowerChangeOverride, &powerState, &changeFlags);
3405
3406 // Forks to either Driver or Parent initiated power change paths.
3407
3408 fHeadNoteChangeFlags = changeFlags;
3409 fHeadNotePowerState = powerState;
3410 fHeadNotePowerArrayEntry = &fPowerStates[ powerState ];
3411 fHeadNoteParentConnection = NULL;
3412
3413 if (changeFlags & kIOPMSelfInitiated)
3414 {
3415 if (changeFlags & kIOPMSynchronize)
3416 OurSyncStart();
3417 else
3418 OurChangeStart();
3419 return 0;
3420 }
3421 else
3422 {
3423 assert(changeFlags & kIOPMParentInitiated);
3424 fHeadNoteDomainFlags = domainFlags;
3425 fHeadNoteParentFlags = parentFlags;
3426 fHeadNoteParentConnection = parentConnection;
3427 return ParentChangeStart();
3428 }
3429 }
3430
3431 //*********************************************************************************
3432 // [private] notifyInterestedDrivers
3433 //*********************************************************************************
3434
3435 bool IOService::notifyInterestedDrivers ( void )
3436 {
3437 IOPMinformee * informee;
3438 IOPMinformeeList * list = fInterestedDrivers;
3439 DriverCallParam * param;
3440 IOItemCount count;
3441
3442 PM_ASSERT_IN_GATE();
3443 assert( fDriverCallParamCount == 0 );
3444 assert( fHeadNotePendingAcks == 0 );
3445
3446 fHeadNotePendingAcks = 0;
3447
3448 count = list->numberOfItems();
3449 if (!count)
3450 goto done; // no interested drivers
3451
3452 // Allocate an array of interested drivers and their return values
3453 // for the callout thread. Everything else is still "owned" by the
3454 // PM work loop, which can run to process acknowledgePowerChange()
3455 // responses.
3456
3457 param = (DriverCallParam *) fDriverCallParamPtr;
3458 if (count > fDriverCallParamSlots)
3459 {
3460 if (fDriverCallParamSlots)
3461 {
3462 assert(fDriverCallParamPtr);
3463 IODelete(fDriverCallParamPtr, DriverCallParam, fDriverCallParamSlots);
3464 fDriverCallParamPtr = 0;
3465 fDriverCallParamSlots = 0;
3466 }
3467
3468 param = IONew(DriverCallParam, count);
3469 if (!param)
3470 goto done; // no memory
3471
3472 fDriverCallParamPtr = (void *) param;
3473 fDriverCallParamSlots = count;
3474 }
3475
3476 informee = list->firstInList();
3477 assert(informee);
3478 for (IOItemCount i = 0; i < count; i++)
3479 {
3480 informee->timer = -1;
3481 param[i].Target = informee;
3482 informee->retain();
3483 informee = list->nextInList( informee );
3484 }
3485
3486 fDriverCallParamCount = count;
3487 fHeadNotePendingAcks = count;
3488
3489 // Block state machine and wait for callout completion.
3490 assert(!fDriverCallBusy);
3491 fDriverCallBusy = true;
3492 thread_call_enter( fDriverCallEntry );
3493 return true;
3494
3495 done:
3496 // Return false if there are no interested drivers or could not schedule
3497 // callout thread due to error.
3498 return false;
3499 }
3500
3501 //*********************************************************************************
3502 // [private] notifyInterestedDriversDone
3503 //*********************************************************************************
3504
3505 void IOService::notifyInterestedDriversDone ( void )
3506 {
3507 IOPMinformee * informee;
3508 IOItemCount count;
3509 DriverCallParam * param;
3510 IOReturn result;
3511
3512 PM_ASSERT_IN_GATE();
3513 assert( fDriverCallBusy == false );
3514 assert( fMachineState == kIOPM_DriverThreadCallDone );
3515
3516 param = (DriverCallParam *) fDriverCallParamPtr;
3517 count = fDriverCallParamCount;
3518
3519 if (param && count)
3520 {
3521 for (IOItemCount i = 0; i < count; i++, param++)
3522 {
3523 informee = (IOPMinformee *) param->Target;
3524 result = param->Result;
3525
3526 if ((result == IOPMAckImplied) || (result < 0))
3527 {
3528 // Interested driver return IOPMAckImplied.
3529 // If informee timer is zero, it must have de-registered
3530 // interest during the thread callout. That also drops
3531 // the pending ack count.
3532
3533 if (fHeadNotePendingAcks && informee->timer)
3534 fHeadNotePendingAcks--;
3535
3536 informee->timer = 0;
3537 }
3538 else if (informee->timer)
3539 {
3540 assert(informee->timer == -1);
3541
3542 // Driver has not acked, and has returned a positive result.
3543 // Enforce a minimum permissible timeout value.
3544 // Make the min value large enough so timeout is less likely
3545 // to occur if a driver misinterpreted that the return value
3546 // should be in microsecond units. And make it large enough
3547 // to be noticeable if a driver neglects to ack.
3548
3549 if (result < kMinAckTimeoutTicks)
3550 result = kMinAckTimeoutTicks;
3551
3552 informee->timer = (result / (ACK_TIMER_PERIOD / ns_per_us)) + 1;
3553 }
3554 // else, child has already acked or driver has removed interest,
3555 // and head_note_pendingAcks decremented.
3556 // informee may have been removed from the interested drivers list,
3557 // thus the informee must be retained across the callout.
3558
3559 informee->release();
3560 }
3561
3562 fDriverCallParamCount = 0;
3563
3564 if ( fHeadNotePendingAcks )
3565 {
3566 OUR_PMLog(kPMLogStartAckTimer, 0, 0);
3567 start_ack_timer();
3568 }
3569 }
3570
3571 MS_POP(); // pushed by notifyAll()
3572
3573 // If interest acks are outstanding, wait for fHeadNotePendingAcks to become
3574 // zero before notifying children. This enforces the children after interest
3575 // ordering even for async interest clients.
3576
3577 if (!fHeadNotePendingAcks)
3578 {
3579 notifyChildren();
3580 }
3581 else
3582 {
3583 MS_PUSH(fMachineState);
3584 fMachineState = kIOPM_NotifyChildrenStart;
3585 PM_LOG2("%s: %u outstanding async interest\n",
3586 getName(), fHeadNotePendingAcks);
3587 }
3588 }
3589
3590 //*********************************************************************************
3591 // [private] notifyChildren
3592 //*********************************************************************************
3593
3594 void IOService::notifyChildren ( void )
3595 {
3596 OSIterator * iter;
3597 OSObject * next;
3598 IOPowerConnection * connection;
3599 OSArray * children = 0;
3600 IOPMrootDomain * rootDomain;
3601 bool delayNotify = false;
3602
3603 if ((fHeadNotePowerState != fCurrentPowerState) &&
3604 (IS_POWER_DROP == fIsPreChange) &&
3605 ((rootDomain = getPMRootDomain()) == this))
3606 {
3607 rootDomain->tracePoint( IS_POWER_DROP ?
3608 kIOPMTracePointSleepPowerPlaneDrivers :
3609 kIOPMTracePointWakePowerPlaneDrivers );
3610 }
3611
3612 if (fStrictTreeOrder)
3613 children = OSArray::withCapacity(8);
3614
3615 // Sum child power consumption in notifyChild()
3616 fHeadNotePowerArrayEntry->staticPower = 0;
3617
3618 iter = getChildIterator(gIOPowerPlane);
3619 if ( iter )
3620 {
3621 while ((next = iter->getNextObject()))
3622 {
3623 if ((connection = OSDynamicCast(IOPowerConnection, next)))
3624 {
3625 if (connection->getReadyFlag() == false)
3626 {
3627 PM_LOG3("[%s] %s: connection not ready\n",
3628 getName(), __FUNCTION__);
3629 continue;
3630 }
3631
3632 // Mechanism to postpone the did-change notification to
3633 // certain power children to order those children last.
3634 // Cannot be used together with strict tree ordering.
3635
3636 if (!fIsPreChange &&
3637 (connection->delayChildNotification) &&
3638 getPMRootDomain()->shouldDelayChildNotification(this))
3639 {
3640 if (!children)
3641 {
3642 children = OSArray::withCapacity(8);
3643 if (children)
3644 delayNotify = true;
3645 }
3646 if (delayNotify)
3647 {
3648 children->setObject( connection );
3649 continue;
3650 }
3651 }
3652
3653 if (!delayNotify && children)
3654 children->setObject( connection );
3655 else
3656 notifyChild( connection );
3657 }
3658 }
3659 iter->release();
3660 }
3661
3662 if (children && (children->getCount() == 0))
3663 {
3664 children->release();
3665 children = 0;
3666 }
3667 if (children)
3668 {
3669 assert(fNotifyChildArray == 0);
3670 fNotifyChildArray = children;
3671 MS_PUSH(fMachineState);
3672
3673 if (delayNotify)
3674 {
3675 // Wait for exiting child notifications to complete,
3676 // before notifying the children in the array.
3677 fMachineState = kIOPM_NotifyChildrenDelayed;
3678 PM_LOG2("%s: %d children in delayed array\n",
3679 getName(), children->getCount());
3680 }
3681 else
3682 {
3683 // Notify children in the array one at a time.
3684 fMachineState = kIOPM_NotifyChildrenOrdered;
3685 }
3686 }
3687 }
3688
3689 //*********************************************************************************
3690 // [private] notifyChildrenOrdered
3691 //*********************************************************************************
3692
3693 void IOService::notifyChildrenOrdered ( void )
3694 {
3695 PM_ASSERT_IN_GATE();
3696 assert(fNotifyChildArray);
3697 assert(fMachineState == kIOPM_NotifyChildrenOrdered);
3698
3699 // Notify one child, wait for it to ack, then repeat for next child.
3700 // This is a workaround for some drivers with multiple instances at
3701 // the same branch in the power tree, but the driver is slow to power
3702 // up unless the tree ordering is observed. Problem observed only on
3703 // system wake, not on system sleep.
3704 //
3705 // We have the ability to power off in reverse child index order.
3706 // That works nicely on some machines, but not on all HW configs.
3707
3708 if (fNotifyChildArray->getCount())
3709 {
3710 IOPowerConnection * connection;
3711 connection = (IOPowerConnection *) fNotifyChildArray->getObject(0);
3712 notifyChild( connection );
3713 fNotifyChildArray->removeObject(0);
3714 }
3715 else
3716 {
3717 fNotifyChildArray->release();
3718 fNotifyChildArray = 0;
3719
3720 MS_POP(); // pushed by notifyChildren()
3721 }
3722 }
3723
3724 //*********************************************************************************
3725 // [private] notifyChildrenDelayed
3726 //*********************************************************************************
3727
3728 void IOService::notifyChildrenDelayed ( void )
3729 {
3730 IOPowerConnection * connection;
3731
3732 PM_ASSERT_IN_GATE();
3733 assert(fNotifyChildArray);
3734 assert(fMachineState == kIOPM_NotifyChildrenDelayed);
3735
3736 // Wait after all non-delayed children and interested drivers have ack'ed,
3737 // then notify all delayed children. When explicitly cancelled, interest
3738 // acks (and ack timer) may still be outstanding.
3739
3740 for (int i = 0; ; i++)
3741 {
3742 connection = (IOPowerConnection *) fNotifyChildArray->getObject(i);
3743 if (!connection)
3744 break;
3745
3746 notifyChild( connection );
3747 }
3748
3749 PM_LOG2("%s: notified delayed children\n", getName());
3750 fNotifyChildArray->release();
3751 fNotifyChildArray = 0;
3752
3753 MS_POP(); // pushed by notifyChildren()
3754 }
3755
3756 //*********************************************************************************
3757 // [private] notifyAll
3758 //*********************************************************************************
3759
3760 IOReturn IOService::notifyAll ( uint32_t nextMS )
3761 {
3762 // Save the next machine_state to be restored by notifyInterestedDriversDone()
3763
3764 PM_ASSERT_IN_GATE();
3765 MS_PUSH(nextMS);
3766 fMachineState = kIOPM_DriverThreadCallDone;
3767 fDriverCallReason = fIsPreChange ?
3768 kDriverCallInformPreChange : kDriverCallInformPostChange;
3769
3770 if (!notifyInterestedDrivers())
3771 notifyInterestedDriversDone();
3772
3773 return IOPMWillAckLater;
3774 }
3775
3776 //*********************************************************************************
3777 // [private, static] pmDriverCallout
3778 //
3779 // Thread call context
3780 //*********************************************************************************
3781
3782 IOReturn IOService::actionDriverCalloutDone (
3783 OSObject * target,
3784 void * arg0, void * arg1,
3785 void * arg2, void * arg3 )
3786 {
3787 IOServicePM * pwrMgt = (IOServicePM *) arg0;
3788
3789 assert( fDriverCallBusy );
3790 fDriverCallBusy = false;
3791
3792 assert(gIOPMWorkQueue);
3793 gIOPMWorkQueue->signalWorkAvailable();
3794
3795 return kIOReturnSuccess;
3796 }
3797
3798 void IOService::pmDriverCallout ( IOService * from )
3799 {
3800 assert(from);
3801 switch (from->fDriverCallReason)
3802 {
3803 case kDriverCallSetPowerState:
3804 from->driverSetPowerState();
3805 break;
3806
3807 case kDriverCallInformPreChange:
3808 case kDriverCallInformPostChange:
3809 from->driverInformPowerChange();
3810 break;
3811
3812 default:
3813 panic("IOService::pmDriverCallout bad machine state %x",
3814 from->fDriverCallReason);
3815 }
3816
3817 gIOPMWorkLoop->runAction(actionDriverCalloutDone,
3818 /* target */ from,
3819 /* arg0 */ (void *) from->pwrMgt );
3820 }
3821
3822 //*********************************************************************************
3823 // [private] driverSetPowerState
3824 //
3825 // Thread call context
3826 //*********************************************************************************
3827
3828 void IOService::driverSetPowerState ( void )
3829 {
3830 IOPMPowerStateIndex powerState;
3831 DriverCallParam * param;
3832 IOPMDriverCallEntry callEntry;
3833 AbsoluteTime end;
3834 IOReturn result;
3835 uint32_t oldPowerState = getPowerState();
3836
3837 assert( fDriverCallBusy );
3838 assert( fDriverCallParamPtr );
3839 assert( fDriverCallParamCount == 1 );
3840
3841 param = (DriverCallParam *) fDriverCallParamPtr;
3842 powerState = fHeadNotePowerState;
3843
3844 if (assertPMDriverCall(&callEntry))
3845 {
3846 OUR_PMLog( kPMLogProgramHardware, (uintptr_t) this, powerState);
3847 clock_get_uptime(&fDriverCallStartTime);
3848 result = fControllingDriver->setPowerState( powerState, this );
3849 clock_get_uptime(&end);
3850 OUR_PMLog((UInt32) -kPMLogProgramHardware, (uintptr_t) this, (UInt32) result);
3851
3852 deassertPMDriverCall(&callEntry);
3853
3854 if (result < 0)
3855 {
3856 PM_LOG("%s::setPowerState(%p, %lu -> %lu) returned 0x%x\n",
3857 fName, this, fCurrentPowerState, powerState, result);
3858 }
3859
3860 #if LOG_SETPOWER_TIMES
3861 if ((result == IOPMAckImplied) || (result < 0))
3862 {
3863 uint64_t nsec;
3864
3865 SUB_ABSOLUTETIME(&end, &fDriverCallStartTime);
3866 absolutetime_to_nanoseconds(end, &nsec);
3867 if (nsec > LOG_SETPOWER_TIMES)
3868 PM_LOG("%s::setPowerState(%p, %lu -> %lu) took %d ms\n",
3869 fName, this, fCurrentPowerState, powerState, NS_TO_MS(nsec));
3870
3871 PMEventDetails *details = PMEventDetails::eventDetails(
3872 kIOPMEventTypeSetPowerStateImmediate, // type
3873 fName, // who
3874 (uintptr_t)this, // owner unique
3875 NULL, // interest name
3876 (uint8_t)oldPowerState, // old
3877 (uint8_t)powerState, // new
3878 0, // result
3879 NS_TO_US(nsec)); // usec completion time
3880
3881 getPMRootDomain()->recordAndReleasePMEventGated( details );
3882 }
3883 #endif
3884 }
3885 else
3886 result = kIOPMAckImplied;
3887
3888 param->Result = result;
3889 }
3890
3891 //*********************************************************************************
3892 // [private] driverInformPowerChange
3893 //
3894 // Thread call context
3895 //*********************************************************************************
3896
3897 void IOService::driverInformPowerChange ( void )
3898 {
3899 IOPMinformee * informee;
3900 IOService * driver;
3901 DriverCallParam * param;
3902 IOPMDriverCallEntry callEntry;
3903 IOPMPowerFlags powerFlags;
3904 IOPMPowerStateIndex powerState;
3905 AbsoluteTime end;
3906 IOReturn result;
3907 IOItemCount count;
3908
3909 assert( fDriverCallBusy );
3910 assert( fDriverCallParamPtr );
3911 assert( fDriverCallParamCount );
3912
3913 param = (DriverCallParam *) fDriverCallParamPtr;
3914 count = fDriverCallParamCount;
3915
3916 powerFlags = fHeadNotePowerArrayEntry->capabilityFlags;
3917 powerState = fHeadNotePowerState;
3918
3919 for (IOItemCount i = 0; i < count; i++)
3920 {
3921 informee = (IOPMinformee *) param->Target;
3922 driver = informee->whatObject;
3923
3924 if (assertPMDriverCall(&callEntry, 0, informee))
3925 {
3926 if (fDriverCallReason == kDriverCallInformPreChange)
3927 {
3928 OUR_PMLog(kPMLogInformDriverPreChange, (uintptr_t) this, powerState);
3929 clock_get_uptime(&informee->startTime);
3930 result = driver->powerStateWillChangeTo(powerFlags, powerState, this);
3931 clock_get_uptime(&end);
3932 OUR_PMLog((UInt32)-kPMLogInformDriverPreChange, (uintptr_t) this, result);
3933 }
3934 else
3935 {
3936 OUR_PMLog(kPMLogInformDriverPostChange, (uintptr_t) this, powerState);
3937 clock_get_uptime(&informee->startTime);
3938 result = driver->powerStateDidChangeTo(powerFlags, powerState, this);
3939 clock_get_uptime(&end);
3940 OUR_PMLog((UInt32)-kPMLogInformDriverPostChange, (uintptr_t) this, result);
3941 }
3942
3943 deassertPMDriverCall(&callEntry);
3944
3945 #if LOG_SETPOWER_TIMES
3946 if ((result == IOPMAckImplied) || (result < 0))
3947 {
3948 uint64_t nsec;
3949
3950 SUB_ABSOLUTETIME(&end, &informee->startTime);
3951 absolutetime_to_nanoseconds(end, &nsec);
3952 if (nsec > LOG_SETPOWER_TIMES)
3953 PM_LOG("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) took %d ms\n",
3954 driver->getName(),
3955 (fDriverCallReason == kDriverCallInformPreChange) ? "Will" : "Did",
3956 driver, fName, fCurrentPowerState, powerState, NS_TO_MS(nsec));
3957
3958 uint16_t logType = (fDriverCallReason == kDriverCallInformPreChange)
3959 ? kIOPMEventTypePSWillChangeTo
3960 : kIOPMEventTypePSDidChangeTo;
3961
3962 PMEventDetails *details = PMEventDetails::eventDetails(
3963 logType, // type
3964 fName, // who
3965 (uintptr_t)this, // owner unique
3966 driver->getName(), // interest name
3967 (uint8_t)fCurrentPowerState, // old
3968 (uint8_t)fHeadNotePowerState, // new
3969 0, // result
3970 NS_TO_US(nsec)); // usec completion time
3971
3972 getPMRootDomain()->recordAndReleasePMEventGated( details );
3973 }
3974 #endif
3975 }
3976 else
3977 result = kIOPMAckImplied;
3978
3979 param->Result = result;
3980 param++;
3981 }
3982 }
3983
3984 //*********************************************************************************
3985 // [private] notifyChild
3986 //
3987 // Notify a power domain child of an upcoming power change.
3988 // If the object acknowledges the current change, we return TRUE.
3989 //*********************************************************************************
3990
3991 bool IOService::notifyChild ( IOPowerConnection * theNub )
3992 {
3993 IOReturn ret = IOPMAckImplied;
3994 unsigned long childPower;
3995 IOService * theChild;
3996 IOPMRequest * childRequest;
3997 IOPMPowerChangeFlags requestArg2;
3998 int requestType;
3999
4000 PM_ASSERT_IN_GATE();
4001 theChild = (IOService *)(theNub->copyChildEntry(gIOPowerPlane));
4002 if (!theChild)
4003 {
4004 return true;
4005 }
4006
4007 // Unless the child handles the notification immediately and returns
4008 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
4009 fHeadNotePendingAcks++;
4010 theNub->setAwaitingAck(true);
4011
4012 requestArg2 = fHeadNoteChangeFlags;
4013 if (fHeadNotePowerState < fCurrentPowerState)
4014 requestArg2 |= kIOPMDomainPowerDrop;
4015
4016 requestType = fIsPreChange ?
4017 kIOPMRequestTypePowerDomainWillChange :
4018 kIOPMRequestTypePowerDomainDidChange;
4019
4020 childRequest = acquirePMRequest( theChild, requestType );
4021 if (childRequest)
4022 {
4023 theNub->retain();
4024 childRequest->fArg0 = (void *) fHeadNotePowerArrayEntry->outputPowerFlags;
4025 childRequest->fArg1 = (void *) theNub;
4026 childRequest->fArg2 = (void *) requestArg2;
4027 theChild->submitPMRequest( childRequest );
4028 ret = IOPMWillAckLater;
4029 }
4030 else
4031 {
4032 ret = IOPMAckImplied;
4033 fHeadNotePendingAcks--;
4034 theNub->setAwaitingAck(false);
4035 childPower = theChild->currentPowerConsumption();
4036 if ( childPower == kIOPMUnknown )
4037 {
4038 fHeadNotePowerArrayEntry->staticPower = kIOPMUnknown;
4039 } else {
4040 if (fHeadNotePowerArrayEntry->staticPower != kIOPMUnknown )
4041 fHeadNotePowerArrayEntry->staticPower += childPower;
4042 }
4043 }
4044
4045 theChild->release();
4046 return (IOPMAckImplied == ret);
4047 }
4048
4049 //*********************************************************************************
4050 // [private] notifyControllingDriver
4051 //*********************************************************************************
4052
4053 bool IOService::notifyControllingDriver ( void )
4054 {
4055 DriverCallParam * param;
4056
4057 PM_ASSERT_IN_GATE();
4058 assert( fDriverCallParamCount == 0 );
4059 assert( fControllingDriver );
4060
4061 if (fInitialSetPowerState)
4062 {
4063 fInitialSetPowerState = false;
4064 fHeadNoteChangeFlags |= kIOPMInitialPowerChange;
4065
4066 // Driver specified flag to skip the inital setPowerState()
4067 if (fHeadNotePowerArrayEntry->capabilityFlags & kIOPMInitialDeviceState)
4068 {
4069 return false;
4070 }
4071 }
4072
4073 param = (DriverCallParam *) fDriverCallParamPtr;
4074 if (!param)
4075 {
4076 param = IONew(DriverCallParam, 1);
4077 if (!param)
4078 return false; // no memory
4079
4080 fDriverCallParamPtr = (void *) param;
4081 fDriverCallParamSlots = 1;
4082 }
4083
4084 param->Target = fControllingDriver;
4085 fDriverCallParamCount = 1;
4086 fDriverTimer = -1;
4087
4088 // Block state machine and wait for callout completion.
4089 assert(!fDriverCallBusy);
4090 fDriverCallBusy = true;
4091 thread_call_enter( fDriverCallEntry );
4092
4093 return true;
4094 }
4095
4096 //*********************************************************************************
4097 // [private] notifyControllingDriverDone
4098 //*********************************************************************************
4099
4100 void IOService::notifyControllingDriverDone( void )
4101 {
4102 DriverCallParam * param;
4103 IOReturn result;
4104
4105 PM_ASSERT_IN_GATE();
4106 param = (DriverCallParam *) fDriverCallParamPtr;
4107
4108 assert( fDriverCallBusy == false );
4109 assert( fMachineState == kIOPM_DriverThreadCallDone );
4110
4111 if (param && fDriverCallParamCount)
4112 {
4113 assert(fDriverCallParamCount == 1);
4114
4115 // the return value from setPowerState()
4116 result = param->Result;
4117
4118 if ((result == IOPMAckImplied) || (result < 0))
4119 {
4120 fDriverTimer = 0;
4121 }
4122 else if (fDriverTimer)
4123 {
4124 assert(fDriverTimer == -1);
4125
4126 // Driver has not acked, and has returned a positive result.
4127 // Enforce a minimum permissible timeout value.
4128 // Make the min value large enough so timeout is less likely
4129 // to occur if a driver misinterpreted that the return value
4130 // should be in microsecond units. And make it large enough
4131 // to be noticeable if a driver neglects to ack.
4132
4133 if (result < kMinAckTimeoutTicks)
4134 result = kMinAckTimeoutTicks;
4135
4136 fDriverTimer = (result / (ACK_TIMER_PERIOD / ns_per_us)) + 1;
4137 }
4138 // else, child has already acked and driver_timer reset to 0.
4139
4140 fDriverCallParamCount = 0;
4141
4142 if ( fDriverTimer )
4143 {
4144 OUR_PMLog(kPMLogStartAckTimer, 0, 0);
4145 start_ack_timer();
4146 }
4147 }
4148
4149 MS_POP(); // pushed by OurChangeSetPowerState()
4150 fIsPreChange = false;
4151 }
4152
4153 //*********************************************************************************
4154 // [private] all_done
4155 //
4156 // A power change is done.
4157 //*********************************************************************************
4158
4159 void IOService::all_done ( void )
4160 {
4161 IOPMPowerStateIndex prevPowerState;
4162 const IOPMPSEntry * powerStatePtr;
4163 IOPMDriverCallEntry callEntry;
4164 uint32_t prevMachineState = fMachineState;
4165 bool callAction = false;
4166
4167 fMachineState = kIOPM_Finished;
4168
4169 if ((fHeadNoteChangeFlags & kIOPMSynchronize) &&
4170 ((prevMachineState == kIOPM_Finished) ||
4171 (prevMachineState == kIOPM_SyncFinish)))
4172 {
4173 // Sync operation and no power change occurred.
4174 // Do not inform driver and clients about this request completion,
4175 // except for the originator (root domain).
4176
4177 PM_ACTION_2(actionPowerChangeDone,
4178 fHeadNotePowerState, fHeadNoteChangeFlags);
4179
4180 if (getPMRequestType() == kIOPMRequestTypeSynchronizePowerTree)
4181 {
4182 powerChangeDone(fCurrentPowerState);
4183 }
4184 else if (fAdvisoryTickleUsed)
4185 {
4186 // Not root domain and advisory tickle target.
4187 // Re-adjust power after power tree sync at the 'did' pass
4188 // to recompute desire and adjust power state between dark
4189 // and full wake transitions. Root domain is responsible
4190 // for calling setAdvisoryTickleEnable() before starting
4191 // the kIOPMSynchronize power change.
4192
4193 if (!fAdjustPowerScheduled &&
4194 (fHeadNoteChangeFlags & kIOPMDomainDidChange))
4195 {
4196 IOPMRequest * request;
4197 request = acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState );
4198 if (request)
4199 {
4200 submitPMRequest( request );
4201 fAdjustPowerScheduled = true;
4202 }
4203 }
4204 }
4205
4206 return;
4207 }
4208
4209 // our power change
4210 if ( fHeadNoteChangeFlags & kIOPMSelfInitiated )
4211 {
4212 // could our driver switch to the new state?
4213 if ( !( fHeadNoteChangeFlags & kIOPMNotDone) )
4214 {
4215 trackSystemSleepPreventers(
4216 fCurrentPowerState, fHeadNotePowerState, fHeadNoteChangeFlags);
4217
4218 // we changed, tell our parent
4219 requestDomainPower(fHeadNotePowerState);
4220
4221 // yes, did power raise?
4222 if ( fCurrentPowerState < fHeadNotePowerState )
4223 {
4224 // yes, inform clients and apps
4225 tellChangeUp (fHeadNotePowerState);
4226 }
4227 prevPowerState = fCurrentPowerState;
4228 // either way
4229 fCurrentPowerState = fHeadNotePowerState;
4230 #if PM_VARS_SUPPORT
4231 fPMVars->myCurrentState = fCurrentPowerState;
4232 #endif
4233 OUR_PMLog(kPMLogChangeDone, fCurrentPowerState, prevPowerState);
4234 PM_ACTION_2(actionPowerChangeDone,
4235 fHeadNotePowerState, fHeadNoteChangeFlags);
4236 callAction = true;
4237
4238 powerStatePtr = &fPowerStates[fCurrentPowerState];
4239 fCurrentCapabilityFlags = powerStatePtr->capabilityFlags;
4240 if (fCurrentCapabilityFlags & kIOPMStaticPowerValid)
4241 fCurrentPowerConsumption = powerStatePtr->staticPower;
4242
4243 if (fHeadNoteChangeFlags & kIOPMRootChangeDown)
4244 {
4245 // Bump tickle generation count once the entire tree is down
4246 gIOPMTickleGeneration++;
4247 }
4248
4249 // inform subclass policy-maker
4250 if (fPCDFunctionOverride && fParentsKnowState &&
4251 assertPMDriverCall(&callEntry, kIOPMADC_NoInactiveCheck))
4252 {
4253 powerChangeDone(prevPowerState);
4254 deassertPMDriverCall(&callEntry);
4255 }
4256 }
4257 else if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride)
4258 {
4259 // changePowerStateWithOverrideTo() was cancelled
4260 fOverrideMaxPowerState = kIOPMPowerStateMax;
4261 }
4262 }
4263
4264 // parent's power change
4265 if ( fHeadNoteChangeFlags & kIOPMParentInitiated)
4266 {
4267 if (fHeadNoteChangeFlags & kIOPMRootChangeDown)
4268 ParentChangeRootChangeDown();
4269
4270 if (((fHeadNoteChangeFlags & kIOPMDomainWillChange) &&
4271 (fCurrentPowerState >= fHeadNotePowerState)) ||
4272 ((fHeadNoteChangeFlags & kIOPMDomainDidChange) &&
4273 (fCurrentPowerState < fHeadNotePowerState)))
4274 {
4275 trackSystemSleepPreventers(
4276 fCurrentPowerState, fHeadNotePowerState, fHeadNoteChangeFlags);
4277
4278 // did power raise?
4279 if ( fCurrentPowerState < fHeadNotePowerState )
4280 {
4281 // yes, inform clients and apps
4282 tellChangeUp (fHeadNotePowerState);
4283 }
4284 // either way
4285 prevPowerState = fCurrentPowerState;
4286 fCurrentPowerState = fHeadNotePowerState;
4287 #if PM_VARS_SUPPORT
4288 fPMVars->myCurrentState = fCurrentPowerState;
4289 #endif
4290 fMaxPowerState = fControllingDriver->maxCapabilityForDomainState(fHeadNoteDomainFlags);
4291
4292 OUR_PMLog(kPMLogChangeDone, fCurrentPowerState, prevPowerState);
4293 PM_ACTION_2(actionPowerChangeDone,
4294 fHeadNotePowerState, fHeadNoteChangeFlags);
4295 callAction = true;
4296
4297 powerStatePtr = &fPowerStates[fCurrentPowerState];
4298 fCurrentCapabilityFlags = powerStatePtr->capabilityFlags;
4299 if (fCurrentCapabilityFlags & kIOPMStaticPowerValid)
4300 fCurrentPowerConsumption = powerStatePtr->staticPower;
4301
4302 // inform subclass policy-maker
4303 if (fPCDFunctionOverride && fParentsKnowState &&
4304 assertPMDriverCall(&callEntry, kIOPMADC_NoInactiveCheck))
4305 {
4306 powerChangeDone(prevPowerState);
4307 deassertPMDriverCall(&callEntry);
4308 }
4309 }
4310 }
4311
4312 // When power rises enough to satisfy the tickle's desire for more power,
4313 // the condition preventing idle-timer from dropping power is removed.
4314
4315 if (fCurrentPowerState >= fIdleTimerMinPowerState)
4316 {
4317 fIdleTimerMinPowerState = 0;
4318 }
4319
4320 if (!callAction)
4321 {
4322 PM_ACTION_2(actionPowerChangeDone,
4323 fHeadNotePowerState, fHeadNoteChangeFlags);
4324 }
4325 }
4326
4327 // MARK: -
4328 // MARK: Power Change Initiated by Driver
4329
4330 //*********************************************************************************
4331 // [private] OurChangeStart
4332 //
4333 // Begin the processing of a power change initiated by us.
4334 //*********************************************************************************
4335
4336 void IOService::OurChangeStart ( void )
4337 {
4338 PM_ASSERT_IN_GATE();
4339 OUR_PMLog( kPMLogStartDeviceChange, fHeadNotePowerState, fCurrentPowerState );
4340
4341 // fMaxPowerState is our maximum possible power state based on the current
4342 // power state of our parents. If we are trying to raise power beyond the
4343 // maximum, send an async request for more power to all parents.
4344
4345 if (!IS_PM_ROOT && (fMaxPowerState < fHeadNotePowerState))
4346 {
4347 fHeadNoteChangeFlags |= kIOPMNotDone;
4348 requestDomainPower(fHeadNotePowerState);
4349 OurChangeFinish();
4350 return;
4351 }
4352
4353 // Redundant power changes skips to the end of the state machine.
4354
4355 if (!fInitialPowerChange && (fHeadNotePowerState == fCurrentPowerState))
4356 {
4357 OurChangeFinish();
4358 return;
4359 }
4360 fInitialPowerChange = false;
4361
4362 // Change started, but may not complete...
4363 // Can be canceled (power drop) or deferred (power rise).
4364
4365 PM_ACTION_2(actionPowerChangeStart, fHeadNotePowerState, &fHeadNoteChangeFlags);
4366
4367 // Two separate paths, depending if power is being raised or lowered.
4368 // Lowering power is subject to approval by clients of this service.
4369
4370 if (IS_POWER_DROP)
4371 {
4372 fDoNotPowerDown = false;
4373
4374 // Ask for persmission to drop power state
4375 fMachineState = kIOPM_OurChangeTellClientsPowerDown;
4376 fOutOfBandParameter = kNotifyApps;
4377 askChangeDown(fHeadNotePowerState);
4378 }
4379 else
4380 {
4381 // This service is raising power and parents are able to support the
4382 // new power state. However a parent may have already committed to
4383 // drop power, which might force this object to temporarily drop power.
4384 // This results in "oscillations" before the state machines converge
4385 // to a steady state.
4386 //
4387 // To prevent this, a child must make a power reservation against all
4388 // parents before raising power. If the reservation fails, indicating
4389 // that the child will be unable to sustain the higher power state,
4390 // then the child will signal the parent to adjust power, and the child
4391 // will defer its power change.
4392
4393 IOReturn ret;
4394
4395 // Reserve parent power necessary to achieve fHeadNotePowerState.
4396 ret = requestDomainPower( fHeadNotePowerState, kReserveDomainPower );
4397 if (ret != kIOReturnSuccess)
4398 {
4399 // Reservation failed, defer power rise.
4400 fHeadNoteChangeFlags |= kIOPMNotDone;
4401 OurChangeFinish();
4402 return;
4403 }
4404
4405 OurChangeTellCapabilityWillChange();
4406 }
4407 }
4408
4409 //*********************************************************************************
4410 // [private] requestDomainPowerApplier
4411 //
4412 // Call requestPowerDomainState() on all power parents.
4413 //*********************************************************************************
4414
4415 struct IOPMRequestDomainPowerContext {
4416 IOService * child; // the requesting child
4417 IOPMPowerFlags requestPowerFlags; // power flags requested by child
4418 };
4419
4420 static void
4421 requestDomainPowerApplier(
4422 IORegistryEntry * entry,
4423 void * inContext )
4424 {
4425 IOPowerConnection * connection;
4426 IOService * parent;
4427 IOPMRequestDomainPowerContext * context;
4428
4429 if ((connection = OSDynamicCast(IOPowerConnection, entry)) == 0)
4430 return;
4431 parent = (IOService *) connection->copyParentEntry(gIOPowerPlane);
4432 if (!parent)
4433 return;
4434
4435 assert(inContext);
4436 context = (IOPMRequestDomainPowerContext *) inContext;
4437
4438 if (connection->parentKnowsState() && connection->getReadyFlag())
4439 {
4440 parent->requestPowerDomainState(
4441 context->requestPowerFlags,
4442 connection,
4443 IOPMLowestState);
4444 }
4445
4446 parent->release();
4447 }
4448
4449 //*********************************************************************************
4450 // [private] requestDomainPower
4451 //
4452 // Called by a power child to broadcast its desired power state to all parents.
4453 // If the child self-initiates a power change, it must call this function to
4454 // allow its parents to adjust power state.
4455 //*********************************************************************************
4456
4457 IOReturn IOService::requestDomainPower(
4458 IOPMPowerStateIndex ourPowerState,
4459 IOOptionBits options )
4460 {
4461 IOPMPowerFlags requestPowerFlags;
4462 IOPMPowerStateIndex maxPowerState;
4463 IOPMRequestDomainPowerContext context;
4464
4465 PM_ASSERT_IN_GATE();
4466 assert(ourPowerState < fNumberOfPowerStates);
4467 if (ourPowerState >= fNumberOfPowerStates)
4468 return kIOReturnBadArgument;
4469 if (IS_PM_ROOT)
4470 return kIOReturnSuccess;
4471
4472 // Fetch our input power flags for the requested power state.
4473 // Parent request is stated in terms of required power flags.
4474
4475 requestPowerFlags = fPowerStates[ourPowerState].inputPowerFlags;
4476
4477 // Disregard the "previous request" for power reservation.
4478
4479 if (((options & kReserveDomainPower) == 0) &&
4480 (fPreviousRequestPowerFlags == requestPowerFlags))
4481 {
4482 // skip if domain already knows our requirements
4483 goto done;
4484 }
4485 fPreviousRequestPowerFlags = requestPowerFlags;
4486
4487 // The results will be collected by fHeadNoteDomainTargetFlags
4488 context.child = this;
4489 context.requestPowerFlags = requestPowerFlags;
4490 fHeadNoteDomainTargetFlags = 0;
4491 applyToParents(requestDomainPowerApplier, &context, gIOPowerPlane);
4492
4493 if (options & kReserveDomainPower)
4494 {
4495 maxPowerState = fControllingDriver->maxCapabilityForDomainState(
4496 fHeadNoteDomainTargetFlags );
4497
4498 if (maxPowerState < ourPowerState)
4499 {
4500 PM_LOG1("%s: power desired %u:0x%x got %u:0x%x\n",
4501 getName(),
4502 (uint32_t) ourPowerState, (uint32_t) requestPowerFlags,
4503 (uint32_t) maxPowerState, (uint32_t) fHeadNoteDomainTargetFlags);
4504 return kIOReturnNoPower;
4505 }
4506 }
4507
4508 done:
4509 return kIOReturnSuccess;
4510 }
4511
4512 //*********************************************************************************
4513 // [private] OurSyncStart
4514 //*********************************************************************************
4515
4516 void IOService::OurSyncStart ( void )
4517 {
4518 PM_ASSERT_IN_GATE();
4519
4520 if (fInitialPowerChange)
4521 return;
4522
4523 PM_ACTION_2(actionPowerChangeStart, fHeadNotePowerState, &fHeadNoteChangeFlags);
4524
4525 if (fHeadNoteChangeFlags & kIOPMNotDone)
4526 {
4527 OurChangeFinish();
4528 return;
4529 }
4530
4531 if (fHeadNoteChangeFlags & kIOPMSyncTellPowerDown)
4532 {
4533 fDoNotPowerDown = false;
4534
4535 // Ask for permission to drop power state
4536 fMachineState = kIOPM_SyncTellClientsPowerDown;
4537 fOutOfBandParameter = kNotifyApps;
4538 askChangeDown(fHeadNotePowerState);
4539 }
4540 else
4541 {
4542 // Only inform capability app and clients.
4543 tellSystemCapabilityChange( kIOPM_SyncNotifyWillChange );
4544 }
4545 }
4546
4547 //*********************************************************************************
4548 // [private] OurChangeTellClientsPowerDown
4549 //
4550 // All applications and kernel clients have acknowledged our permission to drop
4551 // power. Here we notify them that we will lower the power and wait for acks.
4552 //*********************************************************************************
4553
4554 void IOService::OurChangeTellClientsPowerDown ( void )
4555 {
4556 fMachineState = kIOPM_OurChangeTellPriorityClientsPowerDown;
4557 tellChangeDown1(fHeadNotePowerState);
4558 }
4559
4560 //*********************************************************************************
4561 // [private] OurChangeTellPriorityClientsPowerDown
4562 //
4563 // All applications and kernel clients have acknowledged our intention to drop
4564 // power. Here we notify "priority" clients that we are lowering power.
4565 //*********************************************************************************
4566
4567 void IOService::OurChangeTellPriorityClientsPowerDown ( void )
4568 {
4569 fMachineState = kIOPM_OurChangeNotifyInterestedDriversWillChange;
4570 tellChangeDown2(fHeadNotePowerState);
4571 }
4572
4573 //*********************************************************************************
4574 // [private] OurChangeTellCapabilityWillChange
4575 //
4576 // Extra stage for root domain to notify apps and drivers about the
4577 // system capability change when raising power state.
4578 //*********************************************************************************
4579
4580 void IOService::OurChangeTellCapabilityWillChange ( void )
4581 {
4582 if (!IS_ROOT_DOMAIN)
4583 return OurChangeNotifyInterestedDriversWillChange();
4584
4585 tellSystemCapabilityChange( kIOPM_OurChangeNotifyInterestedDriversWillChange );
4586 }
4587
4588 //*********************************************************************************
4589 // [private] OurChangeNotifyInterestedDriversWillChange
4590 //
4591 // All applications and kernel clients have acknowledged our power state change.
4592 // Here we notify interested drivers pre-change.
4593 //*********************************************************************************
4594
4595 void IOService::OurChangeNotifyInterestedDriversWillChange ( void )
4596 {
4597 IOPMrootDomain * rootDomain;
4598 if ((rootDomain = getPMRootDomain()) == this)
4599 {
4600 if (IS_POWER_DROP)
4601 {
4602 rootDomain->tracePoint( kIOPMTracePointSleepWillChangeInterests );
4603
4604 PMEventDetails *details = PMEventDetails::eventDetails(
4605 kIOPMEventTypeAppNotificationsFinished,
4606 NULL,
4607 100,
4608 kIOReturnSuccess);
4609 rootDomain->recordAndReleasePMEventGated( details );
4610 }
4611 else
4612 rootDomain->tracePoint( kIOPMTracePointWakeWillChangeInterests );
4613 }
4614
4615 notifyAll( kIOPM_OurChangeSetPowerState );
4616 }
4617
4618 //*********************************************************************************
4619 // [private] OurChangeSetPowerState
4620 //
4621 // Instruct our controlling driver to program the hardware for the power state
4622 // change. Wait for async completions.
4623 //*********************************************************************************
4624
4625 void IOService::OurChangeSetPowerState ( void )
4626 {
4627 MS_PUSH( kIOPM_OurChangeWaitForPowerSettle );
4628 fMachineState = kIOPM_DriverThreadCallDone;
4629 fDriverCallReason = kDriverCallSetPowerState;
4630
4631 if (notifyControllingDriver() == false)
4632 notifyControllingDriverDone();
4633 }
4634
4635 //*********************************************************************************
4636 // [private] OurChangeWaitForPowerSettle
4637 //
4638 // Our controlling driver has completed the power state change we initiated.
4639 // Wait for the driver specified settle time to expire.
4640 //*********************************************************************************
4641
4642 void IOService::OurChangeWaitForPowerSettle ( void )
4643 {
4644 fMachineState = kIOPM_OurChangeNotifyInterestedDriversDidChange;
4645 startSettleTimer();
4646 }
4647
4648 //*********************************************************************************
4649 // [private] OurChangeNotifyInterestedDriversDidChange
4650 //
4651 // Power has settled on a power change we initiated. Here we notify
4652 // all our interested drivers post-change.
4653 //*********************************************************************************
4654
4655 void IOService::OurChangeNotifyInterestedDriversDidChange ( void )
4656 {
4657 IOPMrootDomain * rootDomain;
4658 if ((rootDomain = getPMRootDomain()) == this)
4659 {
4660 rootDomain->tracePoint( IS_POWER_DROP ?
4661 kIOPMTracePointSleepDidChangeInterests :
4662 kIOPMTracePointWakeDidChangeInterests );
4663 }
4664
4665 notifyAll( kIOPM_OurChangeTellCapabilityDidChange );
4666 }
4667
4668 //*********************************************************************************
4669 // [private] OurChangeTellCapabilityDidChange
4670 //
4671 // For root domain to notify capability power-change.
4672 //*********************************************************************************
4673
4674 void IOService::OurChangeTellCapabilityDidChange ( void )
4675 {
4676 if (!IS_ROOT_DOMAIN)
4677 return OurChangeFinish();
4678
4679 getPMRootDomain()->tracePoint( IS_POWER_DROP ?
4680 kIOPMTracePointSleepCapabilityClients :
4681 kIOPMTracePointWakeCapabilityClients );
4682
4683 tellSystemCapabilityChange( kIOPM_OurChangeFinish );
4684 }
4685
4686 //*********************************************************************************
4687 // [private] OurChangeFinish
4688 //
4689 // Done with this self-induced power state change.
4690 //*********************************************************************************
4691
4692 void IOService::OurChangeFinish ( void )
4693 {
4694 all_done();
4695 }
4696
4697 // MARK: -
4698 // MARK: Power Change Initiated by Parent
4699
4700 //*********************************************************************************
4701 // [private] ParentChangeStart
4702 //
4703 // Here we begin the processing of a power change initiated by our parent.
4704 //*********************************************************************************
4705
4706 IOReturn IOService::ParentChangeStart ( void )
4707 {
4708 PM_ASSERT_IN_GATE();
4709 OUR_PMLog( kPMLogStartParentChange, fHeadNotePowerState, fCurrentPowerState );
4710
4711 // Root power domain has transitioned to its max power state
4712 if ((fHeadNoteChangeFlags & (kIOPMDomainDidChange | kIOPMRootChangeUp)) ==
4713 (kIOPMDomainDidChange | kIOPMRootChangeUp))
4714 {
4715 // Restart the idle timer stopped by ParentChangeRootChangeDown()
4716 if (fIdleTimerPeriod && fIdleTimerStopped)
4717 {
4718 restartIdleTimer();
4719 }
4720 }
4721
4722 // Power domain is forcing us to lower power
4723 if ( fHeadNotePowerState < fCurrentPowerState )
4724 {
4725 PM_ACTION_2(actionPowerChangeStart, fHeadNotePowerState, &fHeadNoteChangeFlags);
4726
4727 // Tell apps and kernel clients
4728 fInitialPowerChange = false;
4729 fMachineState = kIOPM_ParentChangeTellPriorityClientsPowerDown;
4730 tellChangeDown1(fHeadNotePowerState);
4731 return IOPMWillAckLater;
4732 }
4733
4734 // Power domain is raising power
4735 if ( fHeadNotePowerState > fCurrentPowerState )
4736 {
4737 if ( fDesiredPowerState > fCurrentPowerState )
4738 {
4739 if ( fDesiredPowerState < fHeadNotePowerState )
4740 {
4741 // We power up, but not all the way
4742 fHeadNotePowerState = fDesiredPowerState;
4743 fHeadNotePowerArrayEntry = &fPowerStates[fDesiredPowerState];
4744 OUR_PMLog(kPMLogAmendParentChange, fHeadNotePowerState, 0);
4745 }
4746 } else {
4747 // We don't need to change
4748 fHeadNotePowerState = fCurrentPowerState;
4749 fHeadNotePowerArrayEntry = &fPowerStates[fCurrentPowerState];
4750 OUR_PMLog(kPMLogAmendParentChange, fHeadNotePowerState, 0);
4751 }
4752 }
4753
4754 if ( fHeadNoteChangeFlags & kIOPMDomainDidChange )
4755 {
4756 if ( fHeadNotePowerState > fCurrentPowerState )
4757 {
4758 PM_ACTION_2(actionPowerChangeStart,
4759 fHeadNotePowerState, &fHeadNoteChangeFlags);
4760
4761 // Parent did change up - start our change up
4762 fInitialPowerChange = false;
4763 ParentChangeTellCapabilityWillChange();
4764 return IOPMWillAckLater;
4765 }
4766 else if (fHeadNoteChangeFlags & kIOPMRootBroadcastFlags)
4767 {
4768 // No need to change power state, but broadcast change
4769 // to our children.
4770 fMachineState = kIOPM_SyncNotifyDidChange;
4771 fDriverCallReason = kDriverCallInformPreChange;
4772 notifyChildren();
4773 return IOPMWillAckLater;
4774 }
4775 }
4776
4777 all_done();
4778 return IOPMAckImplied;
4779 }
4780
4781 //******************************************************************************
4782 // [private] ParentChangeRootChangeDown
4783 //
4784 // Root domain has finished the transition to the system sleep state. And all
4785 // drivers in the power plane should have powered down. Cancel the idle timer,
4786 // and also reset the device desire for those drivers that don't want power
4787 // automatically restored on wake.
4788 //******************************************************************************
4789
4790 void IOService::ParentChangeRootChangeDown( void )
4791 {
4792 // Always stop the idle timer before root power down
4793 if (fIdleTimerPeriod && !fIdleTimerStopped)
4794 {
4795 fIdleTimerStopped = true;
4796 if (fIdleTimer && thread_call_cancel(fIdleTimer))
4797 release();
4798 }
4799
4800 if (fResetPowerStateOnWake)
4801 {
4802 // Reset device desire down to the lowest power state.
4803 // Advisory tickle desire is intentionally untouched since
4804 // it has no effect until system is promoted to full wake.
4805
4806 if (fDeviceDesire != 0)
4807 {
4808 updatePowerClient(gIOPMPowerClientDevice, 0);
4809 computeDesiredState(0, true);
4810 PM_LOG1("%s: tickle desire removed\n", fName);
4811 }
4812
4813 // Invalidate tickle cache so the next tickle will issue a request
4814 IOLockLock(fActivityLock);
4815 fDeviceWasActive = false;
4816 fActivityTicklePowerState = kInvalidTicklePowerState;
4817 IOLockUnlock(fActivityLock);
4818
4819 fIdleTimerMinPowerState = 0;
4820 }
4821 else if (fAdvisoryTickleUsed)
4822 {
4823 // Less aggressive mechanism to accelerate idle timer expiration
4824 // before system sleep. May not always allow the driver to wake
4825 // up from system sleep in the min power state.
4826
4827 AbsoluteTime now;
4828 uint64_t nsec;
4829 bool dropTickleDesire = false;
4830
4831 if (fIdleTimerPeriod && !fIdleTimerIgnored &&
4832 (fIdleTimerMinPowerState == 0) &&
4833 (fDeviceDesire != 0))
4834 {
4835 IOLockLock(fActivityLock);
4836
4837 if (!fDeviceWasActive)
4838 {
4839 // No tickles since the last idle timer expiration.
4840 // Safe to drop the device desire to zero.
4841 dropTickleDesire = true;
4842 }
4843 else
4844 {
4845 // Was tickled since the last idle timer expiration,
4846 // but not in the last minute.
4847 clock_get_uptime(&now);
4848 SUB_ABSOLUTETIME(&now, &fDeviceActiveTimestamp);
4849 absolutetime_to_nanoseconds(now, &nsec);
4850 if (nsec >= kNoTickleCancelWindow)
4851 {
4852 dropTickleDesire = true;
4853 }
4854 }
4855
4856 if (dropTickleDesire)
4857 {
4858 // Force the next tickle to raise power state
4859 fDeviceWasActive = false;
4860 fActivityTicklePowerState = kInvalidTicklePowerState;
4861 }
4862
4863 IOLockUnlock(fActivityLock);
4864 }
4865
4866 if (dropTickleDesire)
4867 {
4868 // Advisory tickle desire is intentionally untouched since
4869 // it has no effect until system is promoted to full wake.
4870
4871 updatePowerClient(gIOPMPowerClientDevice, 0);
4872 computeDesiredState(0, true);
4873 PM_LOG1("%s: tickle desire dropped\n", fName);
4874 }
4875 }
4876 }
4877
4878 //*********************************************************************************
4879 // [private] ParentChangeTellPriorityClientsPowerDown
4880 //
4881 // All applications and kernel clients have acknowledged our intention to drop
4882 // power. Here we notify "priority" clients that we are lowering power.
4883 //*********************************************************************************
4884
4885 void IOService::ParentChangeTellPriorityClientsPowerDown ( void )
4886 {
4887 fMachineState = kIOPM_ParentChangeNotifyInterestedDriversWillChange;
4888 tellChangeDown2(fHeadNotePowerState);
4889 }
4890
4891 //*********************************************************************************
4892 // [private] ParentChangeTellCapabilityWillChange
4893 //
4894 // All (legacy) applications and kernel clients have acknowledged, extra stage for
4895 // root domain to notify apps and drivers about the system capability change.
4896 //*********************************************************************************
4897
4898 void IOService::ParentChangeTellCapabilityWillChange ( void )
4899 {
4900 if (!IS_ROOT_DOMAIN)
4901 return ParentChangeNotifyInterestedDriversWillChange();
4902
4903 tellSystemCapabilityChange( kIOPM_ParentChangeNotifyInterestedDriversWillChange );
4904 }
4905
4906 //*********************************************************************************
4907 // [private] ParentChangeNotifyInterestedDriversWillChange
4908 //
4909 // All applications and kernel clients have acknowledged our power state change.
4910 // Here we notify interested drivers pre-change.
4911 //*********************************************************************************
4912
4913 void IOService::ParentChangeNotifyInterestedDriversWillChange ( void )
4914 {
4915 notifyAll( kIOPM_ParentChangeSetPowerState );
4916 }
4917
4918 //*********************************************************************************
4919 // [private] ParentChangeSetPowerState
4920 //
4921 // Instruct our controlling driver to program the hardware for the power state
4922 // change. Wait for async completions.
4923 //*********************************************************************************
4924
4925 void IOService::ParentChangeSetPowerState ( void )
4926 {
4927 MS_PUSH( kIOPM_ParentChangeWaitForPowerSettle );
4928 fMachineState = kIOPM_DriverThreadCallDone;
4929 fDriverCallReason = kDriverCallSetPowerState;
4930
4931 if (notifyControllingDriver() == false)
4932 notifyControllingDriverDone();
4933 }
4934
4935 //*********************************************************************************
4936 // [private] ParentChangeWaitForPowerSettle
4937 //
4938 // Our controlling driver has completed the power state change initiated by our
4939 // parent. Wait for the driver specified settle time to expire.
4940 //*********************************************************************************
4941
4942 void IOService::ParentChangeWaitForPowerSettle ( void )
4943 {
4944 fMachineState = kIOPM_ParentChangeNotifyInterestedDriversDidChange;
4945 startSettleTimer();
4946 }
4947
4948 //*********************************************************************************
4949 // [private] ParentChangeNotifyInterestedDriversDidChange
4950 //
4951 // Power has settled on a power change initiated by our parent. Here we notify
4952 // all our interested drivers post-change.
4953 //*********************************************************************************
4954
4955 void IOService::ParentChangeNotifyInterestedDriversDidChange ( void )
4956 {
4957 notifyAll( kIOPM_ParentChangeTellCapabilityDidChange );
4958 }
4959
4960 //*********************************************************************************
4961 // [private] ParentChangeTellCapabilityDidChange
4962 //
4963 // For root domain to notify capability power-change.
4964 //*********************************************************************************
4965
4966 void IOService::ParentChangeTellCapabilityDidChange ( void )
4967 {
4968 if (!IS_ROOT_DOMAIN)
4969 return ParentChangeAcknowledgePowerChange();
4970
4971 tellSystemCapabilityChange( kIOPM_ParentChangeAcknowledgePowerChange );
4972 }
4973
4974 //*********************************************************************************
4975 // [private] ParentAcknowledgePowerChange
4976 //
4977 // Acknowledge our power parent that our power change is done.
4978 //*********************************************************************************
4979
4980 void IOService::ParentChangeAcknowledgePowerChange ( void )
4981 {
4982 IORegistryEntry * nub;
4983 IOService * parent;
4984
4985 nub = fHeadNoteParentConnection;
4986 nub->retain();
4987 all_done();
4988 parent = (IOService *)nub->copyParentEntry(gIOPowerPlane);
4989 if ( parent )
4990 {
4991 parent->acknowledgePowerChange((IOService *)nub);
4992 parent->release();
4993 }
4994 nub->release();
4995 }
4996
4997 // MARK: -
4998 // MARK: Ack and Settle timers
4999
5000 //*********************************************************************************
5001 // [private] settleTimerExpired
5002 //
5003 // Power has settled after our last change. Notify interested parties that
5004 // there is a new power state.
5005 //*********************************************************************************
5006
5007 void IOService::settleTimerExpired( void )
5008 {
5009 fSettleTimeUS = 0;
5010 gIOPMWorkQueue->signalWorkAvailable();
5011 }
5012
5013 //*********************************************************************************
5014 // settle_timer_expired
5015 //
5016 // Holds a retain while the settle timer callout is in flight.
5017 //*********************************************************************************
5018
5019 static void
5020 settle_timer_expired( thread_call_param_t arg0, thread_call_param_t arg1 )
5021 {
5022 IOService * me = (IOService *) arg0;
5023
5024 if (gIOPMWorkLoop && gIOPMWorkQueue)
5025 {
5026 gIOPMWorkLoop->runAction(
5027 OSMemberFunctionCast(IOWorkLoop::Action, me, &IOService::settleTimerExpired),
5028 me);
5029 }
5030 me->release();
5031 }
5032
5033 //*********************************************************************************
5034 // [private] startSettleTimer
5035 //
5036 // Calculate a power-settling delay in microseconds and start a timer.
5037 //*********************************************************************************
5038
5039 void IOService::startSettleTimer( void )
5040 {
5041 #if NOT_USEFUL
5042 // This function is broken and serves no useful purpose since it never
5043 // updates fSettleTimeUS to a non-zero value to stall the state machine,
5044 // yet it starts a delay timer. It appears no driver relies on a delay
5045 // from settleUpTime and settleDownTime in the power state table.
5046
5047 AbsoluteTime deadline;
5048 IOPMPowerStateIndex i;
5049 uint32_t settleTime = 0;
5050 boolean_t pending;
5051
5052 PM_ASSERT_IN_GATE();
5053
5054 i = fCurrentPowerState;
5055
5056 // lowering power
5057 if ( fHeadNotePowerState < fCurrentPowerState )
5058 {
5059 while ( i > fHeadNotePowerState )
5060 {
5061 settleTime += (uint32_t) fPowerStates[i].settleDownTime;
5062 i--;
5063 }
5064 }
5065
5066 // raising power
5067 if ( fHeadNotePowerState > fCurrentPowerState )
5068 {
5069 while ( i < fHeadNotePowerState )
5070 {
5071 settleTime += (uint32_t) fPowerStates[i+1].settleUpTime;
5072 i++;
5073 }
5074 }
5075
5076 if (settleTime)
5077 {
5078 retain();
5079 clock_interval_to_deadline(settleTime, kMicrosecondScale, &deadline);
5080 pending = thread_call_enter_delayed(fSettleTimer, deadline);
5081 if (pending) release();
5082 }
5083 #endif
5084 }
5085
5086 //*********************************************************************************
5087 // [private] ackTimerTick
5088 //
5089 // The acknowledgement timeout periodic timer has ticked.
5090 // If we are awaiting acks for a power change notification,
5091 // we decrement the timer word of each interested driver which hasn't acked.
5092 // If a timer word becomes zero, we pretend the driver aknowledged.
5093 // If we are waiting for the controlling driver to change the power
5094 // state of the hardware, we decrement its timer word, and if it becomes
5095 // zero, we pretend the driver acknowledged.
5096 //
5097 // Returns true if the timer tick made it possible to advance to the next
5098 // machine state, false otherwise.
5099 //*********************************************************************************
5100
5101 #ifndef __LP64__
5102 void IOService::ack_timer_ticked ( void )
5103 {
5104 assert(false);
5105 }
5106 #endif /* !__LP64__ */
5107
5108 bool IOService::ackTimerTick( void )
5109 {
5110 IOPMinformee * nextObject;
5111 bool done = false;
5112
5113 PM_ASSERT_IN_GATE();
5114 switch (fMachineState) {
5115 case kIOPM_OurChangeWaitForPowerSettle:
5116 case kIOPM_ParentChangeWaitForPowerSettle:
5117 // are we waiting for controlling driver to acknowledge?
5118 if ( fDriverTimer > 0 )
5119 {
5120 // yes, decrement timer tick
5121 fDriverTimer--;
5122 if ( fDriverTimer == 0 )
5123 {
5124 // controlling driver is tardy
5125 uint64_t nsec = computeTimeDeltaNS(&fDriverCallStartTime);
5126 OUR_PMLog(kPMLogCtrlDriverTardy, 0, 0);
5127 setProperty(kIOPMTardyAckSPSKey, kOSBooleanTrue);
5128 PM_ERROR("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms\n",
5129 fName, this, fCurrentPowerState, fHeadNotePowerState, NS_TO_MS(nsec));
5130
5131 #if LOG_SETPOWER_TIMES
5132 PMEventDetails *details = PMEventDetails::eventDetails(
5133 kIOPMEventTypeSetPowerStateDelayed, // type
5134 fName, // who
5135 (uintptr_t)this, // owner unique
5136 NULL, // interest name
5137 (uint8_t)getPowerState(), // old
5138 0, // new
5139 kIOReturnTimeout, // result
5140 NS_TO_US(nsec)); // usec completion time
5141
5142 getPMRootDomain()->recordAndReleasePMEventGated( details );
5143 #endif
5144
5145 if (gIOKitDebug & kIOLogDebugPower)
5146 {
5147 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
5148 fName, this, fCurrentPowerState, fHeadNotePowerState, NS_TO_MS(nsec));
5149 }
5150 else
5151 {
5152 // Unblock state machine and pretend driver has acked.
5153 done = true;
5154 }
5155 } else {
5156 // still waiting, set timer again
5157 start_ack_timer();
5158 }
5159 }
5160 break;
5161
5162 case kIOPM_NotifyChildrenStart:
5163 // are we waiting for interested parties to acknowledge?
5164 if ( fHeadNotePendingAcks != 0 )
5165 {
5166 // yes, go through the list of interested drivers
5167 nextObject = fInterestedDrivers->firstInList();
5168 // and check each one
5169 while ( nextObject != NULL )
5170 {
5171 if ( nextObject->timer > 0 )
5172 {
5173 nextObject->timer--;
5174 // this one should have acked by now
5175 if ( nextObject->timer == 0 )
5176 {
5177 uint64_t nsec = computeTimeDeltaNS(&nextObject->startTime);
5178 OUR_PMLog(kPMLogIntDriverTardy, 0, 0);
5179 nextObject->whatObject->setProperty(kIOPMTardyAckPSCKey, kOSBooleanTrue);
5180 PM_ERROR("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) timed out after %d ms\n",
5181 nextObject->whatObject->getName(),
5182 (fDriverCallReason == kDriverCallInformPreChange) ? "Will" : "Did",
5183 nextObject->whatObject, fName, fCurrentPowerState, fHeadNotePowerState,
5184 NS_TO_MS(nsec));
5185
5186 #if LOG_SETPOWER_TIMES
5187 uint16_t logType = (fDriverCallReason == kDriverCallInformPreChange)
5188 ? kIOPMEventTypePSWillChangeTo
5189 : kIOPMEventTypePSDidChangeTo;
5190
5191 PMEventDetails *details = PMEventDetails::eventDetails(
5192 logType, // type
5193 fName, // who
5194 (uintptr_t)this, // owner unique
5195 nextObject->whatObject->getName(), // interest name
5196 (uint8_t)fCurrentPowerState, // old
5197 (uint8_t)fHeadNotePowerState, // new
5198 kIOReturnTimeout, // result
5199 NS_TO_US(nsec)); // usec completion time
5200
5201 getPMRootDomain()->recordAndReleasePMEventGated( details );
5202 #endif
5203
5204 // Pretend driver has acked.
5205 fHeadNotePendingAcks--;
5206 }
5207 }
5208 nextObject = fInterestedDrivers->nextInList(nextObject);
5209 }
5210
5211 // is that the last?
5212 if ( fHeadNotePendingAcks == 0 )
5213 {
5214 // yes, we can continue
5215 done = true;
5216 } else {
5217 // no, set timer again
5218 start_ack_timer();
5219 }
5220 }
5221 break;
5222
5223 // TODO: aggreggate this
5224 case kIOPM_OurChangeTellClientsPowerDown:
5225 case kIOPM_OurChangeTellPriorityClientsPowerDown:
5226 case kIOPM_OurChangeNotifyInterestedDriversWillChange:
5227 case kIOPM_ParentChangeTellPriorityClientsPowerDown:
5228 case kIOPM_ParentChangeNotifyInterestedDriversWillChange:
5229 case kIOPM_SyncTellClientsPowerDown:
5230 case kIOPM_SyncTellPriorityClientsPowerDown:
5231 case kIOPM_SyncNotifyWillChange:
5232 case kIOPM_TellCapabilityChangeDone:
5233 // apps didn't respond in time
5234 cleanClientResponses(true);
5235 OUR_PMLog(kPMLogClientTardy, 0, 1);
5236 // tardy equates to approval
5237 done = true;
5238 break;
5239
5240 default:
5241 PM_LOG1("%s: unexpected ack timer tick (state = %d)\n",
5242 getName(), fMachineState);
5243 break;
5244 }
5245 return done;
5246 }
5247
5248 //*********************************************************************************
5249 // [private] start_ack_timer
5250 //*********************************************************************************
5251
5252 void IOService::start_ack_timer ( void )
5253 {
5254 start_ack_timer( ACK_TIMER_PERIOD, kNanosecondScale );
5255 }
5256
5257 void IOService::start_ack_timer ( UInt32 interval, UInt32 scale )
5258 {
5259 AbsoluteTime deadline;
5260 boolean_t pending;
5261
5262 clock_interval_to_deadline(interval, scale, &deadline);
5263
5264 retain();
5265 pending = thread_call_enter_delayed(fAckTimer, deadline);
5266 if (pending) release();
5267 }
5268
5269 //*********************************************************************************
5270 // [private] stop_ack_timer
5271 //*********************************************************************************
5272
5273 void IOService::stop_ack_timer ( void )
5274 {
5275 boolean_t pending;
5276
5277 pending = thread_call_cancel(fAckTimer);
5278 if (pending) release();
5279 }
5280
5281 //*********************************************************************************
5282 // [static] actionAckTimerExpired
5283 //
5284 // Inside PM work loop's gate.
5285 //*********************************************************************************
5286
5287 IOReturn
5288 IOService::actionAckTimerExpired (
5289 OSObject * target,
5290 void * arg0, void * arg1,
5291 void * arg2, void * arg3 )
5292 {
5293 IOService * me = (IOService *) target;
5294 bool done;
5295
5296 // done will be true if the timer tick unblocks the machine state,
5297 // otherwise no need to signal the work loop.
5298
5299 done = me->ackTimerTick();
5300 if (done && gIOPMWorkQueue)
5301 gIOPMWorkQueue->signalWorkAvailable();
5302
5303 return kIOReturnSuccess;
5304 }
5305
5306 //*********************************************************************************
5307 // ack_timer_expired
5308 //
5309 // Thread call function. Holds a retain while the callout is in flight.
5310 //*********************************************************************************
5311
5312 void
5313 IOService::ack_timer_expired ( thread_call_param_t arg0, thread_call_param_t arg1 )
5314 {
5315 IOService * me = (IOService *) arg0;
5316
5317 if (gIOPMWorkLoop)
5318 {
5319 gIOPMWorkLoop->runAction(&actionAckTimerExpired, me);
5320 }
5321 me->release();
5322 }
5323
5324 // MARK: -
5325 // MARK: Client Messaging
5326
5327 //*********************************************************************************
5328 // [private] tellSystemCapabilityChange
5329 //*********************************************************************************
5330
5331 void IOService::tellSystemCapabilityChange( uint32_t nextMS )
5332 {
5333 MS_PUSH( nextMS );
5334 fMachineState = kIOPM_TellCapabilityChangeDone;
5335 fOutOfBandMessage = kIOMessageSystemCapabilityChange;
5336
5337 if (fIsPreChange)
5338 {
5339 // Notify app first on pre-change.
5340 fOutOfBandParameter = kNotifyCapabilityChangeApps;
5341 }
5342 else
5343 {
5344 // Notify kernel clients first on post-change.
5345 fOutOfBandParameter = kNotifyCapabilityChangePriority;
5346 }
5347
5348 tellClientsWithResponse( fOutOfBandMessage );
5349 }
5350
5351 //*********************************************************************************
5352 // [public] askChangeDown
5353 //
5354 // Ask registered applications and kernel clients if we can change to a lower
5355 // power state.
5356 //
5357 // Subclass can override this to send a different message type. Parameter is
5358 // the destination state number.
5359 //
5360 // Return true if we don't have to wait for acknowledgements
5361 //*********************************************************************************
5362
5363 bool IOService::askChangeDown ( unsigned long stateNum )
5364 {
5365 return tellClientsWithResponse( kIOMessageCanDevicePowerOff );
5366 }
5367
5368 //*********************************************************************************
5369 // [private] tellChangeDown1
5370 //
5371 // Notify registered applications and kernel clients that we are definitely
5372 // dropping power.
5373 //
5374 // Return true if we don't have to wait for acknowledgements
5375 //*********************************************************************************
5376
5377 bool IOService::tellChangeDown1 ( unsigned long stateNum )
5378 {
5379 fOutOfBandParameter = kNotifyApps;
5380 return tellChangeDown(stateNum);
5381 }
5382
5383 //*********************************************************************************
5384 // [private] tellChangeDown2
5385 //
5386 // Notify priority clients that we are definitely dropping power.
5387 //
5388 // Return true if we don't have to wait for acknowledgements
5389 //*********************************************************************************
5390
5391 bool IOService::tellChangeDown2 ( unsigned long stateNum )
5392 {
5393 fOutOfBandParameter = kNotifyPriority;
5394 return tellChangeDown(stateNum);
5395 }
5396
5397 //*********************************************************************************
5398 // [public] tellChangeDown
5399 //
5400 // Notify registered applications and kernel clients that we are definitely
5401 // dropping power.
5402 //
5403 // Subclass can override this to send a different message type. Parameter is
5404 // the destination state number.
5405 //
5406 // Return true if we don't have to wait for acknowledgements
5407 //*********************************************************************************
5408
5409 bool IOService::tellChangeDown ( unsigned long stateNum )
5410 {
5411 return tellClientsWithResponse( kIOMessageDeviceWillPowerOff );
5412 }
5413
5414 //*********************************************************************************
5415 // cleanClientResponses
5416 //
5417 //*********************************************************************************
5418
5419 static void logAppTimeouts ( OSObject * object, void * arg )
5420 {
5421 IOPMInterestContext * context = (IOPMInterestContext *) arg;
5422 OSObject * flag;
5423 unsigned int clientIndex;
5424
5425 if (OSDynamicCast(_IOServiceInterestNotifier, object))
5426 {
5427 // Discover the 'counter' value or index assigned to this client
5428 // when it was notified, by searching for the array index of the
5429 // client in an array holding the cached interested clients.
5430
5431 clientIndex = context->notifyClients->getNextIndexOfObject(object, 0);
5432
5433 if ((clientIndex != (unsigned int) -1) &&
5434 (flag = context->responseArray->getObject(clientIndex)) &&
5435 (flag != kOSBooleanTrue))
5436 {
5437 OSString *logClientID = NULL;
5438 OSNumber *clientID = copyClientIDForNotification(object, context);
5439
5440 if (clientID) {
5441 logClientID = IOCopyLogNameForPID(clientID->unsigned32BitValue());
5442 clientID->release();
5443 }
5444
5445 PM_ERROR(context->errorLog, logClientID ? logClientID->getCStringNoCopy() : "");
5446
5447 // TODO: record message type if possible
5448 IOService::getPMRootDomain()->pmStatsRecordApplicationResponse(
5449 gIOPMStatsApplicationResponseTimedOut,
5450 logClientID ? logClientID->getCStringNoCopy() : "",
5451 0, (30*1000), -1);
5452
5453 if (logClientID)
5454 logClientID->release();
5455 }
5456 }
5457 }
5458
5459 void IOService::cleanClientResponses ( bool logErrors )
5460 {
5461 if (logErrors && fResponseArray)
5462 {
5463 switch ( fOutOfBandParameter ) {
5464 case kNotifyApps:
5465 case kNotifyCapabilityChangeApps:
5466 if (fNotifyClientArray)
5467 {
5468 IOPMInterestContext context;
5469
5470 context.responseArray = fResponseArray;
5471 context.notifyClients = fNotifyClientArray;
5472 context.serialNumber = fSerialNumber;
5473 context.messageType = kIOMessageCopyClientID;
5474 context.notifyType = kNotifyApps;
5475 context.isPreChange = fIsPreChange;
5476 context.enableTracing = false;
5477 context.us = this;
5478 context.maxTimeRequested = 0;
5479 context.stateNumber = fHeadNotePowerState;
5480 context.stateFlags = fHeadNotePowerArrayEntry->capabilityFlags;
5481 context.changeFlags = fHeadNoteChangeFlags;
5482 context.errorLog = "PM notification timeout (%s)\n";
5483
5484 applyToInterested(gIOAppPowerStateInterest, logAppTimeouts, (void *) &context);
5485 }
5486 break;
5487
5488 default:
5489 // kNotifyPriority, kNotifyCapabilityChangePriority
5490 // TODO: identify the priority client that has not acked
5491 PM_ERROR("PM priority notification timeout\n");
5492 if (gIOKitDebug & kIOLogDebugPower)
5493 {
5494 panic("PM priority notification timeout");
5495 }
5496 break;
5497 }
5498 }
5499
5500 if (fResponseArray)
5501 {
5502 fResponseArray->release();
5503 fResponseArray = NULL;
5504 }
5505 if (fNotifyClientArray)
5506 {
5507 fNotifyClientArray->release();
5508 fNotifyClientArray = NULL;
5509 }
5510 }
5511
5512 //*********************************************************************************
5513 // [protected] tellClientsWithResponse
5514 //
5515 // Notify registered applications and kernel clients that we are definitely
5516 // dropping power.
5517 //
5518 // Return true if we don't have to wait for acknowledgements
5519 //*********************************************************************************
5520
5521 bool IOService::tellClientsWithResponse ( int messageType )
5522 {
5523 IOPMInterestContext context;
5524 bool isRootDomain = IS_ROOT_DOMAIN;
5525
5526 PM_ASSERT_IN_GATE();
5527 assert( fResponseArray == NULL );
5528 assert( fNotifyClientArray == NULL );
5529
5530 RD_LOG("tellClientsWithResponse( %s, %d )\n",
5531 getIOMessageString(messageType), fOutOfBandParameter);
5532
5533 fResponseArray = OSArray::withCapacity( 1 );
5534 if (!fResponseArray)
5535 goto exit;
5536
5537 fResponseArray->setCapacityIncrement(8);
5538 if (++fSerialNumber == 0)
5539 fSerialNumber++;
5540
5541 context.responseArray = fResponseArray;
5542 context.notifyClients = 0;
5543 context.serialNumber = fSerialNumber;
5544 context.messageType = messageType;
5545 context.notifyType = fOutOfBandParameter;
5546 context.isPreChange = fIsPreChange;
5547 context.enableTracing = false;
5548 context.us = this;
5549 context.maxTimeRequested = 0;
5550 context.stateNumber = fHeadNotePowerState;
5551 context.stateFlags = fHeadNotePowerArrayEntry->capabilityFlags;
5552 context.changeFlags = fHeadNoteChangeFlags;
5553 context.messageFilter = (isRootDomain) ?
5554 OSMemberFunctionCast(
5555 IOPMMessageFilter,
5556 this,
5557 &IOPMrootDomain::systemMessageFilter) : 0;
5558
5559 switch ( fOutOfBandParameter ) {
5560 case kNotifyApps:
5561 applyToInterested( gIOAppPowerStateInterest,
5562 pmTellAppWithResponse, (void *) &context );
5563
5564 if (isRootDomain &&
5565 (fMachineState != kIOPM_OurChangeTellClientsPowerDown) &&
5566 (fMachineState != kIOPM_SyncTellClientsPowerDown))
5567 {
5568 // Notify capability app for tellChangeDown1()
5569 // but not for askChangeDown().
5570 context.notifyType = kNotifyCapabilityChangeApps;
5571 context.messageType = kIOMessageSystemCapabilityChange;
5572 applyToInterested( gIOAppPowerStateInterest,
5573 pmTellCapabilityAppWithResponse, (void *) &context );
5574 context.notifyType = fOutOfBandParameter;
5575 context.messageType = messageType;
5576 }
5577 context.maxTimeRequested = k30Seconds;
5578
5579 applyToInterested( gIOGeneralInterest,
5580 pmTellClientWithResponse, (void *) &context );
5581
5582 fNotifyClientArray = context.notifyClients;
5583 break;
5584
5585 case kNotifyPriority:
5586 context.enableTracing = isRootDomain;
5587 applyToInterested( gIOPriorityPowerStateInterest,
5588 pmTellClientWithResponse, (void *) &context );
5589
5590 if (isRootDomain)
5591 {
5592 // Notify capability clients for tellChangeDown2().
5593 context.notifyType = kNotifyCapabilityChangePriority;
5594 context.messageType = kIOMessageSystemCapabilityChange;
5595 applyToInterested( gIOPriorityPowerStateInterest,
5596 pmTellCapabilityClientWithResponse, (void *) &context );
5597 }
5598 break;
5599
5600 case kNotifyCapabilityChangeApps:
5601 applyToInterested( gIOAppPowerStateInterest,
5602 pmTellCapabilityAppWithResponse, (void *) &context );
5603 fNotifyClientArray = context.notifyClients;
5604 context.maxTimeRequested = k30Seconds;
5605 break;
5606
5607 case kNotifyCapabilityChangePriority:
5608 applyToInterested( gIOPriorityPowerStateInterest,
5609 pmTellCapabilityClientWithResponse, (void *) &context );
5610 break;
5611 }
5612
5613 // do we have to wait for somebody?
5614 if ( !checkForDone() )
5615 {
5616 OUR_PMLog(kPMLogStartAckTimer, context.maxTimeRequested, 0);
5617 if (context.enableTracing)
5618 getPMRootDomain()->traceDetail( context.maxTimeRequested / 1000 );
5619 start_ack_timer( context.maxTimeRequested / 1000, kMillisecondScale );
5620 return false;
5621 }
5622
5623 exit:
5624 // everybody responded
5625 if (fResponseArray)
5626 {
5627 fResponseArray->release();
5628 fResponseArray = NULL;
5629 }
5630 if (fNotifyClientArray)
5631 {
5632 fNotifyClientArray->release();
5633 fNotifyClientArray = NULL;
5634 }
5635
5636 return true;
5637 }
5638
5639 //*********************************************************************************
5640 // [static private] pmTellAppWithResponse
5641 //
5642 // We send a message to an application, and we expect a response, so we compute a
5643 // cookie we can identify the response with.
5644 //*********************************************************************************
5645
5646 void IOService::pmTellAppWithResponse ( OSObject * object, void * arg )
5647 {
5648 IOPMInterestContext * context = (IOPMInterestContext *) arg;
5649 IOServicePM * pwrMgt = context->us->pwrMgt;
5650 uint32_t msgIndex, msgRef, msgType;
5651 OSNumber *clientID = NULL;
5652 proc_t proc = NULL;
5653 boolean_t proc_suspended = FALSE;
5654 #if LOG_APP_RESPONSE_TIMES
5655 AbsoluteTime now;
5656 #endif
5657
5658 if (!OSDynamicCast(_IOServiceInterestNotifier, object))
5659 return;
5660
5661 if (context->us == getPMRootDomain())
5662 {
5663 if ((clientID = copyClientIDForNotification(object, context)))
5664 {
5665 uint32_t clientPID = clientID->unsigned32BitValue();
5666 clientID->release();
5667 proc = proc_find(clientPID);
5668
5669 if (proc)
5670 {
5671 proc_suspended = get_task_pidsuspended((task_t) proc->task);
5672 proc_rele(proc);
5673
5674 if (proc_suspended)
5675 {
5676 logClientIDForNotification(object, context, "PMTellAppWithResponse - Suspended");
5677 return;
5678 }
5679 }
5680 }
5681 }
5682
5683 if (context->messageFilter &&
5684 !context->messageFilter(context->us, object, context, 0, 0))
5685 {
5686 if (kIOLogDebugPower & gIOKitDebug)
5687 {
5688 logClientIDForNotification(object, context, "DROP App");
5689 }
5690 return;
5691 }
5692
5693 // Create client array (for tracking purposes) only if the service
5694 // has app clients. Usually only root domain does.
5695 if (0 == context->notifyClients)
5696 context->notifyClients = OSArray::withCapacity( 32 );
5697
5698 msgType = context->messageType;
5699 msgIndex = context->responseArray->getCount();
5700 msgRef = ((context->serialNumber & 0xFFFF) << 16) + (msgIndex & 0xFFFF);
5701
5702 OUR_PMLog(kPMLogAppNotify, msgType, msgRef);
5703 if (kIOLogDebugPower & gIOKitDebug)
5704 {
5705 logClientIDForNotification(object, context, "MESG App");
5706 }
5707
5708 #if LOG_APP_RESPONSE_TIMES
5709 OSNumber * num;
5710 clock_get_uptime(&now);
5711 num = OSNumber::withNumber(AbsoluteTime_to_scalar(&now), sizeof(uint64_t) * 8);
5712 if (num)
5713 {
5714 context->responseArray->setObject(msgIndex, num);
5715 num->release();
5716 }
5717 else
5718 #endif
5719 context->responseArray->setObject(msgIndex, kOSBooleanFalse);
5720
5721 if (context->notifyClients)
5722 context->notifyClients->setObject(msgIndex, object);
5723
5724 context->us->messageClient(msgType, object, (void *) msgRef);
5725 }
5726
5727 //*********************************************************************************
5728 // [static private] pmTellClientWithResponse
5729 //
5730 // We send a message to an in-kernel client, and we expect a response,
5731 // so we compute a cookie we can identify the response with.
5732 //*********************************************************************************
5733
5734 void IOService::pmTellClientWithResponse ( OSObject * object, void * arg )
5735 {
5736 IOPowerStateChangeNotification notify;
5737 IOPMInterestContext * context = (IOPMInterestContext *) arg;
5738 OSObject * replied = kOSBooleanTrue;
5739 _IOServiceInterestNotifier * notifier;
5740 uint32_t msgIndex, msgRef, msgType;
5741 IOReturn retCode;
5742
5743 if (context->messageFilter &&
5744 !context->messageFilter(context->us, object, context, 0, 0))
5745 {
5746 if ((kIOLogDebugPower & gIOKitDebug) &&
5747 (OSDynamicCast(_IOServiceInterestNotifier, object)))
5748 {
5749 _IOServiceInterestNotifier *n = (_IOServiceInterestNotifier *) object;
5750 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
5751 context->us->getName(),
5752 getIOMessageString(context->messageType),
5753 object, n->handler);
5754 }
5755 return;
5756 }
5757
5758 notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
5759 msgType = context->messageType;
5760 msgIndex = context->responseArray->getCount();
5761 msgRef = ((context->serialNumber & 0xFFFF) << 16) + (msgIndex & 0xFFFF);
5762
5763 IOServicePM * pwrMgt = context->us->pwrMgt;
5764 if (gIOKitDebug & kIOLogPower) {
5765 OUR_PMLog(kPMLogClientNotify, msgRef, msgType);
5766 if (OSDynamicCast(IOService, object)) {
5767 const char *who = ((IOService *) object)->getName();
5768 gPlatform->PMLog(who, kPMLogClientNotify, (uintptr_t) object, 0);
5769 }
5770 else if (notifier) {
5771 OUR_PMLog(kPMLogClientNotify, (uintptr_t) notifier->handler, 0);
5772 }
5773 }
5774 if ((kIOLogDebugPower & gIOKitDebug) && notifier)
5775 {
5776 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
5777 context->us->getName(),
5778 getIOMessageString(msgType),
5779 object, notifier->handler);
5780 }
5781
5782 notify.powerRef = (void *)(uintptr_t) msgRef;
5783 notify.returnValue = 0;
5784 notify.stateNumber = context->stateNumber;
5785 notify.stateFlags = context->stateFlags;
5786
5787 if (context->enableTracing && (notifier != 0))
5788 {
5789 uint32_t detail = ((msgIndex & 0xff) << 24) |
5790 ((msgType & 0xfff) << 12) |
5791 (((uintptr_t) notifier->handler) & 0xfff);
5792 getPMRootDomain()->traceDetail( detail );
5793 }
5794
5795 retCode = context->us->messageClient(msgType, object, (void *) &notify, sizeof(notify));
5796
5797 if (kIOReturnSuccess == retCode)
5798 {
5799 if (0 == notify.returnValue) {
5800 OUR_PMLog(kPMLogClientAcknowledge, msgRef, (uintptr_t) object);
5801 } else {
5802 replied = kOSBooleanFalse;
5803 if ( notify.returnValue > context->maxTimeRequested )
5804 {
5805 if (notify.returnValue > kPriorityClientMaxWait)
5806 {
5807 context->maxTimeRequested = kPriorityClientMaxWait;
5808 PM_ERROR("%s: client %p returned %llu for %s\n",
5809 context->us->getName(),
5810 notifier ? (void *) notifier->handler : object,
5811 (uint64_t) notify.returnValue,
5812 getIOMessageString(msgType));
5813 }
5814 else
5815 context->maxTimeRequested = notify.returnValue;
5816 }
5817 }
5818 } else {
5819 // not a client of ours
5820 // so we won't be waiting for response
5821 OUR_PMLog(kPMLogClientAcknowledge, msgRef, 0);
5822 }
5823
5824 context->responseArray->setObject(msgIndex, replied);
5825 }
5826
5827 //*********************************************************************************
5828 // [static private] pmTellCapabilityAppWithResponse
5829 //*********************************************************************************
5830
5831 void IOService::pmTellCapabilityAppWithResponse ( OSObject * object, void * arg )
5832 {
5833 IOPMSystemCapabilityChangeParameters msgArg;
5834 IOPMInterestContext * context = (IOPMInterestContext *) arg;
5835 OSObject * replied = kOSBooleanTrue;
5836 IOServicePM * pwrMgt = context->us->pwrMgt;
5837 uint32_t msgIndex, msgRef, msgType;
5838 #if LOG_APP_RESPONSE_TIMES
5839 AbsoluteTime now;
5840 #endif
5841
5842 if (!OSDynamicCast(_IOServiceInterestNotifier, object))
5843 return;
5844
5845 memset(&msgArg, 0, sizeof(msgArg));
5846 if (context->messageFilter &&
5847 !context->messageFilter(context->us, object, context, &msgArg, &replied))
5848 {
5849 return;
5850 }
5851
5852 // Create client array (for tracking purposes) only if the service
5853 // has app clients. Usually only root domain does.
5854 if (0 == context->notifyClients)
5855 context->notifyClients = OSArray::withCapacity( 32 );
5856
5857 msgType = context->messageType;
5858 msgIndex = context->responseArray->getCount();
5859 msgRef = ((context->serialNumber & 0xFFFF) << 16) + (msgIndex & 0xFFFF);
5860
5861 OUR_PMLog(kPMLogAppNotify, msgType, msgRef);
5862 if (kIOLogDebugPower & gIOKitDebug)
5863 {
5864 // Log client pid/name and client array index.
5865 OSNumber * clientID = NULL;
5866 OSString * clientIDString = NULL;;
5867 context->us->messageClient(kIOMessageCopyClientID, object, &clientID);
5868 if (clientID) {
5869 clientIDString = IOCopyLogNameForPID(clientID->unsigned32BitValue());
5870 }
5871
5872 PM_LOG("%s MESG App(%u) %s, wait %u, %s\n",
5873 context->us->getName(),
5874 msgIndex, getIOMessageString(msgType),
5875 (replied != kOSBooleanTrue),
5876 clientIDString ? clientIDString->getCStringNoCopy() : "");
5877 if (clientID) clientID->release();
5878 if (clientIDString) clientIDString->release();
5879 }
5880
5881 msgArg.notifyRef = msgRef;
5882 msgArg.maxWaitForReply = 0;
5883
5884 if (replied == kOSBooleanTrue)
5885 {
5886 msgArg.notifyRef = 0;
5887 context->responseArray->setObject(msgIndex, kOSBooleanTrue);
5888 if (context->notifyClients)
5889 context->notifyClients->setObject(msgIndex, kOSBooleanTrue);
5890 }
5891 else
5892 {
5893 #if LOG_APP_RESPONSE_TIMES
5894 OSNumber * num;
5895 clock_get_uptime(&now);
5896 num = OSNumber::withNumber(AbsoluteTime_to_scalar(&now), sizeof(uint64_t) * 8);
5897 if (num)
5898 {
5899 context->responseArray->setObject(msgIndex, num);
5900 num->release();
5901 }
5902 else
5903 #endif
5904 context->responseArray->setObject(msgIndex, kOSBooleanFalse);
5905
5906 if (context->notifyClients)
5907 context->notifyClients->setObject(msgIndex, object);
5908 }
5909
5910 context->us->messageClient(msgType, object, (void *) &msgArg, sizeof(msgArg));
5911 }
5912
5913 //*********************************************************************************
5914 // [static private] pmTellCapabilityClientWithResponse
5915 //*********************************************************************************
5916
5917 void IOService::pmTellCapabilityClientWithResponse(
5918 OSObject * object, void * arg )
5919 {
5920 IOPMSystemCapabilityChangeParameters msgArg;
5921 IOPMInterestContext * context = (IOPMInterestContext *) arg;
5922 OSObject * replied = kOSBooleanTrue;
5923 _IOServiceInterestNotifier * notifier;
5924 uint32_t msgIndex, msgRef, msgType;
5925 IOReturn retCode;
5926
5927 memset(&msgArg, 0, sizeof(msgArg));
5928 if (context->messageFilter &&
5929 !context->messageFilter(context->us, object, context, &msgArg, 0))
5930 {
5931 if ((kIOLogDebugPower & gIOKitDebug) &&
5932 (OSDynamicCast(_IOServiceInterestNotifier, object)))
5933 {
5934 _IOServiceInterestNotifier *n = (_IOServiceInterestNotifier *) object;
5935 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
5936 context->us->getName(),
5937 getIOMessageString(context->messageType),
5938 object, n->handler);
5939 }
5940 return;
5941 }
5942
5943 notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
5944 msgType = context->messageType;
5945 msgIndex = context->responseArray->getCount();
5946 msgRef = ((context->serialNumber & 0xFFFF) << 16) + (msgIndex & 0xFFFF);
5947
5948 IOServicePM * pwrMgt = context->us->pwrMgt;
5949 if (gIOKitDebug & kIOLogPower) {
5950 OUR_PMLog(kPMLogClientNotify, msgRef, msgType);
5951 if (OSDynamicCast(IOService, object)) {
5952 const char *who = ((IOService *) object)->getName();
5953 gPlatform->PMLog(who, kPMLogClientNotify, (uintptr_t) object, 0);
5954 }
5955 else if (notifier) {
5956 OUR_PMLog(kPMLogClientNotify, (uintptr_t) notifier->handler, 0);
5957 }
5958 }
5959 if ((kIOLogDebugPower & gIOKitDebug) && notifier)
5960 {
5961 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
5962 context->us->getName(),
5963 getIOMessageString(msgType),
5964 object, notifier->handler);
5965 }
5966
5967 msgArg.notifyRef = msgRef;
5968 msgArg.maxWaitForReply = 0;
5969
5970 if (context->enableTracing && (notifier != 0))
5971 {
5972 uint32_t detail = ((msgIndex & 0xff) << 24) |
5973 ((msgType & 0xfff) << 12) |
5974 (((uintptr_t) notifier->handler) & 0xfff);
5975 getPMRootDomain()->traceDetail( detail );
5976 }
5977
5978 retCode = context->us->messageClient(
5979 msgType, object, (void *) &msgArg, sizeof(msgArg));
5980
5981 if ( kIOReturnSuccess == retCode )
5982 {
5983 if ( 0 == msgArg.maxWaitForReply )
5984 {
5985 // client doesn't want time to respond
5986 OUR_PMLog(kPMLogClientAcknowledge, msgRef, (uintptr_t) object);
5987 }
5988 else
5989 {
5990 replied = kOSBooleanFalse;
5991 if ( msgArg.maxWaitForReply > context->maxTimeRequested )
5992 {
5993 if (msgArg.maxWaitForReply > kCapabilityClientMaxWait)
5994 {
5995 context->maxTimeRequested = kCapabilityClientMaxWait;
5996 PM_ERROR("%s: client %p returned %u for %s\n",
5997 context->us->getName(),
5998 notifier ? (void *) notifier->handler : object,
5999 msgArg.maxWaitForReply,
6000 getIOMessageString(msgType));
6001 }
6002 else
6003 context->maxTimeRequested = msgArg.maxWaitForReply;
6004 }
6005 }
6006 }
6007 else
6008 {
6009 // not a client of ours
6010 // so we won't be waiting for response
6011 OUR_PMLog(kPMLogClientAcknowledge, msgRef, 0);
6012 }
6013
6014 context->responseArray->setObject(msgIndex, replied);
6015 }
6016
6017 //*********************************************************************************
6018 // [public] tellNoChangeDown
6019 //
6020 // Notify registered applications and kernel clients that we are not
6021 // dropping power.
6022 //
6023 // Subclass can override this to send a different message type. Parameter is
6024 // the aborted destination state number.
6025 //*********************************************************************************
6026
6027 void IOService::tellNoChangeDown ( unsigned long )
6028 {
6029 return tellClients( kIOMessageDeviceWillNotPowerOff );
6030 }
6031
6032 //*********************************************************************************
6033 // [public] tellChangeUp
6034 //
6035 // Notify registered applications and kernel clients that we are raising power.
6036 //
6037 // Subclass can override this to send a different message type. Parameter is
6038 // the aborted destination state number.
6039 //*********************************************************************************
6040
6041 void IOService::tellChangeUp ( unsigned long )
6042 {
6043 return tellClients( kIOMessageDeviceHasPoweredOn );
6044 }
6045
6046 //*********************************************************************************
6047 // [protected] tellClients
6048 //
6049 // Notify registered applications and kernel clients of something.
6050 //*********************************************************************************
6051
6052 void IOService::tellClients ( int messageType )
6053 {
6054 IOPMInterestContext context;
6055
6056 RD_LOG("tellClients( %s )\n", getIOMessageString(messageType));
6057
6058 memset(&context, 0, sizeof(context));
6059 context.messageType = messageType;
6060 context.isPreChange = fIsPreChange;
6061 context.us = this;
6062 context.stateNumber = fHeadNotePowerState;
6063 context.stateFlags = fHeadNotePowerArrayEntry->capabilityFlags;
6064 context.changeFlags = fHeadNoteChangeFlags;
6065 context.messageFilter = (IS_ROOT_DOMAIN) ?
6066 OSMemberFunctionCast(
6067 IOPMMessageFilter,
6068 this,
6069 &IOPMrootDomain::systemMessageFilter) : 0;
6070
6071 context.notifyType = kNotifyPriority;
6072 applyToInterested( gIOPriorityPowerStateInterest,
6073 tellKernelClientApplier, (void *) &context );
6074
6075 context.notifyType = kNotifyApps;
6076 applyToInterested( gIOAppPowerStateInterest,
6077 tellAppClientApplier, (void *) &context );
6078
6079 applyToInterested( gIOGeneralInterest,
6080 tellKernelClientApplier, (void *) &context );
6081 }
6082
6083 //*********************************************************************************
6084 // [private] tellKernelClientApplier
6085 //
6086 // Message a kernel client.
6087 //*********************************************************************************
6088
6089 static void tellKernelClientApplier ( OSObject * object, void * arg )
6090 {
6091 IOPowerStateChangeNotification notify;
6092 IOPMInterestContext * context = (IOPMInterestContext *) arg;
6093
6094 if (context->messageFilter &&
6095 !context->messageFilter(context->us, object, context, 0, 0))
6096 {
6097 if ((kIOLogDebugPower & gIOKitDebug) &&
6098 (OSDynamicCast(_IOServiceInterestNotifier, object)))
6099 {
6100 _IOServiceInterestNotifier *n = (_IOServiceInterestNotifier *) object;
6101 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6102 context->us->getName(),
6103 IOService::getIOMessageString(context->messageType),
6104 object, n->handler);
6105 }
6106 return;
6107 }
6108
6109 notify.powerRef = (void *) 0;
6110 notify.returnValue = 0;
6111 notify.stateNumber = context->stateNumber;
6112 notify.stateFlags = context->stateFlags;
6113
6114 context->us->messageClient(context->messageType, object, &notify, sizeof(notify));
6115
6116 if ((kIOLogDebugPower & gIOKitDebug) &&
6117 (OSDynamicCast(_IOServiceInterestNotifier, object)))
6118 {
6119 _IOServiceInterestNotifier *n = (_IOServiceInterestNotifier *) object;
6120 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6121 context->us->getName(),
6122 IOService::getIOMessageString(context->messageType),
6123 object, n->handler);
6124 }
6125 }
6126
6127 static OSNumber * copyClientIDForNotification(
6128 OSObject *object,
6129 IOPMInterestContext *context)
6130 {
6131 OSNumber *clientID = NULL;
6132 context->us->messageClient(kIOMessageCopyClientID, object, &clientID);
6133 return clientID;
6134 }
6135
6136 static void logClientIDForNotification(
6137 OSObject *object,
6138 IOPMInterestContext *context,
6139 const char *logString)
6140 {
6141 OSString *logClientID = NULL;
6142 OSNumber *clientID = copyClientIDForNotification(object, context);
6143
6144 if (logString)
6145 {
6146 if (clientID)
6147 logClientID = IOCopyLogNameForPID(clientID->unsigned32BitValue());
6148
6149 PM_LOG("%s %s %s, %s\n",
6150 context->us->getName(), logString,
6151 IOService::getIOMessageString(context->messageType),
6152 logClientID ? logClientID->getCStringNoCopy() : "");
6153
6154 if (logClientID)
6155 logClientID->release();
6156 }
6157
6158 if (clientID)
6159 clientID->release();
6160
6161 return;
6162 }
6163
6164
6165 static void tellAppClientApplier ( OSObject * object, void * arg )
6166 {
6167 IOPMInterestContext * context = (IOPMInterestContext *) arg;
6168 OSNumber * clientID = NULL;
6169 proc_t proc = NULL;
6170 boolean_t proc_suspended = FALSE;
6171
6172 if (context->us == IOService::getPMRootDomain())
6173 {
6174 if ((clientID = copyClientIDForNotification(object, context)))
6175 {
6176 uint32_t clientPID = clientID->unsigned32BitValue();
6177 clientID->release();
6178 proc = proc_find(clientPID);
6179
6180 if (proc)
6181 {
6182 proc_suspended = get_task_pidsuspended((task_t) proc->task);
6183 proc_rele(proc);
6184
6185 if (proc_suspended)
6186 {
6187 logClientIDForNotification(object, context, "tellAppClientApplier - Suspended");
6188 return;
6189 }
6190 }
6191 }
6192 }
6193
6194 if (context->messageFilter &&
6195 !context->messageFilter(context->us, object, context, 0, 0))
6196 {
6197 if (kIOLogDebugPower & gIOKitDebug)
6198 {
6199 logClientIDForNotification(object, context, "DROP App");
6200 }
6201 return;
6202 }
6203
6204 if (kIOLogDebugPower & gIOKitDebug)
6205 {
6206 logClientIDForNotification(object, context, "MESG App");
6207 }
6208
6209 context->us->messageClient(context->messageType, object, 0);
6210 }
6211
6212 //*********************************************************************************
6213 // [private] checkForDone
6214 //*********************************************************************************
6215
6216 bool IOService::checkForDone ( void )
6217 {
6218 int i = 0;
6219 OSObject * theFlag;
6220
6221 if (fResponseArray == NULL) {
6222 return true;
6223 }
6224
6225 for (i = 0; ; i++) {
6226 theFlag = fResponseArray->getObject(i);
6227
6228 if (NULL == theFlag) {
6229 break;
6230 }
6231
6232 if (kOSBooleanTrue != theFlag) {
6233 return false;
6234 }
6235 }
6236 return true;
6237 }
6238
6239 //*********************************************************************************
6240 // [public] responseValid
6241 //*********************************************************************************
6242
6243 bool IOService::responseValid ( uint32_t refcon, int pid )
6244 {
6245 UInt16 serialComponent;
6246 UInt16 ordinalComponent;
6247 OSObject * theFlag;
6248
6249 serialComponent = (refcon >> 16) & 0xFFFF;
6250 ordinalComponent = (refcon & 0xFFFF);
6251
6252 if ( serialComponent != fSerialNumber )
6253 {
6254 return false;
6255 }
6256
6257 if ( fResponseArray == NULL )
6258 {
6259 return false;
6260 }
6261
6262 theFlag = fResponseArray->getObject(ordinalComponent);
6263
6264 if ( theFlag == 0 )
6265 {
6266 return false;
6267 }
6268
6269 OSNumber * num;
6270 if ((num = OSDynamicCast(OSNumber, theFlag)))
6271 {
6272 #if LOG_APP_RESPONSE_TIMES
6273 AbsoluteTime now;
6274 AbsoluteTime start;
6275 uint64_t nsec;
6276 OSString *name = IOCopyLogNameForPID(pid);
6277
6278 clock_get_uptime(&now);
6279 AbsoluteTime_to_scalar(&start) = num->unsigned64BitValue();
6280 SUB_ABSOLUTETIME(&now, &start);
6281 absolutetime_to_nanoseconds(now, &nsec);
6282
6283 PMEventDetails *details = PMEventDetails::eventDetails(
6284 kIOPMEventTypeAppResponse, // type
6285 name ? name->getCStringNoCopy() : "", // who
6286 (uintptr_t)pid, // owner unique
6287 NULL, // interest name
6288 0, // old
6289 0, // new
6290 0, // result
6291 NS_TO_US(nsec)); // usec completion time
6292
6293 getPMRootDomain()->recordAndReleasePMEventGated( details );
6294
6295 if (kIOLogDebugPower & gIOKitDebug)
6296 {
6297 PM_LOG("Ack(%u) %u ms\n",
6298 (uint32_t) ordinalComponent,
6299 NS_TO_MS(nsec));
6300 }
6301
6302 // > 100 ms
6303 if (nsec > LOG_APP_RESPONSE_TIMES)
6304 {
6305 PM_LOG("PM response took %d ms (%s)\n", NS_TO_MS(nsec),
6306 name ? name->getCStringNoCopy() : "");
6307
6308 if (nsec > LOG_APP_RESPONSE_MSG_TRACER)
6309 {
6310 // TODO: populate the messageType argument
6311 getPMRootDomain()->pmStatsRecordApplicationResponse(
6312 gIOPMStatsApplicationResponseSlow,
6313 name ? name->getCStringNoCopy() : "", 0,
6314 NS_TO_MS(nsec), pid);
6315 }
6316 }
6317
6318 if (name)
6319 name->release();
6320 #endif
6321 theFlag = kOSBooleanFalse;
6322 }
6323
6324 if ( kOSBooleanFalse == theFlag )
6325 {
6326 fResponseArray->replaceObject(ordinalComponent, kOSBooleanTrue);
6327 }
6328
6329 return true;
6330 }
6331
6332 //*********************************************************************************
6333 // [public] allowPowerChange
6334 //
6335 // Our power state is about to lower, and we have notified applications
6336 // and kernel clients, and one of them has acknowledged. If this is the last to do
6337 // so, and all acknowledgements are positive, we continue with the power change.
6338 //*********************************************************************************
6339
6340 IOReturn IOService::allowPowerChange ( unsigned long refcon )
6341 {
6342 IOPMRequest * request;
6343
6344 if ( !initialized )
6345 {
6346 // we're unloading
6347 return kIOReturnSuccess;
6348 }
6349
6350 request = acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange );
6351 if (!request)
6352 return kIOReturnNoMemory;
6353
6354 request->fArg0 = (void *) refcon;
6355 request->fArg1 = (void *) proc_selfpid();
6356 request->fArg2 = (void *) 0;
6357 submitPMRequest( request );
6358
6359 return kIOReturnSuccess;
6360 }
6361
6362 #ifndef __LP64__
6363 IOReturn IOService::serializedAllowPowerChange2 ( unsigned long refcon )
6364 {
6365 // [deprecated] public
6366 return kIOReturnUnsupported;
6367 }
6368 #endif /* !__LP64__ */
6369
6370 //*********************************************************************************
6371 // [public] cancelPowerChange
6372 //
6373 // Our power state is about to lower, and we have notified applications
6374 // and kernel clients, and one of them has vetoed the change. If this is the last
6375 // client to respond, we abandon the power change.
6376 //*********************************************************************************
6377
6378 IOReturn IOService::cancelPowerChange ( unsigned long refcon )
6379 {
6380 IOPMRequest * request;
6381 OSString * name;
6382
6383 if ( !initialized )
6384 {
6385 // we're unloading
6386 return kIOReturnSuccess;
6387 }
6388
6389 name = IOCopyLogNameForPID(proc_selfpid());
6390 PM_ERROR("PM notification cancel (%s)\n", name ? name->getCStringNoCopy() : "");
6391
6392 request = acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange );
6393 if (!request)
6394 {
6395 if (name)
6396 name->release();
6397 return kIOReturnNoMemory;
6398 }
6399
6400 request->fArg0 = (void *) refcon;
6401 request->fArg1 = (void *) proc_selfpid();
6402 request->fArg2 = (void *) name;
6403 submitPMRequest( request );
6404
6405 return kIOReturnSuccess;
6406 }
6407
6408 #ifndef __LP64__
6409 IOReturn IOService::serializedCancelPowerChange2 ( unsigned long refcon )
6410 {
6411 // [deprecated] public
6412 return kIOReturnUnsupported;
6413 }
6414
6415 //*********************************************************************************
6416 // PM_Clamp_Timer_Expired
6417 //
6418 // called when clamp timer expires...set power state to 0.
6419 //*********************************************************************************
6420
6421 void IOService::PM_Clamp_Timer_Expired ( void )
6422 {
6423 }
6424
6425 //*********************************************************************************
6426 // clampPowerOn
6427 //
6428 // Set to highest available power state for a minimum of duration milliseconds
6429 //*********************************************************************************
6430
6431 void IOService::clampPowerOn ( unsigned long duration )
6432 {
6433 }
6434 #endif /* !__LP64__ */
6435
6436 // MARK: -
6437 // MARK: Driver Overrides
6438
6439 //*********************************************************************************
6440 // [public] setPowerState
6441 //
6442 // Does nothing here. This should be implemented in a subclass driver.
6443 //*********************************************************************************
6444
6445 IOReturn IOService::setPowerState (
6446 unsigned long powerStateOrdinal, IOService * whatDevice )
6447 {
6448 return IOPMNoErr;
6449 }
6450
6451 //*********************************************************************************
6452 // [public] maxCapabilityForDomainState
6453 //
6454 // Finds the highest power state in the array whose input power
6455 // requirement is equal to the input parameter. Where a more intelligent
6456 // decision is possible, override this in the subclassed driver.
6457 //*********************************************************************************
6458
6459 unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainState )
6460 {
6461 int i;
6462
6463 if (fNumberOfPowerStates == 0 )
6464 {
6465 return 0;
6466 }
6467 for ( i = fNumberOfPowerStates - 1; i >= 0; i-- )
6468 {
6469 if ( (domainState & fPowerStates[i].inputPowerFlags) ==
6470 fPowerStates[i].inputPowerFlags )
6471 {
6472 return i;
6473 }
6474 }
6475 return 0;
6476 }
6477
6478 //*********************************************************************************
6479 // [public] initialPowerStateForDomainState
6480 //
6481 // Finds the highest power state in the array whose input power
6482 // requirement is equal to the input parameter. Where a more intelligent
6483 // decision is possible, override this in the subclassed driver.
6484 //*********************************************************************************
6485
6486 unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domainState )
6487 {
6488 int i;
6489
6490 if (fResetPowerStateOnWake && (domainState & kIOPMRootDomainState))
6491 {
6492 // Return lowest power state for any root power domain changes
6493 return 0;
6494 }
6495
6496 if (fNumberOfPowerStates == 0 )
6497 {
6498 return 0;
6499 }
6500 for ( i = fNumberOfPowerStates - 1; i >= 0; i-- )
6501 {
6502 if ( (domainState & fPowerStates[i].inputPowerFlags) ==
6503 fPowerStates[i].inputPowerFlags )
6504 {
6505 return i;
6506 }
6507 }
6508 return 0;
6509 }
6510
6511 //*********************************************************************************
6512 // [public] powerStateForDomainState
6513 //
6514 // Finds the highest power state in the array whose input power
6515 // requirement is equal to the input parameter. Where a more intelligent
6516 // decision is possible, override this in the subclassed driver.
6517 //*********************************************************************************
6518
6519 unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState )
6520 {
6521 int i;
6522
6523 if (fNumberOfPowerStates == 0 )
6524 {
6525 return 0;
6526 }
6527 for ( i = fNumberOfPowerStates - 1; i >= 0; i-- )
6528 {
6529 if ( (domainState & fPowerStates[i].inputPowerFlags) ==
6530 fPowerStates[i].inputPowerFlags )
6531 {
6532 return i;
6533 }
6534 }
6535 return 0;
6536 }
6537
6538 #ifndef __LP64__
6539 //*********************************************************************************
6540 // [deprecated] didYouWakeSystem
6541 //
6542 // Does nothing here. This should be implemented in a subclass driver.
6543 //*********************************************************************************
6544
6545 bool IOService::didYouWakeSystem ( void )
6546 {
6547 return false;
6548 }
6549 #endif /* !__LP64__ */
6550
6551 //*********************************************************************************
6552 // [public] powerStateWillChangeTo
6553 //
6554 // Does nothing here. This should be implemented in a subclass driver.
6555 //*********************************************************************************
6556
6557 IOReturn IOService::powerStateWillChangeTo ( IOPMPowerFlags, unsigned long, IOService * )
6558 {
6559 return kIOPMAckImplied;
6560 }
6561
6562 //*********************************************************************************
6563 // [public] powerStateDidChangeTo
6564 //
6565 // Does nothing here. This should be implemented in a subclass driver.
6566 //*********************************************************************************
6567
6568 IOReturn IOService::powerStateDidChangeTo ( IOPMPowerFlags, unsigned long, IOService * )
6569 {
6570 return kIOPMAckImplied;
6571 }
6572
6573 //*********************************************************************************
6574 // [protected] powerChangeDone
6575 //
6576 // Called from PM work loop thread.
6577 // Does nothing here. This should be implemented in a subclass policy-maker.
6578 //*********************************************************************************
6579
6580 void IOService::powerChangeDone ( unsigned long )
6581 {
6582 }
6583
6584 #ifndef __LP64__
6585 //*********************************************************************************
6586 // [deprecated] newTemperature
6587 //
6588 // Does nothing here. This should be implemented in a subclass driver.
6589 //*********************************************************************************
6590
6591 IOReturn IOService::newTemperature ( long currentTemp, IOService * whichZone )
6592 {
6593 return IOPMNoErr;
6594 }
6595 #endif /* !__LP64__ */
6596
6597 //*********************************************************************************
6598 // [public] systemWillShutdown
6599 //
6600 // System shutdown and restart notification.
6601 //*********************************************************************************
6602
6603 void IOService::systemWillShutdown( IOOptionBits specifier )
6604 {
6605 IOPMrootDomain * rootDomain = IOService::getPMRootDomain();
6606 if (rootDomain)
6607 rootDomain->acknowledgeSystemWillShutdown( this );
6608 }
6609
6610 // MARK: -
6611 // MARK: PM State Machine
6612
6613 //*********************************************************************************
6614 // [private static] acquirePMRequest
6615 //*********************************************************************************
6616
6617 IOPMRequest *
6618 IOService::acquirePMRequest( IOService * target, IOOptionBits requestType,
6619 IOPMRequest * active )
6620 {
6621 IOPMRequest * request;
6622
6623 assert(target);
6624
6625 request = IOPMRequest::create();
6626 if (request)
6627 {
6628 request->init( target, requestType );
6629 if (active)
6630 {
6631 IOPMRequest * root = active->getRootRequest();
6632 if (root) request->attachRootRequest(root);
6633 }
6634 }
6635 else
6636 {
6637 PM_ERROR("%s: No memory for PM request type 0x%x\n",
6638 target->getName(), (uint32_t) requestType);
6639 }
6640 return request;
6641 }
6642
6643 //*********************************************************************************
6644 // [private static] releasePMRequest
6645 //*********************************************************************************
6646
6647 void IOService::releasePMRequest( IOPMRequest * request )
6648 {
6649 if (request)
6650 {
6651 request->reset();
6652 request->release();
6653 }
6654 }
6655
6656 //*********************************************************************************
6657 // [private] submitPMRequest
6658 //*********************************************************************************
6659
6660 void IOService::submitPMRequest( IOPMRequest * request )
6661 {
6662 assert( request );
6663 assert( gIOPMReplyQueue );
6664 assert( gIOPMRequestQueue );
6665
6666 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
6667 (long)request->getType(), request,
6668 request->getTarget(), request->getTarget()->getName(),
6669 request->fArg0, request->fArg1, request->fArg2);
6670
6671 if (request->isReplyType())
6672 gIOPMReplyQueue->queuePMRequest( request );
6673 else
6674 gIOPMRequestQueue->queuePMRequest( request );
6675 }
6676
6677 void IOService::submitPMRequest( IOPMRequest ** requests, IOItemCount count )
6678 {
6679 assert( requests );
6680 assert( count > 0 );
6681 assert( gIOPMRequestQueue );
6682
6683 for (IOItemCount i = 0; i < count; i++)
6684 {
6685 IOPMRequest * req = requests[i];
6686 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
6687 (long)req->getType(), req,
6688 req->getTarget(), req->getTarget()->getName(),
6689 req->fArg0, req->fArg1, req->fArg2);
6690 }
6691
6692 gIOPMRequestQueue->queuePMRequestChain( requests, count );
6693 }
6694
6695 //*********************************************************************************
6696 // [private] servicePMRequestQueue
6697 //
6698 // Called from IOPMRequestQueue::checkForWork().
6699 //*********************************************************************************
6700
6701 bool IOService::servicePMRequestQueue(
6702 IOPMRequest * request,
6703 IOPMRequestQueue * queue )
6704 {
6705 bool more;
6706
6707 if (initialized)
6708 {
6709 // Work queue will immediately execute the queue'd request if possible.
6710 // If execution blocks, the work queue will wait for a producer signal.
6711 // Only need to signal more when completing attached requests.
6712
6713 more = gIOPMWorkQueue->queuePMRequest(request, pwrMgt);
6714 return more;
6715 }
6716
6717 // Calling PM without PMinit() is not allowed, fail the request.
6718
6719 PM_LOG("%s: PM not initialized\n", getName());
6720 fAdjustPowerScheduled = false;
6721 more = gIOPMFreeQueue->queuePMRequest(request);
6722 if (more) gIOPMWorkQueue->incrementProducerCount();
6723 return more;
6724 }
6725
6726 //*********************************************************************************
6727 // [private] servicePMFreeQueue
6728 //
6729 // Called from IOPMCompletionQueue::checkForWork().
6730 //*********************************************************************************
6731
6732 bool IOService::servicePMFreeQueue(
6733 IOPMRequest * request,
6734 IOPMCompletionQueue * queue )
6735 {
6736 bool more = request->getNextRequest();
6737 IOPMRequest * root = request->getRootRequest();
6738
6739 if (root && (root != request))
6740 more = true;
6741 if (more)
6742 gIOPMWorkQueue->incrementProducerCount();
6743
6744 releasePMRequest( request );
6745 return more;
6746 }
6747
6748 //*********************************************************************************
6749 // [private] retirePMRequest
6750 //
6751 // Called by IOPMWorkQueue to retire a completed request.
6752 //*********************************************************************************
6753
6754 bool IOService::retirePMRequest( IOPMRequest * request, IOPMWorkQueue * queue )
6755 {
6756 assert(request && queue);
6757
6758 PM_LOG1("[- %02x] %p [%p %s] state %d, busy %d\n",
6759 request->getType(), request, this, getName(),
6760 fMachineState, gIOPMBusyCount);
6761
6762 // Catch requests created by idleTimerExpired().
6763
6764 if ((request->getType() == kIOPMRequestTypeActivityTickle) &&
6765 (((uintptr_t) request->fArg1) & kTickleTypePowerDrop) &&
6766 fIdleTimerPeriod)
6767 {
6768 restartIdleTimer();
6769 }
6770
6771 // If the request is linked, then Work queue has already incremented its
6772 // producer count.
6773
6774 return (gIOPMFreeQueue->queuePMRequest( request ));
6775 }
6776
6777 //*********************************************************************************
6778 // [private] isPMBlocked
6779 //
6780 // Check if machine state transition is blocked.
6781 //*********************************************************************************
6782
6783 bool IOService::isPMBlocked ( IOPMRequest * request, int count )
6784 {
6785 int reason = 0;
6786
6787 do {
6788 if (kIOPM_Finished == fMachineState)
6789 break;
6790
6791 if (kIOPM_DriverThreadCallDone == fMachineState)
6792 {
6793 // 5 = kDriverCallInformPreChange
6794 // 6 = kDriverCallInformPostChange
6795 // 7 = kDriverCallSetPowerState
6796 if (fDriverCallBusy)
6797 reason = 5 + fDriverCallReason;
6798 break;
6799 }
6800
6801 // Waiting on driver's setPowerState() timeout.
6802 if (fDriverTimer)
6803 {
6804 reason = 1; break;
6805 }
6806
6807 // Child or interested driver acks pending.
6808 if (fHeadNotePendingAcks)
6809 {
6810 reason = 2; break;
6811 }
6812
6813 // Waiting on apps or priority power interest clients.
6814 if (fResponseArray)
6815 {
6816 reason = 3; break;
6817 }
6818
6819 // Waiting on settle timer expiration.
6820 if (fSettleTimeUS)
6821 {
6822 reason = 4; break;
6823 }
6824 } while (false);
6825
6826 fWaitReason = reason;
6827
6828 if (reason)
6829 {
6830 if (count)
6831 {
6832 PM_LOG1("[B %02x] %p [%p %s] state %d, reason %d\n",
6833 request->getType(), request, this, getName(),
6834 fMachineState, reason);
6835 }
6836
6837 return true;
6838 }
6839
6840 return false;
6841 }
6842
6843 //*********************************************************************************
6844 // [private] servicePMRequest
6845 //
6846 // Service a request from our work queue.
6847 //*********************************************************************************
6848
6849 bool IOService::servicePMRequest( IOPMRequest * request, IOPMWorkQueue * queue )
6850 {
6851 bool done = false;
6852 int loop = 0;
6853
6854 assert(request && queue);
6855
6856 while (isPMBlocked(request, loop++) == false)
6857 {
6858 PM_LOG1("[W %02x] %p [%p %s] state %d\n",
6859 request->getType(), request, this, getName(), fMachineState);
6860
6861 gIOPMRequest = request;
6862 gIOPMWorkCount++;
6863
6864 // Every PM machine states must be handled in one of the cases below.
6865
6866 switch ( fMachineState )
6867 {
6868 case kIOPM_Finished:
6869 executePMRequest( request );
6870 break;
6871
6872 case kIOPM_OurChangeTellClientsPowerDown:
6873 // Root domain might self cancel due to assertions.
6874 if (IS_ROOT_DOMAIN)
6875 {
6876 bool cancel = (bool) fDoNotPowerDown;
6877 getPMRootDomain()->askChangeDownDone(
6878 &fHeadNoteChangeFlags, &cancel);
6879 fDoNotPowerDown = cancel;
6880 }
6881
6882 // askChangeDown() done, was it vetoed?
6883 if (!fDoNotPowerDown)
6884 {
6885 if (IS_ROOT_DOMAIN) {
6886 PMEventDetails *details = PMEventDetails::eventDetails(
6887 kIOPMEventTypeAppNotificationsFinished,
6888 NULL,
6889 0,
6890 0);
6891
6892 getPMRootDomain()->recordAndReleasePMEventGated( details );
6893 }
6894
6895 // no, we can continue
6896 OurChangeTellClientsPowerDown();
6897 }
6898 else
6899 {
6900 if (IS_ROOT_DOMAIN) {
6901 PMEventDetails *details = PMEventDetails::eventDetails(
6902 kIOPMEventTypeSleepDone,
6903 NULL,
6904 1, /* reason: 1 == Ask clients succeeded */
6905 kIOReturnAborted); /* result */
6906
6907 getPMRootDomain()->recordAndReleasePMEventGated( details );
6908 }
6909
6910 OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState);
6911 PM_ERROR("%s: idle cancel\n", fName);
6912 // yes, rescind the warning
6913 tellNoChangeDown(fHeadNotePowerState);
6914 // mark the change note un-actioned
6915 fHeadNoteChangeFlags |= kIOPMNotDone;
6916 // and we're done
6917 OurChangeFinish();
6918 }
6919 break;
6920
6921 case kIOPM_OurChangeTellPriorityClientsPowerDown:
6922 // tellChangeDown(kNotifyApps) done, was it cancelled?
6923 if (fDoNotPowerDown)
6924 {
6925 if (IS_ROOT_DOMAIN) {
6926 PMEventDetails *details = PMEventDetails::eventDetails(
6927 kIOPMEventTypeSleepDone,
6928 NULL,
6929 2, /* reason: 2 == Client cancelled wake */
6930 kIOReturnAborted); /* result */
6931
6932 getPMRootDomain()->recordAndReleasePMEventGated( details );
6933 }
6934 OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState);
6935 PM_ERROR("%s: idle revert\n", fName);
6936 // no, tell clients we're back in the old state
6937 tellChangeUp(fCurrentPowerState);
6938 // mark the change note un-actioned
6939 fHeadNoteChangeFlags |= kIOPMNotDone;
6940 // and we're done
6941 OurChangeFinish();
6942 }
6943 else
6944 {
6945 if (IS_ROOT_DOMAIN) {
6946 PMEventDetails *details = PMEventDetails::eventDetails(
6947 kIOPMEventTypeAppNotificationsFinished,
6948 NULL,
6949 2, /* reason: 2 == TellPriorityClientsDone */
6950 kIOReturnSuccess); /* result */
6951
6952 getPMRootDomain()->recordAndReleasePMEventGated( details );
6953 }
6954 // yes, we can continue
6955 OurChangeTellPriorityClientsPowerDown();
6956 }
6957 break;
6958
6959 case kIOPM_OurChangeNotifyInterestedDriversWillChange:
6960 OurChangeNotifyInterestedDriversWillChange();
6961 break;
6962
6963 case kIOPM_OurChangeSetPowerState:
6964 OurChangeSetPowerState();
6965 break;
6966
6967 case kIOPM_OurChangeWaitForPowerSettle:
6968 OurChangeWaitForPowerSettle();
6969 break;
6970
6971 case kIOPM_OurChangeNotifyInterestedDriversDidChange:
6972 OurChangeNotifyInterestedDriversDidChange();
6973 break;
6974
6975 case kIOPM_OurChangeTellCapabilityDidChange:
6976 OurChangeTellCapabilityDidChange();
6977 break;
6978
6979 case kIOPM_OurChangeFinish:
6980 OurChangeFinish();
6981 break;
6982
6983 case kIOPM_ParentChangeTellPriorityClientsPowerDown:
6984 ParentChangeTellPriorityClientsPowerDown();
6985 break;
6986
6987 case kIOPM_ParentChangeNotifyInterestedDriversWillChange:
6988 ParentChangeNotifyInterestedDriversWillChange();
6989 break;
6990
6991 case kIOPM_ParentChangeSetPowerState:
6992 ParentChangeSetPowerState();
6993 break;
6994
6995 case kIOPM_ParentChangeWaitForPowerSettle:
6996 ParentChangeWaitForPowerSettle();
6997 break;
6998
6999 case kIOPM_ParentChangeNotifyInterestedDriversDidChange:
7000 ParentChangeNotifyInterestedDriversDidChange();
7001 break;
7002
7003 case kIOPM_ParentChangeTellCapabilityDidChange:
7004 ParentChangeTellCapabilityDidChange();
7005 break;
7006
7007 case kIOPM_ParentChangeAcknowledgePowerChange:
7008 ParentChangeAcknowledgePowerChange();
7009 break;
7010
7011 case kIOPM_DriverThreadCallDone:
7012 if (fDriverCallReason == kDriverCallSetPowerState)
7013 notifyControllingDriverDone();
7014 else
7015 notifyInterestedDriversDone();
7016 break;
7017
7018 case kIOPM_NotifyChildrenOrdered:
7019 notifyChildrenOrdered();
7020 break;
7021
7022 case kIOPM_NotifyChildrenDelayed:
7023 notifyChildrenDelayed();
7024 break;
7025
7026 case kIOPM_NotifyChildrenStart:
7027 PM_LOG2("%s: kIOPM_NotifyChildrenStart done\n", getName());
7028 MS_POP(); // from notifyInterestedDriversDone()
7029 notifyChildren();
7030 break;
7031
7032 case kIOPM_SyncTellClientsPowerDown:
7033 // Root domain might self cancel due to assertions.
7034 if (IS_ROOT_DOMAIN)
7035 {
7036 bool cancel = (bool) fDoNotPowerDown;
7037 getPMRootDomain()->askChangeDownDone(
7038 &fHeadNoteChangeFlags, &cancel);
7039 fDoNotPowerDown = cancel;
7040 }
7041 if (!fDoNotPowerDown)
7042 {
7043 fMachineState = kIOPM_SyncTellPriorityClientsPowerDown;
7044 fOutOfBandParameter = kNotifyApps;
7045 tellChangeDown(fHeadNotePowerState);
7046 }
7047 else
7048 {
7049 OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState);
7050 PM_ERROR("%s: idle cancel\n", fName);
7051 tellNoChangeDown(fHeadNotePowerState);
7052 fHeadNoteChangeFlags |= kIOPMNotDone;
7053 OurChangeFinish();
7054 }
7055 break;
7056
7057 case kIOPM_SyncTellPriorityClientsPowerDown:
7058 if (!fDoNotPowerDown)
7059 {
7060 fMachineState = kIOPM_SyncNotifyWillChange;
7061 fOutOfBandParameter = kNotifyPriority;
7062 tellChangeDown(fHeadNotePowerState);
7063 }
7064 else
7065 {
7066 OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState);
7067 PM_ERROR("%s: idle revert\n", fName);
7068 tellChangeUp(fCurrentPowerState);
7069 fHeadNoteChangeFlags |= kIOPMNotDone;
7070 OurChangeFinish();
7071 }
7072 break;
7073
7074 case kIOPM_SyncNotifyWillChange:
7075 if (kIOPMSyncNoChildNotify & fHeadNoteChangeFlags)
7076 {
7077 fMachineState = kIOPM_SyncFinish;
7078 continue;
7079 }
7080 fMachineState = kIOPM_SyncNotifyDidChange;
7081 fDriverCallReason = kDriverCallInformPreChange;
7082 notifyChildren();
7083 break;
7084
7085 case kIOPM_SyncNotifyDidChange:
7086 fIsPreChange = false;
7087
7088 if (fHeadNoteChangeFlags & kIOPMParentInitiated)
7089 {
7090 fMachineState = kIOPM_SyncFinish;
7091 }
7092 else
7093 {
7094 assert(IS_ROOT_DOMAIN);
7095 fMachineState = kIOPM_SyncTellCapabilityDidChange;
7096 }
7097
7098 fDriverCallReason = kDriverCallInformPostChange;
7099 notifyChildren();
7100 break;
7101
7102 case kIOPM_SyncTellCapabilityDidChange:
7103 tellSystemCapabilityChange( kIOPM_SyncFinish );
7104 break;
7105
7106 case kIOPM_SyncFinish:
7107 if (fHeadNoteChangeFlags & kIOPMParentInitiated)
7108 ParentChangeAcknowledgePowerChange();
7109 else
7110 OurChangeFinish();
7111 break;
7112
7113 case kIOPM_TellCapabilityChangeDone:
7114 if (fIsPreChange)
7115 {
7116 if (fOutOfBandParameter == kNotifyCapabilityChangePriority)
7117 {
7118 MS_POP(); // tellSystemCapabilityChange()
7119 continue;
7120 }
7121 fOutOfBandParameter = kNotifyCapabilityChangePriority;
7122 }
7123 else
7124 {
7125 if (fOutOfBandParameter == kNotifyCapabilityChangeApps)
7126 {
7127 MS_POP(); // tellSystemCapabilityChange()
7128 continue;
7129 }
7130 fOutOfBandParameter = kNotifyCapabilityChangeApps;
7131 }
7132 tellClientsWithResponse( fOutOfBandMessage );
7133 break;
7134
7135 default:
7136 panic("servicePMWorkQueue: unknown machine state %x",
7137 fMachineState);
7138 }
7139
7140 gIOPMRequest = 0;
7141
7142 if (fMachineState == kIOPM_Finished)
7143 {
7144 done = true;
7145 break;
7146 }
7147 }
7148
7149 return done;
7150 }
7151
7152 //*********************************************************************************
7153 // [private] executePMRequest
7154 //*********************************************************************************
7155
7156 void IOService::executePMRequest( IOPMRequest * request )
7157 {
7158 assert( kIOPM_Finished == fMachineState );
7159
7160 switch (request->getType())
7161 {
7162 case kIOPMRequestTypePMStop:
7163 handlePMstop( request );
7164 break;
7165
7166 case kIOPMRequestTypeAddPowerChild1:
7167 addPowerChild1( request );
7168 break;
7169
7170 case kIOPMRequestTypeAddPowerChild2:
7171 addPowerChild2( request );
7172 break;
7173
7174 case kIOPMRequestTypeAddPowerChild3:
7175 addPowerChild3( request );
7176 break;
7177
7178 case kIOPMRequestTypeRegisterPowerDriver:
7179 handleRegisterPowerDriver( request );
7180 break;
7181
7182 case kIOPMRequestTypeAdjustPowerState:
7183 fAdjustPowerScheduled = false;
7184 adjustPowerState();
7185 break;
7186
7187 case kIOPMRequestTypePowerDomainWillChange:
7188 handlePowerDomainWillChangeTo( request );
7189 break;
7190
7191 case kIOPMRequestTypePowerDomainDidChange:
7192 handlePowerDomainDidChangeTo( request );
7193 break;
7194
7195 case kIOPMRequestTypeRequestPowerState:
7196 case kIOPMRequestTypeRequestPowerStateOverride:
7197 handleRequestPowerState( request );
7198 break;
7199
7200 case kIOPMRequestTypePowerOverrideOnPriv:
7201 case kIOPMRequestTypePowerOverrideOffPriv:
7202 handlePowerOverrideChanged( request );
7203 break;
7204
7205 case kIOPMRequestTypeActivityTickle:
7206 handleActivityTickle( request );
7207 break;
7208
7209 case kIOPMRequestTypeSynchronizePowerTree:
7210 handleSynchronizePowerTree( request );
7211 break;
7212
7213 case kIOPMRequestTypeSetIdleTimerPeriod:
7214 {
7215 fIdleTimerPeriod = (uintptr_t) request->fArg0;
7216 if ((false == fLockedFlags.PMStop) && (fIdleTimerPeriod > 0))
7217 restartIdleTimer();
7218 }
7219 break;
7220
7221 case kIOPMRequestTypeIgnoreIdleTimer:
7222 fIdleTimerIgnored = request->fArg0 ? 1 : 0;
7223 break;
7224
7225 default:
7226 panic("executePMRequest: unknown request type %x", request->getType());
7227 }
7228 }
7229
7230 //*********************************************************************************
7231 // [private] servicePMReplyQueue
7232 //*********************************************************************************
7233
7234 bool IOService::servicePMReplyQueue( IOPMRequest * request, IOPMRequestQueue * queue )
7235 {
7236 bool more = false;
7237
7238 assert( request && queue );
7239 assert( request->isReplyType() );
7240
7241 PM_LOG1("[A %02x] %p [%p %s] state %d\n",
7242 request->getType(), request, this, getName(), fMachineState);
7243
7244 switch ( request->getType() )
7245 {
7246 case kIOPMRequestTypeAllowPowerChange:
7247 case kIOPMRequestTypeCancelPowerChange:
7248 // Check if we are expecting this response.
7249 if (responseValid((uint32_t)(uintptr_t) request->fArg0,
7250 (int)(uintptr_t) request->fArg1))
7251 {
7252 if (kIOPMRequestTypeCancelPowerChange == request->getType())
7253 {
7254 // Clients are not allowed to cancel when kIOPMSkipAskPowerDown
7255 // flag is set. Only root domain will set this flag.
7256
7257 if ((fHeadNoteChangeFlags & kIOPMSkipAskPowerDown) == 0)
7258 {
7259 fDoNotPowerDown = true;
7260
7261 OSString * name = (OSString *) request->fArg2;
7262 getPMRootDomain()->pmStatsRecordApplicationResponse(
7263 gIOPMStatsApplicationResponseCancel,
7264 name ? name->getCStringNoCopy() : "", 0,
7265 0, (int)(uintptr_t) request->fArg1);
7266 }
7267 }
7268
7269 if (checkForDone())
7270 {
7271 stop_ack_timer();
7272 cleanClientResponses(false);
7273 more = true;
7274 }
7275 }
7276 // OSString containing app name in Arg2 must be released.
7277 if (request->getType() == kIOPMRequestTypeCancelPowerChange)
7278 {
7279 OSObject * obj = (OSObject *) request->fArg2;
7280 if (obj) obj->release();
7281 }
7282 break;
7283
7284 case kIOPMRequestTypeAckPowerChange:
7285 more = handleAcknowledgePowerChange( request );
7286 break;
7287
7288 case kIOPMRequestTypeAckSetPowerState:
7289 if (fDriverTimer == -1)
7290 {
7291 // driver acked while setPowerState() call is in-flight.
7292 // take this ack, return value from setPowerState() is irrelevant.
7293 OUR_PMLog(kPMLogDriverAcknowledgeSet,
7294 (uintptr_t) this, fDriverTimer);
7295 fDriverTimer = 0;
7296 }
7297 else if (fDriverTimer > 0)
7298 {
7299 // expected ack, stop the timer
7300 stop_ack_timer();
7301
7302 #if LOG_SETPOWER_TIMES
7303 uint64_t nsec = computeTimeDeltaNS(&fDriverCallStartTime);
7304 if (nsec > LOG_SETPOWER_TIMES)
7305 PM_LOG("%s::setPowerState(%p, %lu -> %lu) async took %d ms\n",
7306 fName, this, fCurrentPowerState, fHeadNotePowerState, NS_TO_MS(nsec));
7307
7308 PMEventDetails *details = PMEventDetails::eventDetails(
7309 kIOPMEventTypeSetPowerStateDelayed, // type
7310 fName, // who
7311 (uintptr_t)this, // owner unique
7312 NULL, // interest name
7313 (uint8_t)getPowerState(), // old
7314 (uint8_t)fHeadNotePowerState, // new
7315 0, // result
7316 NS_TO_US(nsec)); // usec completion time
7317
7318 getPMRootDomain()->recordAndReleasePMEventGated( details );
7319 #endif
7320 OUR_PMLog(kPMLogDriverAcknowledgeSet, (uintptr_t) this, fDriverTimer);
7321 fDriverTimer = 0;
7322 more = true;
7323 }
7324 else
7325 {
7326 // unexpected ack
7327 OUR_PMLog(kPMLogAcknowledgeErr4, (uintptr_t) this, 0);
7328 }
7329 break;
7330
7331 case kIOPMRequestTypeInterestChanged:
7332 handleInterestChanged( request );
7333 more = true;
7334 break;
7335
7336 case kIOPMRequestTypeIdleCancel:
7337 if ((fMachineState == kIOPM_OurChangeTellClientsPowerDown)
7338 || (fMachineState == kIOPM_OurChangeTellPriorityClientsPowerDown)
7339 || (fMachineState == kIOPM_SyncTellClientsPowerDown)
7340 || (fMachineState == kIOPM_SyncTellPriorityClientsPowerDown))
7341 {
7342 OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState);
7343 PM_LOG2("%s: cancel from machine state %d\n",
7344 getName(), fMachineState);
7345 fDoNotPowerDown = true;
7346 // Stop waiting for app replys.
7347 if ((fMachineState == kIOPM_OurChangeTellPriorityClientsPowerDown) ||
7348 (fMachineState == kIOPM_SyncTellPriorityClientsPowerDown))
7349 cleanClientResponses(false);
7350 more = true;
7351 }
7352 break;
7353
7354 case kIOPMRequestTypeChildNotifyDelayCancel:
7355 if (fMachineState == kIOPM_NotifyChildrenDelayed)
7356 {
7357 PM_LOG2("%s: delay notify cancelled\n", getName());
7358 notifyChildrenDelayed();
7359 }
7360 break;
7361
7362 default:
7363 panic("servicePMReplyQueue: unknown reply type %x",
7364 request->getType());
7365 }
7366
7367 more |= gIOPMFreeQueue->queuePMRequest(request);
7368 if (more)
7369 gIOPMWorkQueue->incrementProducerCount();
7370
7371 return more;
7372 }
7373
7374 //*********************************************************************************
7375 // [private] assertPMDriverCall / deassertPMDriverCall
7376 //*********************************************************************************
7377
7378 bool IOService::assertPMDriverCall(
7379 IOPMDriverCallEntry * entry,
7380 IOOptionBits options,
7381 IOPMinformee * inform )
7382 {
7383 IOService * target = 0;
7384 bool ok = false;
7385
7386 if (!initialized)
7387 return false;
7388
7389 PM_LOCK();
7390
7391 if (fLockedFlags.PMStop)
7392 {
7393 goto fail;
7394 }
7395
7396 if (((options & kIOPMADC_NoInactiveCheck) == 0) && isInactive())
7397 {
7398 goto fail;
7399 }
7400
7401 if (inform)
7402 {
7403 if (!inform->active)
7404 {
7405 goto fail;
7406 }
7407 target = inform->whatObject;
7408 if (target->isInactive())
7409 {
7410 goto fail;
7411 }
7412 }
7413
7414 entry->thread = current_thread();
7415 entry->target = target;
7416 queue_enter(&fPMDriverCallQueue, entry, IOPMDriverCallEntry *, link);
7417 ok = true;
7418
7419 fail:
7420 PM_UNLOCK();
7421
7422 return ok;
7423 }
7424
7425 void IOService::deassertPMDriverCall( IOPMDriverCallEntry * entry )
7426 {
7427 bool wakeup = false;
7428
7429 PM_LOCK();
7430
7431 assert( !queue_empty(&fPMDriverCallQueue) );
7432 queue_remove(&fPMDriverCallQueue, entry, IOPMDriverCallEntry *, link);
7433 if (fLockedFlags.PMDriverCallWait)
7434 {
7435 wakeup = true;
7436 }
7437
7438 PM_UNLOCK();
7439
7440 if (wakeup)
7441 PM_LOCK_WAKEUP(&fPMDriverCallQueue);
7442 }
7443
7444 void IOService::waitForPMDriverCall( IOService * target )
7445 {
7446 const IOPMDriverCallEntry * entry;
7447 thread_t thread = current_thread();
7448 AbsoluteTime deadline;
7449 int waitResult;
7450 bool log = true;
7451 bool wait;
7452
7453 do {
7454 wait = false;
7455 queue_iterate(&fPMDriverCallQueue, entry, const IOPMDriverCallEntry *, link)
7456 {
7457 // Target of interested driver call
7458 if (target && (target != entry->target))
7459 continue;
7460
7461 if (entry->thread == thread)
7462 {
7463 if (log)
7464 {
7465 PM_LOG("%s: %s(%s) on PM thread\n",
7466 fName, __FUNCTION__, target ? target->getName() : "");
7467 OSReportWithBacktrace("%s: %s(%s) on PM thread\n",
7468 fName, __FUNCTION__, target ? target->getName() : "");
7469 log = false;
7470 }
7471 continue;
7472 }
7473
7474 wait = true;
7475 break;
7476 }
7477
7478 if (wait)
7479 {
7480 fLockedFlags.PMDriverCallWait = true;
7481 clock_interval_to_deadline(15, kSecondScale, &deadline);
7482 waitResult = PM_LOCK_SLEEP(&fPMDriverCallQueue, deadline);
7483 fLockedFlags.PMDriverCallWait = false;
7484 if (THREAD_TIMED_OUT == waitResult)
7485 {
7486 PM_ERROR("%s: waitForPMDriverCall timeout\n", fName);
7487 wait = false;
7488 }
7489 }
7490 } while (wait);
7491 }
7492
7493 //*********************************************************************************
7494 // [private] Debug helpers
7495 //*********************************************************************************
7496
7497 const char * IOService::getIOMessageString( uint32_t msg )
7498 {
7499 #define MSG_ENTRY(x) {x, #x}
7500
7501 static const IONamedValue msgNames[] = {
7502 MSG_ENTRY( kIOMessageCanDevicePowerOff ),
7503 MSG_ENTRY( kIOMessageDeviceWillPowerOff ),
7504 MSG_ENTRY( kIOMessageDeviceWillNotPowerOff ),
7505 MSG_ENTRY( kIOMessageDeviceHasPoweredOn ),
7506 MSG_ENTRY( kIOMessageCanSystemPowerOff ),
7507 MSG_ENTRY( kIOMessageSystemWillPowerOff ),
7508 MSG_ENTRY( kIOMessageSystemWillNotPowerOff ),
7509 MSG_ENTRY( kIOMessageCanSystemSleep ),
7510 MSG_ENTRY( kIOMessageSystemWillSleep ),
7511 MSG_ENTRY( kIOMessageSystemWillNotSleep ),
7512 MSG_ENTRY( kIOMessageSystemHasPoweredOn ),
7513 MSG_ENTRY( kIOMessageSystemWillRestart ),
7514 MSG_ENTRY( kIOMessageSystemWillPowerOn ),
7515 MSG_ENTRY( kIOMessageSystemCapabilityChange )
7516 };
7517
7518 return IOFindNameForValue(msg, msgNames);
7519 }
7520
7521 // MARK: -
7522 // MARK: IOPMRequest
7523
7524 //*********************************************************************************
7525 // IOPMRequest Class
7526 //
7527 // Requests from PM clients, and also used for inter-object messaging within PM.
7528 //*********************************************************************************
7529
7530 OSDefineMetaClassAndStructors( IOPMRequest, IOCommand );
7531
7532 IOPMRequest * IOPMRequest::create( void )
7533 {
7534 IOPMRequest * me = OSTypeAlloc(IOPMRequest);
7535 if (me && !me->init(0, kIOPMRequestTypeInvalid))
7536 {
7537 me->release();
7538 me = 0;
7539 }
7540 return me;
7541 }
7542
7543 bool IOPMRequest::init( IOService * target, IOOptionBits type )
7544 {
7545 if (!IOCommand::init())
7546 return false;
7547
7548 fType = type;
7549 fTarget = target;
7550 fCompletionStatus = kIOReturnSuccess;
7551
7552 if (fTarget)
7553 fTarget->retain();
7554
7555 return true;
7556 }
7557
7558 void IOPMRequest::reset( void )
7559 {
7560 assert( fWorkWaitCount == 0 );
7561 assert( fFreeWaitCount == 0 );
7562
7563 detachNextRequest();
7564 detachRootRequest();
7565
7566 fType = kIOPMRequestTypeInvalid;
7567
7568 #if NOT_READY
7569 if (fCompletionAction)
7570 {
7571 fCompletionAction(fCompletionTarget, fCompletionParam, fCompletionStatus);
7572 }
7573 #endif
7574
7575 if (fTarget)
7576 {
7577 fTarget->release();
7578 fTarget = 0;
7579 }
7580 }
7581
7582 bool IOPMRequest::attachNextRequest( IOPMRequest * next )
7583 {
7584 bool ok = false;
7585
7586 if (!fRequestNext)
7587 {
7588 // Postpone the execution of the next request after
7589 // this request.
7590 fRequestNext = next;
7591 fRequestNext->fWorkWaitCount++;
7592 #if LOG_REQUEST_ATTACH
7593 PM_LOG("Attached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
7594 this, (uint32_t) fType, fRequestNext,
7595 (uint32_t) fRequestNext->fType,
7596 (uint32_t) fRequestNext->fWorkWaitCount,
7597 fTarget->getName());
7598 #endif
7599 ok = true;
7600 }
7601 return ok;
7602 }
7603
7604 bool IOPMRequest::detachNextRequest( void )
7605 {
7606 bool ok = false;
7607
7608 if (fRequestNext)
7609 {
7610 assert(fRequestNext->fWorkWaitCount);
7611 if (fRequestNext->fWorkWaitCount)
7612 fRequestNext->fWorkWaitCount--;
7613 #if LOG_REQUEST_ATTACH
7614 PM_LOG("Detached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
7615 this, (uint32_t) fType, fRequestNext,
7616 (uint32_t) fRequestNext->fType,
7617 (uint32_t) fRequestNext->fWorkWaitCount,
7618 fTarget->getName());
7619 #endif
7620 fRequestNext = 0;
7621 ok = true;
7622 }
7623 return ok;
7624 }
7625
7626 bool IOPMRequest::attachRootRequest( IOPMRequest * root )
7627 {
7628 bool ok = false;
7629
7630 if (!fRequestRoot)
7631 {
7632 // Delay the completion of the root request after
7633 // this request.
7634 fRequestRoot = root;
7635 fRequestRoot->fFreeWaitCount++;
7636 #if LOG_REQUEST_ATTACH
7637 PM_LOG("Attached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
7638 this, (uint32_t) fType, fRequestRoot,
7639 (uint32_t) fRequestRoot->fType,
7640 (uint32_t) fRequestRoot->fFreeWaitCount,
7641 fTarget->getName());
7642 #endif
7643 ok = true;
7644 }
7645 return ok;
7646 }
7647
7648 bool IOPMRequest::detachRootRequest( void )
7649 {
7650 bool ok = false;
7651
7652 if (fRequestRoot)
7653 {
7654 assert(fRequestRoot->fFreeWaitCount);
7655 if (fRequestRoot->fFreeWaitCount)
7656 fRequestRoot->fFreeWaitCount--;
7657 #if LOG_REQUEST_ATTACH
7658 PM_LOG("Detached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
7659 this, (uint32_t) fType, fRequestRoot,
7660 (uint32_t) fRequestRoot->fType,
7661 (uint32_t) fRequestRoot->fFreeWaitCount,
7662 fTarget->getName());
7663 #endif
7664 fRequestRoot = 0;
7665 ok = true;
7666 }
7667 return ok;
7668 }
7669
7670 // MARK: -
7671 // MARK: IOPMRequestQueue
7672
7673 //*********************************************************************************
7674 // IOPMRequestQueue Class
7675 //
7676 // Global queues. Queues are created once and never released.
7677 //*********************************************************************************
7678
7679 OSDefineMetaClassAndStructors( IOPMRequestQueue, IOEventSource );
7680
7681 IOPMRequestQueue * IOPMRequestQueue::create( IOService * inOwner, Action inAction )
7682 {
7683 IOPMRequestQueue * me = OSTypeAlloc(IOPMRequestQueue);
7684 if (me && !me->init(inOwner, inAction))
7685 {
7686 me->release();
7687 me = 0;
7688 }
7689 return me;
7690 }
7691
7692 bool IOPMRequestQueue::init( IOService * inOwner, Action inAction )
7693 {
7694 if (!inAction || !IOEventSource::init(inOwner, (IOEventSourceAction)inAction))
7695 return false;
7696
7697 queue_init(&fQueue);
7698 fLock = IOLockAlloc();
7699 return (fLock != 0);
7700 }
7701
7702 void IOPMRequestQueue::free( void )
7703 {
7704 if (fLock)
7705 {
7706 IOLockFree(fLock);
7707 fLock = 0;
7708 }
7709 return IOEventSource::free();
7710 }
7711
7712 void IOPMRequestQueue::queuePMRequest( IOPMRequest * request )
7713 {
7714 assert(request);
7715 IOLockLock(fLock);
7716 queue_enter(&fQueue, request, IOPMRequest *, fCommandChain);
7717 IOLockUnlock(fLock);
7718 if (workLoop) signalWorkAvailable();
7719 }
7720
7721 void
7722 IOPMRequestQueue::queuePMRequestChain( IOPMRequest ** requests, IOItemCount count )
7723 {
7724 IOPMRequest * next;
7725
7726 assert(requests && count);
7727 IOLockLock(fLock);
7728 while (count--)
7729 {
7730 next = *requests;
7731 requests++;
7732 queue_enter(&fQueue, next, IOPMRequest *, fCommandChain);
7733 }
7734 IOLockUnlock(fLock);
7735 if (workLoop) signalWorkAvailable();
7736 }
7737
7738 bool IOPMRequestQueue::checkForWork( void )
7739 {
7740 Action dqAction = (Action) action;
7741 IOPMRequest * request;
7742 IOService * target;
7743 bool more = false;
7744
7745 IOLockLock( fLock );
7746
7747 while (!queue_empty(&fQueue))
7748 {
7749 queue_remove_first( &fQueue, request, IOPMRequest *, fCommandChain );
7750 IOLockUnlock( fLock );
7751 target = request->getTarget();
7752 assert(target);
7753 more |= (*dqAction)( target, request, this );
7754 IOLockLock( fLock );
7755 }
7756
7757 IOLockUnlock( fLock );
7758 return more;
7759 }
7760
7761 // MARK: -
7762 // MARK: IOPMWorkQueue
7763
7764 //*********************************************************************************
7765 // IOPMWorkQueue Class
7766 //
7767 // Queue of IOServicePM objects with busy IOPMRequest(s).
7768 //*********************************************************************************
7769
7770 OSDefineMetaClassAndStructors( IOPMWorkQueue, IOEventSource );
7771
7772 IOPMWorkQueue *
7773 IOPMWorkQueue::create( IOService * inOwner, Action work, Action retire )
7774 {
7775 IOPMWorkQueue * me = OSTypeAlloc(IOPMWorkQueue);
7776 if (me && !me->init(inOwner, work, retire))
7777 {
7778 me->release();
7779 me = 0;
7780 }
7781 return me;
7782 }
7783
7784 bool IOPMWorkQueue::init( IOService * inOwner, Action work, Action retire )
7785 {
7786 if (!work || !retire ||
7787 !IOEventSource::init(inOwner, (IOEventSourceAction)0))
7788 return false;
7789
7790 queue_init(&fWorkQueue);
7791
7792 fWorkAction = work;
7793 fRetireAction = retire;
7794 fConsumerCount = fProducerCount = 0;
7795
7796 return true;
7797 }
7798
7799 bool IOPMWorkQueue::queuePMRequest( IOPMRequest * request, IOServicePM * pwrMgt )
7800 {
7801 bool more = false;
7802 bool empty;
7803
7804 assert( request );
7805 assert( pwrMgt );
7806 assert( onThread() );
7807 assert( queue_next(&request->fCommandChain) ==
7808 queue_prev(&request->fCommandChain) );
7809
7810 gIOPMBusyCount++;
7811
7812 // Add new request to the tail of the per-service request queue.
7813 // Then immediately check the request queue to minimize latency
7814 // if the queue was empty.
7815
7816 empty = queue_empty(&pwrMgt->RequestHead);
7817 queue_enter(&pwrMgt->RequestHead, request, IOPMRequest *, fCommandChain);
7818 if (empty)
7819 {
7820 more = checkRequestQueue(&pwrMgt->RequestHead, &empty);
7821 if (!empty)
7822 {
7823 // New Request is blocked, add IOServicePM to work queue.
7824 assert( queue_next(&pwrMgt->WorkChain) ==
7825 queue_prev(&pwrMgt->WorkChain) );
7826
7827 queue_enter(&fWorkQueue, pwrMgt, IOServicePM *, WorkChain);
7828 fQueueLength++;
7829 PM_LOG3("IOPMWorkQueue: [%u] added %s@%p to queue\n",
7830 fQueueLength, pwrMgt->Name, pwrMgt);
7831 }
7832 }
7833
7834 return more;
7835 }
7836
7837 bool IOPMWorkQueue::checkRequestQueue( queue_head_t * queue, bool * empty )
7838 {
7839 IOPMRequest * request;
7840 IOService * target;
7841 bool more = false;
7842 bool done = false;
7843
7844 assert(!queue_empty(queue));
7845 do {
7846 request = (IOPMRequest *) queue_first(queue);
7847 if (request->isWorkBlocked())
7848 break; // cannot start, blocked on attached request
7849
7850 target = request->getTarget();
7851 done = (*fWorkAction)( target, request, this );
7852 if (!done)
7853 break; // work started, blocked on PM state machine
7854
7855 assert(gIOPMBusyCount > 0);
7856 if (gIOPMBusyCount)
7857 gIOPMBusyCount--;
7858
7859 queue_remove_first(queue, request, IOPMRequest *, fCommandChain);
7860 more |= (*fRetireAction)( target, request, this );
7861 done = queue_empty(queue);
7862 } while (!done);
7863
7864 *empty = done;
7865
7866 if (more)
7867 {
7868 // Retired request blocks another request, since the
7869 // blocked request may reside in the work queue, we
7870 // must bump the producer count to avoid work stall.
7871 fProducerCount++;
7872 }
7873
7874 return more;
7875 }
7876
7877 bool IOPMWorkQueue::checkForWork( void )
7878 {
7879 IOServicePM * entry;
7880 IOServicePM * next;
7881 bool more = false;
7882 bool empty;
7883
7884 #if WORK_QUEUE_STATS
7885 fStatCheckForWork++;
7886 #endif
7887
7888 // Each producer signal triggers a full iteration over
7889 // all IOServicePM entries in the work queue.
7890
7891 while (fConsumerCount != fProducerCount)
7892 {
7893 PM_LOG3("IOPMWorkQueue: checkForWork %u %u\n",
7894 fProducerCount, fConsumerCount);
7895
7896 fConsumerCount = fProducerCount;
7897
7898 #if WORK_QUEUE_STATS
7899 if (queue_empty(&fWorkQueue))
7900 {
7901 fStatQueueEmpty++;
7902 break;
7903 }
7904 fStatScanEntries++;
7905 uint32_t cachedWorkCount = gIOPMWorkCount;
7906 #endif
7907
7908 entry = (IOServicePM *) queue_first(&fWorkQueue);
7909 while (!queue_end(&fWorkQueue, (queue_entry_t) entry))
7910 {
7911 more |= checkRequestQueue(&entry->RequestHead, &empty);
7912
7913 // Get next entry, points to head if current entry is last.
7914 next = (IOServicePM *) queue_next(&entry->WorkChain);
7915
7916 // if request queue is empty, remove IOServicePM from queue.
7917 if (empty)
7918 {
7919 assert(fQueueLength);
7920 if (fQueueLength) fQueueLength--;
7921 PM_LOG3("IOPMWorkQueue: [%u] removed %s@%p from queue\n",
7922 fQueueLength, entry->Name, entry);
7923 queue_remove(&fWorkQueue, entry, IOServicePM *, WorkChain);
7924 }
7925 entry = next;
7926 }
7927
7928 #if WORK_QUEUE_STATS
7929 if (cachedWorkCount == gIOPMWorkCount)
7930 fStatNoWorkDone++;
7931 #endif
7932 }
7933
7934 return more;
7935 }
7936
7937 void IOPMWorkQueue::signalWorkAvailable( void )
7938 {
7939 fProducerCount++;
7940 IOEventSource::signalWorkAvailable();
7941 }
7942
7943 void IOPMWorkQueue::incrementProducerCount( void )
7944 {
7945 fProducerCount++;
7946 }
7947
7948 // MARK: -
7949 // MARK: IOPMCompletionQueue
7950
7951 //*********************************************************************************
7952 // IOPMCompletionQueue Class
7953 //*********************************************************************************
7954
7955 OSDefineMetaClassAndStructors( IOPMCompletionQueue, IOEventSource );
7956
7957 IOPMCompletionQueue *
7958 IOPMCompletionQueue::create( IOService * inOwner, Action inAction )
7959 {
7960 IOPMCompletionQueue * me = OSTypeAlloc(IOPMCompletionQueue);
7961 if (me && !me->init(inOwner, inAction))
7962 {
7963 me->release();
7964 me = 0;
7965 }
7966 return me;
7967 }
7968
7969 bool IOPMCompletionQueue::init( IOService * inOwner, Action inAction )
7970 {
7971 if (!inAction || !IOEventSource::init(inOwner, (IOEventSourceAction)inAction))
7972 return false;
7973
7974 queue_init(&fQueue);
7975 return true;
7976 }
7977
7978 bool IOPMCompletionQueue::queuePMRequest( IOPMRequest * request )
7979 {
7980 bool more;
7981
7982 assert(request);
7983 // unblock dependent request
7984 more = request->detachNextRequest();
7985 queue_enter(&fQueue, request, IOPMRequest *, fCommandChain);
7986 return more;
7987 }
7988
7989 bool IOPMCompletionQueue::checkForWork( void )
7990 {
7991 Action dqAction = (Action) action;
7992 IOPMRequest * request;
7993 IOPMRequest * next;
7994 IOService * target;
7995 bool more = false;
7996
7997 request = (IOPMRequest *) queue_first(&fQueue);
7998 while (!queue_end(&fQueue, (queue_entry_t) request))
7999 {
8000 next = (IOPMRequest *) queue_next(&request->fCommandChain);
8001 if (!request->isFreeBlocked())
8002 {
8003 queue_remove(&fQueue, request, IOPMRequest *, fCommandChain);
8004 target = request->getTarget();
8005 assert(target);
8006 more |= (*dqAction)( target, request, this );
8007 }
8008 request = next;
8009 }
8010
8011 return more;
8012 }
8013
8014 // MARK: -
8015 // MARK: IOServicePM
8016
8017 OSDefineMetaClassAndStructors(IOServicePM, OSObject)
8018
8019 //*********************************************************************************
8020 // serialize
8021 //
8022 // Serialize IOServicePM for debugging.
8023 //*********************************************************************************
8024
8025 static void
8026 setPMProperty( OSDictionary * dict, const char * key, uint64_t value )
8027 {
8028 OSNumber * num = OSNumber::withNumber(value, sizeof(value) * 8);
8029 if (num)
8030 {
8031 dict->setObject(key, num);
8032 num->release();
8033 }
8034 }
8035
8036 IOReturn IOServicePM::gatedSerialize( OSSerialize * s )
8037 {
8038 OSDictionary * dict;
8039 bool ok = false;
8040 int dictSize = 5;
8041
8042 if (IdleTimerPeriod)
8043 dictSize += 4;
8044
8045 #if WORK_QUEUE_STATS
8046 if (gIOPMRootNode == ControllingDriver)
8047 dictSize += 4;
8048 #endif
8049
8050 if (PowerClients)
8051 dict = OSDictionary::withDictionary(
8052 PowerClients, PowerClients->getCount() + dictSize);
8053 else
8054 dict = OSDictionary::withCapacity(dictSize);
8055
8056 if (dict)
8057 {
8058 setPMProperty(dict, "CurrentPowerState", CurrentPowerState);
8059 if (NumberOfPowerStates)
8060 setPMProperty(dict, "MaxPowerState", NumberOfPowerStates-1);
8061 if (DesiredPowerState != CurrentPowerState)
8062 setPMProperty(dict, "DesiredPowerState", DesiredPowerState);
8063 if (kIOPM_Finished != MachineState)
8064 setPMProperty(dict, "MachineState", MachineState);
8065 if (DeviceOverrideEnabled)
8066 dict->setObject("PowerOverrideOn", kOSBooleanTrue);
8067
8068 if (IdleTimerPeriod)
8069 {
8070 AbsoluteTime now;
8071 AbsoluteTime delta;
8072 uint64_t nsecs;
8073
8074 clock_get_uptime(&now);
8075
8076 // The idle timer period in milliseconds.
8077 setPMProperty(dict, "IdleTimerPeriod", IdleTimerPeriod * 1000ULL);
8078
8079 // The number of activity tickles recorded since device idle
8080 setPMProperty(dict, "ActivityTickles", ActivityTickleCount);
8081
8082 if (AbsoluteTime_to_scalar(&DeviceActiveTimestamp))
8083 {
8084 // The number of milliseconds since the last activity tickle.
8085 delta = now;
8086 SUB_ABSOLUTETIME(&delta, &DeviceActiveTimestamp);
8087 absolutetime_to_nanoseconds(delta, &nsecs);
8088 setPMProperty(dict, "TimeSinceLastTickle", NS_TO_MS(nsecs));
8089 }
8090
8091 if (AbsoluteTime_to_scalar(&IdleTimerStartTime))
8092 {
8093 // The number of milliseconds since the last device idle.
8094 delta = now;
8095 SUB_ABSOLUTETIME(&delta, &IdleTimerStartTime);
8096 absolutetime_to_nanoseconds(delta, &nsecs);
8097 setPMProperty(dict, "TimeSinceDeviceIdle", NS_TO_MS(nsecs));
8098 }
8099 }
8100
8101 #if WORK_QUEUE_STATS
8102 if (gIOPMRootNode == Owner)
8103 {
8104 setPMProperty(dict, "WQ-CheckForWork",
8105 gIOPMWorkQueue->fStatCheckForWork);
8106 setPMProperty(dict, "WQ-ScanEntries",
8107 gIOPMWorkQueue->fStatScanEntries);
8108 setPMProperty(dict, "WQ-QueueEmpty",
8109 gIOPMWorkQueue->fStatQueueEmpty);
8110 setPMProperty(dict, "WQ-NoWorkDone",
8111 gIOPMWorkQueue->fStatNoWorkDone);
8112 }
8113 #endif
8114
8115 if (HasAdvisoryDesire && !gIOPMAdvisoryTickleEnabled)
8116 {
8117 // Don't report advisory tickle when it has no influence
8118 dict->removeObject(gIOPMPowerClientAdvisoryTickle);
8119 }
8120
8121 ok = dict->serialize(s);
8122 dict->release();
8123 }
8124
8125 return (ok ? kIOReturnSuccess : kIOReturnNoMemory);
8126 }
8127
8128 bool IOServicePM::serialize( OSSerialize * s ) const
8129 {
8130 IOReturn ret = kIOReturnNotReady;
8131
8132 if (gIOPMWorkLoop)
8133 {
8134 ret = gIOPMWorkLoop->runAction(
8135 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOServicePM::gatedSerialize),
8136 (OSObject *) this, (void *) s);
8137 }
8138
8139 return (kIOReturnSuccess == ret);
8140 }
8141
8142 void IOServicePM::pmPrint(
8143 uint32_t event,
8144 uintptr_t param1,
8145 uintptr_t param2 ) const
8146 {
8147 gPlatform->PMLog(Name, event, param1, param2);
8148 }
8149
8150 void IOServicePM::pmTrace(
8151 uint32_t event,
8152 uintptr_t param1,
8153 uintptr_t param2 ) const
8154 {
8155 const char * who = Name;
8156 uint64_t regId = Owner->getRegistryEntryID();
8157 uintptr_t name = 0;
8158
8159 static const uint32_t sStartStopBitField[] =
8160 { 0x00000000, 0x00000040 }; // Only Program Hardware so far
8161
8162 // Arcane formula from Hacker's Delight by Warren
8163 // abs(x) = ((int) x >> 31) ^ (x + ((int) x >> 31))
8164 uint32_t sgnevent = ((int) event >> 31);
8165 uint32_t absevent = sgnevent ^ (event + sgnevent);
8166 uint32_t code = IODBG_POWER(absevent);
8167
8168 uint32_t bit = 1 << (absevent & 0x1f);
8169 if ((absevent < (sizeof(sStartStopBitField) * 8)) &&
8170 (sStartStopBitField[absevent >> 5] & bit))
8171 {
8172 // Or in the START or END bits, Start = 1 & END = 2
8173 // If sgnevent == 0 then START - 0 => START
8174 // else if sgnevent == -1 then START - -1 => END
8175 code |= DBG_FUNC_START - sgnevent;
8176 }
8177
8178 // Copy the first characters of the name into an uintptr_t
8179 for (uint32_t i = 0; (i < sizeof(uintptr_t) && who[i] != 0); i++)
8180 {
8181 ((char *) &name)[sizeof(uintptr_t) - i - 1] = who[i];
8182 }
8183
8184 IOTimeStampConstant(code, name, (uintptr_t) regId, param1, param2);
8185 }
8186
8187 PMEventDetails* PMEventDetails::eventDetails(uint32_t type,
8188 const char *ownerName,
8189 uintptr_t ownerUnique,
8190 const char *interestName,
8191 uint8_t oldState,
8192 uint8_t newState,
8193 uint32_t result,
8194 uint32_t elapsedTimeUS) {
8195
8196 PMEventDetails *myself;
8197 myself = new PMEventDetails;
8198
8199 if(myself) {
8200 myself->eventType = type;
8201 myself->ownerName = ownerName;
8202 myself->ownerUnique = ownerUnique;
8203 myself->interestName = interestName;
8204 myself->oldState = oldState;
8205 myself->newState = newState;
8206 myself->result = result;
8207 myself->elapsedTimeUS = elapsedTimeUS;
8208
8209 myself->eventClassifier = kIOPMEventClassDriverEvent;
8210 }
8211
8212 return myself;
8213 }
8214
8215
8216 PMEventDetails* PMEventDetails::eventDetails(uint32_t type,
8217 const char *uuid,
8218 uint32_t reason,
8219 uint32_t result) {
8220
8221 PMEventDetails *myself;
8222 myself = new PMEventDetails;
8223
8224 if(myself) {
8225 myself->eventType = type;
8226 myself->uuid = uuid;
8227 myself->reason = reason;
8228 myself->result = result;
8229
8230 myself->eventClassifier = kIOPMEventClassSystemEvent;
8231 }
8232
8233 return myself;
8234 }
8235