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