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