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