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