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