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