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