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