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