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(informee->whatObject->getRegistryEntryID()), VALUE(this->getRegistryEntryID())),
1556 PACK_2X32(VALUE(fDriverCallReason), VALUE(0)));
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(controllingDriverRegistryEntryID), VALUE(this->getRegistryEntryID())),
1694 PACK_2X32(VALUE(0), VALUE(fHeadNotePowerState)));
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(controllingDriverRegistryEntryID), VALUE(this->getRegistryEntryID())),
4171 PACK_2X32(VALUE(oldPowerState), VALUE(powerState)));
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(controllingDriverRegistryEntryID), VALUE(this->getRegistryEntryID())),
4187 PACK_2X32(VALUE(result), VALUE(powerState)));
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(driver->getRegistryEntryID()), VALUE(this->getRegistryEntryID())),
4264 PACK_2X32(VALUE(fDriverCallReason), VALUE(powerState)));
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(driver->getRegistryEntryID()), VALUE(this->getRegistryEntryID())),
4284 PACK_2X32(VALUE(fDriverCallReason), VALUE(result)));
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(context->errorLog, 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 context.errorLog = "PM notification timeout (pid %d, %s)\n";
6014
6015 applyToInterested(gIOAppPowerStateInterest, logAppTimeouts, (void *) &context);
6016 }
6017 break;
6018
6019 default:
6020 // kNotifyPriority, kNotifyCapabilityChangePriority
6021 // TODO: identify the priority client that has not acked
6022 PM_ERROR("PM priority notification timeout\n");
6023 if (gIOKitDebug & kIOLogDebugPower) {
6024 panic("PM priority notification timeout");
6025 }
6026 break;
6027 }
6028 }
6029
6030 if (IS_ROOT_DOMAIN) {
6031 getPMRootDomain()->reset_watchdog_timer(this, 0);
6032 }
6033 if (fResponseArray) {
6034 fResponseArray->release();
6035 fResponseArray = NULL;
6036 }
6037 if (fNotifyClientArray) {
6038 fNotifyClientArray->release();
6039 fNotifyClientArray = NULL;
6040 }
6041 }
6042
6043 //*********************************************************************************
6044 // [protected] tellClientsWithResponse
6045 //
6046 // Notify registered applications and kernel clients that we are definitely
6047 // dropping power.
6048 //
6049 // Return true if we don't have to wait for acknowledgements
6050 //*********************************************************************************
6051
6052 bool
tellClientsWithResponse(int messageType)6053 IOService::tellClientsWithResponse( int messageType )
6054 {
6055 IOPMInterestContext context;
6056 bool isRootDomain = IS_ROOT_DOMAIN;
6057 uint32_t maxTimeOut = kMaxTimeRequested;
6058
6059 PM_ASSERT_IN_GATE();
6060 assert( fResponseArray == NULL );
6061 assert( fNotifyClientArray == NULL );
6062
6063 RD_LOG("tellClientsWithResponse( %s, %s )\n", getIOMessageString(messageType),
6064 getNotificationPhaseString(fOutOfBandParameter));
6065
6066 fResponseArray = OSArray::withCapacity( 1 );
6067 if (!fResponseArray) {
6068 goto exit;
6069 }
6070
6071 fResponseArray->setCapacityIncrement(8);
6072 if (++fSerialNumber == 0) {
6073 fSerialNumber++;
6074 }
6075
6076 context.responseArray = fResponseArray;
6077 context.notifyClients = NULL;
6078 context.serialNumber = fSerialNumber;
6079 context.messageType = messageType;
6080 context.notifyType = fOutOfBandParameter;
6081 context.skippedInDark = 0;
6082 context.notSkippedInDark = 0;
6083 context.isPreChange = fIsPreChange;
6084 context.enableTracing = false;
6085 context.us = this;
6086 context.maxTimeRequested = 0;
6087 context.stateNumber = fHeadNotePowerState;
6088 context.stateFlags = fHeadNotePowerArrayEntry->capabilityFlags;
6089 context.changeFlags = fHeadNoteChangeFlags;
6090 context.messageFilter = (isRootDomain) ?
6091 OSMemberFunctionCast(
6092 IOPMMessageFilter,
6093 (IOPMrootDomain *)this,
6094 &IOPMrootDomain::systemMessageFilter) : NULL;
6095
6096 switch (fOutOfBandParameter) {
6097 case kNotifyApps:
6098 applyToInterested( gIOAppPowerStateInterest,
6099 pmTellAppWithResponse, (void *) &context );
6100
6101 if (isRootDomain &&
6102 (fMachineState != kIOPM_OurChangeTellClientsPowerDown) &&
6103 (fMachineState != kIOPM_SyncTellClientsPowerDown) &&
6104 (context.messageType != kIOPMMessageLastCallBeforeSleep)) {
6105 // Notify capability app for tellChangeDown1()
6106 // but not for askChangeDown().
6107 context.notifyType = kNotifyCapabilityChangeApps;
6108 context.messageType = kIOMessageSystemCapabilityChange;
6109 applyToInterested( gIOAppPowerStateInterest,
6110 pmTellCapabilityAppWithResponse, (void *) &context );
6111 context.notifyType = fOutOfBandParameter;
6112 context.messageType = messageType;
6113 }
6114 if (context.messageType == kIOMessageCanSystemSleep) {
6115 maxTimeOut = kCanSleepMaxTimeReq;
6116 if (gCanSleepTimeout) {
6117 maxTimeOut = (gCanSleepTimeout * us_per_s);
6118 }
6119 }
6120 context.maxTimeRequested = maxTimeOut;
6121 context.enableTracing = isRootDomain;
6122 applyToInterested( gIOGeneralInterest,
6123 pmTellClientWithResponse, (void *) &context );
6124
6125 break;
6126
6127 case kNotifyPriority:
6128 context.enableTracing = isRootDomain;
6129 applyToInterested( gIOPriorityPowerStateInterest,
6130 pmTellClientWithResponse, (void *) &context );
6131
6132 if (isRootDomain) {
6133 // Notify capability clients for tellChangeDown2().
6134 context.notifyType = kNotifyCapabilityChangePriority;
6135 context.messageType = kIOMessageSystemCapabilityChange;
6136 applyToInterested( gIOPriorityPowerStateInterest,
6137 pmTellCapabilityClientWithResponse, (void *) &context );
6138 }
6139 break;
6140
6141 case kNotifyCapabilityChangeApps:
6142 context.enableTracing = isRootDomain;
6143 applyToInterested( gIOAppPowerStateInterest,
6144 pmTellCapabilityAppWithResponse, (void *) &context );
6145 if (context.messageType == kIOMessageCanSystemSleep) {
6146 maxTimeOut = kCanSleepMaxTimeReq;
6147 if (gCanSleepTimeout) {
6148 maxTimeOut = (gCanSleepTimeout * us_per_s);
6149 }
6150 }
6151 context.maxTimeRequested = maxTimeOut;
6152 break;
6153
6154 case kNotifyCapabilityChangePriority:
6155 context.enableTracing = isRootDomain;
6156 applyToInterested( gIOPriorityPowerStateInterest,
6157 pmTellCapabilityClientWithResponse, (void *) &context );
6158 break;
6159 }
6160 fNotifyClientArray = context.notifyClients;
6161
6162 if (context.skippedInDark) {
6163 IOLog("tellClientsWithResponse(%s, %s) %d of %d skipped in dark\n",
6164 getIOMessageString(messageType), getNotificationPhaseString(fOutOfBandParameter),
6165 context.skippedInDark, context.skippedInDark + context.notSkippedInDark);
6166 }
6167
6168 // do we have to wait for somebody?
6169 if (!checkForDone()) {
6170 OUR_PMLog(kPMLogStartAckTimer, context.maxTimeRequested, 0);
6171 if (context.enableTracing) {
6172 getPMRootDomain()->traceDetail(context.messageType, 0, context.maxTimeRequested / 1000);
6173 getPMRootDomain()->reset_watchdog_timer(this, context.maxTimeRequested / USEC_PER_SEC + 1);
6174 }
6175 start_ack_timer( context.maxTimeRequested / 1000, kMillisecondScale );
6176 return false;
6177 }
6178
6179 exit:
6180 // everybody responded
6181 if (fResponseArray) {
6182 fResponseArray->release();
6183 fResponseArray = NULL;
6184 }
6185 if (fNotifyClientArray) {
6186 fNotifyClientArray->release();
6187 fNotifyClientArray = NULL;
6188 }
6189
6190 return true;
6191 }
6192
6193 //*********************************************************************************
6194 // [static private] pmTellAppWithResponse
6195 //
6196 // We send a message to an application, and we expect a response, so we compute a
6197 // cookie we can identify the response with.
6198 //*********************************************************************************
6199
6200 void
pmTellAppWithResponse(OSObject * object,void * arg)6201 IOService::pmTellAppWithResponse( OSObject * object, void * arg )
6202 {
6203 IOPMInterestContext * context = (IOPMInterestContext *) arg;
6204 IOServicePM * pwrMgt = context->us->pwrMgt;
6205 uint32_t msgIndex, msgRef, msgType;
6206 OSNumber *clientID = NULL;
6207 proc_t proc = NULL;
6208 boolean_t proc_suspended = FALSE;
6209 OSObject * waitForReply = kOSBooleanTrue;
6210 #if LOG_APP_RESPONSE_TIMES
6211 AbsoluteTime now;
6212 #endif
6213
6214 if (!OSDynamicCast(_IOServiceInterestNotifier, object)) {
6215 return;
6216 }
6217
6218 if (context->us == getPMRootDomain()) {
6219 if ((clientID = copyClientIDForNotification(object, context))) {
6220 uint32_t clientPID = clientID->unsigned32BitValue();
6221 clientID->release();
6222 proc = proc_find(clientPID);
6223
6224 if (proc) {
6225 proc_suspended = get_task_pidsuspended((task_t) proc->task);
6226 if (proc_suspended) {
6227 logClientIDForNotification(object, context, "PMTellAppWithResponse - Suspended");
6228 } else if (getPMRootDomain()->isAOTMode() && get_task_suspended((task_t) proc->task)) {
6229 proc_suspended = true;
6230 context->skippedInDark++;
6231 }
6232 proc_rele(proc);
6233 if (proc_suspended) {
6234 return;
6235 }
6236 }
6237 }
6238 }
6239
6240 if (context->messageFilter &&
6241 !context->messageFilter(context->us, object, context, NULL, &waitForReply)) {
6242 if (kIOLogDebugPower & gIOKitDebug) {
6243 logClientIDForNotification(object, context, "DROP App");
6244 }
6245 return;
6246 }
6247 context->notSkippedInDark++;
6248
6249 // Create client array (for tracking purposes) only if the service
6250 // has app clients. Usually only root domain does.
6251 if (NULL == context->notifyClients) {
6252 context->notifyClients = OSArray::withCapacity( 32 );
6253 }
6254
6255 msgType = context->messageType;
6256 msgIndex = context->responseArray->getCount();
6257 msgRef = ((context->serialNumber & 0xFFFF) << 16) + (msgIndex & 0xFFFF);
6258
6259 OUR_PMLog(kPMLogAppNotify, msgType, msgRef);
6260 if (kIOLogDebugPower & gIOKitDebug) {
6261 logClientIDForNotification(object, context, "MESG App");
6262 }
6263
6264 if (waitForReply == kOSBooleanTrue) {
6265 OSNumber * num;
6266 clock_get_uptime(&now);
6267 num = OSNumber::withNumber(AbsoluteTime_to_scalar(&now), sizeof(uint64_t) * 8);
6268 if (num) {
6269 context->responseArray->setObject(msgIndex, num);
6270 num->release();
6271 } else {
6272 context->responseArray->setObject(msgIndex, kOSBooleanFalse);
6273 }
6274 } else {
6275 context->responseArray->setObject(msgIndex, kOSBooleanTrue);
6276 if (kIOLogDebugPower & gIOKitDebug) {
6277 logClientIDForNotification(object, context, "App response ignored");
6278 }
6279 }
6280
6281 if (context->notifyClients) {
6282 context->notifyClients->setObject(msgIndex, object);
6283 }
6284
6285 context->us->messageClient(msgType, object, (void *)(uintptr_t) msgRef);
6286 }
6287
6288 //*********************************************************************************
6289 // [static private] pmTellClientWithResponse
6290 //
6291 // We send a message to an in-kernel client, and we expect a response,
6292 // so we compute a cookie we can identify the response with.
6293 //*********************************************************************************
6294
6295 void
pmTellClientWithResponse(OSObject * object,void * arg)6296 IOService::pmTellClientWithResponse( OSObject * object, void * arg )
6297 {
6298 IOPowerStateChangeNotification notify;
6299 IOPMInterestContext * context = (IOPMInterestContext *) arg;
6300 OSObject * replied = kOSBooleanTrue;
6301 _IOServiceInterestNotifier * notifier;
6302 uint32_t msgIndex, msgRef, msgType;
6303 IOReturn retCode;
6304 AbsoluteTime start, end;
6305 uint64_t nsec;
6306 bool enableTracing;
6307
6308 if (context->messageFilter &&
6309 !context->messageFilter(context->us, object, context, NULL, NULL)) {
6310 getPMRootDomain()->traceFilteredNotification(object);
6311 return;
6312 }
6313
6314 // Besides interest notifiers this applier function can also be invoked against
6315 // IOService clients of context->us, so notifier can be NULL. But for tracing
6316 // purposes the IOService clients can be ignored but each will still consume
6317 // an entry in the responseArray and also advance msgIndex.
6318 notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
6319 msgType = context->messageType;
6320 msgIndex = context->responseArray->getCount();
6321 msgRef = ((context->serialNumber & 0xFFFF) << 16) + (msgIndex & 0xFFFF);
6322 enableTracing = context->enableTracing && (notifier != NULL);
6323
6324 IOServicePM * pwrMgt = context->us->pwrMgt;
6325 if (gIOKitDebug & kIOLogPower) {
6326 OUR_PMLog(kPMLogClientNotify, msgRef, msgType);
6327 if (OSDynamicCast(IOService, object)) {
6328 const char *who = ((IOService *) object)->getName();
6329 gPlatform->PMLog(who, kPMLogClientNotify, (uintptr_t) object, 0);
6330 } else if (notifier) {
6331 OUR_PMLog(kPMLogClientNotify, (uintptr_t) notifier->handler, 0);
6332 }
6333 }
6334
6335 if (NULL == context->notifyClients) {
6336 context->notifyClients = OSArray::withCapacity(32);
6337 assert(context->notifyClients != NULL);
6338 }
6339
6340 notify.powerRef = (void *)(uintptr_t) msgRef;
6341 notify.returnValue = 0;
6342 notify.stateNumber = context->stateNumber;
6343 notify.stateFlags = context->stateFlags;
6344
6345 clock_get_uptime(&start);
6346 if (enableTracing) {
6347 getPMRootDomain()->traceNotification(notifier, true, start, msgIndex);
6348 }
6349
6350 retCode = context->us->messageClient(msgType, object, (void *) ¬ify, sizeof(notify));
6351
6352 clock_get_uptime(&end);
6353 if (enableTracing) {
6354 getPMRootDomain()->traceNotification(notifier, false, end);
6355 }
6356
6357 if (kIOReturnSuccess == retCode) {
6358 if (0 == notify.returnValue) {
6359 OUR_PMLog(kPMLogClientAcknowledge, msgRef, (uintptr_t) object);
6360 context->responseArray->setObject(msgIndex, replied);
6361 } else {
6362 replied = kOSBooleanFalse;
6363 if (notify.returnValue > context->maxTimeRequested) {
6364 if (notify.returnValue > kPriorityClientMaxWait) {
6365 context->maxTimeRequested = kPriorityClientMaxWait;
6366 PM_ERROR("%s: client %p returned %llu for %s\n",
6367 context->us->getName(),
6368 notifier ? (void *) OBFUSCATE(notifier->handler) : OBFUSCATE(object),
6369 (uint64_t) notify.returnValue,
6370 getIOMessageString(msgType));
6371 } else {
6372 context->maxTimeRequested = (typeof(context->maxTimeRequested))notify.returnValue;
6373 }
6374 }
6375 //
6376 // Track time taken to ack, by storing the timestamp of
6377 // callback completion
6378 OSNumber * num;
6379 num = OSNumber::withNumber(AbsoluteTime_to_scalar(&end), sizeof(uint64_t) * 8);
6380 if (num) {
6381 context->responseArray->setObject(msgIndex, num);
6382 num->release();
6383 } else {
6384 context->responseArray->setObject(msgIndex, replied);
6385 }
6386 }
6387
6388 if (enableTracing) {
6389 SUB_ABSOLUTETIME(&end, &start);
6390 absolutetime_to_nanoseconds(end, &nsec);
6391
6392 if ((nsec > LOG_KEXT_RESPONSE_TIMES) || (notify.returnValue != 0)) {
6393 getPMRootDomain()->traceNotificationResponse(notifier, NS_TO_MS(nsec), (uint32_t) notify.returnValue);
6394 }
6395 }
6396 } else {
6397 // not a client of ours
6398 // so we won't be waiting for response
6399 OUR_PMLog(kPMLogClientAcknowledge, msgRef, 0);
6400 context->responseArray->setObject(msgIndex, replied);
6401 }
6402 if (context->notifyClients) {
6403 context->notifyClients->setObject(msgIndex, object);
6404 }
6405 }
6406
6407 //*********************************************************************************
6408 // [static private] pmTellCapabilityAppWithResponse
6409 //*********************************************************************************
6410
6411 void
pmTellCapabilityAppWithResponse(OSObject * object,void * arg)6412 IOService::pmTellCapabilityAppWithResponse( OSObject * object, void * arg )
6413 {
6414 IOPMSystemCapabilityChangeParameters msgArg;
6415 IOPMInterestContext * context = (IOPMInterestContext *) arg;
6416 OSObject * waitForReply = kOSBooleanFalse;
6417 IOServicePM * pwrMgt = context->us->pwrMgt;
6418 uint32_t msgIndex, msgRef, msgType;
6419 #if LOG_APP_RESPONSE_TIMES
6420 AbsoluteTime now;
6421 #endif
6422
6423 if (!OSDynamicCast(_IOServiceInterestNotifier, object)) {
6424 return;
6425 }
6426
6427 memset(&msgArg, 0, sizeof(msgArg));
6428 if (context->messageFilter &&
6429 !context->messageFilter(context->us, object, context, &msgArg, &waitForReply)) {
6430 return;
6431 }
6432
6433 if (context->us == getPMRootDomain() &&
6434 getPMRootDomain()->isAOTMode()
6435 ) {
6436 OSNumber *clientID = NULL;
6437 boolean_t proc_suspended = FALSE;
6438 proc_t proc = NULL;
6439 if ((clientID = copyClientIDForNotification(object, context))) {
6440 uint32_t clientPID = clientID->unsigned32BitValue();
6441 clientID->release();
6442 proc = proc_find(clientPID);
6443 if (proc) {
6444 proc_suspended = get_task_pidsuspended((task_t) proc->task);
6445 if (proc_suspended) {
6446 logClientIDForNotification(object, context, "PMTellCapablityAppWithResponse - Suspended");
6447 } else if (get_task_suspended((task_t) proc->task)) {
6448 proc_suspended = true;
6449 context->skippedInDark++;
6450 }
6451 proc_rele(proc);
6452 if (proc_suspended) {
6453 return;
6454 }
6455 }
6456 }
6457 }
6458 context->notSkippedInDark++;
6459
6460 // Create client array (for tracking purposes) only if the service
6461 // has app clients. Usually only root domain does.
6462 if (NULL == context->notifyClients) {
6463 context->notifyClients = OSArray::withCapacity(32);
6464 assert(context->notifyClients != NULL);
6465 }
6466
6467 msgType = context->messageType;
6468 msgIndex = context->responseArray->getCount();
6469 msgRef = ((context->serialNumber & 0xFFFF) << 16) + (msgIndex & 0xFFFF);
6470
6471 OUR_PMLog(kPMLogAppNotify, msgType, msgRef);
6472 if (kIOLogDebugPower & gIOKitDebug) {
6473 // Log client pid/name and client array index.
6474 OSNumber * clientID = NULL;
6475 OSString * clientIDString = NULL;
6476 context->us->messageClient(kIOMessageCopyClientID, object, &clientID);
6477 if (clientID) {
6478 clientIDString = IOCopyLogNameForPID(clientID->unsigned32BitValue());
6479 }
6480
6481 PM_LOG("%s MESG App(%u) %s, wait %u, %s\n",
6482 context->us->getName(),
6483 msgIndex, getIOMessageString(msgType),
6484 (waitForReply == kOSBooleanTrue),
6485 clientIDString ? clientIDString->getCStringNoCopy() : "");
6486 if (clientID) {
6487 clientID->release();
6488 }
6489 if (clientIDString) {
6490 clientIDString->release();
6491 }
6492 }
6493
6494 msgArg.notifyRef = msgRef;
6495 msgArg.maxWaitForReply = 0;
6496
6497 if (waitForReply == kOSBooleanFalse) {
6498 msgArg.notifyRef = 0;
6499 context->responseArray->setObject(msgIndex, kOSBooleanTrue);
6500 if (context->notifyClients) {
6501 context->notifyClients->setObject(msgIndex, kOSBooleanTrue);
6502 }
6503 } else {
6504 OSNumber * num;
6505 clock_get_uptime(&now);
6506 num = OSNumber::withNumber(AbsoluteTime_to_scalar(&now), sizeof(uint64_t) * 8);
6507 if (num) {
6508 context->responseArray->setObject(msgIndex, num);
6509 num->release();
6510 } else {
6511 context->responseArray->setObject(msgIndex, kOSBooleanFalse);
6512 }
6513
6514 if (context->notifyClients) {
6515 context->notifyClients->setObject(msgIndex, object);
6516 }
6517 }
6518
6519 context->us->messageClient(msgType, object, (void *) &msgArg, sizeof(msgArg));
6520 }
6521
6522 //*********************************************************************************
6523 // [static private] pmTellCapabilityClientWithResponse
6524 //*********************************************************************************
6525
6526 void
pmTellCapabilityClientWithResponse(OSObject * object,void * arg)6527 IOService::pmTellCapabilityClientWithResponse(
6528 OSObject * object, void * arg )
6529 {
6530 IOPMSystemCapabilityChangeParameters msgArg;
6531 IOPMInterestContext * context = (IOPMInterestContext *) arg;
6532 OSObject * replied = kOSBooleanTrue;
6533 _IOServiceInterestNotifier * notifier;
6534 uint32_t msgIndex, msgRef, msgType;
6535 IOReturn retCode;
6536 AbsoluteTime start, end;
6537 uint64_t nsec;
6538 bool enableTracing;
6539
6540 memset(&msgArg, 0, sizeof(msgArg));
6541 if (context->messageFilter &&
6542 !context->messageFilter(context->us, object, context, &msgArg, NULL)) {
6543 getPMRootDomain()->traceFilteredNotification(object);
6544 return;
6545 }
6546
6547 if (NULL == context->notifyClients) {
6548 context->notifyClients = OSArray::withCapacity(32);
6549 assert(context->notifyClients != NULL);
6550 }
6551
6552 notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
6553 msgType = context->messageType;
6554 msgIndex = context->responseArray->getCount();
6555 msgRef = ((context->serialNumber & 0xFFFF) << 16) + (msgIndex & 0xFFFF);
6556 enableTracing = context->enableTracing && (notifier != NULL);
6557
6558 IOServicePM * pwrMgt = context->us->pwrMgt;
6559 if (gIOKitDebug & kIOLogPower) {
6560 OUR_PMLog(kPMLogClientNotify, msgRef, msgType);
6561 if (OSDynamicCast(IOService, object)) {
6562 const char *who = ((IOService *) object)->getName();
6563 gPlatform->PMLog(who, kPMLogClientNotify, (uintptr_t) object, 0);
6564 } else if (notifier) {
6565 OUR_PMLog(kPMLogClientNotify, (uintptr_t) notifier->handler, 0);
6566 }
6567 }
6568
6569 msgArg.notifyRef = msgRef;
6570 msgArg.maxWaitForReply = 0;
6571
6572 clock_get_uptime(&start);
6573 if (enableTracing) {
6574 getPMRootDomain()->traceNotification(notifier, true, start, msgIndex);
6575 }
6576
6577 retCode = context->us->messageClient(msgType, object, (void *) &msgArg, sizeof(msgArg));
6578
6579 clock_get_uptime(&end);
6580 if (enableTracing) {
6581 getPMRootDomain()->traceNotification(notifier, false, end, msgIndex);
6582 }
6583
6584 if (kIOReturnSuccess == retCode) {
6585 if (0 == msgArg.maxWaitForReply) {
6586 // client doesn't want time to respond
6587 OUR_PMLog(kPMLogClientAcknowledge, msgRef, (uintptr_t) object);
6588 context->responseArray->setObject(msgIndex, replied);
6589 } else {
6590 replied = kOSBooleanFalse;
6591 if (msgArg.maxWaitForReply > context->maxTimeRequested) {
6592 if (msgArg.maxWaitForReply > kCapabilityClientMaxWait) {
6593 context->maxTimeRequested = kCapabilityClientMaxWait;
6594 PM_ERROR("%s: client %p returned %u for %s\n",
6595 context->us->getName(),
6596 notifier ? (void *) OBFUSCATE(notifier->handler) : OBFUSCATE(object),
6597 msgArg.maxWaitForReply,
6598 getIOMessageString(msgType));
6599 } else {
6600 context->maxTimeRequested = msgArg.maxWaitForReply;
6601 }
6602 }
6603
6604 // Track time taken to ack, by storing the timestamp of
6605 // callback completion
6606 OSNumber * num;
6607 num = OSNumber::withNumber(AbsoluteTime_to_scalar(&end), sizeof(uint64_t) * 8);
6608 if (num) {
6609 context->responseArray->setObject(msgIndex, num);
6610 num->release();
6611 } else {
6612 context->responseArray->setObject(msgIndex, replied);
6613 }
6614 }
6615
6616 if (enableTracing) {
6617 SUB_ABSOLUTETIME(&end, &start);
6618 absolutetime_to_nanoseconds(end, &nsec);
6619
6620 if ((nsec > LOG_KEXT_RESPONSE_TIMES) || (msgArg.maxWaitForReply != 0)) {
6621 getPMRootDomain()->traceNotificationResponse(notifier, NS_TO_MS(nsec), msgArg.maxWaitForReply);
6622 }
6623 }
6624 } else {
6625 // not a client of ours
6626 // so we won't be waiting for response
6627 OUR_PMLog(kPMLogClientAcknowledge, msgRef, 0);
6628 context->responseArray->setObject(msgIndex, replied);
6629 }
6630 if (context->notifyClients) {
6631 context->notifyClients->setObject(msgIndex, object);
6632 }
6633 }
6634
6635 //*********************************************************************************
6636 // [public] tellNoChangeDown
6637 //
6638 // Notify registered applications and kernel clients that we are not
6639 // dropping power.
6640 //
6641 // Subclass can override this to send a different message type. Parameter is
6642 // the aborted destination state number.
6643 //*********************************************************************************
6644
6645 void
tellNoChangeDown(unsigned long)6646 IOService::tellNoChangeDown( unsigned long )
6647 {
6648 return tellClients( kIOMessageDeviceWillNotPowerOff );
6649 }
6650
6651 //*********************************************************************************
6652 // [public] tellChangeUp
6653 //
6654 // Notify registered applications and kernel clients that we are raising power.
6655 //
6656 // Subclass can override this to send a different message type. Parameter is
6657 // the aborted destination state number.
6658 //*********************************************************************************
6659
6660 void
tellChangeUp(unsigned long)6661 IOService::tellChangeUp( unsigned long )
6662 {
6663 return tellClients( kIOMessageDeviceHasPoweredOn );
6664 }
6665
6666 //*********************************************************************************
6667 // [protected] tellClients
6668 //
6669 // Notify registered applications and kernel clients of something.
6670 //*********************************************************************************
6671
6672 void
tellClients(int messageType)6673 IOService::tellClients( int messageType )
6674 {
6675 IOPMInterestContext context;
6676
6677 RD_LOG("tellClients( %s )\n", getIOMessageString(messageType));
6678
6679 memset(&context, 0, sizeof(context));
6680 context.messageType = messageType;
6681 context.isPreChange = fIsPreChange;
6682 context.us = this;
6683 context.stateNumber = fHeadNotePowerState;
6684 context.stateFlags = fHeadNotePowerArrayEntry->capabilityFlags;
6685 context.changeFlags = fHeadNoteChangeFlags;
6686 context.enableTracing = IS_ROOT_DOMAIN;
6687 context.messageFilter = (IS_ROOT_DOMAIN) ?
6688 OSMemberFunctionCast(
6689 IOPMMessageFilter,
6690 (IOPMrootDomain *)this,
6691 &IOPMrootDomain::systemMessageFilter) : NULL;
6692
6693 context.notifyType = kNotifyPriority;
6694 applyToInterested( gIOPriorityPowerStateInterest,
6695 tellKernelClientApplier, (void *) &context );
6696
6697 context.notifyType = kNotifyApps;
6698 applyToInterested( gIOAppPowerStateInterest,
6699 tellAppClientApplier, (void *) &context );
6700
6701 applyToInterested( gIOGeneralInterest,
6702 tellKernelClientApplier, (void *) &context );
6703 }
6704
6705 //*********************************************************************************
6706 // [private] tellKernelClientApplier
6707 //
6708 // Message a kernel client.
6709 //*********************************************************************************
6710
6711 static void
tellKernelClientApplier(OSObject * object,void * arg)6712 tellKernelClientApplier( OSObject * object, void * arg )
6713 {
6714 IOPowerStateChangeNotification notify;
6715 IOPMInterestContext * context = (IOPMInterestContext *) arg;
6716 bool enableTracing = context->enableTracing;
6717
6718 if (context->messageFilter &&
6719 !context->messageFilter(context->us, object, context, NULL, NULL)) {
6720 IOService::getPMRootDomain()->traceFilteredNotification(object);
6721 return;
6722 }
6723
6724 notify.powerRef = (void *) NULL;
6725 notify.returnValue = 0;
6726 notify.stateNumber = context->stateNumber;
6727 notify.stateFlags = context->stateFlags;
6728
6729 if (enableTracing) {
6730 IOService::getPMRootDomain()->traceNotification(object, true);
6731 }
6732
6733 context->us->messageClient(context->messageType, object, ¬ify, sizeof(notify));
6734
6735 if (enableTracing) {
6736 IOService::getPMRootDomain()->traceNotification(object, false);
6737 }
6738 }
6739
6740 static OSNumber *
copyClientIDForNotification(OSObject * object,IOPMInterestContext * context)6741 copyClientIDForNotification(
6742 OSObject *object,
6743 IOPMInterestContext *context)
6744 {
6745 OSNumber *clientID = NULL;
6746 context->us->messageClient(kIOMessageCopyClientID, object, &clientID);
6747 return clientID;
6748 }
6749
6750 static void
logClientIDForNotification(OSObject * object,IOPMInterestContext * context,const char * logString)6751 logClientIDForNotification(
6752 OSObject *object,
6753 IOPMInterestContext *context,
6754 const char *logString)
6755 {
6756 OSString *logClientID = NULL;
6757 OSNumber *clientID = copyClientIDForNotification(object, context);
6758
6759 if (logString) {
6760 if (clientID) {
6761 logClientID = IOCopyLogNameForPID(clientID->unsigned32BitValue());
6762 }
6763
6764 PM_LOG("%s %s %s, %s\n",
6765 context->us->getName(), logString,
6766 IOService::getIOMessageString(context->messageType),
6767 logClientID ? logClientID->getCStringNoCopy() : "");
6768
6769 if (logClientID) {
6770 logClientID->release();
6771 }
6772 }
6773
6774 if (clientID) {
6775 clientID->release();
6776 }
6777
6778 return;
6779 }
6780
6781 static void
tellAppClientApplier(OSObject * object,void * arg)6782 tellAppClientApplier( OSObject * object, void * arg )
6783 {
6784 IOPMInterestContext * context = (IOPMInterestContext *) arg;
6785 OSNumber * clientID = NULL;
6786 proc_t proc = NULL;
6787 boolean_t proc_suspended = FALSE;
6788
6789 if (context->us == IOService::getPMRootDomain()) {
6790 if ((clientID = copyClientIDForNotification(object, context))) {
6791 uint32_t clientPID = clientID->unsigned32BitValue();
6792 clientID->release();
6793 proc = proc_find(clientPID);
6794
6795 if (proc) {
6796 proc_suspended = get_task_pidsuspended((task_t) proc->task);
6797 if (proc_suspended) {
6798 logClientIDForNotification(object, context, "tellAppClientApplier - Suspended");
6799 } else if (IOService::getPMRootDomain()->isAOTMode() && get_task_suspended((task_t) proc->task)) {
6800 proc_suspended = true;
6801 context->skippedInDark++;
6802 }
6803 proc_rele(proc);
6804 if (proc_suspended) {
6805 return;
6806 }
6807 }
6808 }
6809 }
6810
6811 if (context->messageFilter &&
6812 !context->messageFilter(context->us, object, context, NULL, NULL)) {
6813 if (kIOLogDebugPower & gIOKitDebug) {
6814 logClientIDForNotification(object, context, "DROP App");
6815 }
6816 return;
6817 }
6818 context->notSkippedInDark++;
6819
6820 if (kIOLogDebugPower & gIOKitDebug) {
6821 logClientIDForNotification(object, context, "MESG App");
6822 }
6823
6824 context->us->messageClient(context->messageType, object, NULL);
6825 }
6826
6827 //*********************************************************************************
6828 // [private] checkForDone
6829 //*********************************************************************************
6830
6831 bool
checkForDone(void)6832 IOService::checkForDone( void )
6833 {
6834 int i = 0;
6835 OSObject * theFlag;
6836
6837 if (fResponseArray == NULL) {
6838 return true;
6839 }
6840
6841 for (i = 0;; i++) {
6842 theFlag = fResponseArray->getObject(i);
6843
6844 if (NULL == theFlag) {
6845 break;
6846 }
6847
6848 if (kOSBooleanTrue != theFlag) {
6849 return false;
6850 }
6851 }
6852 return true;
6853 }
6854
6855 //*********************************************************************************
6856 // [public] responseValid
6857 //*********************************************************************************
6858
6859 bool
responseValid(uint32_t refcon,int pid)6860 IOService::responseValid( uint32_t refcon, int pid )
6861 {
6862 UInt16 serialComponent;
6863 UInt16 ordinalComponent;
6864 OSObject * theFlag;
6865 OSObject *object = NULL;
6866
6867 serialComponent = (refcon >> 16) & 0xFFFF;
6868 ordinalComponent = (refcon & 0xFFFF);
6869
6870 if (serialComponent != fSerialNumber) {
6871 return false;
6872 }
6873
6874 if (fResponseArray == NULL) {
6875 return false;
6876 }
6877
6878 theFlag = fResponseArray->getObject(ordinalComponent);
6879
6880 if (theFlag == NULL) {
6881 return false;
6882 }
6883
6884 if (fNotifyClientArray) {
6885 object = fNotifyClientArray->getObject(ordinalComponent);
6886 }
6887
6888 OSNumber * num;
6889 if ((num = OSDynamicCast(OSNumber, theFlag))) {
6890 AbsoluteTime now;
6891 AbsoluteTime start;
6892 uint64_t nsec;
6893 char name[128];
6894
6895 clock_get_uptime(&now);
6896 AbsoluteTime_to_scalar(&start) = num->unsigned64BitValue();
6897 SUB_ABSOLUTETIME(&now, &start);
6898 absolutetime_to_nanoseconds(now, &nsec);
6899
6900 if (pid != 0) {
6901 name[0] = '\0';
6902 proc_name(pid, name, sizeof(name));
6903
6904 if (nsec > LOG_APP_RESPONSE_TIMES) {
6905 IOLog("PM response took %d ms (%d, %s)\n", NS_TO_MS(nsec),
6906 pid, name);
6907 }
6908
6909 if (nsec > LOG_APP_RESPONSE_MSG_TRACER) {
6910 // TODO: populate the messageType argument
6911 getPMRootDomain()->pmStatsRecordApplicationResponse(
6912 gIOPMStatsResponseSlow,
6913 name, 0, NS_TO_MS(nsec), pid, object);
6914 } else {
6915 getPMRootDomain()->pmStatsRecordApplicationResponse(
6916 gIOPMStatsResponsePrompt,
6917 name, 0, NS_TO_MS(nsec), pid, object);
6918 }
6919 } else {
6920 getPMRootDomain()->traceNotificationAck(object, NS_TO_MS(nsec));
6921 }
6922
6923 if (kIOLogDebugPower & gIOKitDebug) {
6924 PM_LOG("Ack(%u) %u ms\n",
6925 (uint32_t) ordinalComponent,
6926 NS_TO_MS(nsec));
6927 }
6928 theFlag = kOSBooleanFalse;
6929 } else if (object) {
6930 getPMRootDomain()->pmStatsRecordApplicationResponse(
6931 gIOPMStatsResponsePrompt,
6932 NULL, 0, 0, pid, object);
6933 }
6934
6935 if (kOSBooleanFalse == theFlag) {
6936 fResponseArray->replaceObject(ordinalComponent, kOSBooleanTrue);
6937 }
6938
6939 return true;
6940 }
6941
6942 //*********************************************************************************
6943 // [public] allowPowerChange
6944 //
6945 // Our power state is about to lower, and we have notified applications
6946 // and kernel clients, and one of them has acknowledged. If this is the last to do
6947 // so, and all acknowledgements are positive, we continue with the power change.
6948 //*********************************************************************************
6949
6950 IOReturn
allowPowerChange(unsigned long refcon)6951 IOService::allowPowerChange( unsigned long refcon )
6952 {
6953 IOPMRequest * request;
6954
6955 if (!initialized) {
6956 // we're unloading
6957 return kIOReturnSuccess;
6958 }
6959
6960 request = acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange );
6961 if (!request) {
6962 return kIOReturnNoMemory;
6963 }
6964
6965 request->fArg0 = (void *) refcon;
6966 request->fArg1 = (void *)(uintptr_t) proc_selfpid();
6967 request->fArg2 = (void *) NULL;
6968 submitPMRequest( request );
6969
6970 return kIOReturnSuccess;
6971 }
6972
6973 #ifndef __LP64__
6974 IOReturn
serializedAllowPowerChange2(unsigned long refcon)6975 IOService::serializedAllowPowerChange2( unsigned long refcon )
6976 {
6977 // [deprecated] public
6978 return kIOReturnUnsupported;
6979 }
6980 #endif /* !__LP64__ */
6981
6982 //*********************************************************************************
6983 // [public] cancelPowerChange
6984 //
6985 // Our power state is about to lower, and we have notified applications
6986 // and kernel clients, and one of them has vetoed the change. If this is the last
6987 // client to respond, we abandon the power change.
6988 //*********************************************************************************
6989
6990 IOReturn
cancelPowerChange(unsigned long refcon)6991 IOService::cancelPowerChange( unsigned long refcon )
6992 {
6993 IOPMRequest * request;
6994 char name[128];
6995 pid_t pid = proc_selfpid();
6996
6997 if (!initialized) {
6998 // we're unloading
6999 return kIOReturnSuccess;
7000 }
7001
7002 name[0] = '\0';
7003 proc_name(pid, name, sizeof(name));
7004 PM_ERROR("PM notification cancel (pid %d, %s)\n", pid, name);
7005
7006 request = acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange );
7007 if (!request) {
7008 return kIOReturnNoMemory;
7009 }
7010
7011 request->fArg0 = (void *) refcon;
7012 request->fArg1 = (void *)(uintptr_t) proc_selfpid();
7013 request->fArg2 = (void *) OSString::withCString(name);
7014 submitPMRequest( request );
7015
7016 return kIOReturnSuccess;
7017 }
7018
7019 //*********************************************************************************
7020 // cancelIdlePowerDown
7021 //
7022 // Internal method to trigger an idle cancel or revert
7023 //*********************************************************************************
7024
7025 void
cancelIdlePowerDown(IOService * service)7026 IOService::cancelIdlePowerDown( IOService * service )
7027 {
7028 IOPMRequest * request;
7029
7030 request = acquirePMRequest(service, kIOPMRequestTypeIdleCancel);
7031 if (request) {
7032 submitPMRequest(request);
7033 }
7034 }
7035
7036 #ifndef __LP64__
7037 IOReturn
serializedCancelPowerChange2(unsigned long refcon)7038 IOService::serializedCancelPowerChange2( unsigned long refcon )
7039 {
7040 // [deprecated] public
7041 return kIOReturnUnsupported;
7042 }
7043
7044 //*********************************************************************************
7045 // PM_Clamp_Timer_Expired
7046 //
7047 // called when clamp timer expires...set power state to 0.
7048 //*********************************************************************************
7049
7050 void
PM_Clamp_Timer_Expired(void)7051 IOService::PM_Clamp_Timer_Expired( void )
7052 {
7053 }
7054
7055 //*********************************************************************************
7056 // clampPowerOn
7057 //
7058 // Set to highest available power state for a minimum of duration milliseconds
7059 //*********************************************************************************
7060
7061 void
clampPowerOn(unsigned long duration)7062 IOService::clampPowerOn( unsigned long duration )
7063 {
7064 }
7065 #endif /* !__LP64__ */
7066
7067 //*********************************************************************************
7068 // configurePowerStateReport
7069 //
7070 // Configures the IOStateReport for kPMPowerStateChannel
7071 //*********************************************************************************
7072 IOReturn
configurePowerStatesReport(IOReportConfigureAction action,void * result)7073 IOService::configurePowerStatesReport( IOReportConfigureAction action, void *result )
7074 {
7075 IOReturn rc = kIOReturnSuccess;
7076 size_t reportSize;
7077 unsigned long i;
7078 uint64_t ts;
7079
7080 if (!pwrMgt) {
7081 return kIOReturnUnsupported;
7082 }
7083
7084 if (!fNumberOfPowerStates) {
7085 return kIOReturnSuccess; // For drivers which are in power plane, but haven't called registerPowerDriver()
7086 }
7087
7088 if (fNumberOfPowerStates > INT16_MAX) {
7089 return kIOReturnOverrun;
7090 }
7091 PM_LOCK();
7092
7093 switch (action) {
7094 case kIOReportEnable:
7095 if (fReportBuf) {
7096 fReportClientCnt++;
7097 break;
7098 }
7099 reportSize = STATEREPORT_BUFSIZE(fNumberOfPowerStates);
7100 fReportBuf = IOMallocZeroData(reportSize);
7101 if (!fReportBuf) {
7102 rc = kIOReturnNoMemory;
7103 break;
7104 }
7105
7106 STATEREPORT_INIT((uint16_t) fNumberOfPowerStates, fReportBuf, reportSize,
7107 getRegistryEntryID(), kPMPowerStatesChID, kIOReportCategoryPower);
7108
7109 for (i = 0; i < fNumberOfPowerStates; i++) {
7110 unsigned bits = 0;
7111
7112 if (fPowerStates[i].capabilityFlags & kIOPMPowerOn) {
7113 bits |= kPMReportPowerOn;
7114 }
7115 if (fPowerStates[i].capabilityFlags & kIOPMDeviceUsable) {
7116 bits |= kPMReportDeviceUsable;
7117 }
7118 if (fPowerStates[i].capabilityFlags & kIOPMLowPower) {
7119 bits |= kPMReportLowPower;
7120 }
7121
7122 STATEREPORT_SETSTATEID(fReportBuf, i, ((bits & 0xff) << 8) |
7123 ((StateOrder(fMaxPowerState) & 0xf) << 4) | (StateOrder(i) & 0xf));
7124 }
7125 ts = mach_absolute_time();
7126 STATEREPORT_SETSTATE(fReportBuf, (uint16_t) fCurrentPowerState, ts);
7127 break;
7128
7129 case kIOReportDisable:
7130 if (fReportClientCnt == 0) {
7131 rc = kIOReturnBadArgument;
7132 break;
7133 }
7134 if (fReportClientCnt == 1) {
7135 IOFreeData(fReportBuf, STATEREPORT_BUFSIZE(fNumberOfPowerStates));
7136 fReportBuf = NULL;
7137 }
7138 fReportClientCnt--;
7139 break;
7140
7141 case kIOReportGetDimensions:
7142 if (fReportBuf) {
7143 STATEREPORT_UPDATERES(fReportBuf, kIOReportGetDimensions, result);
7144 }
7145 break;
7146 }
7147
7148 PM_UNLOCK();
7149
7150 return rc;
7151 }
7152
7153 //*********************************************************************************
7154 // updatePowerStateReport
7155 //
7156 // Updates the IOStateReport for kPMPowerStateChannel
7157 //*********************************************************************************
7158 IOReturn
updatePowerStatesReport(IOReportConfigureAction action,void * result,void * destination)7159 IOService::updatePowerStatesReport( IOReportConfigureAction action, void *result, void *destination )
7160 {
7161 uint32_t size2cpy;
7162 void *data2cpy;
7163 uint64_t ts;
7164 IOReturn rc = kIOReturnSuccess;
7165 IOBufferMemoryDescriptor *dest = OSDynamicCast(IOBufferMemoryDescriptor, (OSObject *)destination);
7166
7167
7168 if (!pwrMgt) {
7169 return kIOReturnUnsupported;
7170 }
7171 if (!fNumberOfPowerStates) {
7172 return kIOReturnSuccess;
7173 }
7174
7175 if (!result || !dest) {
7176 return kIOReturnBadArgument;
7177 }
7178 PM_LOCK();
7179
7180 switch (action) {
7181 case kIOReportCopyChannelData:
7182 if (!fReportBuf) {
7183 rc = kIOReturnNotOpen;
7184 break;
7185 }
7186
7187 ts = mach_absolute_time();
7188 STATEREPORT_UPDATEPREP(fReportBuf, ts, data2cpy, size2cpy);
7189 if (size2cpy > (dest->getCapacity() - dest->getLength())) {
7190 rc = kIOReturnOverrun;
7191 break;
7192 }
7193
7194 STATEREPORT_UPDATERES(fReportBuf, kIOReportCopyChannelData, result);
7195 dest->appendBytes(data2cpy, size2cpy);
7196 break;
7197
7198 default:
7199 break;
7200 }
7201
7202 PM_UNLOCK();
7203
7204 return rc;
7205 }
7206
7207 //*********************************************************************************
7208 // configureSimplePowerReport
7209 //
7210 // Configures the IOSimpleReport for given channel id
7211 //*********************************************************************************
7212 IOReturn
configureSimplePowerReport(IOReportConfigureAction action,void * result)7213 IOService::configureSimplePowerReport(IOReportConfigureAction action, void *result )
7214 {
7215 IOReturn rc = kIOReturnSuccess;
7216
7217 if (!pwrMgt) {
7218 return kIOReturnUnsupported;
7219 }
7220
7221 if (!fNumberOfPowerStates) {
7222 return rc;
7223 }
7224
7225 switch (action) {
7226 case kIOReportEnable:
7227 case kIOReportDisable:
7228 break;
7229
7230 case kIOReportGetDimensions:
7231 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions, result);
7232 break;
7233 }
7234
7235
7236 return rc;
7237 }
7238
7239 //*********************************************************************************
7240 // updateSimplePowerReport
7241 //
7242 // Updates the IOSimpleReport for the given chanel id
7243 //*********************************************************************************
7244 IOReturn
updateSimplePowerReport(IOReportConfigureAction action,void * result,void * destination)7245 IOService::updateSimplePowerReport( IOReportConfigureAction action, void *result, void *destination )
7246 {
7247 uint32_t size2cpy;
7248 void *data2cpy;
7249 uint64_t buf[SIMPLEREPORT_BUFSIZE / sizeof(uint64_t) + 1]; // Force a 8-byte alignment
7250 IOBufferMemoryDescriptor *dest = OSDynamicCast(IOBufferMemoryDescriptor, (OSObject *)destination);
7251 IOReturn rc = kIOReturnSuccess;
7252 unsigned bits = 0;
7253
7254
7255 if (!pwrMgt) {
7256 return kIOReturnUnsupported;
7257 }
7258 if (!result || !dest) {
7259 return kIOReturnBadArgument;
7260 }
7261
7262 if (!fNumberOfPowerStates) {
7263 return rc;
7264 }
7265 PM_LOCK();
7266
7267 switch (action) {
7268 case kIOReportCopyChannelData:
7269
7270 SIMPLEREPORT_INIT(buf, sizeof(buf), getRegistryEntryID(), kPMCurrStateChID, kIOReportCategoryPower);
7271
7272 if (fPowerStates[fCurrentPowerState].capabilityFlags & kIOPMPowerOn) {
7273 bits |= kPMReportPowerOn;
7274 }
7275 if (fPowerStates[fCurrentPowerState].capabilityFlags & kIOPMDeviceUsable) {
7276 bits |= kPMReportDeviceUsable;
7277 }
7278 if (fPowerStates[fCurrentPowerState].capabilityFlags & kIOPMLowPower) {
7279 bits |= kPMReportLowPower;
7280 }
7281
7282
7283 SIMPLEREPORT_SETVALUE(buf, ((bits & 0xff) << 8) | ((StateOrder(fMaxPowerState) & 0xf) << 4) |
7284 (StateOrder(fCurrentPowerState) & 0xf));
7285
7286 SIMPLEREPORT_UPDATEPREP(buf, data2cpy, size2cpy);
7287 if (size2cpy > (dest->getCapacity() - dest->getLength())) {
7288 rc = kIOReturnOverrun;
7289 break;
7290 }
7291
7292 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData, result);
7293 dest->appendBytes(data2cpy, size2cpy);
7294 break;
7295
7296 default:
7297 break;
7298 }
7299
7300 PM_UNLOCK();
7301
7302 return rc;
7303 }
7304
7305
7306
7307 // MARK: -
7308 // MARK: Driver Overrides
7309
7310 //*********************************************************************************
7311 // [public] setPowerState
7312 //
7313 // Does nothing here. This should be implemented in a subclass driver.
7314 //*********************************************************************************
7315
7316 IOReturn
setPowerState(unsigned long powerStateOrdinal,IOService * whatDevice)7317 IOService::setPowerState(
7318 unsigned long powerStateOrdinal, IOService * whatDevice )
7319 {
7320 return IOPMNoErr;
7321 }
7322
7323 //*********************************************************************************
7324 // [public] maxCapabilityForDomainState
7325 //
7326 // Finds the highest power state in the array whose input power requirement
7327 // is equal to the input parameter. Where a more intelligent decision is
7328 // possible, override this in the subclassed driver.
7329 //*********************************************************************************
7330
7331 IOPMPowerStateIndex
getPowerStateForDomainFlags(IOPMPowerFlags flags)7332 IOService::getPowerStateForDomainFlags( IOPMPowerFlags flags )
7333 {
7334 IOPMPowerStateIndex stateIndex;
7335
7336 if (!fNumberOfPowerStates) {
7337 return kPowerStateZero;
7338 }
7339
7340 for (long order = fNumberOfPowerStates - 1; order >= 0; order--) {
7341 stateIndex = fPowerStates[order].stateOrderToIndex;
7342
7343 if ((flags & fPowerStates[stateIndex].inputPowerFlags) ==
7344 fPowerStates[stateIndex].inputPowerFlags) {
7345 return stateIndex;
7346 }
7347 }
7348 return kPowerStateZero;
7349 }
7350
7351 unsigned long
maxCapabilityForDomainState(IOPMPowerFlags domainState)7352 IOService::maxCapabilityForDomainState( IOPMPowerFlags domainState )
7353 {
7354 return getPowerStateForDomainFlags(domainState);
7355 }
7356
7357 //*********************************************************************************
7358 // [public] initialPowerStateForDomainState
7359 //
7360 // Called to query the power state for the initial power transition.
7361 //*********************************************************************************
7362
7363 unsigned long
initialPowerStateForDomainState(IOPMPowerFlags domainState)7364 IOService::initialPowerStateForDomainState( IOPMPowerFlags domainState )
7365 {
7366 if (fResetPowerStateOnWake && (domainState & kIOPMRootDomainState)) {
7367 // Return lowest power state for any root power domain changes
7368 return kPowerStateZero;
7369 }
7370
7371 return getPowerStateForDomainFlags(domainState);
7372 }
7373
7374 //*********************************************************************************
7375 // [public] powerStateForDomainState
7376 //
7377 // This method is not called from PM.
7378 //*********************************************************************************
7379
7380 unsigned long
powerStateForDomainState(IOPMPowerFlags domainState)7381 IOService::powerStateForDomainState( IOPMPowerFlags domainState )
7382 {
7383 return getPowerStateForDomainFlags(domainState);
7384 }
7385
7386 #ifndef __LP64__
7387 //*********************************************************************************
7388 // [deprecated] didYouWakeSystem
7389 //
7390 // Does nothing here. This should be implemented in a subclass driver.
7391 //*********************************************************************************
7392
7393 bool
didYouWakeSystem(void)7394 IOService::didYouWakeSystem( void )
7395 {
7396 return false;
7397 }
7398 #endif /* !__LP64__ */
7399
7400 //*********************************************************************************
7401 // [public] powerStateWillChangeTo
7402 //
7403 // Does nothing here. This should be implemented in a subclass driver.
7404 //*********************************************************************************
7405
7406 IOReturn
powerStateWillChangeTo(IOPMPowerFlags,unsigned long,IOService *)7407 IOService::powerStateWillChangeTo( IOPMPowerFlags, unsigned long, IOService * )
7408 {
7409 return kIOPMAckImplied;
7410 }
7411
7412 //*********************************************************************************
7413 // [public] powerStateDidChangeTo
7414 //
7415 // Does nothing here. This should be implemented in a subclass driver.
7416 //*********************************************************************************
7417
7418 IOReturn
powerStateDidChangeTo(IOPMPowerFlags,unsigned long,IOService *)7419 IOService::powerStateDidChangeTo( IOPMPowerFlags, unsigned long, IOService * )
7420 {
7421 return kIOPMAckImplied;
7422 }
7423
7424 //*********************************************************************************
7425 // [protected] powerChangeDone
7426 //
7427 // Called from PM work loop thread.
7428 // Does nothing here. This should be implemented in a subclass policy-maker.
7429 //*********************************************************************************
7430
7431 void
powerChangeDone(unsigned long)7432 IOService::powerChangeDone( unsigned long )
7433 {
7434 }
7435
7436 #ifndef __LP64__
7437 //*********************************************************************************
7438 // [deprecated] newTemperature
7439 //
7440 // Does nothing here. This should be implemented in a subclass driver.
7441 //*********************************************************************************
7442
7443 IOReturn
newTemperature(long currentTemp,IOService * whichZone)7444 IOService::newTemperature( long currentTemp, IOService * whichZone )
7445 {
7446 return IOPMNoErr;
7447 }
7448 #endif /* !__LP64__ */
7449
7450 //*********************************************************************************
7451 // [public] systemWillShutdown
7452 //
7453 // System shutdown and restart notification.
7454 //*********************************************************************************
7455
7456 void
systemWillShutdown(IOOptionBits specifier)7457 IOService::systemWillShutdown( IOOptionBits specifier )
7458 {
7459 IOPMrootDomain * rootDomain = IOService::getPMRootDomain();
7460 if (rootDomain) {
7461 rootDomain->acknowledgeSystemWillShutdown( this );
7462 }
7463 }
7464
7465 // MARK: -
7466 // MARK: PM State Machine
7467
7468 //*********************************************************************************
7469 // [private static] acquirePMRequest
7470 //*********************************************************************************
7471
7472 IOPMRequest *
acquirePMRequest(IOService * target,IOOptionBits requestType,IOPMRequest * active)7473 IOService::acquirePMRequest( IOService * target, IOOptionBits requestType,
7474 IOPMRequest * active )
7475 {
7476 IOPMRequest * request;
7477
7478 assert(target);
7479
7480 request = IOPMRequest::create();
7481 if (request) {
7482 request->init( target, requestType );
7483 if (active) {
7484 IOPMRequest * root = active->getRootRequest();
7485 if (root) {
7486 request->attachRootRequest(root);
7487 }
7488 }
7489 } else {
7490 PM_ERROR("%s: No memory for PM request type 0x%x\n",
7491 target->getName(), (uint32_t) requestType);
7492 }
7493 return request;
7494 }
7495
7496 //*********************************************************************************
7497 // [private static] releasePMRequest
7498 //*********************************************************************************
7499
7500 void
releasePMRequest(IOPMRequest * request)7501 IOService::releasePMRequest( IOPMRequest * request )
7502 {
7503 if (request) {
7504 request->reset();
7505 request->release();
7506 }
7507 }
7508
7509 //*********************************************************************************
7510 // [private static] submitPMRequest
7511 //*********************************************************************************
7512
7513 void
submitPMRequest(IOPMRequest * request)7514 IOService::submitPMRequest( IOPMRequest * request )
7515 {
7516 assert( request );
7517 assert( gIOPMReplyQueue );
7518 assert( gIOPMRequestQueue );
7519
7520 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7521 (long)request->getType(), OBFUSCATE(request),
7522 OBFUSCATE(request->getTarget()), request->getTarget()->getName(),
7523 OBFUSCATE(request->fArg0),
7524 OBFUSCATE(request->fArg1), OBFUSCATE(request->fArg2));
7525
7526 if (request->isReplyType()) {
7527 gIOPMReplyQueue->queuePMRequest( request );
7528 } else {
7529 gIOPMRequestQueue->queuePMRequest( request );
7530 }
7531 }
7532
7533 void
submitPMRequests(IOPMRequest ** requests,IOItemCount count)7534 IOService::submitPMRequests( IOPMRequest ** requests, IOItemCount count )
7535 {
7536 assert( requests );
7537 assert( count > 0 );
7538 assert( gIOPMRequestQueue );
7539
7540 for (IOItemCount i = 0; i < count; i++) {
7541 IOPMRequest * req = requests[i];
7542 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7543 (long)req->getType(), OBFUSCATE(req),
7544 OBFUSCATE(req->getTarget()), req->getTarget()->getName(),
7545 OBFUSCATE(req->fArg0),
7546 OBFUSCATE(req->fArg1), OBFUSCATE(req->fArg2));
7547 }
7548
7549 gIOPMRequestQueue->queuePMRequestChain( requests, count );
7550 }
7551
7552 //*********************************************************************************
7553 // [private] actionPMRequestQueue
7554 //
7555 // IOPMRequestQueue::checkForWork() passing a new request to the request target.
7556 //*********************************************************************************
7557
7558 bool
actionPMRequestQueue(IOPMRequest * request,IOPMRequestQueue * queue)7559 IOService::actionPMRequestQueue(
7560 IOPMRequest * request,
7561 IOPMRequestQueue * queue )
7562 {
7563 bool more;
7564
7565 if (initialized) {
7566 // Work queue will immediately execute the request if the per-service
7567 // request queue is empty. Note pwrMgt is the target's IOServicePM.
7568
7569 more = gIOPMWorkQueue->queuePMRequest(request, pwrMgt);
7570 } else {
7571 // Calling PM without PMinit() is not allowed, fail the request.
7572 // Need to signal more when completing attached requests.
7573
7574 PM_LOG("%s: PM not initialized\n", getName());
7575 PM_LOG1("[- %02x] %p [%p %s] !initialized\n",
7576 request->getType(), OBFUSCATE(request),
7577 OBFUSCATE(this), getName());
7578
7579 more = gIOPMCompletionQueue->queuePMRequest(request);
7580 if (more) {
7581 gIOPMWorkQueue->incrementProducerCount();
7582 }
7583 }
7584
7585 return more;
7586 }
7587
7588 //*********************************************************************************
7589 // [private] actionPMCompletionQueue
7590 //
7591 // IOPMCompletionQueue::checkForWork() passing a completed request to the
7592 // request target.
7593 //*********************************************************************************
7594
7595 bool
actionPMCompletionQueue(IOPMRequest * request,IOPMCompletionQueue * queue)7596 IOService::actionPMCompletionQueue(
7597 IOPMRequest * request,
7598 IOPMCompletionQueue * queue )
7599 {
7600 bool more = (request->getNextRequest() != NULL);
7601 IOPMRequest * root = request->getRootRequest();
7602
7603 if (root && (root != request)) {
7604 more = true;
7605 }
7606 if (more) {
7607 gIOPMWorkQueue->incrementProducerCount();
7608 }
7609
7610 releasePMRequest( request );
7611 return more;
7612 }
7613
7614 //*********************************************************************************
7615 // [private] actionPMWorkQueueRetire
7616 //
7617 // IOPMWorkQueue::checkForWork() passing a retired request to the request target.
7618 //*********************************************************************************
7619
7620 bool
actionPMWorkQueueRetire(IOPMRequest * request,IOPMWorkQueue * queue)7621 IOService::actionPMWorkQueueRetire( IOPMRequest * request, IOPMWorkQueue * queue )
7622 {
7623 assert(request && queue);
7624
7625 PM_LOG1("[- %02x] %p [%p %s] state %d, busy %d\n",
7626 request->getType(), OBFUSCATE(request),
7627 OBFUSCATE(this), getName(),
7628 fMachineState, gIOPMBusyRequestCount);
7629
7630 // Catch requests created by idleTimerExpired()
7631 if (request->getType() == kIOPMRequestTypeActivityTickle) {
7632 uint32_t tickleFlags = (uint32_t)(uintptr_t) request->fArg1;
7633
7634 if ((tickleFlags & kTickleTypePowerDrop) && fIdleTimerPeriod) {
7635 restartIdleTimer();
7636 } else if (tickleFlags == (kTickleTypeActivity | kTickleTypePowerRise)) {
7637 // Invalidate any idle power drop that got queued while
7638 // processing this request.
7639 fIdleTimerGeneration++;
7640 }
7641 }
7642
7643 // When the completed request is linked, tell work queue there is
7644 // more work pending.
7645
7646 return gIOPMCompletionQueue->queuePMRequest( request );
7647 }
7648
7649 //*********************************************************************************
7650 // [private] isPMBlocked
7651 //
7652 // Check if machine state transition is blocked.
7653 //*********************************************************************************
7654
7655 bool
isPMBlocked(IOPMRequest * request,int count)7656 IOService::isPMBlocked( IOPMRequest * request, int count )
7657 {
7658 int reason = 0;
7659
7660 do {
7661 if (kIOPM_Finished == fMachineState) {
7662 break;
7663 }
7664
7665 if (kIOPM_DriverThreadCallDone == fMachineState) {
7666 // 5 = kDriverCallInformPreChange
7667 // 6 = kDriverCallInformPostChange
7668 // 7 = kDriverCallSetPowerState
7669 // 8 = kRootDomainInformPreChange
7670 if (fDriverCallBusy) {
7671 reason = 5 + fDriverCallReason;
7672 }
7673 break;
7674 }
7675
7676 // Waiting on driver's setPowerState() timeout.
7677 if (fDriverTimer) {
7678 reason = 1; break;
7679 }
7680
7681 // Child or interested driver acks pending.
7682 if (fHeadNotePendingAcks) {
7683 reason = 2; break;
7684 }
7685
7686 // Waiting on apps or priority power interest clients.
7687 if (fResponseArray) {
7688 reason = 3; break;
7689 }
7690
7691 #if USE_SETTLE_TIMER
7692 // Waiting on settle timer expiration.
7693 if (fSettleTimeUS) {
7694 reason = 4; break;
7695 }
7696 #endif
7697 } while (false);
7698
7699 fWaitReason = reason;
7700
7701 if (reason) {
7702 if (count) {
7703 PM_LOG1("[B %02x] %p [%p %s] state %d, reason %d\n",
7704 request->getType(), OBFUSCATE(request),
7705 OBFUSCATE(this), getName(),
7706 fMachineState, reason);
7707 }
7708
7709 return true;
7710 }
7711
7712 return false;
7713 }
7714
7715 //*********************************************************************************
7716 // [private] actionPMWorkQueueInvoke
7717 //
7718 // IOPMWorkQueue::checkForWork() passing a request to the
7719 // request target for execution.
7720 //*********************************************************************************
7721
7722 bool
actionPMWorkQueueInvoke(IOPMRequest * request,IOPMWorkQueue * queue)7723 IOService::actionPMWorkQueueInvoke( IOPMRequest * request, IOPMWorkQueue * queue )
7724 {
7725 bool done = false;
7726 int loop = 0;
7727
7728 assert(request && queue);
7729
7730 while (isPMBlocked(request, loop++) == false) {
7731 PM_LOG1("[W %02x] %p [%p %s] state %d\n",
7732 request->getType(), OBFUSCATE(request),
7733 OBFUSCATE(this), getName(), fMachineState);
7734
7735 gIOPMRequest = request;
7736 gIOPMWorkInvokeCount++;
7737
7738 // Every PM machine states must be handled in one of the cases below.
7739
7740 switch (fMachineState) {
7741 case kIOPM_Finished:
7742 start_watchdog_timer();
7743
7744 executePMRequest( request );
7745 break;
7746
7747 case kIOPM_OurChangeTellClientsPowerDown:
7748 // Root domain might self cancel due to assertions.
7749 if (IS_ROOT_DOMAIN) {
7750 bool cancel = (bool) fDoNotPowerDown;
7751 getPMRootDomain()->askChangeDownDone(
7752 &fHeadNoteChangeFlags, &cancel);
7753 fDoNotPowerDown = cancel;
7754 }
7755
7756 // askChangeDown() done, was it vetoed?
7757 if (!fDoNotPowerDown) {
7758 // no, we can continue
7759 OurChangeTellClientsPowerDown();
7760 } else {
7761 OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState);
7762 PM_ERROR("%s: idle cancel, state %u\n", fName, fMachineState);
7763 if (IS_ROOT_DOMAIN) {
7764 // RootDomain already sent "WillSleep" to its clients
7765 tellChangeUp(fCurrentPowerState);
7766 } else {
7767 tellNoChangeDown(fHeadNotePowerState);
7768 }
7769 // mark the change note un-actioned
7770 fHeadNoteChangeFlags |= kIOPMNotDone;
7771 // and we're done
7772 OurChangeFinish();
7773 }
7774 break;
7775
7776 case kIOPM_OurChangeTellUserPMPolicyPowerDown:
7777 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7778 if (fDoNotPowerDown) {
7779 OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState);
7780 PM_ERROR("%s: idle cancel, state %u\n", fName, fMachineState);
7781 if (IS_ROOT_DOMAIN) {
7782 // RootDomain already sent "WillSleep" to its clients
7783 tellChangeUp(fCurrentPowerState);
7784 } else {
7785 tellNoChangeDown(fHeadNotePowerState);
7786 }
7787 // mark the change note un-actioned
7788 fHeadNoteChangeFlags |= kIOPMNotDone;
7789 // and we're done
7790 OurChangeFinish();
7791 } else {
7792 OurChangeTellUserPMPolicyPowerDown();
7793 }
7794 break;
7795
7796 case kIOPM_OurChangeTellPriorityClientsPowerDown:
7797 // PMRD: LastCallBeforeSleep notify done
7798 // Non-PMRD: tellChangeDown/kNotifyApps done
7799 if (fDoNotPowerDown) {
7800 OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState);
7801 PM_ERROR("%s: idle revert, state %u\n", fName, fMachineState);
7802 // no, tell clients we're back in the old state
7803 tellChangeUp(fCurrentPowerState);
7804 // mark the change note un-actioned
7805 fHeadNoteChangeFlags |= kIOPMNotDone;
7806 // and we're done
7807 OurChangeFinish();
7808 } else {
7809 // yes, we can continue
7810 OurChangeTellPriorityClientsPowerDown();
7811 }
7812 break;
7813
7814 case kIOPM_OurChangeNotifyInterestedDriversWillChange:
7815 OurChangeNotifyInterestedDriversWillChange();
7816 break;
7817
7818 case kIOPM_OurChangeSetPowerState:
7819 OurChangeSetPowerState();
7820 break;
7821
7822 case kIOPM_OurChangeWaitForPowerSettle:
7823 OurChangeWaitForPowerSettle();
7824 break;
7825
7826 case kIOPM_OurChangeNotifyInterestedDriversDidChange:
7827 OurChangeNotifyInterestedDriversDidChange();
7828 break;
7829
7830 case kIOPM_OurChangeTellCapabilityDidChange:
7831 OurChangeTellCapabilityDidChange();
7832 break;
7833
7834 case kIOPM_OurChangeFinish:
7835 OurChangeFinish();
7836 break;
7837
7838 case kIOPM_ParentChangeTellPriorityClientsPowerDown:
7839 ParentChangeTellPriorityClientsPowerDown();
7840 break;
7841
7842 case kIOPM_ParentChangeNotifyInterestedDriversWillChange:
7843 ParentChangeNotifyInterestedDriversWillChange();
7844 break;
7845
7846 case kIOPM_ParentChangeSetPowerState:
7847 ParentChangeSetPowerState();
7848 break;
7849
7850 case kIOPM_ParentChangeWaitForPowerSettle:
7851 ParentChangeWaitForPowerSettle();
7852 break;
7853
7854 case kIOPM_ParentChangeNotifyInterestedDriversDidChange:
7855 ParentChangeNotifyInterestedDriversDidChange();
7856 break;
7857
7858 case kIOPM_ParentChangeTellCapabilityDidChange:
7859 ParentChangeTellCapabilityDidChange();
7860 break;
7861
7862 case kIOPM_ParentChangeAcknowledgePowerChange:
7863 ParentChangeAcknowledgePowerChange();
7864 break;
7865
7866 case kIOPM_DriverThreadCallDone:
7867 switch (fDriverCallReason) {
7868 case kDriverCallInformPreChange:
7869 case kDriverCallInformPostChange:
7870 notifyInterestedDriversDone();
7871 break;
7872 case kDriverCallSetPowerState:
7873 notifyControllingDriverDone();
7874 break;
7875 case kRootDomainInformPreChange:
7876 notifyRootDomainDone();
7877 break;
7878 default:
7879 panic("%s: bad call reason %x",
7880 getName(), fDriverCallReason);
7881 }
7882 break;
7883
7884 case kIOPM_NotifyChildrenOrdered:
7885 notifyChildrenOrdered();
7886 break;
7887
7888 case kIOPM_NotifyChildrenDelayed:
7889 notifyChildrenDelayed();
7890 break;
7891
7892 case kIOPM_NotifyChildrenStart:
7893 // pop notifyAll() state saved by notifyInterestedDriversDone()
7894 MS_POP();
7895 notifyRootDomain();
7896 break;
7897
7898 case kIOPM_SyncTellClientsPowerDown:
7899 // Root domain might self cancel due to assertions.
7900 if (IS_ROOT_DOMAIN) {
7901 bool cancel = (bool) fDoNotPowerDown;
7902 getPMRootDomain()->askChangeDownDone(
7903 &fHeadNoteChangeFlags, &cancel);
7904 fDoNotPowerDown = cancel;
7905 }
7906 if (!fDoNotPowerDown) {
7907 fMachineState = kIOPM_SyncTellPriorityClientsPowerDown;
7908 fOutOfBandParameter = kNotifyApps;
7909 tellChangeDown(fHeadNotePowerState);
7910 } else {
7911 // Cancelled by IOPMrootDomain::askChangeDownDone() or
7912 // askChangeDown/kNotifyApps
7913 OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState);
7914 PM_ERROR("%s: idle cancel, state %u\n", fName, fMachineState);
7915 tellNoChangeDown(fHeadNotePowerState);
7916 fHeadNoteChangeFlags |= kIOPMNotDone;
7917 OurChangeFinish();
7918 }
7919 break;
7920
7921 case kIOPM_SyncTellPriorityClientsPowerDown:
7922 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7923 if (!fDoNotPowerDown) {
7924 fMachineState = kIOPM_SyncNotifyWillChange;
7925 fOutOfBandParameter = kNotifyPriority;
7926 tellChangeDown(fHeadNotePowerState);
7927 } else {
7928 OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState);
7929 PM_ERROR("%s: idle revert, state %u\n", fName, fMachineState);
7930 tellChangeUp(fCurrentPowerState);
7931 fHeadNoteChangeFlags |= kIOPMNotDone;
7932 OurChangeFinish();
7933 }
7934 break;
7935
7936 case kIOPM_SyncNotifyWillChange:
7937 if (kIOPMSyncNoChildNotify & fHeadNoteChangeFlags) {
7938 fMachineState = kIOPM_SyncFinish;
7939 continue;
7940 }
7941 fMachineState = kIOPM_SyncNotifyDidChange;
7942 fDriverCallReason = kDriverCallInformPreChange;
7943 notifyChildren();
7944 break;
7945
7946 case kIOPM_SyncNotifyDidChange:
7947 fIsPreChange = false;
7948
7949 if (fHeadNoteChangeFlags & kIOPMParentInitiated) {
7950 fMachineState = kIOPM_SyncFinish;
7951 } else {
7952 assert(IS_ROOT_DOMAIN);
7953 fMachineState = kIOPM_SyncTellCapabilityDidChange;
7954 }
7955
7956 fDriverCallReason = kDriverCallInformPostChange;
7957 notifyChildren();
7958 break;
7959
7960 case kIOPM_SyncTellCapabilityDidChange:
7961 tellSystemCapabilityChange( kIOPM_SyncFinish );
7962 break;
7963
7964 case kIOPM_SyncFinish:
7965 if (fHeadNoteChangeFlags & kIOPMParentInitiated) {
7966 ParentChangeAcknowledgePowerChange();
7967 } else {
7968 OurChangeFinish();
7969 }
7970 break;
7971
7972 case kIOPM_TellCapabilityChangeDone:
7973 if (fIsPreChange) {
7974 if (fOutOfBandParameter == kNotifyCapabilityChangePriority) {
7975 MS_POP(); // MS passed to tellSystemCapabilityChange()
7976 continue;
7977 }
7978 fOutOfBandParameter = kNotifyCapabilityChangePriority;
7979 } else {
7980 if (fOutOfBandParameter == kNotifyCapabilityChangeApps) {
7981 MS_POP(); // MS passed to tellSystemCapabilityChange()
7982 continue;
7983 }
7984 fOutOfBandParameter = kNotifyCapabilityChangeApps;
7985 }
7986 tellClientsWithResponse( fOutOfBandMessage );
7987 break;
7988
7989 default:
7990 panic("PMWorkQueueInvoke: unknown machine state %x",
7991 fMachineState);
7992 }
7993
7994 gIOPMRequest = NULL;
7995
7996 if (fMachineState == kIOPM_Finished) {
7997 stop_watchdog_timer();
7998 done = true;
7999 break;
8000 }
8001 }
8002
8003 return done;
8004 }
8005
8006 //*********************************************************************************
8007 // [private] executePMRequest
8008 //*********************************************************************************
8009
8010 void
executePMRequest(IOPMRequest * request)8011 IOService::executePMRequest( IOPMRequest * request )
8012 {
8013 assert( kIOPM_Finished == fMachineState );
8014
8015 switch (request->getType()) {
8016 case kIOPMRequestTypePMStop:
8017 handlePMstop( request );
8018 break;
8019
8020 case kIOPMRequestTypeAddPowerChild1:
8021 addPowerChild1( request );
8022 break;
8023
8024 case kIOPMRequestTypeAddPowerChild2:
8025 addPowerChild2( request );
8026 break;
8027
8028 case kIOPMRequestTypeAddPowerChild3:
8029 addPowerChild3( request );
8030 break;
8031
8032 case kIOPMRequestTypeRegisterPowerDriver:
8033 handleRegisterPowerDriver( request );
8034 break;
8035
8036 case kIOPMRequestTypeAdjustPowerState:
8037 fAdjustPowerScheduled = false;
8038 adjustPowerState();
8039 break;
8040
8041 case kIOPMRequestTypePowerDomainWillChange:
8042 handlePowerDomainWillChangeTo( request );
8043 break;
8044
8045 case kIOPMRequestTypePowerDomainDidChange:
8046 handlePowerDomainDidChangeTo( request );
8047 break;
8048
8049 case kIOPMRequestTypeRequestPowerState:
8050 case kIOPMRequestTypeRequestPowerStateOverride:
8051 handleRequestPowerState( request );
8052 break;
8053
8054 case kIOPMRequestTypePowerOverrideOnPriv:
8055 case kIOPMRequestTypePowerOverrideOffPriv:
8056 handlePowerOverrideChanged( request );
8057 break;
8058
8059 case kIOPMRequestTypeActivityTickle:
8060 handleActivityTickle( request );
8061 break;
8062
8063 case kIOPMRequestTypeSynchronizePowerTree:
8064 handleSynchronizePowerTree( request );
8065 break;
8066
8067 case kIOPMRequestTypeSetIdleTimerPeriod:
8068 {
8069 fIdleTimerPeriod = (typeof(fIdleTimerPeriod))(uintptr_t) request->fArg0;
8070 fNextIdleTimerPeriod = fIdleTimerPeriod;
8071 if ((false == fLockedFlags.PMStop) && (fIdleTimerPeriod > 0)) {
8072 restartIdleTimer();
8073 }
8074 }
8075 break;
8076
8077 case kIOPMRequestTypeIgnoreIdleTimer:
8078 fIdleTimerIgnored = request->fArg0 ? 1 : 0;
8079 break;
8080
8081 case kIOPMRequestTypeQuiescePowerTree:
8082 gIOPMWorkQueue->finishQuiesceRequest(request);
8083 break;
8084
8085 case kIOPMRequestTypeDeferredActivityTickle:
8086 handleDeferredActivityTickle(request);
8087 break;
8088
8089 default:
8090 panic("executePMRequest: unknown request type %x", request->getType());
8091 }
8092 }
8093
8094 //*********************************************************************************
8095 // [private] actionPMReplyQueue
8096 //
8097 // IOPMRequestQueue::checkForWork() passing a reply-type request to the
8098 // request target.
8099 //*********************************************************************************
8100
8101 bool
actionPMReplyQueue(IOPMRequest * request,IOPMRequestQueue * queue)8102 IOService::actionPMReplyQueue( IOPMRequest * request, IOPMRequestQueue * queue )
8103 {
8104 bool more = false;
8105
8106 assert( request && queue );
8107 assert( request->isReplyType());
8108
8109 PM_LOG1("[A %02x] %p [%p %s] state %d\n",
8110 request->getType(), OBFUSCATE(request),
8111 OBFUSCATE(this), getName(), fMachineState);
8112
8113 switch (request->getType()) {
8114 case kIOPMRequestTypeAllowPowerChange:
8115 case kIOPMRequestTypeCancelPowerChange:
8116 // Check if we are expecting this response.
8117 if (responseValid((uint32_t)(uintptr_t) request->fArg0,
8118 (int)(uintptr_t) request->fArg1)) {
8119 if (kIOPMRequestTypeCancelPowerChange == request->getType()) {
8120 // Clients are not allowed to cancel when kIOPMSkipAskPowerDown
8121 // flag is set. Only root domain will set this flag.
8122 // However, there is one exception to this rule. User-space PM
8123 // policy may choose to cancel sleep even after all clients have
8124 // been notified that we will lower power.
8125
8126 if ((fMachineState == kIOPM_OurChangeTellUserPMPolicyPowerDown)
8127 || (fMachineState == kIOPM_OurChangeTellPriorityClientsPowerDown)
8128 || ((fHeadNoteChangeFlags & kIOPMSkipAskPowerDown) == 0)) {
8129 fDoNotPowerDown = true;
8130
8131 OSString * name = (OSString *) request->fArg2;
8132 getPMRootDomain()->pmStatsRecordApplicationResponse(
8133 gIOPMStatsResponseCancel,
8134 name ? name->getCStringNoCopy() : "", 0,
8135 0, (int)(uintptr_t) request->fArg1, NULL);
8136 }
8137 }
8138
8139 if (checkForDone()) {
8140 stop_ack_timer();
8141 cleanClientResponses(false);
8142 more = true;
8143 }
8144 }
8145 // OSString containing app name in Arg2 must be released.
8146 if (request->getType() == kIOPMRequestTypeCancelPowerChange) {
8147 OSObject * obj = (OSObject *) request->fArg2;
8148 if (obj) {
8149 obj->release();
8150 }
8151 }
8152 break;
8153
8154 case kIOPMRequestTypeAckPowerChange:
8155 more = handleAcknowledgePowerChange( request );
8156 break;
8157
8158 case kIOPMRequestTypeAckSetPowerState:
8159 more = handleAcknowledgeSetPowerState( request );
8160 break;
8161
8162 case kIOPMRequestTypeInterestChanged:
8163 handleInterestChanged( request );
8164 more = true;
8165 break;
8166
8167 case kIOPMRequestTypeIdleCancel:
8168 if ((fMachineState == kIOPM_OurChangeTellClientsPowerDown)
8169 || (fMachineState == kIOPM_OurChangeTellUserPMPolicyPowerDown)
8170 || (fMachineState == kIOPM_OurChangeTellPriorityClientsPowerDown)
8171 || (fMachineState == kIOPM_SyncTellClientsPowerDown)
8172 || (fMachineState == kIOPM_SyncTellPriorityClientsPowerDown)) {
8173 OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState);
8174 PM_LOG2("%s: cancel from machine state %d\n",
8175 getName(), fMachineState);
8176 fDoNotPowerDown = true;
8177 // Stop waiting for app replys.
8178 if ((fMachineState == kIOPM_OurChangeTellPriorityClientsPowerDown) ||
8179 (fMachineState == kIOPM_OurChangeTellUserPMPolicyPowerDown) ||
8180 (fMachineState == kIOPM_SyncTellPriorityClientsPowerDown) ||
8181 (fMachineState == kIOPM_SyncTellClientsPowerDown)) {
8182 cleanClientResponses(false);
8183 }
8184 more = true;
8185 }
8186 break;
8187
8188 case kIOPMRequestTypeChildNotifyDelayCancel:
8189 if (fMachineState == kIOPM_NotifyChildrenDelayed) {
8190 PM_LOG2("%s: delay notify cancelled\n", getName());
8191 notifyChildrenDelayed();
8192 }
8193 break;
8194
8195 default:
8196 panic("PMReplyQueue: unknown reply type %x", request->getType());
8197 }
8198
8199 more |= gIOPMCompletionQueue->queuePMRequest(request);
8200 if (more) {
8201 gIOPMWorkQueue->incrementProducerCount();
8202 }
8203
8204 return more;
8205 }
8206
8207 //*********************************************************************************
8208 // [private] assertPMDriverCall / deassertPMDriverCall
8209 //*********************************************************************************
8210
8211 bool
assertPMDriverCall(IOPMDriverCallEntry * entry,IOOptionBits method,const IOPMinformee * inform,IOOptionBits options)8212 IOService::assertPMDriverCall(
8213 IOPMDriverCallEntry * entry,
8214 IOOptionBits method,
8215 const IOPMinformee * inform,
8216 IOOptionBits options )
8217 {
8218 IOService * target = NULL;
8219 bool ok = false;
8220
8221 if (!initialized) {
8222 return false;
8223 }
8224
8225 PM_LOCK();
8226
8227 if (fLockedFlags.PMStop) {
8228 goto fail;
8229 }
8230
8231 if (((options & kIOPMDriverCallNoInactiveCheck) == 0) && isInactive()) {
8232 goto fail;
8233 }
8234
8235 if (inform) {
8236 if (!inform->active) {
8237 goto fail;
8238 }
8239 target = inform->whatObject;
8240 if (target->isInactive()) {
8241 goto fail;
8242 }
8243 }
8244
8245 // Record calling address for sleep failure diagnostics
8246 switch (method) {
8247 case kIOPMDriverCallMethodSetPowerState:
8248 entry->callMethod = OSMemberFunctionCast(const void *, fControllingDriver, &IOService::setPowerState);
8249 break;
8250 case kIOPMDriverCallMethodWillChange:
8251 entry->callMethod = OSMemberFunctionCast(const void *, target, &IOService::powerStateWillChangeTo);
8252 break;
8253 case kIOPMDriverCallMethodDidChange:
8254 entry->callMethod = OSMemberFunctionCast(const void *, target, &IOService::powerStateDidChangeTo);
8255 break;
8256 case kIOPMDriverCallMethodUnknown:
8257 case kIOPMDriverCallMethodSetAggressive:
8258 default:
8259 entry->callMethod = NULL;
8260 break;
8261 }
8262
8263 entry->thread = current_thread();
8264 entry->target = target;
8265 queue_enter(&fPMDriverCallQueue, entry, IOPMDriverCallEntry *, link);
8266 ok = true;
8267
8268 fail:
8269 PM_UNLOCK();
8270
8271 return ok;
8272 }
8273
8274 void
deassertPMDriverCall(IOPMDriverCallEntry * entry)8275 IOService::deassertPMDriverCall( IOPMDriverCallEntry * entry )
8276 {
8277 bool wakeup = false;
8278
8279 PM_LOCK();
8280
8281 assert( !queue_empty(&fPMDriverCallQueue));
8282 queue_remove(&fPMDriverCallQueue, entry, IOPMDriverCallEntry *, link);
8283 if (fLockedFlags.PMDriverCallWait) {
8284 wakeup = true;
8285 }
8286
8287 PM_UNLOCK();
8288
8289 if (wakeup) {
8290 PM_LOCK_WAKEUP(&fPMDriverCallQueue);
8291 }
8292 }
8293
8294 bool
getBlockingDriverCall(thread_t * thread,const void ** callMethod)8295 IOService::getBlockingDriverCall(thread_t *thread, const void **callMethod)
8296 {
8297 const IOPMDriverCallEntry * entry = NULL;
8298 bool blocked = false;
8299
8300 if (!initialized) {
8301 return false;
8302 }
8303
8304 if (current_thread() != gIOPMWatchDogThread) {
8305 // Meant to be accessed only from watchdog thread
8306 return false;
8307 }
8308
8309 PM_LOCK();
8310 entry = qe_queue_first(&fPMDriverCallQueue, IOPMDriverCallEntry, link);
8311 if (entry) {
8312 *thread = entry->thread;
8313 *callMethod = entry->callMethod;
8314 blocked = true;
8315 }
8316 PM_UNLOCK();
8317
8318 return blocked;
8319 }
8320
8321
8322 void
waitForPMDriverCall(IOService * target)8323 IOService::waitForPMDriverCall( IOService * target )
8324 {
8325 const IOPMDriverCallEntry * entry;
8326 thread_t thread = current_thread();
8327 AbsoluteTime deadline;
8328 int waitResult;
8329 bool log = true;
8330 bool wait;
8331
8332 do {
8333 wait = false;
8334 queue_iterate(&fPMDriverCallQueue, entry, const IOPMDriverCallEntry *, link)
8335 {
8336 // Target of interested driver call
8337 if (target && (target != entry->target)) {
8338 continue;
8339 }
8340
8341 if (entry->thread == thread) {
8342 if (log) {
8343 PM_LOG("%s: %s(%s) on PM thread\n",
8344 fName, __FUNCTION__, target ? target->getName() : "");
8345 OSReportWithBacktrace("%s: %s(%s) on PM thread\n",
8346 fName, __FUNCTION__, target ? target->getName() : "");
8347 log = false;
8348 }
8349 continue;
8350 }
8351
8352 wait = true;
8353 break;
8354 }
8355
8356 if (wait) {
8357 fLockedFlags.PMDriverCallWait = true;
8358 clock_interval_to_deadline(15, kSecondScale, &deadline);
8359 waitResult = PM_LOCK_SLEEP(&fPMDriverCallQueue, deadline);
8360 fLockedFlags.PMDriverCallWait = false;
8361 if (THREAD_TIMED_OUT == waitResult) {
8362 PM_ERROR("%s: waitForPMDriverCall timeout\n", fName);
8363 wait = false;
8364 }
8365 }
8366 } while (wait);
8367 }
8368
8369 //*********************************************************************************
8370 // [private] Debug helpers
8371 //*********************************************************************************
8372
8373 const char *
getIOMessageString(uint32_t msg)8374 IOService::getIOMessageString( uint32_t msg )
8375 {
8376 #define MSG_ENTRY(x) {(int) x, #x}
8377
8378 static const IONamedValue msgNames[] = {
8379 MSG_ENTRY( kIOMessageCanDevicePowerOff ),
8380 MSG_ENTRY( kIOMessageDeviceWillPowerOff ),
8381 MSG_ENTRY( kIOMessageDeviceWillNotPowerOff ),
8382 MSG_ENTRY( kIOMessageDeviceHasPoweredOn ),
8383 MSG_ENTRY( kIOMessageCanSystemPowerOff ),
8384 MSG_ENTRY( kIOMessageSystemWillPowerOff ),
8385 MSG_ENTRY( kIOMessageSystemWillNotPowerOff ),
8386 MSG_ENTRY( kIOMessageCanSystemSleep ),
8387 MSG_ENTRY( kIOMessageSystemWillSleep ),
8388 MSG_ENTRY( kIOMessageSystemWillNotSleep ),
8389 MSG_ENTRY( kIOMessageSystemHasPoweredOn ),
8390 MSG_ENTRY( kIOMessageSystemWillRestart ),
8391 MSG_ENTRY( kIOMessageSystemWillPowerOn ),
8392 MSG_ENTRY( kIOMessageSystemCapabilityChange ),
8393 MSG_ENTRY( kIOPMMessageLastCallBeforeSleep ),
8394 MSG_ENTRY( kIOMessageSystemPagingOff ),
8395 { 0, NULL }
8396 };
8397
8398 return IOFindNameForValue(msg, msgNames);
8399 }
8400
8401 static const char *
getNotificationPhaseString(uint32_t phase)8402 getNotificationPhaseString( uint32_t phase )
8403 {
8404 #define PHASE_ENTRY(x) {(int) x, #x}
8405
8406 static const IONamedValue phaseNames[] = {
8407 PHASE_ENTRY( kNotifyApps ),
8408 PHASE_ENTRY( kNotifyPriority ),
8409 PHASE_ENTRY( kNotifyCapabilityChangeApps ),
8410 PHASE_ENTRY( kNotifyCapabilityChangePriority ),
8411 { 0, NULL }
8412 };
8413
8414 return IOFindNameForValue(phase, phaseNames);
8415 }
8416
8417 // MARK: -
8418 // MARK: IOPMRequest
8419
8420 //*********************************************************************************
8421 // IOPMRequest Class
8422 //
8423 // Requests from PM clients, and also used for inter-object messaging within PM.
8424 //*********************************************************************************
8425
8426 OSDefineMetaClassAndStructors( IOPMRequest, IOCommand );
8427
8428 IOPMRequest *
create(void)8429 IOPMRequest::create( void )
8430 {
8431 IOPMRequest * me = OSTypeAlloc(IOPMRequest);
8432 if (me && !me->init(NULL, kIOPMRequestTypeInvalid)) {
8433 me->release();
8434 me = NULL;
8435 }
8436 return me;
8437 }
8438
8439 bool
init(IOService * target,IOOptionBits type)8440 IOPMRequest::init( IOService * target, IOOptionBits type )
8441 {
8442 if (!IOCommand::init()) {
8443 return false;
8444 }
8445
8446 fRequestType = type;
8447 fTarget = target;
8448
8449 if (fTarget) {
8450 fTarget->retain();
8451 }
8452
8453 // Root node and root domain requests does not prevent the power tree from
8454 // becoming quiescent.
8455
8456 fIsQuiesceBlocker = ((fTarget != gIOPMRootNode) &&
8457 (fTarget != IOService::getPMRootDomain()));
8458
8459 return true;
8460 }
8461
8462 void
reset(void)8463 IOPMRequest::reset( void )
8464 {
8465 assert( fWorkWaitCount == 0 );
8466 assert( fFreeWaitCount == 0 );
8467
8468 detachNextRequest();
8469 detachRootRequest();
8470
8471 if (fCompletionAction && (fRequestType == kIOPMRequestTypeQuiescePowerTree)) {
8472 // Call the completion on PM work loop context
8473 fCompletionAction(fCompletionTarget, fCompletionParam);
8474 fCompletionAction = NULL;
8475 }
8476
8477 fRequestType = kIOPMRequestTypeInvalid;
8478
8479 if (fTarget) {
8480 fTarget->release();
8481 fTarget = NULL;
8482 }
8483 }
8484
8485 bool
attachNextRequest(IOPMRequest * next)8486 IOPMRequest::attachNextRequest( IOPMRequest * next )
8487 {
8488 bool ok = false;
8489
8490 if (!fRequestNext) {
8491 // Postpone the execution of the next request after
8492 // this request.
8493 fRequestNext = next;
8494 fRequestNext->fWorkWaitCount++;
8495 #if LOG_REQUEST_ATTACH
8496 PM_LOG("Attached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
8497 OBFUSCATE(this), fRequestType, OBFUSCATE(fRequestNext),
8498 fRequestNext->fRequestType,
8499 (uint32_t) fRequestNext->fWorkWaitCount,
8500 fTarget->getName());
8501 #endif
8502 ok = true;
8503 }
8504 return ok;
8505 }
8506
8507 bool
detachNextRequest(void)8508 IOPMRequest::detachNextRequest( void )
8509 {
8510 bool ok = false;
8511
8512 if (fRequestNext) {
8513 assert(fRequestNext->fWorkWaitCount);
8514 if (fRequestNext->fWorkWaitCount) {
8515 fRequestNext->fWorkWaitCount--;
8516 }
8517 #if LOG_REQUEST_ATTACH
8518 PM_LOG("Detached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
8519 OBFUSCATE(this), fRequestType, OBFUSCATE(fRequestNext),
8520 fRequestNext->fRequestType,
8521 (uint32_t) fRequestNext->fWorkWaitCount,
8522 fTarget->getName());
8523 #endif
8524 fRequestNext = NULL;
8525 ok = true;
8526 }
8527 return ok;
8528 }
8529
8530 bool
attachRootRequest(IOPMRequest * root)8531 IOPMRequest::attachRootRequest( IOPMRequest * root )
8532 {
8533 bool ok = false;
8534
8535 if (!fRequestRoot) {
8536 // Delay the completion of the root request after
8537 // this request.
8538 fRequestRoot = root;
8539 fRequestRoot->fFreeWaitCount++;
8540 #if LOG_REQUEST_ATTACH
8541 PM_LOG("Attached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8542 OBFUSCATE(this), (uint32_t) fType, OBFUSCATE(fRequestRoot),
8543 (uint32_t) fRequestRoot->fType,
8544 (uint32_t) fRequestRoot->fFreeWaitCount,
8545 fTarget->getName());
8546 #endif
8547 ok = true;
8548 }
8549 return ok;
8550 }
8551
8552 bool
detachRootRequest(void)8553 IOPMRequest::detachRootRequest( void )
8554 {
8555 bool ok = false;
8556
8557 if (fRequestRoot) {
8558 assert(fRequestRoot->fFreeWaitCount);
8559 if (fRequestRoot->fFreeWaitCount) {
8560 fRequestRoot->fFreeWaitCount--;
8561 }
8562 #if LOG_REQUEST_ATTACH
8563 PM_LOG("Detached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8564 OBFUSCATE(this), (uint32_t) fType, OBFUSCATE(fRequestRoot),
8565 (uint32_t) fRequestRoot->fType,
8566 (uint32_t) fRequestRoot->fFreeWaitCount,
8567 fTarget->getName());
8568 #endif
8569 fRequestRoot = NULL;
8570 ok = true;
8571 }
8572 return ok;
8573 }
8574
8575 // MARK: -
8576 // MARK: IOPMRequestQueue
8577
8578 //*********************************************************************************
8579 // IOPMRequestQueue Class
8580 //
8581 // Global queues. Queues are created once and never released.
8582 //*********************************************************************************
8583
8584 OSDefineMetaClassAndStructors( IOPMRequestQueue, IOEventSource );
8585
8586 IOPMRequestQueue *
create(IOService * inOwner,Action inAction)8587 IOPMRequestQueue::create( IOService * inOwner, Action inAction )
8588 {
8589 IOPMRequestQueue * me = OSTypeAlloc(IOPMRequestQueue);
8590 if (me && !me->init(inOwner, inAction)) {
8591 me->release();
8592 me = NULL;
8593 }
8594 return me;
8595 }
8596
8597 bool
init(IOService * inOwner,Action inAction)8598 IOPMRequestQueue::init( IOService * inOwner, Action inAction )
8599 {
8600 if (!inAction || !IOEventSource::init(inOwner, (IOEventSourceAction)inAction)) {
8601 return false;
8602 }
8603
8604 queue_init(&fQueue);
8605 fLock = IOLockAlloc();
8606 return fLock != NULL;
8607 }
8608
8609 void
free(void)8610 IOPMRequestQueue::free( void )
8611 {
8612 if (fLock) {
8613 IOLockFree(fLock);
8614 fLock = NULL;
8615 }
8616 return IOEventSource::free();
8617 }
8618
8619 void
queuePMRequest(IOPMRequest * request)8620 IOPMRequestQueue::queuePMRequest( IOPMRequest * request )
8621 {
8622 uint64_t now = mach_continuous_time();
8623
8624 assert(request);
8625 request->setTimestamp(now);
8626 IOLockLock(fLock);
8627 queue_enter(&fQueue, request, typeof(request), fCommandChain);
8628 IOLockUnlock(fLock);
8629 if (workLoop) {
8630 signalWorkAvailable();
8631 }
8632 }
8633
8634 void
queuePMRequestChain(IOPMRequest ** requests,IOItemCount count)8635 IOPMRequestQueue::queuePMRequestChain( IOPMRequest ** requests, IOItemCount count )
8636 {
8637 IOPMRequest * next;
8638 uint64_t now = mach_continuous_time();
8639
8640 assert(requests && count);
8641 IOLockLock(fLock);
8642 while (count--) {
8643 next = *requests;
8644 next->setTimestamp(now);
8645 requests++;
8646 queue_enter(&fQueue, next, typeof(next), fCommandChain);
8647 }
8648 IOLockUnlock(fLock);
8649 if (workLoop) {
8650 signalWorkAvailable();
8651 }
8652 }
8653
8654 bool
checkForWork(void)8655 IOPMRequestQueue::checkForWork( void )
8656 {
8657 Action dqAction = (Action) action;
8658 IOPMRequest * request;
8659 IOService * target;
8660 int dequeueCount = 0;
8661 bool more = false;
8662
8663 IOLockLock( fLock );
8664
8665 while (!queue_empty(&fQueue)) {
8666 if (dequeueCount++ >= kMaxDequeueCount) {
8667 // Allow other queues a chance to work
8668 more = true;
8669 break;
8670 }
8671
8672 queue_remove_first(&fQueue, request, typeof(request), fCommandChain);
8673 IOLockUnlock(fLock);
8674 target = request->getTarget();
8675 assert(target);
8676 more |= (*dqAction)( target, request, this );
8677 IOLockLock( fLock );
8678 }
8679
8680 IOLockUnlock( fLock );
8681 return more;
8682 }
8683
8684 // MARK: -
8685 // MARK: IOPMWorkQueue
8686
8687 //*********************************************************************************
8688 // IOPMWorkQueue Class
8689 //
8690 // Queue of IOServicePM objects, each with a queue of IOPMRequest sharing the
8691 // same target.
8692 //*********************************************************************************
8693
8694 OSDefineMetaClassAndStructors( IOPMWorkQueue, IOEventSource );
8695
8696 IOPMWorkQueue *
create(IOService * inOwner,Action invoke,Action retire)8697 IOPMWorkQueue::create( IOService * inOwner, Action invoke, Action retire )
8698 {
8699 IOPMWorkQueue * me = OSTypeAlloc(IOPMWorkQueue);
8700 if (me && !me->init(inOwner, invoke, retire)) {
8701 me->release();
8702 me = NULL;
8703 }
8704 return me;
8705 }
8706
8707 bool
init(IOService * inOwner,Action invoke,Action retire)8708 IOPMWorkQueue::init( IOService * inOwner, Action invoke, Action retire )
8709 {
8710 if (!invoke || !retire ||
8711 !IOEventSource::init(inOwner, (IOEventSourceAction)NULL)) {
8712 return false;
8713 }
8714
8715 queue_init(&fWorkQueue);
8716
8717 fInvokeAction = invoke;
8718 fRetireAction = retire;
8719 fConsumerCount = fProducerCount = 0;
8720
8721 return true;
8722 }
8723
8724 bool
queuePMRequest(IOPMRequest * request,IOServicePM * pwrMgt)8725 IOPMWorkQueue::queuePMRequest( IOPMRequest * request, IOServicePM * pwrMgt )
8726 {
8727 queue_head_t * requestQueue;
8728 bool more = false;
8729 bool empty;
8730
8731 assert( request );
8732 assert( pwrMgt );
8733 assert( onThread());
8734 assert( queue_next(&request->fCommandChain) ==
8735 queue_prev(&request->fCommandChain));
8736
8737 gIOPMBusyRequestCount++;
8738
8739 if (request->isQuiesceType()) {
8740 if ((request->getTarget() == gIOPMRootNode) && !fQuiesceStartTime) {
8741 // Attach new quiesce request to all quiesce blockers in the queue
8742 fQuiesceStartTime = mach_absolute_time();
8743 attachQuiesceRequest(request);
8744 fQuiesceRequest = request;
8745 }
8746 } else if (fQuiesceRequest && request->isQuiesceBlocker()) {
8747 // Attach the new quiesce blocker to the blocked quiesce request
8748 request->attachNextRequest(fQuiesceRequest);
8749 }
8750
8751 // Add new request to the tail of the per-service request queue.
8752 // Then immediately check the request queue to minimize latency
8753 // if the queue was empty.
8754
8755 requestQueue = &pwrMgt->RequestHead;
8756 empty = queue_empty(requestQueue);
8757 queue_enter(requestQueue, request, typeof(request), fCommandChain);
8758 if (empty) {
8759 more = checkRequestQueue(requestQueue, &empty);
8760 if (!empty) {
8761 // Request just added is blocked, add its target IOServicePM
8762 // to the work queue.
8763 assert( queue_next(&pwrMgt->WorkChain) ==
8764 queue_prev(&pwrMgt->WorkChain));
8765
8766 queue_enter(&fWorkQueue, pwrMgt, typeof(pwrMgt), WorkChain);
8767 fQueueLength++;
8768 PM_LOG3("IOPMWorkQueue: [%u] added %s@%p to queue\n",
8769 fQueueLength, pwrMgt->Name, OBFUSCATE(pwrMgt));
8770 }
8771 }
8772
8773 return more;
8774 }
8775
8776 bool
checkRequestQueue(queue_head_t * requestQueue,bool * empty)8777 IOPMWorkQueue::checkRequestQueue( queue_head_t * requestQueue, bool * empty )
8778 {
8779 IOPMRequest * request;
8780 IOService * target;
8781 bool more = false;
8782 bool done = false;
8783
8784 assert(!queue_empty(requestQueue));
8785 do {
8786 request = (typeof(request))queue_first(requestQueue);
8787 if (request->isWorkBlocked()) {
8788 break; // request dispatch blocked on attached request
8789 }
8790 target = request->getTarget();
8791 if (fInvokeAction) {
8792 done = (*fInvokeAction)( target, request, this );
8793 } else {
8794 PM_LOG("PM request 0x%x dropped\n", request->getType());
8795 done = true;
8796 }
8797 if (!done) {
8798 break; // PM state machine blocked
8799 }
8800 assert(gIOPMBusyRequestCount > 0);
8801 if (gIOPMBusyRequestCount) {
8802 gIOPMBusyRequestCount--;
8803 }
8804
8805 if (request == fQuiesceRequest) {
8806 fQuiesceRequest = NULL;
8807 }
8808
8809 queue_remove_first(requestQueue, request, typeof(request), fCommandChain);
8810 more |= (*fRetireAction)( target, request, this );
8811 done = queue_empty(requestQueue);
8812 } while (!done);
8813
8814 *empty = done;
8815
8816 if (more) {
8817 // Retired a request that may unblock a previously visited request
8818 // that is still waiting on the work queue. Must trigger another
8819 // queue check.
8820 fProducerCount++;
8821 }
8822
8823 return more;
8824 }
8825
8826 bool
checkForWork(void)8827 IOPMWorkQueue::checkForWork( void )
8828 {
8829 IOServicePM * entry;
8830 IOServicePM * next;
8831 bool more = false;
8832 bool empty;
8833
8834 #if WORK_QUEUE_STATS
8835 fStatCheckForWork++;
8836 #endif
8837
8838 // Iterate over all IOServicePM entries in the work queue,
8839 // and check each entry's request queue.
8840
8841 while (fConsumerCount != fProducerCount) {
8842 PM_LOG3("IOPMWorkQueue: checkForWork %u %u\n",
8843 fProducerCount, fConsumerCount);
8844
8845 fConsumerCount = fProducerCount;
8846
8847 #if WORK_QUEUE_STATS
8848 if (queue_empty(&fWorkQueue)) {
8849 fStatQueueEmpty++;
8850 break;
8851 }
8852 fStatScanEntries++;
8853 uint32_t cachedWorkCount = gIOPMWorkInvokeCount;
8854 #endif
8855
8856 __IGNORE_WCASTALIGN(entry = (typeof(entry))queue_first(&fWorkQueue));
8857 while (!queue_end(&fWorkQueue, (queue_entry_t) entry)) {
8858 more |= checkRequestQueue(&entry->RequestHead, &empty);
8859
8860 // Get next entry, points to head if current entry is last.
8861 __IGNORE_WCASTALIGN(next = (typeof(next))queue_next(&entry->WorkChain));
8862
8863 // if request queue is empty, remove IOServicePM from work queue.
8864 if (empty) {
8865 assert(fQueueLength);
8866 if (fQueueLength) {
8867 fQueueLength--;
8868 }
8869 PM_LOG3("IOPMWorkQueue: [%u] removed %s@%p from queue\n",
8870 fQueueLength, entry->Name, OBFUSCATE(entry));
8871 queue_remove(&fWorkQueue, entry, typeof(entry), WorkChain);
8872 }
8873 entry = next;
8874 }
8875
8876 #if WORK_QUEUE_STATS
8877 if (cachedWorkCount == gIOPMWorkInvokeCount) {
8878 fStatNoWorkDone++;
8879 }
8880 #endif
8881 }
8882
8883 return more;
8884 }
8885
8886 void
signalWorkAvailable(void)8887 IOPMWorkQueue::signalWorkAvailable( void )
8888 {
8889 fProducerCount++;
8890 IOEventSource::signalWorkAvailable();
8891 }
8892
8893 void
incrementProducerCount(void)8894 IOPMWorkQueue::incrementProducerCount( void )
8895 {
8896 fProducerCount++;
8897 }
8898
8899 void
attachQuiesceRequest(IOPMRequest * quiesceRequest)8900 IOPMWorkQueue::attachQuiesceRequest( IOPMRequest * quiesceRequest )
8901 {
8902 IOServicePM * entry;
8903 IOPMRequest * request;
8904
8905 if (queue_empty(&fWorkQueue)) {
8906 return;
8907 }
8908
8909 queue_iterate(&fWorkQueue, entry, typeof(entry), WorkChain)
8910 {
8911 queue_iterate(&entry->RequestHead, request, typeof(request), fCommandChain)
8912 {
8913 // Attach the quiesce request to any request in the queue that
8914 // is not linked to a next request. These requests will block
8915 // the quiesce request.
8916
8917 if (request->isQuiesceBlocker()) {
8918 request->attachNextRequest(quiesceRequest);
8919 }
8920 }
8921 }
8922 }
8923
8924 void
finishQuiesceRequest(IOPMRequest * quiesceRequest)8925 IOPMWorkQueue::finishQuiesceRequest( IOPMRequest * quiesceRequest )
8926 {
8927 if (fQuiesceRequest && (quiesceRequest == fQuiesceRequest) &&
8928 (fQuiesceStartTime != 0)) {
8929 fInvokeAction = NULL;
8930 fQuiesceFinishTime = mach_absolute_time();
8931 }
8932 }
8933
8934 // MARK: -
8935 // MARK: IOPMCompletionQueue
8936
8937 //*********************************************************************************
8938 // IOPMCompletionQueue Class
8939 //*********************************************************************************
8940
8941 OSDefineMetaClassAndStructors( IOPMCompletionQueue, IOEventSource );
8942
8943 IOPMCompletionQueue *
create(IOService * inOwner,Action inAction)8944 IOPMCompletionQueue::create( IOService * inOwner, Action inAction )
8945 {
8946 IOPMCompletionQueue * me = OSTypeAlloc(IOPMCompletionQueue);
8947 if (me && !me->init(inOwner, inAction)) {
8948 me->release();
8949 me = NULL;
8950 }
8951 return me;
8952 }
8953
8954 bool
init(IOService * inOwner,Action inAction)8955 IOPMCompletionQueue::init( IOService * inOwner, Action inAction )
8956 {
8957 if (!inAction || !IOEventSource::init(inOwner, (IOEventSourceAction)inAction)) {
8958 return false;
8959 }
8960
8961 queue_init(&fQueue);
8962 return true;
8963 }
8964
8965 bool
queuePMRequest(IOPMRequest * request)8966 IOPMCompletionQueue::queuePMRequest( IOPMRequest * request )
8967 {
8968 bool more;
8969
8970 assert(request);
8971 // unblock dependent request
8972 more = request->detachNextRequest();
8973 queue_enter(&fQueue, request, typeof(request), fCommandChain);
8974 return more;
8975 }
8976
8977 bool
checkForWork(void)8978 IOPMCompletionQueue::checkForWork( void )
8979 {
8980 Action dqAction = (Action) action;
8981 IOPMRequest * request;
8982 IOPMRequest * next;
8983 IOService * target;
8984 bool more = false;
8985
8986 request = (typeof(request))queue_first(&fQueue);
8987 while (!queue_end(&fQueue, (queue_entry_t) request)) {
8988 next = (typeof(next))queue_next(&request->fCommandChain);
8989 if (!request->isFreeBlocked()) {
8990 queue_remove(&fQueue, request, typeof(request), fCommandChain);
8991 target = request->getTarget();
8992 assert(target);
8993 more |= (*dqAction)( target, request, this );
8994 }
8995 request = next;
8996 }
8997
8998 return more;
8999 }
9000
9001 // MARK: -
9002 // MARK: IOServicePM
9003
OSDefineMetaClassAndStructors(IOServicePM,OSObject)9004 OSDefineMetaClassAndStructors(IOServicePM, OSObject)
9005
9006 //*********************************************************************************
9007 // serialize
9008 //
9009 // Serialize IOServicePM for debugging.
9010 //*********************************************************************************
9011
9012 static void
9013 setPMProperty( OSDictionary * dict, const char * key, uint64_t value )
9014 {
9015 OSNumber * num = OSNumber::withNumber(value, sizeof(value) * 8);
9016 if (num) {
9017 dict->setObject(key, num);
9018 num->release();
9019 }
9020 }
9021
9022 IOReturn
gatedSerialize(OSSerialize * s) const9023 IOServicePM::gatedSerialize( OSSerialize * s ) const
9024 {
9025 OSDictionary * dict;
9026 bool ok = false;
9027 int powerClamp = -1;
9028 int dictSize = 6;
9029
9030 if (IdleTimerPeriod) {
9031 dictSize += 4;
9032 }
9033
9034 if (PMActions.state & kPMActionsStatePowerClamped) {
9035 dictSize += 1;
9036 powerClamp = 0;
9037 if (PMActions.flags &
9038 (kPMActionsFlagIsDisplayWrangler | kPMActionsFlagIsGraphicsDriver)) {
9039 powerClamp++;
9040 }
9041 }
9042
9043 #if WORK_QUEUE_STATS
9044 if (gIOPMRootNode == ControllingDriver) {
9045 dictSize += 4;
9046 }
9047 #endif
9048
9049 if (PowerClients) {
9050 dict = OSDictionary::withDictionary(
9051 PowerClients, PowerClients->getCount() + dictSize);
9052 } else {
9053 dict = OSDictionary::withCapacity(dictSize);
9054 }
9055
9056 if (dict) {
9057 setPMProperty(dict, "CurrentPowerState", CurrentPowerState);
9058 setPMProperty(dict, "CapabilityFlags", CurrentCapabilityFlags);
9059 if (NumberOfPowerStates) {
9060 setPMProperty(dict, "MaxPowerState", NumberOfPowerStates - 1);
9061 }
9062 if (DesiredPowerState != CurrentPowerState) {
9063 setPMProperty(dict, "DesiredPowerState", DesiredPowerState);
9064 }
9065 if (kIOPM_Finished != MachineState) {
9066 setPMProperty(dict, "MachineState", MachineState);
9067 }
9068 if (DeviceOverrideEnabled) {
9069 dict->setObject("PowerOverrideOn", kOSBooleanTrue);
9070 }
9071 if (powerClamp >= 0) {
9072 setPMProperty(dict, "PowerClamp", powerClamp);
9073 }
9074
9075 if (IdleTimerPeriod) {
9076 AbsoluteTime now;
9077 AbsoluteTime delta;
9078 uint64_t nsecs;
9079
9080 clock_get_uptime(&now);
9081
9082 // The idle timer period in milliseconds
9083 setPMProperty(dict, "IdleTimerPeriod", NextIdleTimerPeriod * 1000ULL);
9084
9085 // Number of tickles since the last idle timer expiration
9086 setPMProperty(dict, "ActivityTickles", ActivityTickleCount);
9087
9088 if (AbsoluteTime_to_scalar(&DeviceActiveTimestamp)) {
9089 // Milliseconds since the last activity tickle
9090 delta = now;
9091 SUB_ABSOLUTETIME(&delta, &DeviceActiveTimestamp);
9092 absolutetime_to_nanoseconds(delta, &nsecs);
9093 setPMProperty(dict, "TimeSinceLastTickle", NS_TO_MS(nsecs));
9094 }
9095
9096 if (!IdleTimerStopped && AbsoluteTime_to_scalar(&IdleTimerStartTime)) {
9097 // Idle timer elapsed time in milliseconds
9098 delta = now;
9099 SUB_ABSOLUTETIME(&delta, &IdleTimerStartTime);
9100 absolutetime_to_nanoseconds(delta, &nsecs);
9101 setPMProperty(dict, "IdleTimerElapsedTime", NS_TO_MS(nsecs));
9102 }
9103 }
9104
9105 #if WORK_QUEUE_STATS
9106 if (gIOPMRootNode == Owner) {
9107 setPMProperty(dict, "WQ-CheckForWork",
9108 gIOPMWorkQueue->fStatCheckForWork);
9109 setPMProperty(dict, "WQ-ScanEntries",
9110 gIOPMWorkQueue->fStatScanEntries);
9111 setPMProperty(dict, "WQ-QueueEmpty",
9112 gIOPMWorkQueue->fStatQueueEmpty);
9113 setPMProperty(dict, "WQ-NoWorkDone",
9114 gIOPMWorkQueue->fStatNoWorkDone);
9115 }
9116 #endif
9117
9118 if (HasAdvisoryDesire && !gIOPMAdvisoryTickleEnabled) {
9119 // Don't report advisory tickle when it has no influence
9120 dict->removeObject(gIOPMPowerClientAdvisoryTickle);
9121 }
9122
9123 ok = dict->serialize(s);
9124 dict->release();
9125 }
9126
9127 return ok ? kIOReturnSuccess : kIOReturnNoMemory;
9128 }
9129
9130 bool
serialize(OSSerialize * s) const9131 IOServicePM::serialize( OSSerialize * s ) const
9132 {
9133 IOReturn ret = kIOReturnNotReady;
9134
9135 if (gIOPMWatchDogThread == current_thread()) {
9136 // Calling without lock as this data is collected for debug purpose, before reboot.
9137 // The workloop is probably already hung in state machine.
9138 ret = gatedSerialize(s);
9139 } else if (gIOPMWorkLoop) {
9140 ret = gIOPMWorkLoop->runAction(
9141 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOServicePM::gatedSerialize),
9142 (OSObject *) this, (void *) s);
9143 }
9144
9145 return kIOReturnSuccess == ret;
9146 }
9147
9148 void
pmPrint(uint32_t event,uintptr_t param1,uintptr_t param2) const9149 IOServicePM::pmPrint(
9150 uint32_t event,
9151 uintptr_t param1,
9152 uintptr_t param2 ) const
9153 {
9154 gPlatform->PMLog(Name, event, param1, param2);
9155 }
9156
9157 void
pmTrace(uint32_t event,uint32_t eventFunc,uintptr_t param1,uintptr_t param2) const9158 IOServicePM::pmTrace(
9159 uint32_t event,
9160 uint32_t eventFunc,
9161 uintptr_t param1,
9162 uintptr_t param2 ) const
9163 {
9164 uintptr_t nameAsArg = 0;
9165
9166 assert(event < KDBG_CODE_MAX);
9167 assert((eventFunc & ~KDBG_FUNC_MASK) == 0);
9168
9169 // Copy the first characters of the name into an uintptr_t.
9170 // NULL termination is not required.
9171 strncpy((char*)&nameAsArg, Name, sizeof(nameAsArg));
9172
9173 #if defined(XNU_TARGET_OS_OSX)
9174 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, IODBG_POWER(event) | eventFunc, nameAsArg,
9175 (uintptr_t)Owner->getRegistryEntryID(), (uintptr_t)(OBFUSCATE(param1)),
9176 (uintptr_t)(OBFUSCATE(param2)), 0);
9177 #else
9178 IOTimeStampConstant(IODBG_POWER(event) | eventFunc, nameAsArg, (uintptr_t)Owner->getRegistryEntryID(), (uintptr_t)(OBFUSCATE(param1)), (uintptr_t)(OBFUSCATE(param2)));
9179 #endif
9180 }
9181