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