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