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