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