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