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