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