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