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