2 * Copyright (c) 1998-2016 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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>
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>
49 #include <sys/proc_internal.h>
50 #include <sys/sysctl.h>
51 #include <libkern/OSDebug.h>
52 #include <kern/thread.h>
54 // Required for notification instrumentation
55 #include "IOServicePrivate.h"
56 #include "IOServicePMPrivate.h"
57 #include "IOKitKernelInternal.h"
60 static void settle_timer_expired(thread_call_param_t
, thread_call_param_t
);
61 static void idle_timer_expired(thread_call_param_t
, thread_call_param_t
);
62 static void tellKernelClientApplier(OSObject
* object
, void * arg
);
63 static void tellAppClientApplier(OSObject
* object
, void * arg
);
65 static uint64_t computeTimeDeltaNS( const AbsoluteTime
* start
)
70 clock_get_uptime(&now
);
71 SUB_ABSOLUTETIME(&now
, start
);
72 absolutetime_to_nanoseconds(now
, &nsec
);
77 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
80 //******************************************************************************
82 //******************************************************************************
84 static bool gIOPMInitialized
= false;
85 static uint32_t gIOPMBusyRequestCount
= 0;
86 static uint32_t gIOPMWorkInvokeCount
= 0;
87 static uint32_t gIOPMTickleGeneration
= 0;
88 static IOWorkLoop
* gIOPMWorkLoop
= 0;
89 static IOPMRequestQueue
* gIOPMRequestQueue
= 0;
90 static IOPMRequestQueue
* gIOPMReplyQueue
= 0;
91 static IOPMWorkQueue
* gIOPMWorkQueue
= 0;
92 static IOPMCompletionQueue
* gIOPMCompletionQueue
= 0;
93 static IOPMRequest
* gIOPMRequest
= 0;
94 static IOService
* gIOPMRootNode
= 0;
95 static IOPlatformExpert
* gPlatform
= 0;
97 static char gIOSpinDumpKextName
[128];
98 static char gIOSpinDumpDelayType
[16];
99 static uint32_t gIOSpinDumpDelayDuration
= 0;
101 static SYSCTL_STRING(_debug
, OID_AUTO
, swd_kext_name
,
102 CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
103 &gIOSpinDumpKextName
, sizeof(gIOSpinDumpKextName
), "");
104 static SYSCTL_STRING(_debug
, OID_AUTO
, swd_delay_type
,
105 CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
106 &gIOSpinDumpDelayType
, sizeof(gIOSpinDumpDelayType
), "");
107 static SYSCTL_INT(_debug
, OID_AUTO
, swd_delay_duration
,
108 CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
109 &gIOSpinDumpDelayDuration
, 0, "");
111 const OSSymbol
* gIOPMPowerClientDevice
= 0;
112 const OSSymbol
* gIOPMPowerClientDriver
= 0;
113 const OSSymbol
* gIOPMPowerClientChildProxy
= 0;
114 const OSSymbol
* gIOPMPowerClientChildren
= 0;
115 const OSSymbol
* gIOPMPowerClientRootDomain
= 0;
117 static const OSSymbol
* gIOPMPowerClientAdvisoryTickle
= 0;
118 static bool gIOPMAdvisoryTickleEnabled
= true;
119 static thread_t gIOPMWatchDogThread
= NULL
;
120 uint32_t gCanSleepTimeout
= 0;
122 static uint32_t getPMRequestType( void )
124 uint32_t type
= kIOPMRequestTypeInvalid
;
126 type
= gIOPMRequest
->getType();
130 static IOPMRequestTag
getPMRequestTag( void )
132 IOPMRequestTag tag
= 0;
134 (gIOPMRequest
->getType() == kIOPMRequestTypeRequestPowerStateOverride
))
136 tag
= gIOPMRequest
->fRequestTag
;
141 SYSCTL_UINT(_kern
, OID_AUTO
, pmtimeout
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &gCanSleepTimeout
, 0, "Power Management Timeout");
143 //******************************************************************************
145 //******************************************************************************
147 #define PM_ERROR(x...) do { kprintf(x);IOLog(x); \
149 #define PM_LOG(x...) do { kprintf(x); } while (false)
151 #define PM_LOG1(x...) do { \
152 if (kIOLogDebugPower & gIOKitDebug) \
153 kprintf(x); } while (false)
155 #define PM_LOG2(x...) do { \
156 if (kIOLogDebugPower & gIOKitDebug) \
157 kprintf(x); } while (false)
160 #define PM_LOG3(x...) do { kprintf(x); } while (false)
162 #define PM_LOG3(x...)
165 #define RD_LOG(x...) do { \
166 if ((kIOLogPMRootDomain & gIOKitDebug) && \
167 (getPMRootDomain() == this)) { \
168 kprintf("PMRD: " x); \
170 #define PM_ASSERT_IN_GATE(x) \
172 assert(gIOPMWorkLoop->inGate()); \
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)
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)
185 #define kCanSleepMaxTimeReq k5Seconds
187 #define kCanSleepMaxTimeReq k30Seconds
189 #define kMaxTimeRequested k30Seconds
190 #define kMinAckTimeoutTicks (10*1000000)
191 #define kIOPMTardyAckSPSKey "IOPMTardyAckSetPowerState"
192 #define kIOPMTardyAckPSCKey "IOPMTardyAckPowerStateChange"
193 #define kPwrMgtKey "IOPowerManagement"
195 #define OUR_PMLog(t, a, b) do { \
197 if (gIOKitDebug & kIOLogPower) \
198 pwrMgt->pmPrint(t, a, b); \
199 if (gIOKitTrace & kIOTracePowerMgmt) \
200 pwrMgt->pmTrace(t, DBG_FUNC_NONE, a, b); \
204 #define OUR_PMLogFuncStart(t, a, b) do { \
206 if (gIOKitDebug & kIOLogPower) \
207 pwrMgt->pmPrint(t, a, b); \
208 if (gIOKitTrace & kIOTracePowerMgmt) \
209 pwrMgt->pmTrace(t, DBG_FUNC_START, a, b); \
213 #define OUR_PMLogFuncEnd(t, a, b) do { \
215 if (gIOKitDebug & kIOLogPower) \
216 pwrMgt->pmPrint(-t, a, b); \
217 if (gIOKitTrace & kIOTracePowerMgmt) \
218 pwrMgt->pmTrace(t, DBG_FUNC_END, a, b); \
222 #define NS_TO_MS(nsec) ((int)((nsec) / 1000000ULL))
223 #define NS_TO_US(nsec) ((int)((nsec) / 1000ULL))
225 #define SUPPORT_IDLE_CANCEL 1
227 #define kIOPMPowerStateMax 0xFFFFFFFF
228 #define kInvalidTicklePowerState kIOPMPowerStateMax
230 #define kNoTickleCancelWindow (60ULL * 1000ULL * 1000ULL * 1000ULL)
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))
237 // log setPowerStates longer than (ns):
238 #if defined(__i386__) || defined(__x86_64__)
239 #define LOG_SETPOWER_TIMES (300ULL * 1000ULL * 1000ULL)
241 #define LOG_SETPOWER_TIMES (50ULL * 1000ULL * 1000ULL)
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)
248 // log kext responses longer than (ns):
249 #define LOG_KEXT_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
252 kReserveDomainPower
= 1
256 do { assert(kIOPM_BadMachineState == fSavedMachineState); \
257 assert(kIOPM_BadMachineState != n); \
258 fSavedMachineState = n; } while (false)
261 do { assert(kIOPM_BadMachineState != fSavedMachineState); \
262 fMachineState = fSavedMachineState; \
263 fSavedMachineState = kIOPM_BadMachineState; } while (false)
265 #define PM_ACTION_0(a) \
266 do { if (fPMActions.a) { \
267 (fPMActions.a)(fPMActions.target, this, &fPMActions); } \
270 #define PM_ACTION_2(a, x, y) \
271 do { if (fPMActions.a) { \
272 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y, \
273 getPMRequestTag()); } \
276 #define PM_ACTION_3(a, x, y, z) \
277 do { if (fPMActions.a) { \
278 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y, z); } \
281 static OSNumber
* copyClientIDForNotification(
283 IOPMInterestContext
*context
);
285 static void logClientIDForNotification(
287 IOPMInterestContext
*context
,
288 const char *logString
);
290 //*********************************************************************************
293 // Check kgmacros after modifying machine states.
294 //*********************************************************************************
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,
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,
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,
329 kIOPM_BadMachineState
= 0xFFFFFFFF
332 //*********************************************************************************
335 // Initialize power management.
336 //*********************************************************************************
338 void IOService::PMinit( void )
342 if ( !gIOPMInitialized
)
344 gPlatform
= getPlatform();
345 gIOPMWorkLoop
= IOWorkLoop::workLoop();
348 gIOPMRequestQueue
= IOPMRequestQueue::create(
349 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
350 this, &IOService::actionPMRequestQueue
));
352 gIOPMReplyQueue
= IOPMRequestQueue::create(
353 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
354 this, &IOService::actionPMReplyQueue
));
356 gIOPMWorkQueue
= IOPMWorkQueue::create(this,
357 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
358 &IOService::actionPMWorkQueueInvoke
),
359 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
360 &IOService::actionPMWorkQueueRetire
));
362 gIOPMCompletionQueue
= IOPMCompletionQueue::create(
363 this, OSMemberFunctionCast(IOPMCompletionQueue::Action
,
364 this, &IOService::actionPMCompletionQueue
));
366 if (gIOPMWorkLoop
->addEventSource(gIOPMRequestQueue
) !=
369 gIOPMRequestQueue
->release();
370 gIOPMRequestQueue
= 0;
373 if (gIOPMWorkLoop
->addEventSource(gIOPMReplyQueue
) !=
376 gIOPMReplyQueue
->release();
380 if (gIOPMWorkLoop
->addEventSource(gIOPMWorkQueue
) !=
383 gIOPMWorkQueue
->release();
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
) !=
392 gIOPMCompletionQueue
->release();
393 gIOPMCompletionQueue
= 0;
396 gIOPMPowerClientDevice
=
397 OSSymbol::withCStringNoCopy( "DevicePowerState" );
399 gIOPMPowerClientDriver
=
400 OSSymbol::withCStringNoCopy( "DriverPowerState" );
402 gIOPMPowerClientChildProxy
=
403 OSSymbol::withCStringNoCopy( "ChildProxyPowerState" );
405 gIOPMPowerClientChildren
=
406 OSSymbol::withCStringNoCopy( "ChildrenPowerState" );
408 gIOPMPowerClientAdvisoryTickle
=
409 OSSymbol::withCStringNoCopy( "AdvisoryTicklePowerState" );
411 gIOPMPowerClientRootDomain
=
412 OSSymbol::withCStringNoCopy( "RootDomainPower" );
414 gIOSpinDumpKextName
[0] = '\0';
415 gIOSpinDumpDelayType
[0] = '\0';
418 if (gIOPMRequestQueue
&& gIOPMReplyQueue
&& gIOPMCompletionQueue
)
419 gIOPMInitialized
= true;
421 if (!gIOPMInitialized
)
424 pwrMgt
= new IOServicePM
;
426 setProperty(kPwrMgtKey
, pwrMgt
);
428 queue_init(&pwrMgt
->WorkChain
);
429 queue_init(&pwrMgt
->RequestHead
);
430 queue_init(&pwrMgt
->PMDriverCallQueue
);
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
;
451 fNumberOfPowerStates
= 0;
452 fCurrentPowerState
= kPowerStateZero
;
453 fParentsCurrentPowerFlags
= 0;
454 fMaxPowerState
= kPowerStateZero
;
456 fParentsKnowState
= false;
458 fResponseArray
= NULL
;
459 fNotifyClientArray
= NULL
;
460 fCurrentPowerConsumption
= kIOPMUnknown
;
461 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
463 if (!gIOPMRootNode
&& (getParentEntry(gIOPowerPlane
) == getRegistryRoot()))
465 gIOPMRootNode
= this;
466 fParentsKnowState
= true;
468 else if (getProperty(kIOPMResetPowerStateOnWakeKey
) == kOSBooleanTrue
)
470 fResetPowerStateOnWake
= true;
475 fWatchdogTimer
= thread_call_allocate(
476 &IOService::watchdog_timer_expired
, (thread_call_param_t
)this);
479 fAckTimer
= thread_call_allocate(
480 &IOService::ack_timer_expired
, (thread_call_param_t
)this);
481 fSettleTimer
= thread_call_allocate(
482 &settle_timer_expired
, (thread_call_param_t
)this);
483 fIdleTimer
= thread_call_allocate(
484 &idle_timer_expired
, (thread_call_param_t
)this);
485 fDriverCallEntry
= thread_call_allocate(
486 (thread_call_func_t
) &IOService::pmDriverCallout
, this);
487 assert(fDriverCallEntry
);
488 if (kIOKextSpinDump
& gIOKitDebug
)
490 fSpinDumpTimer
= thread_call_allocate(
491 &IOService::spindump_timer_expired
, (thread_call_param_t
)this);
494 // Check for powerChangeDone override.
495 if (OSMemberFunctionCast(void (*)(void),
496 getResourceService(), &IOService::powerChangeDone
) !=
497 OSMemberFunctionCast(void (*)(void),
498 this, &IOService::powerChangeDone
))
500 fPCDFunctionOverride
= true;
504 IOPMprot
* prot
= new IOPMprot
;
508 prot
->ourName
= fName
;
509 prot
->thePlatform
= gPlatform
;
514 pm_vars
= (void *) (uintptr_t) true;
521 //*********************************************************************************
524 // Free the data created by PMinit. Only called from IOService::free().
525 //*********************************************************************************
527 void IOService::PMfree( void )
534 assert(fMachineState
== kIOPM_Finished
);
535 assert(fInsertInterestSet
== NULL
);
536 assert(fRemoveInterestSet
== NULL
);
537 assert(fNotifyChildArray
== NULL
);
538 assert(queue_empty(&pwrMgt
->RequestHead
));
539 assert(queue_empty(&fPMDriverCallQueue
));
541 if (fWatchdogTimer
) {
542 thread_call_cancel(fWatchdogTimer
);
543 thread_call_free(fWatchdogTimer
);
544 fWatchdogTimer
= NULL
;
547 if ( fSettleTimer
) {
548 thread_call_cancel(fSettleTimer
);
549 thread_call_free(fSettleTimer
);
553 thread_call_cancel(fAckTimer
);
554 thread_call_free(fAckTimer
);
558 thread_call_cancel(fIdleTimer
);
559 thread_call_free(fIdleTimer
);
562 if ( fDriverCallEntry
) {
563 thread_call_free(fDriverCallEntry
);
564 fDriverCallEntry
= NULL
;
566 if ( fSpinDumpTimer
) {
567 thread_call_cancel(fSpinDumpTimer
);
568 thread_call_free(fSpinDumpTimer
);
569 fSpinDumpTimer
= NULL
;
575 if ( fActivityLock
) {
576 IOLockFree(fActivityLock
);
577 fActivityLock
= NULL
;
579 if ( fInterestedDrivers
) {
580 fInterestedDrivers
->release();
581 fInterestedDrivers
= NULL
;
583 if (fDriverCallParamSlots
&& fDriverCallParamPtr
) {
584 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
585 fDriverCallParamPtr
= 0;
586 fDriverCallParamSlots
= 0;
588 if ( fResponseArray
) {
589 fResponseArray
->release();
590 fResponseArray
= NULL
;
592 if ( fNotifyClientArray
) {
593 fNotifyClientArray
->release();
594 fNotifyClientArray
= NULL
;
596 if (fPowerStates
&& fNumberOfPowerStates
) {
597 IODelete(fPowerStates
, IOPMPSEntry
, fNumberOfPowerStates
);
598 fNumberOfPowerStates
= 0;
602 fPowerClients
->release();
619 void IOService::PMDebug( uint32_t event
, uintptr_t param1
, uintptr_t param2
)
621 OUR_PMLog(event
, param1
, param2
);
624 //*********************************************************************************
625 // [public] joinPMtree
627 // A policy-maker calls its nub here when initializing, to be attached into
628 // the power management hierarchy. The default function is to call the
629 // platform expert, which knows how to do it. This method is overridden
630 // by a nub subclass which may either know how to do it, or may need to
631 // take other action.
633 // This may be the only "power management" method used in a nub,
634 // meaning it may not be initialized for power management.
635 //*********************************************************************************
637 void IOService::joinPMtree( IOService
* driver
)
639 IOPlatformExpert
* platform
;
641 platform
= getPlatform();
642 assert(platform
!= 0);
643 platform
->PMRegisterDevice(this, driver
);
647 //*********************************************************************************
648 // [deprecated] youAreRoot
650 // Power Managment is informing us that we are the root power domain.
651 //*********************************************************************************
653 IOReturn
IOService::youAreRoot( void )
657 #endif /* !__LP64__ */
659 //*********************************************************************************
662 // Immediately stop driver callouts. Schedule an async stop request to detach
664 //*********************************************************************************
666 void IOService::PMstop( void )
668 IOPMRequest
* request
;
675 if (fLockedFlags
.PMStop
)
677 PM_LOG2("%s: PMstop() already stopped\n", fName
);
682 // Inhibit future driver calls.
683 fLockedFlags
.PMStop
= true;
685 // Wait for all prior driver calls to finish.
686 waitForPMDriverCall();
690 // The rest of the work is performed async.
691 request
= acquirePMRequest( this, kIOPMRequestTypePMStop
);
694 PM_LOG2("%s: %p PMstop\n", getName(), OBFUSCATE(this));
695 submitPMRequest( request
);
699 //*********************************************************************************
700 // [private] handlePMstop
702 // Disconnect the node from all parents and children in the power plane.
703 //*********************************************************************************
705 void IOService::handlePMstop( IOPMRequest
* request
)
709 IOPowerConnection
* connection
;
710 IOService
* theChild
;
711 IOService
* theParent
;
714 PM_LOG2("%s: %p %s start\n", getName(), OBFUSCATE(this), __FUNCTION__
);
716 // remove driver from prevent system sleep lists
717 getPMRootDomain()->updatePreventIdleSleepList(this, false);
718 getPMRootDomain()->updatePreventSystemSleepList(this, false);
720 // remove the property
721 removeProperty(kPwrMgtKey
);
724 iter
= getParentIterator(gIOPowerPlane
);
727 while ( (next
= iter
->getNextObject()) )
729 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
731 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
734 theParent
->removePowerChild(connection
);
735 theParent
->release();
742 // detach IOConnections
743 detachAbove( gIOPowerPlane
);
745 // no more power state changes
746 fParentsKnowState
= false;
749 iter
= getChildIterator(gIOPowerPlane
);
752 while ( (next
= iter
->getNextObject()) )
754 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
756 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
759 // detach nub from child
760 connection
->detachFromChild(theChild
, gIOPowerPlane
);
763 // detach us from nub
764 detachFromChild(connection
, gIOPowerPlane
);
770 // Remove all interested drivers from the list, including the power
771 // controlling driver.
773 // Usually, the controlling driver and the policy-maker functionality
774 // are implemented by the same object, and without the deregistration,
775 // the object will be holding an extra retain on itself, and cannot
778 if ( fInterestedDrivers
)
780 IOPMinformeeList
* list
= fInterestedDrivers
;
784 while ((item
= list
->firstInList()))
786 list
->removeFromList(item
->whatObject
);
791 // Clear idle period to prevent idleTimerExpired() from servicing
792 // idle timer expirations.
794 fIdleTimerPeriod
= 0;
795 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
))
798 PM_LOG2("%s: %p %s done\n", getName(), OBFUSCATE(this), __FUNCTION__
);
801 //*********************************************************************************
802 // [public] addPowerChild
804 // Power Management is informing us who our children are.
805 //*********************************************************************************
807 IOReturn
IOService::addPowerChild( IOService
* child
)
809 IOPowerConnection
* connection
= 0;
810 IOPMRequest
* requests
[3] = {0, 0, 0};
815 return kIOReturnBadArgument
;
817 if (!initialized
|| !child
->initialized
)
818 return IOPMNotYetInitialized
;
820 OUR_PMLog( kPMLogAddChild
, (uintptr_t) child
, 0 );
823 // Is this child already one of our children?
825 iter
= child
->getParentIterator( gIOPowerPlane
);
828 IORegistryEntry
* entry
;
831 while ((next
= iter
->getNextObject()))
833 if ((entry
= OSDynamicCast(IORegistryEntry
, next
)) &&
834 isChild(entry
, gIOPowerPlane
))
844 PM_LOG("%s: %s (%p) is already a child\n",
845 getName(), child
->getName(), OBFUSCATE(child
));
849 // Add the child to the power plane immediately, but the
850 // joining connection is marked as not ready.
851 // We want the child to appear in the power plane before
852 // returning to the caller, but don't want the caller to
853 // block on the PM work loop.
855 connection
= new IOPowerConnection
;
859 // Create a chain of PM requests to perform the bottom-half
860 // work from the PM work loop.
862 requests
[0] = acquirePMRequest(
864 /* type */ kIOPMRequestTypeAddPowerChild1
);
866 requests
[1] = acquirePMRequest(
868 /* type */ kIOPMRequestTypeAddPowerChild2
);
870 requests
[2] = acquirePMRequest(
872 /* type */ kIOPMRequestTypeAddPowerChild3
);
874 if (!requests
[0] || !requests
[1] || !requests
[2])
877 requests
[0]->attachNextRequest( requests
[1] );
878 requests
[1]->attachNextRequest( requests
[2] );
881 connection
->start(this);
882 connection
->setAwaitingAck(false);
883 connection
->setReadyFlag(false);
885 attachToChild( connection
, gIOPowerPlane
);
886 connection
->attachToChild( child
, gIOPowerPlane
);
888 // connection needs to be released
889 requests
[0]->fArg0
= connection
;
890 requests
[1]->fArg0
= connection
;
891 requests
[2]->fArg0
= connection
;
893 submitPMRequests( requests
, 3 );
894 return kIOReturnSuccess
;
898 if (connection
) connection
->release();
899 if (requests
[0]) releasePMRequest(requests
[0]);
900 if (requests
[1]) releasePMRequest(requests
[1]);
901 if (requests
[2]) releasePMRequest(requests
[2]);
903 // Silent failure, to prevent platform drivers from adding the child
904 // to the root domain.
906 return kIOReturnSuccess
;
909 //*********************************************************************************
910 // [private] addPowerChild1
912 // Step 1/3 of adding a power child. Called on the power parent.
913 //*********************************************************************************
915 void IOService::addPowerChild1( IOPMRequest
* request
)
917 IOPMPowerStateIndex tempDesire
= kPowerStateZero
;
919 // Make us temporary usable before adding the child.
922 OUR_PMLog( kPMLogMakeUsable
, kPMLogMakeUsable
, 0 );
924 if (fControllingDriver
&& inPlane(gIOPowerPlane
) && fParentsKnowState
)
926 tempDesire
= fHighestPowerState
;
929 if ((tempDesire
!= kPowerStateZero
) &&
930 (IS_PM_ROOT
|| (StateOrder(fMaxPowerState
) >= StateOrder(tempDesire
))))
932 adjustPowerState(tempDesire
);
936 //*********************************************************************************
937 // [private] addPowerChild2
939 // Step 2/3 of adding a power child. Called on the joining child.
940 // Execution blocked behind addPowerChild1.
941 //*********************************************************************************
943 void IOService::addPowerChild2( IOPMRequest
* request
)
945 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
947 IOPMPowerFlags powerFlags
;
949 unsigned long powerState
;
950 unsigned long tempDesire
;
953 parent
= (IOService
*) connection
->getParentEntry(gIOPowerPlane
);
955 if (!parent
|| !inPlane(gIOPowerPlane
))
957 PM_LOG("%s: addPowerChild2 not in power plane\n", getName());
961 // Parent will be waiting for us to complete this stage.
962 // It is safe to directly access parent's vars.
964 knowsState
= (parent
->fPowerStates
) && (parent
->fParentsKnowState
);
965 powerState
= parent
->fCurrentPowerState
;
968 powerFlags
= parent
->fPowerStates
[powerState
].outputPowerFlags
;
972 // Set our power parent.
974 OUR_PMLog(kPMLogSetParent
, knowsState
, powerFlags
);
976 setParentInfo( powerFlags
, connection
, knowsState
);
978 connection
->setReadyFlag(true);
980 if ( fControllingDriver
&& fParentsKnowState
)
982 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
983 // initially change into the state we are already in
984 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
985 fPreviousRequestPowerFlags
= (IOPMPowerFlags
)(-1);
986 adjustPowerState(tempDesire
);
989 getPMRootDomain()->tagPowerPlaneService(this, &fPMActions
);
992 //*********************************************************************************
993 // [private] addPowerChild3
995 // Step 3/3 of adding a power child. Called on the parent.
996 // Execution blocked behind addPowerChild2.
997 //*********************************************************************************
999 void IOService::addPowerChild3( IOPMRequest
* request
)
1001 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
1003 IOPMrootDomain
* rootDomain
= getPMRootDomain();
1005 PM_ASSERT_IN_GATE();
1006 child
= (IOService
*) connection
->getChildEntry(gIOPowerPlane
);
1008 if (child
&& inPlane(gIOPowerPlane
))
1010 if ((this != rootDomain
) && child
->getProperty("IOPMStrictTreeOrder"))
1012 PM_LOG1("%s: strict PM order enforced\n", getName());
1013 fStrictTreeOrder
= true;
1017 rootDomain
->joinAggressiveness( child
);
1021 PM_LOG("%s: addPowerChild3 not in power plane\n", getName());
1024 connection
->release();
1028 //*********************************************************************************
1029 // [deprecated] setPowerParent
1031 // Power Management is informing us who our parent is.
1032 // If we have a controlling driver, find out, given our newly-informed
1033 // power domain state, what state it would be in, and then tell it
1034 // to assume that state.
1035 //*********************************************************************************
1037 IOReturn
IOService::setPowerParent(
1038 IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags powerFlags
)
1040 return kIOReturnUnsupported
;
1042 #endif /* !__LP64__ */
1044 //*********************************************************************************
1045 // [public] removePowerChild
1047 // Called on a parent whose child is being removed by PMstop().
1048 //*********************************************************************************
1050 IOReturn
IOService::removePowerChild( IOPowerConnection
* theNub
)
1052 IORegistryEntry
* theChild
;
1054 PM_ASSERT_IN_GATE();
1055 OUR_PMLog( kPMLogRemoveChild
, 0, 0 );
1059 // detach nub from child
1060 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
1063 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
1064 theChild
->release();
1066 // detach from the nub
1067 detachFromChild(theNub
, gIOPowerPlane
);
1069 // Are we awaiting an ack from this child?
1070 if ( theNub
->getAwaitingAck() )
1072 // yes, pretend we got one
1073 theNub
->setAwaitingAck(false);
1074 if (fHeadNotePendingAcks
!= 0 )
1076 // that's one fewer ack to worry about
1077 fHeadNotePendingAcks
--;
1079 // is that the last?
1080 if ( fHeadNotePendingAcks
== 0 )
1084 // This parent may have a request in the work queue that is
1085 // blocked on fHeadNotePendingAcks=0. And removePowerChild()
1086 // is called while executing the child's PMstop request so they
1087 // can occur simultaneously. IOPMWorkQueue::checkForWork() must
1088 // restart and check all request queues again.
1090 gIOPMWorkQueue
->incrementProducerCount();
1097 // A child has gone away, re-scan children desires and clamp bits.
1098 // The fPendingAdjustPowerRequest helps to reduce redundant parent work.
1100 if (!fAdjustPowerScheduled
)
1102 IOPMRequest
* request
;
1103 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
1106 submitPMRequest( request
);
1107 fAdjustPowerScheduled
= true;
1114 //*********************************************************************************
1115 // [public] registerPowerDriver
1117 // A driver has called us volunteering to control power to our device.
1118 //*********************************************************************************
1120 IOReturn
IOService::registerPowerDriver(
1121 IOService
* powerDriver
,
1122 IOPMPowerState
* powerStates
,
1123 unsigned long numberOfStates
)
1125 IOPMRequest
* request
;
1126 IOPMPSEntry
* powerStatesCopy
= 0;
1127 IOPMPowerStateIndex stateOrder
;
1128 IOReturn error
= kIOReturnSuccess
;
1131 return IOPMNotYetInitialized
;
1133 if (!powerStates
|| (numberOfStates
< 2))
1135 OUR_PMLog(kPMLogControllingDriverErr5
, numberOfStates
, 0);
1136 return kIOReturnBadArgument
;
1139 if (!powerDriver
|| !powerDriver
->initialized
)
1141 OUR_PMLog(kPMLogControllingDriverErr4
, 0, 0);
1142 return kIOReturnBadArgument
;
1145 if (powerStates
[0].version
> kIOPMPowerStateVersion2
)
1147 OUR_PMLog(kPMLogControllingDriverErr1
, powerStates
[0].version
, 0);
1148 return kIOReturnBadArgument
;
1152 // Make a copy of the supplied power state array.
1153 powerStatesCopy
= IONew(IOPMPSEntry
, numberOfStates
);
1154 if (!powerStatesCopy
)
1156 error
= kIOReturnNoMemory
;
1160 // Initialize to bogus values
1161 for (IOPMPowerStateIndex i
= 0; i
< numberOfStates
; i
++)
1162 powerStatesCopy
[i
].stateOrderToIndex
= kIOPMPowerStateMax
;
1164 for (uint32_t i
= 0; i
< numberOfStates
; i
++)
1166 powerStatesCopy
[i
].capabilityFlags
= powerStates
[i
].capabilityFlags
;
1167 powerStatesCopy
[i
].outputPowerFlags
= powerStates
[i
].outputPowerCharacter
;
1168 powerStatesCopy
[i
].inputPowerFlags
= powerStates
[i
].inputPowerRequirement
;
1169 powerStatesCopy
[i
].staticPower
= powerStates
[i
].staticPower
;
1170 powerStatesCopy
[i
].settleUpTime
= powerStates
[i
].settleUpTime
;
1171 powerStatesCopy
[i
].settleDownTime
= powerStates
[i
].settleDownTime
;
1172 if (powerStates
[i
].version
>= kIOPMPowerStateVersion2
)
1173 stateOrder
= powerStates
[i
].stateOrder
;
1177 if (stateOrder
< numberOfStates
)
1179 powerStatesCopy
[i
].stateOrder
= stateOrder
;
1180 powerStatesCopy
[stateOrder
].stateOrderToIndex
= i
;
1184 for (IOPMPowerStateIndex i
= 0; i
< numberOfStates
; i
++)
1186 if (powerStatesCopy
[i
].stateOrderToIndex
== kIOPMPowerStateMax
)
1188 // power state order missing
1189 error
= kIOReturnBadArgument
;
1193 if (kIOReturnSuccess
!= error
)
1196 request
= acquirePMRequest( this, kIOPMRequestTypeRegisterPowerDriver
);
1199 error
= kIOReturnNoMemory
;
1203 powerDriver
->retain();
1204 request
->fArg0
= (void *) powerDriver
;
1205 request
->fArg1
= (void *) powerStatesCopy
;
1206 request
->fArg2
= (void *) numberOfStates
;
1208 submitPMRequest( request
);
1209 return kIOReturnSuccess
;
1213 if (powerStatesCopy
)
1214 IODelete(powerStatesCopy
, IOPMPSEntry
, numberOfStates
);
1219 //*********************************************************************************
1220 // [private] handleRegisterPowerDriver
1221 //*********************************************************************************
1223 void IOService::handleRegisterPowerDriver( IOPMRequest
* request
)
1225 IOService
* powerDriver
= (IOService
*) request
->fArg0
;
1226 IOPMPSEntry
* powerStates
= (IOPMPSEntry
*) request
->fArg1
;
1227 unsigned long numberOfStates
= (unsigned long) request
->fArg2
;
1228 unsigned long i
, stateIndex
;
1229 unsigned long lowestPowerState
;
1233 PM_ASSERT_IN_GATE();
1234 assert(powerStates
);
1235 assert(powerDriver
);
1236 assert(numberOfStates
> 1);
1238 if ( !fNumberOfPowerStates
)
1240 OUR_PMLog(kPMLogControllingDriver
,
1241 (unsigned long) numberOfStates
,
1242 (unsigned long) kIOPMPowerStateVersion1
);
1244 fPowerStates
= powerStates
;
1245 fNumberOfPowerStates
= numberOfStates
;
1246 fControllingDriver
= powerDriver
;
1247 fCurrentCapabilityFlags
= fPowerStates
[0].capabilityFlags
;
1249 lowestPowerState
= fPowerStates
[0].stateOrderToIndex
;
1250 fHighestPowerState
= fPowerStates
[numberOfStates
- 1].stateOrderToIndex
;
1252 // OR'in all the output power flags
1253 fMergedOutputPowerFlags
= 0;
1254 fDeviceUsablePowerState
= lowestPowerState
;
1255 for ( i
= 0; i
< numberOfStates
; i
++ )
1257 fMergedOutputPowerFlags
|= fPowerStates
[i
].outputPowerFlags
;
1259 stateIndex
= fPowerStates
[i
].stateOrderToIndex
;
1260 assert(stateIndex
< numberOfStates
);
1261 if ((fDeviceUsablePowerState
== lowestPowerState
) &&
1262 (fPowerStates
[stateIndex
].capabilityFlags
& IOPMDeviceUsable
))
1264 // The minimum power state that the device is usable
1265 fDeviceUsablePowerState
= stateIndex
;
1269 // Register powerDriver as interested, unless already done.
1270 // We don't want to register the default implementation since
1271 // it does nothing. One ramification of not always registering
1272 // is the one fewer retain count held.
1274 root
= getPlatform()->getProvider();
1277 ((OSMemberFunctionCast(void (*)(void),
1278 root
, &IOService::powerStateDidChangeTo
)) !=
1279 ((OSMemberFunctionCast(void (*)(void),
1280 this, &IOService::powerStateDidChangeTo
)))) ||
1281 ((OSMemberFunctionCast(void (*)(void),
1282 root
, &IOService::powerStateWillChangeTo
)) !=
1283 ((OSMemberFunctionCast(void (*)(void),
1284 this, &IOService::powerStateWillChangeTo
)))))
1286 if (fInterestedDrivers
->findItem(powerDriver
) == NULL
)
1289 fInterestedDrivers
->appendNewInformee(powerDriver
);
1294 // Examine all existing power clients and perform limit check.
1296 if (fPowerClients
&&
1297 (iter
= OSCollectionIterator::withCollection(fPowerClients
)))
1299 const OSSymbol
* client
;
1300 while ((client
= (const OSSymbol
*) iter
->getNextObject()))
1302 IOPMPowerStateIndex powerState
= getPowerStateForClient(client
);
1303 if (powerState
>= numberOfStates
)
1305 updatePowerClient(client
, fHighestPowerState
);
1311 if ( inPlane(gIOPowerPlane
) && fParentsKnowState
)
1313 IOPMPowerStateIndex tempDesire
;
1314 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
1315 // initially change into the state we are already in
1316 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
1317 adjustPowerState(tempDesire
);
1322 OUR_PMLog(kPMLogControllingDriverErr2
, numberOfStates
, 0);
1323 IODelete(powerStates
, IOPMPSEntry
, numberOfStates
);
1326 powerDriver
->release();
1329 //*********************************************************************************
1330 // [public] registerInterestedDriver
1332 // Add the caller to our list of interested drivers and return our current
1333 // power state. If we don't have a power-controlling driver yet, we will
1334 // call this interested driver again later when we do get a driver and find
1335 // out what the current power state of the device is.
1336 //*********************************************************************************
1338 IOPMPowerFlags
IOService::registerInterestedDriver( IOService
* driver
)
1340 IOPMRequest
* request
;
1343 if (!driver
|| !initialized
|| !fInterestedDrivers
)
1347 signal
= (!fInsertInterestSet
&& !fRemoveInterestSet
);
1348 if (fInsertInterestSet
== NULL
)
1349 fInsertInterestSet
= OSSet::withCapacity(4);
1350 if (fInsertInterestSet
)
1352 fInsertInterestSet
->setObject(driver
);
1353 if (fRemoveInterestSet
)
1354 fRemoveInterestSet
->removeObject(driver
);
1360 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1362 submitPMRequest( request
);
1365 // This return value cannot be trusted, but return a value
1366 // for those clients that care.
1368 OUR_PMLog(kPMLogInterestedDriver
, kIOPMDeviceUsable
, 2);
1369 return kIOPMDeviceUsable
;
1372 //*********************************************************************************
1373 // [public] deRegisterInterestedDriver
1374 //*********************************************************************************
1376 IOReturn
IOService::deRegisterInterestedDriver( IOService
* driver
)
1378 IOPMinformee
* item
;
1379 IOPMRequest
* request
;
1383 return kIOReturnBadArgument
;
1384 if (!initialized
|| !fInterestedDrivers
)
1385 return IOPMNotPowerManaged
;
1388 if (fInsertInterestSet
)
1390 fInsertInterestSet
->removeObject(driver
);
1393 item
= fInterestedDrivers
->findItem(driver
);
1397 return kIOReturnNotFound
;
1400 signal
= (!fRemoveInterestSet
&& !fInsertInterestSet
);
1401 if (fRemoveInterestSet
== NULL
)
1402 fRemoveInterestSet
= OSSet::withCapacity(4);
1403 if (fRemoveInterestSet
)
1405 fRemoveInterestSet
->setObject(driver
);
1408 item
->active
= false;
1409 waitForPMDriverCall( driver
);
1416 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1418 submitPMRequest( request
);
1424 //*********************************************************************************
1425 // [private] handleInterestChanged
1427 // Handle interest added or removed.
1428 //*********************************************************************************
1430 void IOService::handleInterestChanged( IOPMRequest
* request
)
1433 IOPMinformee
* informee
;
1434 IOPMinformeeList
* list
= fInterestedDrivers
;
1438 if (fInsertInterestSet
)
1440 while ((driver
= (IOService
*) fInsertInterestSet
->getAnyObject()))
1442 if (list
->findItem(driver
) == NULL
)
1444 informee
= list
->appendNewInformee(driver
);
1446 fInsertInterestSet
->removeObject(driver
);
1448 fInsertInterestSet
->release();
1449 fInsertInterestSet
= 0;
1452 if (fRemoveInterestSet
)
1454 while ((driver
= (IOService
*) fRemoveInterestSet
->getAnyObject()))
1456 informee
= list
->findItem(driver
);
1459 // Clean-up async interest acknowledgement
1460 if (fHeadNotePendingAcks
&& informee
->timer
)
1462 informee
->timer
= 0;
1463 fHeadNotePendingAcks
--;
1465 list
->removeFromList(driver
);
1467 fRemoveInterestSet
->removeObject(driver
);
1469 fRemoveInterestSet
->release();
1470 fRemoveInterestSet
= 0;
1476 //*********************************************************************************
1477 // [public] acknowledgePowerChange
1479 // After we notified one of the interested drivers or a power-domain child
1480 // of an impending change in power, it has called to say it is now
1481 // prepared for the change. If this object is the last to
1482 // acknowledge this change, we take whatever action we have been waiting
1484 // That may include acknowledging to our parent. In this case, we do it
1485 // last of all to insure that this doesn't cause the parent to call us some-
1486 // where else and alter data we are relying on here (like the very existance
1487 // of a "current change note".)
1488 //*********************************************************************************
1490 IOReturn
IOService::acknowledgePowerChange( IOService
* whichObject
)
1492 IOPMRequest
* request
;
1495 return IOPMNotYetInitialized
;
1497 return kIOReturnBadArgument
;
1499 request
= acquirePMRequest( this, kIOPMRequestTypeAckPowerChange
);
1501 return kIOReturnNoMemory
;
1503 whichObject
->retain();
1504 request
->fArg0
= whichObject
;
1506 submitPMRequest( request
);
1510 //*********************************************************************************
1511 // [private] handleAcknowledgePowerChange
1512 //*********************************************************************************
1514 bool IOService::handleAcknowledgePowerChange( IOPMRequest
* request
)
1516 IOPMinformee
* informee
;
1517 unsigned long childPower
= kIOPMUnknown
;
1518 IOService
* theChild
;
1519 IOService
* whichObject
;
1520 bool all_acked
= false;
1522 PM_ASSERT_IN_GATE();
1523 whichObject
= (IOService
*) request
->fArg0
;
1524 assert(whichObject
);
1526 // one of our interested drivers?
1527 informee
= fInterestedDrivers
->findItem( whichObject
);
1528 if ( informee
== NULL
)
1530 if ( !isChild(whichObject
, gIOPowerPlane
) )
1532 OUR_PMLog(kPMLogAcknowledgeErr1
, 0, 0);
1535 OUR_PMLog(kPMLogChildAcknowledge
, fHeadNotePendingAcks
, 0);
1538 OUR_PMLog(kPMLogDriverAcknowledge
, fHeadNotePendingAcks
, 0);
1541 if ( fHeadNotePendingAcks
!= 0 )
1543 assert(fPowerStates
!= NULL
);
1545 // yes, make sure we're expecting acks
1546 if ( informee
!= NULL
)
1548 // it's an interested driver
1549 // make sure we're expecting this ack
1550 if ( informee
->timer
!= 0 )
1553 if (informee
->timer
> 0)
1555 uint64_t nsec
= computeTimeDeltaNS(&informee
->startTime
);
1556 if (nsec
> LOG_SETPOWER_TIMES
) {
1557 getPMRootDomain()->pmStatsRecordApplicationResponse(
1558 gIOPMStatsDriverPSChangeSlow
, informee
->whatObject
->getName(),
1559 fDriverCallReason
, NS_TO_MS(nsec
), informee
->whatObject
->getRegistryEntryID(),
1560 NULL
, fHeadNotePowerState
);
1565 informee
->timer
= 0;
1566 // that's one fewer to worry about
1567 fHeadNotePendingAcks
--;
1569 // this driver has already acked
1570 OUR_PMLog(kPMLogAcknowledgeErr2
, 0, 0);
1574 // make sure we're expecting this ack
1575 if ( ((IOPowerConnection
*)whichObject
)->getAwaitingAck() )
1577 // that's one fewer to worry about
1578 fHeadNotePendingAcks
--;
1579 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
1580 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
1583 childPower
= theChild
->currentPowerConsumption();
1584 theChild
->release();
1586 if ( childPower
== kIOPMUnknown
)
1588 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
1590 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
1592 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
1598 if ( fHeadNotePendingAcks
== 0 ) {
1599 // yes, stop the timer
1601 // and now we can continue
1605 OUR_PMLog(kPMLogAcknowledgeErr3
, 0, 0); // not expecting anybody to ack
1610 whichObject
->release();
1615 //*********************************************************************************
1616 // [public] acknowledgeSetPowerState
1618 // After we instructed our controlling driver to change power states,
1619 // it has called to say it has finished doing so.
1620 // We continue to process the power state change.
1621 //*********************************************************************************
1623 IOReturn
IOService::acknowledgeSetPowerState( void )
1625 IOPMRequest
* request
;
1628 return IOPMNotYetInitialized
;
1630 request
= acquirePMRequest( this, kIOPMRequestTypeAckSetPowerState
);
1632 return kIOReturnNoMemory
;
1634 submitPMRequest( request
);
1635 return kIOReturnSuccess
;
1638 //*********************************************************************************
1639 // [private] adjustPowerState
1640 //*********************************************************************************
1642 void IOService::adjustPowerState( uint32_t clamp
)
1644 PM_ASSERT_IN_GATE();
1645 computeDesiredState(clamp
, false);
1646 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
))
1648 IOPMPowerChangeFlags changeFlags
= kIOPMSelfInitiated
;
1650 // Indicate that children desires must be ignored, and do not ask
1651 // apps for permission to drop power. This is used by root domain
1652 // for demand sleep.
1654 if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)
1655 changeFlags
|= (kIOPMIgnoreChildren
| kIOPMSkipAskPowerDown
);
1658 /* flags */ changeFlags
,
1659 /* power state */ fDesiredPowerState
,
1660 /* domain flags */ 0,
1662 /* parent flags */ 0);
1666 //*********************************************************************************
1667 // [public] synchronizePowerTree
1668 //*********************************************************************************
1670 IOReturn
IOService::synchronizePowerTree(
1671 IOOptionBits options
,
1672 IOService
* notifyRoot
)
1674 IOPMRequest
* request_c
= 0;
1675 IOPMRequest
* request_s
;
1677 if (this != getPMRootDomain())
1678 return kIOReturnBadArgument
;
1680 return kIOPMNotYetInitialized
;
1682 OUR_PMLog(kPMLogCSynchronizePowerTree
, options
, (notifyRoot
!= 0));
1688 // Cancels don't need to be synchronized.
1689 nr
= acquirePMRequest(notifyRoot
, kIOPMRequestTypeChildNotifyDelayCancel
);
1690 if (nr
) submitPMRequest(nr
);
1691 nr
= acquirePMRequest(getPMRootDomain(), kIOPMRequestTypeChildNotifyDelayCancel
);
1692 if (nr
) submitPMRequest(nr
);
1695 request_s
= acquirePMRequest( this, kIOPMRequestTypeSynchronizePowerTree
);
1697 goto error_no_memory
;
1699 if (options
& kIOPMSyncCancelPowerDown
)
1700 request_c
= acquirePMRequest( this, kIOPMRequestTypeIdleCancel
);
1703 request_c
->attachNextRequest( request_s
);
1704 submitPMRequest(request_c
);
1707 request_s
->fArg0
= (void *)(uintptr_t) options
;
1708 submitPMRequest(request_s
);
1710 return kIOReturnSuccess
;
1713 if (request_c
) releasePMRequest(request_c
);
1714 if (request_s
) releasePMRequest(request_s
);
1715 return kIOReturnNoMemory
;
1718 //*********************************************************************************
1719 // [private] handleSynchronizePowerTree
1720 //*********************************************************************************
1722 void IOService::handleSynchronizePowerTree( IOPMRequest
* request
)
1724 PM_ASSERT_IN_GATE();
1725 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
) &&
1726 (fCurrentPowerState
== fHighestPowerState
))
1728 IOOptionBits options
= (uintptr_t) request
->fArg0
;
1731 /* flags */ kIOPMSelfInitiated
| kIOPMSynchronize
|
1732 (options
& kIOPMSyncNoChildNotify
),
1733 /* power state */ fCurrentPowerState
,
1734 /* domain flags */ 0,
1736 /* parent flags */ 0);
1741 //*********************************************************************************
1742 // [deprecated] powerDomainWillChangeTo
1744 // Called by the power-hierarchy parent notifying of a new power state
1745 // in the power domain.
1746 // We enqueue a parent power-change to our queue of power changes.
1747 // This may or may not cause us to change power, depending on what
1748 // kind of change is occuring in the domain.
1749 //*********************************************************************************
1751 IOReturn
IOService::powerDomainWillChangeTo(
1752 IOPMPowerFlags newPowerFlags
,
1753 IOPowerConnection
* whichParent
)
1756 return kIOReturnUnsupported
;
1758 #endif /* !__LP64__ */
1760 //*********************************************************************************
1761 // [private] handlePowerDomainWillChangeTo
1762 //*********************************************************************************
1764 void IOService::handlePowerDomainWillChangeTo( IOPMRequest
* request
)
1766 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1767 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1768 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1769 IOPMPowerChangeFlags myChangeFlags
;
1772 IOPowerConnection
* connection
;
1773 IOPMPowerStateIndex maxPowerState
;
1774 IOPMPowerFlags combinedPowerFlags
;
1775 bool savedParentsKnowState
;
1776 IOReturn result
= IOPMAckImplied
;
1778 PM_ASSERT_IN_GATE();
1779 OUR_PMLog(kPMLogWillChange
, parentPowerFlags
, 0);
1781 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1783 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1787 savedParentsKnowState
= fParentsKnowState
;
1789 // Combine parents' output power flags.
1791 combinedPowerFlags
= 0;
1793 iter
= getParentIterator(gIOPowerPlane
);
1796 while ( (next
= iter
->getNextObject()) )
1798 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
1800 if ( connection
== whichParent
)
1801 combinedPowerFlags
|= parentPowerFlags
;
1803 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1809 // If our initial change has yet to occur, then defer the power change
1810 // until after the power domain has completed its power transition.
1812 if ( fControllingDriver
&& !fInitialPowerChange
)
1814 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1815 combinedPowerFlags
);
1817 if (parentChangeFlags
& kIOPMDomainPowerDrop
)
1819 // fMaxPowerState set a limit on self-initiated power changes.
1820 // Update it before a parent power drop.
1821 fMaxPowerState
= maxPowerState
;
1824 // Use kIOPMSynchronize below instead of kIOPMRootBroadcastFlags
1825 // to avoid propagating the root change flags if any service must
1826 // change power state due to root's will-change notification.
1827 // Root does not change power state for kIOPMSynchronize.
1829 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainWillChange
|
1830 (parentChangeFlags
& kIOPMSynchronize
);
1832 result
= startPowerChange(
1833 /* flags */ myChangeFlags
,
1834 /* power state */ maxPowerState
,
1835 /* domain flags */ combinedPowerFlags
,
1836 /* connection */ whichParent
,
1837 /* parent flags */ parentPowerFlags
);
1840 // If parent is dropping power, immediately update the parent's
1841 // capability flags. Any future merging of parent(s) combined
1842 // power flags should account for this power drop.
1844 if (parentChangeFlags
& kIOPMDomainPowerDrop
)
1846 setParentInfo(parentPowerFlags
, whichParent
, true);
1849 // Parent is expecting an ACK from us. If we did not embark on a state
1850 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1851 // still required to issue an ACK to our parent.
1853 if (IOPMAckImplied
== result
)
1856 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1860 parent
->acknowledgePowerChange( whichParent
);
1866 // Drop the retain from notifyChild().
1867 if (whichParent
) whichParent
->release();
1871 //*********************************************************************************
1872 // [deprecated] powerDomainDidChangeTo
1874 // Called by the power-hierarchy parent after the power state of the power domain
1875 // has settled at a new level.
1876 // We enqueue a parent power-change to our queue of power changes.
1877 // This may or may not cause us to change power, depending on what
1878 // kind of change is occuring in the domain.
1879 //*********************************************************************************
1881 IOReturn
IOService::powerDomainDidChangeTo(
1882 IOPMPowerFlags newPowerFlags
,
1883 IOPowerConnection
* whichParent
)
1886 return kIOReturnUnsupported
;
1888 #endif /* !__LP64__ */
1890 //*********************************************************************************
1891 // [private] handlePowerDomainDidChangeTo
1892 //*********************************************************************************
1894 void IOService::handlePowerDomainDidChangeTo( IOPMRequest
* request
)
1896 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1897 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1898 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1899 IOPMPowerChangeFlags myChangeFlags
;
1900 IOPMPowerStateIndex maxPowerState
;
1901 IOPMPowerStateIndex initialDesire
= kPowerStateZero
;
1902 bool computeDesire
= false;
1903 bool desireChanged
= false;
1904 bool savedParentsKnowState
;
1905 IOReturn result
= IOPMAckImplied
;
1907 PM_ASSERT_IN_GATE();
1908 OUR_PMLog(kPMLogDidChange
, parentPowerFlags
, 0);
1910 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1912 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1916 savedParentsKnowState
= fParentsKnowState
;
1918 setParentInfo(parentPowerFlags
, whichParent
, true);
1920 if ( fControllingDriver
)
1922 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1923 fParentsCurrentPowerFlags
);
1925 if ((parentChangeFlags
& kIOPMDomainPowerDrop
) == 0)
1927 // fMaxPowerState set a limit on self-initiated power changes.
1928 // Update it after a parent power rise.
1929 fMaxPowerState
= maxPowerState
;
1932 if (fInitialPowerChange
)
1934 computeDesire
= true;
1935 initialDesire
= fControllingDriver
->initialPowerStateForDomainState(
1936 fParentsCurrentPowerFlags
);
1938 else if (parentChangeFlags
& kIOPMRootChangeUp
)
1940 if (fAdvisoryTickleUsed
)
1942 // On system wake, re-compute the desired power state since
1943 // gIOPMAdvisoryTickleEnabled will change for a full wake,
1944 // which is an input to computeDesiredState(). This is not
1945 // necessary for a dark wake because powerChangeDone() will
1946 // handle the dark to full wake case, but it does no harm.
1948 desireChanged
= true;
1951 if (fResetPowerStateOnWake
)
1953 // Query the driver for the desired power state on system wake.
1954 // Default implementation returns the lowest power state.
1956 IOPMPowerStateIndex wakePowerState
=
1957 fControllingDriver
->initialPowerStateForDomainState(
1958 kIOPMRootDomainState
| kIOPMPowerOn
);
1960 // fDesiredPowerState was adjusted before going to sleep
1961 // with fDeviceDesire at min.
1963 if (StateOrder(wakePowerState
) > StateOrder(fDesiredPowerState
))
1965 // Must schedule a power adjustment if we changed the
1966 // device desire. That will update the desired domain
1967 // power on the parent power connection and ping the
1968 // power parent if necessary.
1970 updatePowerClient(gIOPMPowerClientDevice
, wakePowerState
);
1971 desireChanged
= true;
1976 if (computeDesire
|| desireChanged
)
1977 computeDesiredState(initialDesire
, false);
1979 // Absorb and propagate parent's broadcast flags
1980 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainDidChange
|
1981 (parentChangeFlags
& kIOPMRootBroadcastFlags
);
1983 result
= startPowerChange(
1984 /* flags */ myChangeFlags
,
1985 /* power state */ maxPowerState
,
1986 /* domain flags */ fParentsCurrentPowerFlags
,
1987 /* connection */ whichParent
,
1988 /* parent flags */ 0);
1991 // Parent is expecting an ACK from us. If we did not embark on a state
1992 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1993 // still required to issue an ACK to our parent.
1995 if (IOPMAckImplied
== result
)
1998 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
2002 parent
->acknowledgePowerChange( whichParent
);
2007 // If the parent registers its power driver late, then this is the
2008 // first opportunity to tell our parent about our desire. Or if the
2009 // child's desire changed during a parent change notify.
2011 if (fControllingDriver
&&
2012 ((!savedParentsKnowState
&& fParentsKnowState
) || desireChanged
))
2014 PM_LOG1("%s::powerDomainDidChangeTo parentsKnowState %d\n",
2015 getName(), fParentsKnowState
);
2016 requestDomainPower( fDesiredPowerState
);
2020 // Drop the retain from notifyChild().
2021 if (whichParent
) whichParent
->release();
2024 //*********************************************************************************
2025 // [private] setParentInfo
2027 // Set our connection data for one specific parent, and then combine all the parent
2029 //*********************************************************************************
2031 void IOService::setParentInfo(
2032 IOPMPowerFlags newPowerFlags
,
2033 IOPowerConnection
* whichParent
,
2038 IOPowerConnection
* conn
;
2040 PM_ASSERT_IN_GATE();
2042 // set our connection data
2043 whichParent
->setParentCurrentPowerFlags(newPowerFlags
);
2044 whichParent
->setParentKnowsState(knowsState
);
2046 // recompute our parent info
2047 fParentsCurrentPowerFlags
= 0;
2048 fParentsKnowState
= true;
2050 iter
= getParentIterator(gIOPowerPlane
);
2053 while ( (next
= iter
->getNextObject()) )
2055 if ( (conn
= OSDynamicCast(IOPowerConnection
, next
)) )
2057 fParentsKnowState
&= conn
->parentKnowsState();
2058 fParentsCurrentPowerFlags
|= conn
->parentCurrentPowerFlags();
2065 //******************************************************************************
2066 // [private] trackSystemSleepPreventers
2067 //******************************************************************************
2069 void IOService::trackSystemSleepPreventers(
2070 IOPMPowerStateIndex oldPowerState
,
2071 IOPMPowerStateIndex newPowerState
,
2072 IOPMPowerChangeFlags changeFlags __unused
)
2074 IOPMPowerFlags oldCapability
, newCapability
;
2076 oldCapability
= fPowerStates
[oldPowerState
].capabilityFlags
&
2077 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2078 newCapability
= fPowerStates
[newPowerState
].capabilityFlags
&
2079 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2081 if (fHeadNoteChangeFlags
& kIOPMInitialPowerChange
)
2083 if (oldCapability
== newCapability
)
2086 if ((oldCapability
^ newCapability
) & kIOPMPreventIdleSleep
)
2088 bool enablePrevention
= ((oldCapability
& kIOPMPreventIdleSleep
) == 0);
2089 bool idleCancelAllowed
= getPMRootDomain()->updatePreventIdleSleepList(
2090 this, enablePrevention
);
2091 #if SUPPORT_IDLE_CANCEL
2092 if (idleCancelAllowed
&& enablePrevention
)
2094 IOPMRequest
* cancelRequest
;
2096 cancelRequest
= acquirePMRequest( getPMRootDomain(), kIOPMRequestTypeIdleCancel
);
2099 submitPMRequest( cancelRequest
);
2105 if ((oldCapability
^ newCapability
) & kIOPMPreventSystemSleep
)
2107 getPMRootDomain()->updatePreventSystemSleepList(this,
2108 ((oldCapability
& kIOPMPreventSystemSleep
) == 0));
2112 //*********************************************************************************
2113 // [public] requestPowerDomainState
2115 // Called on a power parent when a child's power requirement changes.
2116 //*********************************************************************************
2118 IOReturn
IOService::requestPowerDomainState(
2119 IOPMPowerFlags childRequestPowerFlags
,
2120 IOPowerConnection
* childConnection
,
2121 unsigned long specification
)
2123 IOPMPowerStateIndex order
, powerState
;
2124 IOPMPowerFlags outputPowerFlags
;
2126 IOPMRequest
* subRequest
;
2127 bool adjustPower
= false;
2130 return IOPMNotYetInitialized
;
2132 if (gIOPMWorkLoop
->onThread() == false)
2134 PM_LOG("%s::requestPowerDomainState\n", getName());
2135 return kIOReturnSuccess
;
2138 OUR_PMLog(kPMLogRequestDomain
, childRequestPowerFlags
, specification
);
2140 if (!isChild(childConnection
, gIOPowerPlane
))
2141 return kIOReturnNotAttached
;
2143 if (!fControllingDriver
|| !fNumberOfPowerStates
)
2144 return kIOReturnNotReady
;
2146 child
= (IOService
*) childConnection
->getChildEntry(gIOPowerPlane
);
2149 // Remove flags from child request which we can't possibly supply
2150 childRequestPowerFlags
&= fMergedOutputPowerFlags
;
2152 // Merge in the power flags contributed by this power parent
2153 // at its current or impending power state.
2155 outputPowerFlags
= fPowerStates
[fCurrentPowerState
].outputPowerFlags
;
2156 if (fMachineState
!= kIOPM_Finished
)
2158 if (IS_POWER_DROP
&& !IS_ROOT_DOMAIN
)
2160 // Use the lower power state when dropping power.
2161 // Must be careful since a power drop can be cancelled
2162 // from the following states:
2163 // - kIOPM_OurChangeTellClientsPowerDown
2164 // - kIOPM_OurChangeTellPriorityClientsPowerDown
2166 // The child must not wait for this parent to raise power
2167 // if the power drop was cancelled. The solution is to cancel
2168 // the power drop if possible, then schedule an adjustment to
2169 // re-evaluate the parent's power state.
2171 // Root domain is excluded to avoid idle sleep issues. And allow
2172 // root domain children to pop up when system is going to sleep.
2174 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
) ||
2175 (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
))
2177 fDoNotPowerDown
= true; // cancel power drop
2178 adjustPower
= true; // schedule an adjustment
2179 PM_LOG1("%s: power drop cancelled in state %u by %s\n",
2180 getName(), fMachineState
, child
->getName());
2184 // Beyond cancellation point, report the impending state.
2186 fPowerStates
[fHeadNotePowerState
].outputPowerFlags
;
2189 else if (IS_POWER_RISE
)
2191 // When raising power, must report the output power flags from
2192 // child's perspective. A child power request may arrive while
2193 // parent is transitioning upwards. If a request arrives after
2194 // setParentInfo() has already recorded the output power flags
2195 // for the next power state, then using the power supplied by
2196 // fCurrentPowerState is incorrect, and might cause the child
2197 // to wait when it should not.
2199 outputPowerFlags
= childConnection
->parentCurrentPowerFlags();
2202 child
->fHeadNoteDomainTargetFlags
|= outputPowerFlags
;
2204 // Map child's requested power flags to one of our power state.
2206 for (order
= 0; order
< fNumberOfPowerStates
; order
++)
2208 powerState
= fPowerStates
[order
].stateOrderToIndex
;
2209 if ((fPowerStates
[powerState
].outputPowerFlags
& childRequestPowerFlags
)
2210 == childRequestPowerFlags
)
2213 if (order
>= fNumberOfPowerStates
)
2215 powerState
= kPowerStateZero
;
2218 // Conditions that warrants a power adjustment on this parent.
2219 // Adjust power will also propagate any changes to the child's
2220 // prevent idle/sleep flags towards the root domain.
2222 if (!childConnection
->childHasRequestedPower() ||
2223 (powerState
!= childConnection
->getDesiredDomainState()))
2226 #if ENABLE_DEBUG_LOGS
2229 PM_LOG("requestPowerDomainState[%s]: %s, init %d, %u->%u\n",
2230 getName(), child
->getName(),
2231 !childConnection
->childHasRequestedPower(),
2232 (uint32_t) childConnection
->getDesiredDomainState(),
2233 (uint32_t) powerState
);
2237 // Record the child's desires on the connection.
2238 childConnection
->setChildHasRequestedPower();
2239 childConnection
->setDesiredDomainState( powerState
);
2241 // Schedule a request to re-evaluate all children desires and
2242 // adjust power state. Submit a request if one wasn't pending,
2243 // or if the current request is part of a call tree.
2245 if (adjustPower
&& !fDeviceOverrideEnabled
&&
2246 (!fAdjustPowerScheduled
|| gIOPMRequest
->getRootRequest()))
2248 subRequest
= acquirePMRequest(
2249 this, kIOPMRequestTypeAdjustPowerState
, gIOPMRequest
);
2252 submitPMRequest( subRequest
);
2253 fAdjustPowerScheduled
= true;
2257 return kIOReturnSuccess
;
2260 //*********************************************************************************
2261 // [public] temporaryPowerClampOn
2263 // A power domain wants to clamp its power on till it has children which
2264 // will thendetermine the power domain state.
2266 // We enter the highest state until addPowerChild is called.
2267 //*********************************************************************************
2269 IOReturn
IOService::temporaryPowerClampOn( void )
2271 return requestPowerState( gIOPMPowerClientChildProxy
, kIOPMPowerStateMax
);
2274 //*********************************************************************************
2275 // [public] makeUsable
2277 // Some client of our device is asking that we become usable. Although
2278 // this has not come from a subclassed device object, treat it exactly
2279 // as if it had. In this way, subsequent requests for lower power from
2280 // a subclassed device object will pre-empt this request.
2282 // We treat this as a subclass object request to switch to the
2283 // highest power state.
2284 //*********************************************************************************
2286 IOReturn
IOService::makeUsable( void )
2288 OUR_PMLog(kPMLogMakeUsable
, 0, 0);
2289 return requestPowerState( gIOPMPowerClientDevice
, kIOPMPowerStateMax
);
2292 //*********************************************************************************
2293 // [public] currentCapability
2294 //*********************************************************************************
2296 IOPMPowerFlags
IOService::currentCapability( void )
2299 return IOPMNotPowerManaged
;
2301 return fCurrentCapabilityFlags
;
2304 //*********************************************************************************
2305 // [public] changePowerStateTo
2307 // Called by our power-controlling driver to change power state. The new desired
2308 // power state is computed and compared against the current power state. If those
2309 // power states differ, then a power state change is initiated.
2310 //*********************************************************************************
2312 IOReturn
IOService::changePowerStateTo( unsigned long ordinal
)
2314 OUR_PMLog(kPMLogChangeStateTo
, ordinal
, 0);
2315 return requestPowerState( gIOPMPowerClientDriver
, ordinal
);
2318 //*********************************************************************************
2319 // [protected] changePowerStateToPriv
2321 // Called by our driver subclass to change power state. The new desired power
2322 // state is computed and compared against the current power state. If those
2323 // power states differ, then a power state change is initiated.
2324 //*********************************************************************************
2326 IOReturn
IOService::changePowerStateToPriv( unsigned long ordinal
)
2328 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2329 return requestPowerState( gIOPMPowerClientDevice
, ordinal
);
2332 //*********************************************************************************
2333 // [public] changePowerStateWithOverrideTo
2335 // Called by our driver subclass to change power state. The new desired power
2336 // state is computed and compared against the current power state. If those
2337 // power states differ, then a power state change is initiated.
2338 // Override enforced - Children and Driver desires are ignored.
2339 //*********************************************************************************
2341 IOReturn
IOService::changePowerStateWithOverrideTo( IOPMPowerStateIndex ordinal
,
2342 IOPMRequestTag tag
)
2344 IOPMRequest
* request
;
2347 return kIOPMNotYetInitialized
;
2349 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2351 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerStateOverride
);
2353 return kIOReturnNoMemory
;
2355 gIOPMPowerClientDevice
->retain();
2356 request
->fRequestTag
= tag
;
2357 request
->fArg0
= (void *) ordinal
;
2358 request
->fArg1
= (void *) gIOPMPowerClientDevice
;
2362 request
->installCompletionAction( action
, target
, param
);
2365 // Prevent needless downwards power transitions by clamping power
2366 // until the scheduled request is executed.
2368 if (gIOPMWorkLoop
->inGate() && (ordinal
< fNumberOfPowerStates
))
2370 fTempClampPowerState
= StateMax(fTempClampPowerState
, ordinal
);
2372 fOverrideMaxPowerState
= ordinal
;
2373 request
->fArg2
= (void *) (uintptr_t) true;
2376 submitPMRequest( request
);
2380 //*********************************************************************************
2381 // [public] changePowerStateForRootDomain
2383 // Adjust the root domain's power desire on the target
2384 //*********************************************************************************
2386 IOReturn
IOService::changePowerStateForRootDomain( IOPMPowerStateIndex ordinal
)
2388 OUR_PMLog(kPMLogChangeStateForRootDomain
, ordinal
, 0);
2389 return requestPowerState( gIOPMPowerClientRootDomain
, ordinal
);
2392 //*********************************************************************************
2393 // [public for PMRD] quiescePowerTree
2395 // For root domain to issue a request to quiesce the power tree.
2396 // Supplied callback invoked upon completion.
2397 //*********************************************************************************
2399 IOReturn
IOService::quiescePowerTree(
2400 void * target
, IOPMCompletionAction action
, void * param
)
2402 IOPMRequest
* request
;
2405 return kIOPMNotYetInitialized
;
2406 if (!target
|| !action
)
2407 return kIOReturnBadArgument
;
2409 OUR_PMLog(kPMLogQuiescePowerTree
, 0, 0);
2411 // Target the root node instead of root domain. This is to avoid blocking
2412 // the quiesce request behind an existing root domain request in the work
2413 // queue. Root parent and root domain requests in the work queue must not
2414 // block the completion of the quiesce request.
2416 request
= acquirePMRequest(gIOPMRootNode
, kIOPMRequestTypeQuiescePowerTree
);
2418 return kIOReturnNoMemory
;
2420 request
->installCompletionAction(target
, action
, param
);
2422 // Submit through the normal request flow. This will make sure any request
2423 // already in the request queue will get pushed over to the work queue for
2424 // execution. Any request submitted after this request may not be serviced.
2426 submitPMRequest( request
);
2427 return kIOReturnSuccess
;
2430 //*********************************************************************************
2431 // [private] requestPowerState
2432 //*********************************************************************************
2434 IOReturn
IOService::requestPowerState(
2435 const OSSymbol
* client
,
2438 IOPMRequest
* request
;
2441 return kIOReturnBadArgument
;
2443 return kIOPMNotYetInitialized
;
2445 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerState
);
2447 return kIOReturnNoMemory
;
2450 request
->fArg0
= (void *)(uintptr_t) state
;
2451 request
->fArg1
= (void *) client
;
2455 request
->installCompletionAction( action
, target
, param
);
2458 // Prevent needless downwards power transitions by clamping power
2459 // until the scheduled request is executed.
2461 if (gIOPMWorkLoop
->inGate() && (state
< fNumberOfPowerStates
))
2463 fTempClampPowerState
= StateMax(fTempClampPowerState
, state
);
2465 request
->fArg2
= (void *) (uintptr_t) true;
2468 submitPMRequest( request
);
2472 //*********************************************************************************
2473 // [private] handleRequestPowerState
2474 //*********************************************************************************
2476 void IOService::handleRequestPowerState( IOPMRequest
* request
)
2478 const OSSymbol
* client
= (const OSSymbol
*) request
->fArg1
;
2479 uint32_t state
= (uint32_t)(uintptr_t) request
->fArg0
;
2481 PM_ASSERT_IN_GATE();
2484 assert(fTempClampCount
!= 0);
2485 if (fTempClampCount
) fTempClampCount
--;
2486 if (!fTempClampCount
) fTempClampPowerState
= kPowerStateZero
;
2489 if (fNumberOfPowerStates
&& (state
>= fNumberOfPowerStates
))
2490 state
= fHighestPowerState
;
2492 // The power suppression due to changePowerStateWithOverrideTo() expires
2493 // upon the next "device" power request - changePowerStateToPriv().
2495 if ((getPMRequestType() != kIOPMRequestTypeRequestPowerStateOverride
) &&
2496 (client
== gIOPMPowerClientDevice
))
2497 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
2499 if ((state
== kPowerStateZero
) &&
2500 (client
!= gIOPMPowerClientDevice
) &&
2501 (client
!= gIOPMPowerClientDriver
) &&
2502 (client
!= gIOPMPowerClientChildProxy
))
2503 removePowerClient(client
);
2505 updatePowerClient(client
, state
);
2511 //*********************************************************************************
2512 // [private] Helper functions to update/remove power clients.
2513 //*********************************************************************************
2515 void IOService::updatePowerClient( const OSSymbol
* client
, uint32_t powerState
)
2517 IOPMPowerStateIndex oldPowerState
= kPowerStateZero
;
2520 fPowerClients
= OSDictionary::withCapacity(4);
2521 if (fPowerClients
&& client
)
2523 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2526 oldPowerState
= num
->unsigned32BitValue();
2527 num
->setValue(powerState
);
2531 num
= OSNumber::withNumber(powerState
, 32);
2534 fPowerClients
->setObject(client
, num
);
2539 PM_ACTION_3(actionUpdatePowerClient
, client
, oldPowerState
, powerState
);
2543 void IOService::removePowerClient( const OSSymbol
* client
)
2545 if (fPowerClients
&& client
)
2546 fPowerClients
->removeObject(client
);
2549 uint32_t IOService::getPowerStateForClient( const OSSymbol
* client
)
2551 uint32_t powerState
= kPowerStateZero
;
2553 if (fPowerClients
&& client
)
2555 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2556 if (num
) powerState
= num
->unsigned32BitValue();
2561 //*********************************************************************************
2562 // [protected] powerOverrideOnPriv
2563 //*********************************************************************************
2565 IOReturn
IOService::powerOverrideOnPriv( void )
2567 IOPMRequest
* request
;
2570 return IOPMNotYetInitialized
;
2572 if (gIOPMWorkLoop
->inGate())
2574 fDeviceOverrideEnabled
= true;
2578 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOnPriv
);
2580 return kIOReturnNoMemory
;
2582 submitPMRequest( request
);
2586 //*********************************************************************************
2587 // [protected] powerOverrideOffPriv
2588 //*********************************************************************************
2590 IOReturn
IOService::powerOverrideOffPriv( void )
2592 IOPMRequest
* request
;
2595 return IOPMNotYetInitialized
;
2597 if (gIOPMWorkLoop
->inGate())
2599 fDeviceOverrideEnabled
= false;
2603 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOffPriv
);
2605 return kIOReturnNoMemory
;
2607 submitPMRequest( request
);
2611 //*********************************************************************************
2612 // [private] handlePowerOverrideChanged
2613 //*********************************************************************************
2615 void IOService::handlePowerOverrideChanged( IOPMRequest
* request
)
2617 PM_ASSERT_IN_GATE();
2618 if (request
->getType() == kIOPMRequestTypePowerOverrideOnPriv
)
2620 OUR_PMLog(kPMLogOverrideOn
, 0, 0);
2621 fDeviceOverrideEnabled
= true;
2625 OUR_PMLog(kPMLogOverrideOff
, 0, 0);
2626 fDeviceOverrideEnabled
= false;
2632 //*********************************************************************************
2633 // [private] computeDesiredState
2634 //*********************************************************************************
2636 void IOService::computeDesiredState( unsigned long localClamp
, bool computeOnly
)
2640 IOPowerConnection
* connection
;
2641 uint32_t desiredState
= kPowerStateZero
;
2642 uint32_t newPowerState
= kPowerStateZero
;
2643 bool hasChildren
= false;
2645 // Desired power state is always 0 without a controlling driver.
2647 if (!fNumberOfPowerStates
)
2649 fDesiredPowerState
= kPowerStateZero
;
2653 // Examine the children's desired power state.
2655 iter
= getChildIterator(gIOPowerPlane
);
2658 while ((next
= iter
->getNextObject()))
2660 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
2662 if (connection
->getReadyFlag() == false)
2664 PM_LOG3("[%s] %s: connection not ready\n",
2665 getName(), __FUNCTION__
);
2668 if (connection
->childHasRequestedPower())
2670 desiredState
= StateMax(connection
->getDesiredDomainState(), desiredState
);
2676 updatePowerClient(gIOPMPowerClientChildren
, desiredState
);
2678 removePowerClient(gIOPMPowerClientChildren
);
2680 // Iterate through all power clients to determine the min power state.
2682 iter
= OSCollectionIterator::withCollection(fPowerClients
);
2685 const OSSymbol
* client
;
2686 while ((client
= (const OSSymbol
*) iter
->getNextObject()))
2688 // Ignore child and driver when override is in effect.
2689 if ((fDeviceOverrideEnabled
||
2690 (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)) &&
2691 ((client
== gIOPMPowerClientChildren
) ||
2692 (client
== gIOPMPowerClientDriver
)))
2695 // Ignore child proxy when children are present.
2696 if (hasChildren
&& (client
== gIOPMPowerClientChildProxy
))
2699 // Advisory tickles are irrelevant unless system is in full wake
2700 if (client
== gIOPMPowerClientAdvisoryTickle
&&
2701 !gIOPMAdvisoryTickleEnabled
)
2704 desiredState
= getPowerStateForClient(client
);
2705 assert(desiredState
< fNumberOfPowerStates
);
2707 desiredState
, client
->getCStringNoCopy());
2709 newPowerState
= StateMax(newPowerState
, desiredState
);
2711 if (client
== gIOPMPowerClientDevice
)
2712 fDeviceDesire
= desiredState
;
2717 // Factor in the temporary power desires.
2719 newPowerState
= StateMax(newPowerState
, localClamp
);
2720 newPowerState
= StateMax(newPowerState
, fTempClampPowerState
);
2722 // Limit check against max power override.
2724 newPowerState
= StateMin(newPowerState
, fOverrideMaxPowerState
);
2726 // Limit check against number of power states.
2728 if (newPowerState
>= fNumberOfPowerStates
)
2729 newPowerState
= fHighestPowerState
;
2731 fDesiredPowerState
= newPowerState
;
2733 PM_LOG1(" temp %u, clamp %u, current %u, new %u\n",
2734 (uint32_t) localClamp
, (uint32_t) fTempClampPowerState
,
2735 (uint32_t) fCurrentPowerState
, newPowerState
);
2739 // Restart idle timer if possible when device desire has increased.
2740 // Or if an advisory desire exists.
2742 if (fIdleTimerPeriod
&& fIdleTimerStopped
)
2747 // Invalidate cached tickle power state when desires change, and not
2748 // due to a tickle request. In case the driver has requested a lower
2749 // power state, but the tickle is caching a higher power state which
2750 // will drop future tickles until the cached value is lowered or in-
2751 // validated. The invalidation must occur before the power transition
2752 // to avoid dropping a necessary tickle.
2754 if ((getPMRequestType() != kIOPMRequestTypeActivityTickle
) &&
2755 (fActivityTicklePowerState
!= kInvalidTicklePowerState
))
2757 IOLockLock(fActivityLock
);
2758 fActivityTicklePowerState
= kInvalidTicklePowerState
;
2759 IOLockUnlock(fActivityLock
);
2764 //*********************************************************************************
2765 // [public] currentPowerConsumption
2767 //*********************************************************************************
2769 unsigned long IOService::currentPowerConsumption( void )
2772 return kIOPMUnknown
;
2774 return fCurrentPowerConsumption
;
2777 //*********************************************************************************
2778 // [deprecated] getPMworkloop
2779 //*********************************************************************************
2782 IOWorkLoop
* IOService::getPMworkloop( void )
2784 return gIOPMWorkLoop
;
2790 //*********************************************************************************
2791 // Power Parent/Children Applier
2792 //*********************************************************************************
2795 applyToPowerChildren(
2796 IOService
* service
,
2797 IOServiceApplierFunction applier
,
2799 IOOptionBits options
)
2801 PM_ASSERT_IN_GATE();
2803 IORegistryEntry
* entry
;
2804 IORegistryIterator
* iter
;
2805 IOPowerConnection
* connection
;
2808 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
, options
);
2811 while ((entry
= iter
->getNextObject()))
2813 // Get child of IOPowerConnection objects
2814 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)))
2816 child
= (IOService
*) connection
->copyChildEntry(gIOPowerPlane
);
2819 (*applier
)(child
, context
);
2830 IOService
* service
,
2831 IOServiceApplierFunction applier
,
2833 IOOptionBits options
)
2835 PM_ASSERT_IN_GATE();
2837 IORegistryEntry
* entry
;
2838 IORegistryIterator
* iter
;
2839 IOPowerConnection
* connection
;
2842 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
,
2843 options
| kIORegistryIterateParents
);
2846 while ((entry
= iter
->getNextObject()))
2848 // Get child of IOPowerConnection objects
2849 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)))
2851 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
2854 (*applier
)(parent
, context
);
2863 #endif /* NOT_YET */
2866 // MARK: Activity Tickle & Idle Timer
2868 void IOService::setAdvisoryTickleEnable( bool enable
)
2870 gIOPMAdvisoryTickleEnabled
= enable
;
2873 //*********************************************************************************
2874 // [public] activityTickle
2876 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
2877 // flag to be set, and the device state checked. If the device has been
2878 // powered down, it is powered up again.
2879 // The tickle with parameter kIOPMSubclassPolicy is ignored here and
2880 // should be intercepted by a subclass.
2881 //*********************************************************************************
2883 bool IOService::activityTickle( unsigned long type
, unsigned long stateNumber
)
2885 IOPMRequest
* request
;
2886 bool noPowerChange
= true;
2887 uint32_t tickleFlags
;
2890 return true; // no power change
2892 if ((type
== kIOPMSuperclassPolicy1
) && StateOrder(stateNumber
))
2894 IOLockLock(fActivityLock
);
2896 // Record device activity for the idle timer handler.
2898 fDeviceWasActive
= true;
2899 fActivityTickleCount
++;
2900 clock_get_uptime(&fDeviceActiveTimestamp
);
2902 PM_ACTION_0(actionActivityTickle
);
2904 // Record the last tickle power state.
2905 // This helps to filter out redundant tickles as
2906 // this function may be called from the data path.
2908 if ((fActivityTicklePowerState
== kInvalidTicklePowerState
)
2909 || StateOrder(fActivityTicklePowerState
) < StateOrder(stateNumber
))
2911 fActivityTicklePowerState
= stateNumber
;
2912 noPowerChange
= false;
2914 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerRise
;
2915 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2918 request
->fArg0
= (void *) stateNumber
;
2919 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
2920 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
2921 submitPMRequest(request
);
2925 IOLockUnlock(fActivityLock
);
2928 else if ((type
== kIOPMActivityTickleTypeAdvisory
) &&
2929 ((stateNumber
= fDeviceUsablePowerState
) != kPowerStateZero
))
2931 IOLockLock(fActivityLock
);
2933 fAdvisoryTickled
= true;
2935 if (fAdvisoryTicklePowerState
!= stateNumber
)
2937 fAdvisoryTicklePowerState
= stateNumber
;
2938 noPowerChange
= false;
2940 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerRise
;
2941 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2944 request
->fArg0
= (void *) stateNumber
;
2945 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
2946 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
2947 submitPMRequest(request
);
2951 IOLockUnlock(fActivityLock
);
2954 // Returns false if the activityTickle might cause a transition to a
2955 // higher powered state, true otherwise.
2957 return noPowerChange
;
2960 //*********************************************************************************
2961 // [private] handleActivityTickle
2962 //*********************************************************************************
2964 void IOService::handleActivityTickle( IOPMRequest
* request
)
2966 uint32_t ticklePowerState
= (uint32_t)(uintptr_t) request
->fArg0
;
2967 uint32_t tickleFlags
= (uint32_t)(uintptr_t) request
->fArg1
;
2968 uint32_t tickleGeneration
= (uint32_t)(uintptr_t) request
->fArg2
;
2969 bool adjustPower
= false;
2971 PM_ASSERT_IN_GATE();
2972 if (fResetPowerStateOnWake
&& (tickleGeneration
!= gIOPMTickleGeneration
))
2974 // Drivers that don't want power restored on wake will drop any
2975 // tickles that pre-dates the current system wake. The model is
2976 // that each wake is a fresh start, with power state depressed
2977 // until a new tickle or an explicit power up request from the
2978 // driver. It is possible for the PM work loop to enter the
2979 // system sleep path with tickle requests queued.
2984 if (tickleFlags
& kTickleTypeActivity
)
2986 IOPMPowerStateIndex deviceDesireOrder
= StateOrder(fDeviceDesire
);
2987 uint32_t idleTimerGeneration
= ticklePowerState
; // kTickleTypePowerDrop
2989 if (tickleFlags
& kTickleTypePowerRise
)
2991 if ((StateOrder(ticklePowerState
) > deviceDesireOrder
) &&
2992 (ticklePowerState
< fNumberOfPowerStates
))
2994 fIdleTimerMinPowerState
= ticklePowerState
;
2995 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
2999 else if ((deviceDesireOrder
> StateOrder(fIdleTimerMinPowerState
)) &&
3000 (idleTimerGeneration
== fIdleTimerGeneration
))
3002 // Power drop due to idle timer expiration.
3003 // Do not allow idle timer to reduce power below tickle power.
3004 // This prevents the idle timer from decreasing the device desire
3005 // to zero and cancelling the effect of a pre-sleep tickle when
3006 // system wakes up to doze state, while the device is unable to
3007 // raise its power state to satisfy the tickle.
3009 deviceDesireOrder
--;
3010 if (deviceDesireOrder
< fNumberOfPowerStates
)
3012 ticklePowerState
= fPowerStates
[deviceDesireOrder
].stateOrderToIndex
;
3013 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
3018 else // advisory tickle
3020 if (tickleFlags
& kTickleTypePowerRise
)
3022 if ((ticklePowerState
== fDeviceUsablePowerState
) &&
3023 (ticklePowerState
< fNumberOfPowerStates
))
3025 updatePowerClient(gIOPMPowerClientAdvisoryTickle
, ticklePowerState
);
3026 fHasAdvisoryDesire
= true;
3027 fAdvisoryTickleUsed
= true;
3032 IOLockLock(fActivityLock
);
3033 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3034 IOLockUnlock(fActivityLock
);
3037 else if (fHasAdvisoryDesire
)
3039 removePowerClient(gIOPMPowerClientAdvisoryTickle
);
3040 fHasAdvisoryDesire
= false;
3051 //******************************************************************************
3052 // [public] setIdleTimerPeriod
3054 // A subclass policy-maker is using our standard idleness detection service.
3055 // Start the idle timer. Period is in seconds.
3056 //******************************************************************************
3058 IOReturn
IOService::setIdleTimerPeriod( unsigned long period
)
3061 return IOPMNotYetInitialized
;
3063 OUR_PMLog(kPMLogSetIdleTimerPeriod
, period
, fIdleTimerPeriod
);
3065 IOPMRequest
* request
=
3066 acquirePMRequest( this, kIOPMRequestTypeSetIdleTimerPeriod
);
3068 return kIOReturnNoMemory
;
3070 request
->fArg0
= (void *) period
;
3071 submitPMRequest( request
);
3073 return kIOReturnSuccess
;
3076 IOReturn
IOService::setIgnoreIdleTimer( bool ignore
)
3079 return IOPMNotYetInitialized
;
3081 OUR_PMLog(kIOPMRequestTypeIgnoreIdleTimer
, ignore
, 0);
3083 IOPMRequest
* request
=
3084 acquirePMRequest( this, kIOPMRequestTypeIgnoreIdleTimer
);
3086 return kIOReturnNoMemory
;
3088 request
->fArg0
= (void *) ignore
;
3089 submitPMRequest( request
);
3091 return kIOReturnSuccess
;
3094 //******************************************************************************
3095 // [public] nextIdleTimeout
3097 // Returns how many "seconds from now" the device should idle into its
3098 // next lowest power state.
3099 //******************************************************************************
3101 SInt32
IOService::nextIdleTimeout(
3102 AbsoluteTime currentTime
,
3103 AbsoluteTime lastActivity
,
3104 unsigned int powerState
)
3111 // Calculate time difference using funky macro from clock.h.
3112 delta
= currentTime
;
3113 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
3115 // Figure it in seconds.
3116 absolutetime_to_nanoseconds(delta
, &delta_ns
);
3117 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
3119 // Be paranoid about delta somehow exceeding timer period.
3120 if (delta_secs
< (int) fIdleTimerPeriod
)
3121 delay_secs
= (int) fIdleTimerPeriod
- delta_secs
;
3123 delay_secs
= (int) fIdleTimerPeriod
;
3125 return (SInt32
)delay_secs
;
3128 //*********************************************************************************
3129 // [public] start_PM_idle_timer
3130 //*********************************************************************************
3132 void IOService::start_PM_idle_timer( void )
3134 static const int maxTimeout
= 100000;
3135 static const int minTimeout
= 1;
3136 AbsoluteTime uptime
, deadline
;
3140 if (!initialized
|| !fIdleTimerPeriod
)
3143 IOLockLock(fActivityLock
);
3145 clock_get_uptime(&uptime
);
3147 // Subclasses may modify idle sleep algorithm
3148 idle_in
= nextIdleTimeout(uptime
, fDeviceActiveTimestamp
, fCurrentPowerState
);
3150 // Check for out-of range responses
3151 if (idle_in
> maxTimeout
)
3153 // use standard implementation
3154 idle_in
= IOService::nextIdleTimeout(uptime
,
3155 fDeviceActiveTimestamp
,
3156 fCurrentPowerState
);
3157 } else if (idle_in
< minTimeout
) {
3158 idle_in
= fIdleTimerPeriod
;
3161 IOLockUnlock(fActivityLock
);
3163 fNextIdleTimerPeriod
= idle_in
;
3164 fIdleTimerStartTime
= uptime
;
3167 clock_interval_to_absolutetime_interval(idle_in
, kSecondScale
, &deadline
);
3168 ADD_ABSOLUTETIME(&deadline
, &uptime
);
3169 pending
= thread_call_enter_delayed(fIdleTimer
, deadline
);
3170 if (pending
) release();
3173 //*********************************************************************************
3174 // [private] restartIdleTimer
3175 //*********************************************************************************
3177 void IOService::restartIdleTimer( void )
3179 if (fDeviceDesire
!= kPowerStateZero
)
3181 fIdleTimerStopped
= false;
3182 fActivityTickleCount
= 0;
3183 start_PM_idle_timer();
3185 else if (fHasAdvisoryDesire
)
3187 fIdleTimerStopped
= false;
3188 start_PM_idle_timer();
3192 fIdleTimerStopped
= true;
3196 //*********************************************************************************
3197 // idle_timer_expired
3198 //*********************************************************************************
3202 thread_call_param_t arg0
, thread_call_param_t arg1
)
3204 IOService
* me
= (IOService
*) arg0
;
3207 gIOPMWorkLoop
->runAction(
3208 OSMemberFunctionCast(IOWorkLoop::Action
, me
,
3209 &IOService::idleTimerExpired
),
3215 //*********************************************************************************
3216 // [private] idleTimerExpired
3218 // The idle timer has expired. If there has been activity since the last
3219 // expiration, just restart the timer and return. If there has not been
3220 // activity, switch to the next lower power state and restart the timer.
3221 //*********************************************************************************
3223 void IOService::idleTimerExpired( void )
3225 IOPMRequest
* request
;
3226 bool restartTimer
= true;
3227 uint32_t tickleFlags
;
3229 if ( !initialized
|| !fIdleTimerPeriod
|| fIdleTimerStopped
||
3230 fLockedFlags
.PMStop
)
3233 fIdleTimerStartTime
= 0;
3235 IOLockLock(fActivityLock
);
3237 // Check for device activity (tickles) over last timer period.
3239 if (fDeviceWasActive
)
3241 // Device was active - do not drop power, restart timer.
3242 fDeviceWasActive
= false;
3244 else if (!fIdleTimerIgnored
)
3246 // No device activity - drop power state by one level.
3247 // Decrement the cached tickle power state when possible.
3248 // This value may be kInvalidTicklePowerState before activityTickle()
3249 // is called, but the power drop request must be issued regardless.
3251 if ((fActivityTicklePowerState
!= kInvalidTicklePowerState
) &&
3252 (fActivityTicklePowerState
!= kPowerStateZero
))
3253 fActivityTicklePowerState
--;
3255 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerDrop
;
3256 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3259 request
->fArg0
= (void *)(uintptr_t) fIdleTimerGeneration
;
3260 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3261 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3262 submitPMRequest( request
);
3264 // Do not restart timer until after the tickle request has been
3267 restartTimer
= false;
3271 if (fAdvisoryTickled
)
3273 fAdvisoryTickled
= false;
3275 else if (fHasAdvisoryDesire
)
3277 // Want new tickles to turn into pm request after we drop the lock
3278 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3280 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerDrop
;
3281 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3284 request
->fArg0
= (void *)(uintptr_t) fIdleTimerGeneration
;
3285 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3286 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3287 submitPMRequest( request
);
3289 // Do not restart timer until after the tickle request has been
3292 restartTimer
= false;
3296 IOLockUnlock(fActivityLock
);
3299 start_PM_idle_timer();
3303 //*********************************************************************************
3304 // [deprecated] PM_idle_timer_expiration
3305 //*********************************************************************************
3307 void IOService::PM_idle_timer_expiration( void )
3311 //*********************************************************************************
3312 // [deprecated] command_received
3313 //*********************************************************************************
3315 void IOService::command_received( void *statePtr
, void *, void * , void * )
3318 #endif /* !__LP64__ */
3320 //*********************************************************************************
3321 // [public] setAggressiveness
3323 // Pass on the input parameters to all power domain children. All those which are
3324 // power domains will pass it on to their children, etc.
3325 //*********************************************************************************
3327 IOReturn
IOService::setAggressiveness( unsigned long type
, unsigned long newLevel
)
3329 return kIOReturnSuccess
;
3332 //*********************************************************************************
3333 // [public] getAggressiveness
3335 // Called by the user client.
3336 //*********************************************************************************
3338 IOReturn
IOService::getAggressiveness( unsigned long type
, unsigned long * currentLevel
)
3340 IOPMrootDomain
* rootDomain
= getPMRootDomain();
3343 return kIOReturnNotReady
;
3345 return rootDomain
->getAggressiveness( type
, currentLevel
);
3348 //*********************************************************************************
3349 // [public] getPowerState
3351 //*********************************************************************************
3353 UInt32
IOService::getPowerState( void )
3356 return kPowerStateZero
;
3358 return fCurrentPowerState
;
3362 //*********************************************************************************
3363 // [deprecated] systemWake
3365 // Pass this to all power domain children. All those which are
3366 // power domains will pass it on to their children, etc.
3367 //*********************************************************************************
3369 IOReturn
IOService::systemWake( void )
3373 IOPowerConnection
* connection
;
3374 IOService
* theChild
;
3376 iter
= getChildIterator(gIOPowerPlane
);
3379 while ( (next
= iter
->getNextObject()) )
3381 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
3383 if (connection
->getReadyFlag() == false)
3385 PM_LOG3("[%s] %s: connection not ready\n",
3386 getName(), __FUNCTION__
);
3390 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
3393 theChild
->systemWake();
3394 theChild
->release();
3401 if ( fControllingDriver
!= NULL
)
3403 if ( fControllingDriver
->didYouWakeSystem() )
3412 //*********************************************************************************
3413 // [deprecated] temperatureCriticalForZone
3414 //*********************************************************************************
3416 IOReturn
IOService::temperatureCriticalForZone( IOService
* whichZone
)
3418 IOService
* theParent
;
3421 OUR_PMLog(kPMLogCriticalTemp
, 0, 0);
3423 if ( inPlane(gIOPowerPlane
) && !IS_PM_ROOT
)
3425 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
3428 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
3432 theParent
->temperatureCriticalForZone(whichZone
);
3433 theParent
->release();
3439 #endif /* !__LP64__ */
3442 // MARK: Power Change (Common)
3444 //*********************************************************************************
3445 // [private] startPowerChange
3447 // All power state changes starts here.
3448 //*********************************************************************************
3450 IOReturn
IOService::startPowerChange(
3451 IOPMPowerChangeFlags changeFlags
,
3452 IOPMPowerStateIndex powerState
,
3453 IOPMPowerFlags domainFlags
,
3454 IOPowerConnection
* parentConnection
,
3455 IOPMPowerFlags parentFlags
)
3457 PM_ASSERT_IN_GATE();
3458 assert( fMachineState
== kIOPM_Finished
);
3459 assert( powerState
< fNumberOfPowerStates
);
3461 if (powerState
>= fNumberOfPowerStates
)
3462 return IOPMAckImplied
;
3464 fIsPreChange
= true;
3465 PM_ACTION_2(actionPowerChangeOverride
, &powerState
, &changeFlags
);
3467 if (changeFlags
& kIOPMExpireIdleTimer
)
3469 // Root domain requested removal of tickle influence
3470 if (StateOrder(fDeviceDesire
) > StateOrder(powerState
))
3472 // Reset device desire down to the clamped power state
3473 updatePowerClient(gIOPMPowerClientDevice
, powerState
);
3474 computeDesiredState(kPowerStateZero
, true);
3476 // Invalidate tickle cache so the next tickle will issue a request
3477 IOLockLock(fActivityLock
);
3478 fDeviceWasActive
= false;
3479 fActivityTicklePowerState
= kInvalidTicklePowerState
;
3480 IOLockUnlock(fActivityLock
);
3482 fIdleTimerMinPowerState
= kPowerStateZero
;
3486 // Root domain's override handler may cancel the power change by
3487 // setting the kIOPMNotDone flag.
3489 if (changeFlags
& kIOPMNotDone
)
3490 return IOPMAckImplied
;
3492 // Forks to either Driver or Parent initiated power change paths.
3494 fHeadNoteChangeFlags
= changeFlags
;
3495 fHeadNotePowerState
= powerState
;
3496 fHeadNotePowerArrayEntry
= &fPowerStates
[ powerState
];
3497 fHeadNoteParentConnection
= NULL
;
3499 if (changeFlags
& kIOPMSelfInitiated
)
3501 if (changeFlags
& kIOPMSynchronize
)
3509 assert(changeFlags
& kIOPMParentInitiated
);
3510 fHeadNoteDomainFlags
= domainFlags
;
3511 fHeadNoteParentFlags
= parentFlags
;
3512 fHeadNoteParentConnection
= parentConnection
;
3513 return ParentChangeStart();
3517 //*********************************************************************************
3518 // [private] notifyInterestedDrivers
3519 //*********************************************************************************
3521 bool IOService::notifyInterestedDrivers( void )
3523 IOPMinformee
* informee
;
3524 IOPMinformeeList
* list
= fInterestedDrivers
;
3525 DriverCallParam
* param
;
3527 IOItemCount skipCnt
= 0;
3529 PM_ASSERT_IN_GATE();
3530 assert( fDriverCallParamCount
== 0 );
3531 assert( fHeadNotePendingAcks
== 0 );
3533 fHeadNotePendingAcks
= 0;
3535 count
= list
->numberOfItems();
3537 goto done
; // no interested drivers
3539 // Allocate an array of interested drivers and their return values
3540 // for the callout thread. Everything else is still "owned" by the
3541 // PM work loop, which can run to process acknowledgePowerChange()
3544 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3545 if (count
> fDriverCallParamSlots
)
3547 if (fDriverCallParamSlots
)
3549 assert(fDriverCallParamPtr
);
3550 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
3551 fDriverCallParamPtr
= 0;
3552 fDriverCallParamSlots
= 0;
3555 param
= IONew(DriverCallParam
, count
);
3557 goto done
; // no memory
3559 fDriverCallParamPtr
= (void *) param
;
3560 fDriverCallParamSlots
= count
;
3563 informee
= list
->firstInList();
3565 for (IOItemCount i
= 0; i
< count
; i
++)
3567 if (fInitialSetPowerState
|| (fHeadNoteChangeFlags
& kIOPMInitialPowerChange
)) {
3568 // Skip notifying self, if 'kIOPMInitialDeviceState' is set and
3569 // this is the initial power state change
3570 if ((this == informee
->whatObject
) &&
3571 (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
)) {
3576 informee
->timer
= -1;
3577 param
[i
].Target
= informee
;
3579 informee
= list
->nextInList( informee
);
3586 fDriverCallParamCount
= count
;
3587 fHeadNotePendingAcks
= count
;
3589 // Block state machine and wait for callout completion.
3590 assert(!fDriverCallBusy
);
3591 fDriverCallBusy
= true;
3592 thread_call_enter( fDriverCallEntry
);
3596 // Return false if there are no interested drivers or could not schedule
3597 // callout thread due to error.
3601 //*********************************************************************************
3602 // [private] notifyInterestedDriversDone
3603 //*********************************************************************************
3605 void IOService::notifyInterestedDriversDone( void )
3607 IOPMinformee
* informee
;
3609 DriverCallParam
* param
;
3612 PM_ASSERT_IN_GATE();
3613 assert( fDriverCallBusy
== false );
3614 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3616 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3617 count
= fDriverCallParamCount
;
3621 for (IOItemCount i
= 0; i
< count
; i
++, param
++)
3623 informee
= (IOPMinformee
*) param
->Target
;
3624 result
= param
->Result
;
3626 if ((result
== IOPMAckImplied
) || (result
< 0))
3628 // Interested driver return IOPMAckImplied.
3629 // If informee timer is zero, it must have de-registered
3630 // interest during the thread callout. That also drops
3631 // the pending ack count.
3633 if (fHeadNotePendingAcks
&& informee
->timer
)
3634 fHeadNotePendingAcks
--;
3636 informee
->timer
= 0;
3638 else if (informee
->timer
)
3640 assert(informee
->timer
== -1);
3642 // Driver has not acked, and has returned a positive result.
3643 // Enforce a minimum permissible timeout value.
3644 // Make the min value large enough so timeout is less likely
3645 // to occur if a driver misinterpreted that the return value
3646 // should be in microsecond units. And make it large enough
3647 // to be noticeable if a driver neglects to ack.
3649 if (result
< kMinAckTimeoutTicks
)
3650 result
= kMinAckTimeoutTicks
;
3652 informee
->timer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3654 // else, child has already acked or driver has removed interest,
3655 // and head_note_pendingAcks decremented.
3656 // informee may have been removed from the interested drivers list,
3657 // thus the informee must be retained across the callout.
3659 informee
->release();
3662 fDriverCallParamCount
= 0;
3664 if ( fHeadNotePendingAcks
)
3666 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
3671 MS_POP(); // pop the machine state passed to notifyAll()
3673 // If interest acks are outstanding, block the state machine until
3674 // fHeadNotePendingAcks drops to zero before notifying root domain.
3675 // Otherwise notify root domain directly.
3677 if (!fHeadNotePendingAcks
)
3683 MS_PUSH(fMachineState
);
3684 fMachineState
= kIOPM_NotifyChildrenStart
;
3688 //*********************************************************************************
3689 // [private] notifyRootDomain
3690 //*********************************************************************************
3692 void IOService::notifyRootDomain( void )
3694 assert( fDriverCallBusy
== false );
3696 // Only for root domain in the will-change phase
3697 if (!IS_ROOT_DOMAIN
|| (fMachineState
!= kIOPM_OurChangeSetPowerState
))
3703 MS_PUSH(fMachineState
); // push notifyAll() machine state
3704 fMachineState
= kIOPM_DriverThreadCallDone
;
3706 // Call IOPMrootDomain::willNotifyPowerChildren() on a thread call
3707 // to avoid a deadlock.
3708 fDriverCallReason
= kRootDomainInformPreChange
;
3709 fDriverCallBusy
= true;
3710 thread_call_enter( fDriverCallEntry
);
3713 void IOService::notifyRootDomainDone( void )
3715 assert( fDriverCallBusy
== false );
3716 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3718 MS_POP(); // pop notifyAll() machine state
3722 //*********************************************************************************
3723 // [private] notifyChildren
3724 //*********************************************************************************
3726 void IOService::notifyChildren( void )
3730 IOPowerConnection
* connection
;
3731 OSArray
* children
= 0;
3732 IOPMrootDomain
* rootDomain
;
3733 bool delayNotify
= false;
3735 if ((fHeadNotePowerState
!= fCurrentPowerState
) &&
3736 (IS_POWER_DROP
== fIsPreChange
) &&
3737 ((rootDomain
= getPMRootDomain()) == this))
3739 rootDomain
->tracePoint( IS_POWER_DROP
?
3740 kIOPMTracePointSleepPowerPlaneDrivers
:
3741 kIOPMTracePointWakePowerPlaneDrivers
);
3744 if (fStrictTreeOrder
)
3745 children
= OSArray::withCapacity(8);
3747 // Sum child power consumption in notifyChild()
3748 fHeadNotePowerArrayEntry
->staticPower
= 0;
3750 iter
= getChildIterator(gIOPowerPlane
);
3753 while ((next
= iter
->getNextObject()))
3755 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
3757 if (connection
->getReadyFlag() == false)
3759 PM_LOG3("[%s] %s: connection not ready\n",
3760 getName(), __FUNCTION__
);
3764 // Mechanism to postpone the did-change notification to
3765 // certain power children to order those children last.
3766 // Cannot be used together with strict tree ordering.
3768 if (!fIsPreChange
&&
3769 connection
->delayChildNotification
&&
3770 getPMRootDomain()->shouldDelayChildNotification(this))
3774 children
= OSArray::withCapacity(8);
3780 children
->setObject( connection
);
3785 if (!delayNotify
&& children
)
3786 children
->setObject( connection
);
3788 notifyChild( connection
);
3794 if (children
&& (children
->getCount() == 0))
3796 children
->release();
3801 assert(fNotifyChildArray
== 0);
3802 fNotifyChildArray
= children
;
3803 MS_PUSH(fMachineState
);
3807 // Block until all non-delayed children have acked their
3808 // notification. Then notify the remaining delayed child
3809 // in the array. This is used to hold off graphics child
3810 // notification while the rest of the system powers up.
3811 // If a hid tickle arrives during this time, the delayed
3812 // children are immediately notified and root domain will
3813 // not clamp power for dark wake.
3815 fMachineState
= kIOPM_NotifyChildrenDelayed
;
3816 PM_LOG2("%s: %d children in delayed array\n",
3817 getName(), children
->getCount());
3821 // Child array created to support strict notification order.
3822 // Notify children in the array one at a time.
3824 fMachineState
= kIOPM_NotifyChildrenOrdered
;
3829 //*********************************************************************************
3830 // [private] notifyChildrenOrdered
3831 //*********************************************************************************
3833 void IOService::notifyChildrenOrdered( void )
3835 PM_ASSERT_IN_GATE();
3836 assert(fNotifyChildArray
);
3837 assert(fMachineState
== kIOPM_NotifyChildrenOrdered
);
3839 // Notify one child, wait for it to ack, then repeat for next child.
3840 // This is a workaround for some drivers with multiple instances at
3841 // the same branch in the power tree, but the driver is slow to power
3842 // up unless the tree ordering is observed. Problem observed only on
3843 // system wake, not on system sleep.
3845 // We have the ability to power off in reverse child index order.
3846 // That works nicely on some machines, but not on all HW configs.
3848 if (fNotifyChildArray
->getCount())
3850 IOPowerConnection
* connection
;
3851 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(0);
3852 notifyChild( connection
);
3853 fNotifyChildArray
->removeObject(0);
3857 fNotifyChildArray
->release();
3858 fNotifyChildArray
= 0;
3860 MS_POP(); // pushed by notifyChildren()
3864 //*********************************************************************************
3865 // [private] notifyChildrenDelayed
3866 //*********************************************************************************
3868 void IOService::notifyChildrenDelayed( void )
3870 IOPowerConnection
* connection
;
3872 PM_ASSERT_IN_GATE();
3873 assert(fNotifyChildArray
);
3874 assert(fMachineState
== kIOPM_NotifyChildrenDelayed
);
3876 // Wait after all non-delayed children and interested drivers have ack'ed,
3877 // then notify all delayed children. If notify delay is canceled, child
3878 // acks may be outstanding with PM blocked on fHeadNotePendingAcks != 0.
3879 // But the handling for either case is identical.
3881 for (int i
= 0; ; i
++)
3883 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(i
);
3887 notifyChild( connection
);
3890 PM_LOG2("%s: notified delayed children\n", getName());
3891 fNotifyChildArray
->release();
3892 fNotifyChildArray
= 0;
3894 MS_POP(); // pushed by notifyChildren()
3897 //*********************************************************************************
3898 // [private] notifyAll
3899 //*********************************************************************************
3901 IOReturn
IOService::notifyAll( uint32_t nextMS
)
3903 // Save the machine state to be restored by notifyInterestedDriversDone()
3905 PM_ASSERT_IN_GATE();
3907 fMachineState
= kIOPM_DriverThreadCallDone
;
3908 fDriverCallReason
= fIsPreChange
?
3909 kDriverCallInformPreChange
: kDriverCallInformPostChange
;
3911 if (!notifyInterestedDrivers())
3912 notifyInterestedDriversDone();
3914 return IOPMWillAckLater
;
3917 //*********************************************************************************
3918 // [private, static] pmDriverCallout
3920 // Thread call context
3921 //*********************************************************************************
3923 IOReturn
IOService::actionDriverCalloutDone(
3925 void * arg0
, void * arg1
,
3926 void * arg2
, void * arg3
)
3928 IOServicePM
* pwrMgt
= (IOServicePM
*) arg0
;
3930 assert( fDriverCallBusy
);
3931 fDriverCallBusy
= false;
3933 assert(gIOPMWorkQueue
);
3934 gIOPMWorkQueue
->signalWorkAvailable();
3936 return kIOReturnSuccess
;
3939 void IOService::pmDriverCallout( IOService
* from
)
3942 switch (from
->fDriverCallReason
)
3944 case kDriverCallSetPowerState
:
3945 from
->driverSetPowerState();
3948 case kDriverCallInformPreChange
:
3949 case kDriverCallInformPostChange
:
3950 from
->driverInformPowerChange();
3953 case kRootDomainInformPreChange
:
3954 getPMRootDomain()->willNotifyPowerChildren(from
->fHeadNotePowerState
);
3958 panic("IOService::pmDriverCallout bad machine state %x",
3959 from
->fDriverCallReason
);
3962 gIOPMWorkLoop
->runAction(actionDriverCalloutDone
,
3964 /* arg0 */ (void *) from
->pwrMgt
);
3967 //*********************************************************************************
3968 // [private] driverSetPowerState
3970 // Thread call context
3971 //*********************************************************************************
3973 void IOService::driverSetPowerState( void )
3975 IOPMPowerStateIndex powerState
;
3976 DriverCallParam
* param
;
3977 IOPMDriverCallEntry callEntry
;
3980 uint32_t oldPowerState
= getPowerState();
3982 assert( fDriverCallBusy
);
3983 assert( fDriverCallParamPtr
);
3984 assert( fDriverCallParamCount
== 1 );
3986 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3987 powerState
= fHeadNotePowerState
;
3989 if (assertPMDriverCall(&callEntry
))
3991 OUR_PMLogFuncStart(kPMLogProgramHardware
, (uintptr_t) this, powerState
);
3992 start_spindump_timer("SetState");
3993 clock_get_uptime(&fDriverCallStartTime
);
3994 result
= fControllingDriver
->setPowerState( powerState
, this );
3995 clock_get_uptime(&end
);
3996 stop_spindump_timer();
3997 OUR_PMLogFuncEnd(kPMLogProgramHardware
, (uintptr_t) this, (UInt32
) result
);
3999 deassertPMDriverCall(&callEntry
);
4001 // Record the most recent max power state residency timings.
4002 // Use with DeviceActiveTimestamp to diagnose tickle issues.
4003 if (powerState
== fHighestPowerState
)
4004 fMaxPowerStateEntryTime
= end
;
4005 else if (oldPowerState
== fHighestPowerState
)
4006 fMaxPowerStateExitTime
= end
;
4010 PM_LOG("%s::setPowerState(%p, %lu -> %lu) returned 0x%x\n",
4011 fName
, OBFUSCATE(this), fCurrentPowerState
, powerState
, result
);
4015 if ((result
== IOPMAckImplied
) || (result
< 0))
4019 SUB_ABSOLUTETIME(&end
, &fDriverCallStartTime
);
4020 absolutetime_to_nanoseconds(end
, &nsec
);
4021 if (nsec
> LOG_SETPOWER_TIMES
) {
4022 getPMRootDomain()->pmStatsRecordApplicationResponse(
4023 gIOPMStatsDriverPSChangeSlow
,
4024 fName
, kDriverCallSetPowerState
, NS_TO_MS(nsec
), getRegistryEntryID(),
4031 result
= kIOPMAckImplied
;
4033 param
->Result
= result
;
4036 //*********************************************************************************
4037 // [private] driverInformPowerChange
4039 // Thread call context
4040 //*********************************************************************************
4042 void IOService::driverInformPowerChange( void )
4044 IOPMinformee
* informee
;
4046 DriverCallParam
* param
;
4047 IOPMDriverCallEntry callEntry
;
4048 IOPMPowerFlags powerFlags
;
4049 IOPMPowerStateIndex powerState
;
4054 assert( fDriverCallBusy
);
4055 assert( fDriverCallParamPtr
);
4056 assert( fDriverCallParamCount
);
4058 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4059 count
= fDriverCallParamCount
;
4061 powerFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
4062 powerState
= fHeadNotePowerState
;
4064 for (IOItemCount i
= 0; i
< count
; i
++)
4066 informee
= (IOPMinformee
*) param
->Target
;
4067 driver
= informee
->whatObject
;
4069 if (assertPMDriverCall(&callEntry
, 0, informee
))
4071 if (fDriverCallReason
== kDriverCallInformPreChange
)
4073 OUR_PMLogFuncStart(kPMLogInformDriverPreChange
, (uintptr_t) this, powerState
);
4074 start_spindump_timer("WillChange");
4075 clock_get_uptime(&informee
->startTime
);
4076 result
= driver
->powerStateWillChangeTo(powerFlags
, powerState
, this);
4077 clock_get_uptime(&end
);
4078 stop_spindump_timer();
4079 OUR_PMLogFuncEnd(kPMLogInformDriverPreChange
, (uintptr_t) this, result
);
4083 OUR_PMLogFuncStart(kPMLogInformDriverPostChange
, (uintptr_t) this, powerState
);
4084 start_spindump_timer("DidChange");
4085 clock_get_uptime(&informee
->startTime
);
4086 result
= driver
->powerStateDidChangeTo(powerFlags
, powerState
, this);
4087 clock_get_uptime(&end
);
4088 stop_spindump_timer();
4089 OUR_PMLogFuncEnd(kPMLogInformDriverPostChange
, (uintptr_t) this, result
);
4092 deassertPMDriverCall(&callEntry
);
4095 if ((result
== IOPMAckImplied
) || (result
< 0))
4099 SUB_ABSOLUTETIME(&end
, &informee
->startTime
);
4100 absolutetime_to_nanoseconds(end
, &nsec
);
4101 if (nsec
> LOG_SETPOWER_TIMES
) {
4102 getPMRootDomain()->pmStatsRecordApplicationResponse(
4103 gIOPMStatsDriverPSChangeSlow
, driver
->getName(),
4104 fDriverCallReason
, NS_TO_MS(nsec
), driver
->getRegistryEntryID(),
4111 result
= kIOPMAckImplied
;
4113 param
->Result
= result
;
4118 //*********************************************************************************
4119 // [private] notifyChild
4121 // Notify a power domain child of an upcoming power change.
4122 // If the object acknowledges the current change, we return TRUE.
4123 //*********************************************************************************
4125 bool IOService::notifyChild( IOPowerConnection
* theNub
)
4127 IOReturn ret
= IOPMAckImplied
;
4128 unsigned long childPower
;
4129 IOService
* theChild
;
4130 IOPMRequest
* childRequest
;
4131 IOPMPowerChangeFlags requestArg2
;
4134 PM_ASSERT_IN_GATE();
4135 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
4141 // Unless the child handles the notification immediately and returns
4142 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
4143 fHeadNotePendingAcks
++;
4144 theNub
->setAwaitingAck(true);
4146 requestArg2
= fHeadNoteChangeFlags
;
4147 if (StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
))
4148 requestArg2
|= kIOPMDomainPowerDrop
;
4150 requestType
= fIsPreChange
?
4151 kIOPMRequestTypePowerDomainWillChange
:
4152 kIOPMRequestTypePowerDomainDidChange
;
4154 childRequest
= acquirePMRequest( theChild
, requestType
);
4158 childRequest
->fArg0
= (void *) fHeadNotePowerArrayEntry
->outputPowerFlags
;
4159 childRequest
->fArg1
= (void *) theNub
;
4160 childRequest
->fArg2
= (void *)(uintptr_t) requestArg2
;
4161 theChild
->submitPMRequest( childRequest
);
4162 ret
= IOPMWillAckLater
;
4166 ret
= IOPMAckImplied
;
4167 fHeadNotePendingAcks
--;
4168 theNub
->setAwaitingAck(false);
4169 childPower
= theChild
->currentPowerConsumption();
4170 if ( childPower
== kIOPMUnknown
)
4172 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
4174 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
4175 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
4179 theChild
->release();
4180 return (IOPMAckImplied
== ret
);
4183 //*********************************************************************************
4184 // [private] notifyControllingDriver
4185 //*********************************************************************************
4187 bool IOService::notifyControllingDriver( void )
4189 DriverCallParam
* param
;
4191 PM_ASSERT_IN_GATE();
4192 assert( fDriverCallParamCount
== 0 );
4193 assert( fControllingDriver
);
4195 if (fInitialSetPowerState
)
4197 fInitialSetPowerState
= false;
4198 fHeadNoteChangeFlags
|= kIOPMInitialPowerChange
;
4200 // Driver specified flag to skip the inital setPowerState()
4201 if (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
)
4207 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4210 param
= IONew(DriverCallParam
, 1);
4212 return false; // no memory
4214 fDriverCallParamPtr
= (void *) param
;
4215 fDriverCallParamSlots
= 1;
4218 param
->Target
= fControllingDriver
;
4219 fDriverCallParamCount
= 1;
4222 // Block state machine and wait for callout completion.
4223 assert(!fDriverCallBusy
);
4224 fDriverCallBusy
= true;
4225 thread_call_enter( fDriverCallEntry
);
4230 //*********************************************************************************
4231 // [private] notifyControllingDriverDone
4232 //*********************************************************************************
4234 void IOService::notifyControllingDriverDone( void )
4236 DriverCallParam
* param
;
4239 PM_ASSERT_IN_GATE();
4240 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4242 assert( fDriverCallBusy
== false );
4243 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
4245 if (param
&& fDriverCallParamCount
)
4247 assert(fDriverCallParamCount
== 1);
4249 // the return value from setPowerState()
4250 result
= param
->Result
;
4252 if ((result
== IOPMAckImplied
) || (result
< 0))
4256 else if (fDriverTimer
)
4258 assert(fDriverTimer
== -1);
4260 // Driver has not acked, and has returned a positive result.
4261 // Enforce a minimum permissible timeout value.
4262 // Make the min value large enough so timeout is less likely
4263 // to occur if a driver misinterpreted that the return value
4264 // should be in microsecond units. And make it large enough
4265 // to be noticeable if a driver neglects to ack.
4267 if (result
< kMinAckTimeoutTicks
)
4268 result
= kMinAckTimeoutTicks
;
4270 fDriverTimer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
4272 // else, child has already acked and driver_timer reset to 0.
4274 fDriverCallParamCount
= 0;
4278 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
4283 MS_POP(); // pushed by OurChangeSetPowerState()
4284 fIsPreChange
= false;
4287 //*********************************************************************************
4288 // [private] all_done
4290 // A power change is done.
4291 //*********************************************************************************
4293 void IOService::all_done( void )
4295 IOPMPowerStateIndex prevPowerState
;
4296 const IOPMPSEntry
* powerStatePtr
;
4297 IOPMDriverCallEntry callEntry
;
4298 uint32_t prevMachineState
= fMachineState
;
4299 bool actionCalled
= false;
4302 fMachineState
= kIOPM_Finished
;
4304 if ((fHeadNoteChangeFlags
& kIOPMSynchronize
) &&
4305 ((prevMachineState
== kIOPM_Finished
) ||
4306 (prevMachineState
== kIOPM_SyncFinish
)))
4308 // Sync operation and no power change occurred.
4309 // Do not inform driver and clients about this request completion,
4310 // except for the originator (root domain).
4312 PM_ACTION_2(actionPowerChangeDone
,
4313 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4315 if (getPMRequestType() == kIOPMRequestTypeSynchronizePowerTree
)
4317 powerChangeDone(fCurrentPowerState
);
4319 else if (fAdvisoryTickleUsed
)
4321 // Not root domain and advisory tickle target.
4322 // Re-adjust power after power tree sync at the 'did' pass
4323 // to recompute desire and adjust power state between dark
4324 // and full wake transitions. Root domain is responsible
4325 // for calling setAdvisoryTickleEnable() before starting
4326 // the kIOPMSynchronize power change.
4328 if (!fAdjustPowerScheduled
&&
4329 (fHeadNoteChangeFlags
& kIOPMDomainDidChange
))
4331 IOPMRequest
* request
;
4332 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
4335 submitPMRequest( request
);
4336 fAdjustPowerScheduled
= true;
4345 if (fHeadNoteChangeFlags
& kIOPMSelfInitiated
)
4347 // power state changed
4348 if ((fHeadNoteChangeFlags
& kIOPMNotDone
) == 0)
4350 trackSystemSleepPreventers(
4351 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4353 // we changed, tell our parent
4354 requestDomainPower(fHeadNotePowerState
);
4356 // yes, did power raise?
4357 if ( StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
) )
4359 // yes, inform clients and apps
4360 tellChangeUp (fHeadNotePowerState
);
4362 prevPowerState
= fCurrentPowerState
;
4364 fCurrentPowerState
= fHeadNotePowerState
;
4367 ts
= mach_absolute_time();
4368 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
4372 fPMVars
->myCurrentState
= fCurrentPowerState
;
4374 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4375 PM_ACTION_2(actionPowerChangeDone
,
4376 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4377 actionCalled
= true;
4379 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4380 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4381 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4382 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4384 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
)
4386 // Bump tickle generation count once the entire tree is down
4387 gIOPMTickleGeneration
++;
4390 // inform subclass policy-maker
4391 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4392 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
))
4394 powerChangeDone(prevPowerState
);
4395 deassertPMDriverCall(&callEntry
);
4398 else if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)
4400 // changePowerStateWithOverrideTo() was cancelled
4401 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
4405 // parent-initiated power change
4406 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
4408 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
)
4409 ParentChangeRootChangeDown();
4411 // power state changed
4412 if ((fHeadNoteChangeFlags
& kIOPMNotDone
) == 0)
4414 trackSystemSleepPreventers(
4415 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4418 if ( StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
) )
4420 // yes, inform clients and apps
4421 tellChangeUp (fHeadNotePowerState
);
4424 prevPowerState
= fCurrentPowerState
;
4425 fCurrentPowerState
= fHeadNotePowerState
;
4428 ts
= mach_absolute_time();
4429 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
4433 fPMVars
->myCurrentState
= fCurrentPowerState
;
4436 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4437 PM_ACTION_2(actionPowerChangeDone
,
4438 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4439 actionCalled
= true;
4441 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4442 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4443 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4444 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4446 // inform subclass policy-maker
4447 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4448 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
))
4450 powerChangeDone(prevPowerState
);
4451 deassertPMDriverCall(&callEntry
);
4456 // When power rises enough to satisfy the tickle's desire for more power,
4457 // the condition preventing idle-timer from dropping power is removed.
4459 if (StateOrder(fCurrentPowerState
) >= StateOrder(fIdleTimerMinPowerState
))
4461 fIdleTimerMinPowerState
= kPowerStateZero
;
4466 PM_ACTION_2(actionPowerChangeDone
,
4467 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4472 // MARK: Power Change Initiated by Driver
4474 //*********************************************************************************
4475 // [private] OurChangeStart
4477 // Begin the processing of a power change initiated by us.
4478 //*********************************************************************************
4480 void IOService::OurChangeStart( void )
4482 PM_ASSERT_IN_GATE();
4483 OUR_PMLog( kPMLogStartDeviceChange
, fHeadNotePowerState
, fCurrentPowerState
);
4485 // fMaxPowerState is our maximum possible power state based on the current
4486 // power state of our parents. If we are trying to raise power beyond the
4487 // maximum, send an async request for more power to all parents.
4489 if (!IS_PM_ROOT
&& (StateOrder(fMaxPowerState
) < StateOrder(fHeadNotePowerState
)))
4491 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4492 requestDomainPower(fHeadNotePowerState
);
4497 // Redundant power changes skips to the end of the state machine.
4499 if (!fInitialPowerChange
&& (fHeadNotePowerState
== fCurrentPowerState
))
4504 fInitialPowerChange
= false;
4506 // Change started, but may not complete...
4507 // Can be canceled (power drop) or deferred (power rise).
4509 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4511 // Two separate paths, depending if power is being raised or lowered.
4512 // Lowering power is subject to approval by clients of this service.
4516 fDoNotPowerDown
= false;
4518 // Ask for persmission to drop power state
4519 fMachineState
= kIOPM_OurChangeTellClientsPowerDown
;
4520 fOutOfBandParameter
= kNotifyApps
;
4521 askChangeDown(fHeadNotePowerState
);
4525 // This service is raising power and parents are able to support the
4526 // new power state. However a parent may have already committed to
4527 // drop power, which might force this object to temporarily drop power.
4528 // This results in "oscillations" before the state machines converge
4529 // to a steady state.
4531 // To prevent this, a child must make a power reservation against all
4532 // parents before raising power. If the reservation fails, indicating
4533 // that the child will be unable to sustain the higher power state,
4534 // then the child will signal the parent to adjust power, and the child
4535 // will defer its power change.
4539 // Reserve parent power necessary to achieve fHeadNotePowerState.
4540 ret
= requestDomainPower( fHeadNotePowerState
, kReserveDomainPower
);
4541 if (ret
!= kIOReturnSuccess
)
4543 // Reservation failed, defer power rise.
4544 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4549 OurChangeTellCapabilityWillChange();
4553 //*********************************************************************************
4554 // [private] requestDomainPowerApplier
4556 // Call requestPowerDomainState() on all power parents.
4557 //*********************************************************************************
4559 struct IOPMRequestDomainPowerContext
{
4560 IOService
* child
; // the requesting child
4561 IOPMPowerFlags requestPowerFlags
; // power flags requested by child
4565 requestDomainPowerApplier(
4566 IORegistryEntry
* entry
,
4569 IOPowerConnection
* connection
;
4571 IOPMRequestDomainPowerContext
* context
;
4573 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)) == 0)
4575 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
4580 context
= (IOPMRequestDomainPowerContext
*) inContext
;
4582 if (connection
->parentKnowsState() && connection
->getReadyFlag())
4584 parent
->requestPowerDomainState(
4585 context
->requestPowerFlags
,
4593 //*********************************************************************************
4594 // [private] requestDomainPower
4596 // Called by a power child to broadcast its desired power state to all parents.
4597 // If the child self-initiates a power change, it must call this function to
4598 // allow its parents to adjust power state.
4599 //*********************************************************************************
4601 IOReturn
IOService::requestDomainPower(
4602 IOPMPowerStateIndex ourPowerState
,
4603 IOOptionBits options
)
4605 IOPMPowerFlags requestPowerFlags
;
4606 IOPMPowerStateIndex maxPowerState
;
4607 IOPMRequestDomainPowerContext context
;
4609 PM_ASSERT_IN_GATE();
4610 assert(ourPowerState
< fNumberOfPowerStates
);
4611 if (ourPowerState
>= fNumberOfPowerStates
)
4612 return kIOReturnBadArgument
;
4614 return kIOReturnSuccess
;
4616 // Fetch our input power flags for the requested power state.
4617 // Parent request is stated in terms of required power flags.
4619 requestPowerFlags
= fPowerStates
[ourPowerState
].inputPowerFlags
;
4621 // Disregard the "previous request" for power reservation.
4623 if (((options
& kReserveDomainPower
) == 0) &&
4624 (fPreviousRequestPowerFlags
== requestPowerFlags
))
4626 // skip if domain already knows our requirements
4629 fPreviousRequestPowerFlags
= requestPowerFlags
;
4631 // The results will be collected by fHeadNoteDomainTargetFlags
4632 context
.child
= this;
4633 context
.requestPowerFlags
= requestPowerFlags
;
4634 fHeadNoteDomainTargetFlags
= 0;
4635 applyToParents(requestDomainPowerApplier
, &context
, gIOPowerPlane
);
4637 if (options
& kReserveDomainPower
)
4639 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
4640 fHeadNoteDomainTargetFlags
);
4642 if (StateOrder(maxPowerState
) < StateOrder(ourPowerState
))
4644 PM_LOG1("%s: power desired %u:0x%x got %u:0x%x\n",
4646 (uint32_t) ourPowerState
, (uint32_t) requestPowerFlags
,
4647 (uint32_t) maxPowerState
, (uint32_t) fHeadNoteDomainTargetFlags
);
4648 return kIOReturnNoPower
;
4653 return kIOReturnSuccess
;
4656 //*********************************************************************************
4657 // [private] OurSyncStart
4658 //*********************************************************************************
4660 void IOService::OurSyncStart( void )
4662 PM_ASSERT_IN_GATE();
4664 if (fInitialPowerChange
)
4667 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4669 if (fHeadNoteChangeFlags
& kIOPMNotDone
)
4675 if (fHeadNoteChangeFlags
& kIOPMSyncTellPowerDown
)
4677 fDoNotPowerDown
= false;
4679 // Ask for permission to drop power state
4680 fMachineState
= kIOPM_SyncTellClientsPowerDown
;
4681 fOutOfBandParameter
= kNotifyApps
;
4682 askChangeDown(fHeadNotePowerState
);
4686 // Only inform capability app and clients.
4687 tellSystemCapabilityChange( kIOPM_SyncNotifyWillChange
);
4691 //*********************************************************************************
4692 // [private] OurChangeTellClientsPowerDown
4694 // All applications and kernel clients have acknowledged our permission to drop
4695 // power. Here we notify them that we will lower the power and wait for acks.
4696 //*********************************************************************************
4698 void IOService::OurChangeTellClientsPowerDown( void )
4701 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4704 fMachineState
= kIOPM_OurChangeTellUserPMPolicyPowerDown
;
4706 tellChangeDown1(fHeadNotePowerState
);
4709 //*********************************************************************************
4710 // [private] OurChangeTellUserPMPolicyPowerDown
4712 // All applications and kernel clients have acknowledged our permission to drop
4713 // power. Here we notify power management policy in user-space and wait for acks
4714 // one last time before we lower power
4715 //*********************************************************************************
4716 void IOService::OurChangeTellUserPMPolicyPowerDown ( void )
4718 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4719 fOutOfBandParameter
= kNotifyApps
;
4721 tellClientsWithResponse(kIOPMMessageLastCallBeforeSleep
);
4724 //*********************************************************************************
4725 // [private] OurChangeTellPriorityClientsPowerDown
4727 // All applications and kernel clients have acknowledged our intention to drop
4728 // power. Here we notify "priority" clients that we are lowering power.
4729 //*********************************************************************************
4731 void IOService::OurChangeTellPriorityClientsPowerDown( void )
4733 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
4734 tellChangeDown2(fHeadNotePowerState
);
4737 //*********************************************************************************
4738 // [private] OurChangeTellCapabilityWillChange
4740 // Extra stage for root domain to notify apps and drivers about the
4741 // system capability change when raising power state.
4742 //*********************************************************************************
4744 void IOService::OurChangeTellCapabilityWillChange( void )
4746 if (!IS_ROOT_DOMAIN
)
4747 return OurChangeNotifyInterestedDriversWillChange();
4749 tellSystemCapabilityChange( kIOPM_OurChangeNotifyInterestedDriversWillChange
);
4752 //*********************************************************************************
4753 // [private] OurChangeNotifyInterestedDriversWillChange
4755 // All applications and kernel clients have acknowledged our power state change.
4756 // Here we notify interested drivers pre-change.
4757 //*********************************************************************************
4759 void IOService::OurChangeNotifyInterestedDriversWillChange( void )
4761 IOPMrootDomain
* rootDomain
;
4762 if ((rootDomain
= getPMRootDomain()) == this)
4766 rootDomain
->tracePoint( kIOPMTracePointSleepWillChangeInterests
);
4769 rootDomain
->tracePoint( kIOPMTracePointWakeWillChangeInterests
);
4772 notifyAll( kIOPM_OurChangeSetPowerState
);
4775 //*********************************************************************************
4776 // [private] OurChangeSetPowerState
4778 // Instruct our controlling driver to program the hardware for the power state
4779 // change. Wait for async completions.
4780 //*********************************************************************************
4782 void IOService::OurChangeSetPowerState( void )
4784 MS_PUSH( kIOPM_OurChangeWaitForPowerSettle
);
4785 fMachineState
= kIOPM_DriverThreadCallDone
;
4786 fDriverCallReason
= kDriverCallSetPowerState
;
4788 if (notifyControllingDriver() == false)
4789 notifyControllingDriverDone();
4792 //*********************************************************************************
4793 // [private] OurChangeWaitForPowerSettle
4795 // Our controlling driver has completed the power state change we initiated.
4796 // Wait for the driver specified settle time to expire.
4797 //*********************************************************************************
4799 void IOService::OurChangeWaitForPowerSettle( void )
4801 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
4805 //*********************************************************************************
4806 // [private] OurChangeNotifyInterestedDriversDidChange
4808 // Power has settled on a power change we initiated. Here we notify
4809 // all our interested drivers post-change.
4810 //*********************************************************************************
4812 void IOService::OurChangeNotifyInterestedDriversDidChange( void )
4814 IOPMrootDomain
* rootDomain
;
4815 if ((rootDomain
= getPMRootDomain()) == this)
4817 rootDomain
->tracePoint( IS_POWER_DROP
?
4818 kIOPMTracePointSleepDidChangeInterests
:
4819 kIOPMTracePointWakeDidChangeInterests
);
4822 notifyAll( kIOPM_OurChangeTellCapabilityDidChange
);
4825 //*********************************************************************************
4826 // [private] OurChangeTellCapabilityDidChange
4828 // For root domain to notify capability power-change.
4829 //*********************************************************************************
4831 void IOService::OurChangeTellCapabilityDidChange( void )
4833 if (!IS_ROOT_DOMAIN
)
4834 return OurChangeFinish();
4836 getPMRootDomain()->tracePoint( IS_POWER_DROP
?
4837 kIOPMTracePointSleepCapabilityClients
:
4838 kIOPMTracePointWakeCapabilityClients
);
4840 tellSystemCapabilityChange( kIOPM_OurChangeFinish
);
4843 //*********************************************************************************
4844 // [private] OurChangeFinish
4846 // Done with this self-induced power state change.
4847 //*********************************************************************************
4849 void IOService::OurChangeFinish( void )
4855 // MARK: Power Change Initiated by Parent
4857 //*********************************************************************************
4858 // [private] ParentChangeStart
4860 // Here we begin the processing of a power change initiated by our parent.
4861 //*********************************************************************************
4863 IOReturn
IOService::ParentChangeStart( void )
4865 PM_ASSERT_IN_GATE();
4866 OUR_PMLog( kPMLogStartParentChange
, fHeadNotePowerState
, fCurrentPowerState
);
4868 // Root power domain has transitioned to its max power state
4869 if ((fHeadNoteChangeFlags
& (kIOPMDomainDidChange
| kIOPMRootChangeUp
)) ==
4870 (kIOPMDomainDidChange
| kIOPMRootChangeUp
))
4872 // Restart the idle timer stopped by ParentChangeRootChangeDown()
4873 if (fIdleTimerPeriod
&& fIdleTimerStopped
)
4879 // Power domain is forcing us to lower power
4880 if ( StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
) )
4882 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4884 // Tell apps and kernel clients
4885 fInitialPowerChange
= false;
4886 fMachineState
= kIOPM_ParentChangeTellPriorityClientsPowerDown
;
4887 tellChangeDown1(fHeadNotePowerState
);
4888 return IOPMWillAckLater
;
4891 // Power domain is allowing us to raise power up to fHeadNotePowerState
4892 if ( StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
) )
4894 if ( StateOrder(fDesiredPowerState
) > StateOrder(fCurrentPowerState
) )
4896 if ( StateOrder(fDesiredPowerState
) < StateOrder(fHeadNotePowerState
) )
4898 // We power up, but not all the way
4899 fHeadNotePowerState
= fDesiredPowerState
;
4900 fHeadNotePowerArrayEntry
= &fPowerStates
[fDesiredPowerState
];
4901 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4904 // We don't need to change
4905 fHeadNotePowerState
= fCurrentPowerState
;
4906 fHeadNotePowerArrayEntry
= &fPowerStates
[fCurrentPowerState
];
4907 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4911 if ( fHeadNoteChangeFlags
& kIOPMDomainDidChange
)
4913 if ( StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
) )
4915 PM_ACTION_2(actionPowerChangeStart
,
4916 fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4918 // Parent did change up - start our change up
4919 fInitialPowerChange
= false;
4920 ParentChangeTellCapabilityWillChange();
4921 return IOPMWillAckLater
;
4923 else if (fHeadNoteChangeFlags
& kIOPMRootBroadcastFlags
)
4925 // No need to change power state, but broadcast change
4927 fMachineState
= kIOPM_SyncNotifyDidChange
;
4928 fDriverCallReason
= kDriverCallInformPreChange
;
4929 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4931 return IOPMWillAckLater
;
4935 // No power state change necessary
4936 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4939 return IOPMAckImplied
;
4942 //******************************************************************************
4943 // [private] ParentChangeRootChangeDown
4945 // Root domain has finished the transition to the system sleep state. And all
4946 // drivers in the power plane should have powered down. Cancel the idle timer,
4947 // and also reset the device desire for those drivers that don't want power
4948 // automatically restored on wake.
4949 //******************************************************************************
4951 void IOService::ParentChangeRootChangeDown( void )
4953 // Always stop the idle timer before root power down
4954 if (fIdleTimerPeriod
&& !fIdleTimerStopped
)
4956 fIdleTimerStopped
= true;
4957 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
))
4961 if (fResetPowerStateOnWake
)
4963 // Reset device desire down to the lowest power state.
4964 // Advisory tickle desire is intentionally untouched since
4965 // it has no effect until system is promoted to full wake.
4967 if (fDeviceDesire
!= kPowerStateZero
)
4969 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
4970 computeDesiredState(kPowerStateZero
, true);
4971 requestDomainPower( fDesiredPowerState
);
4972 PM_LOG1("%s: tickle desire removed\n", fName
);
4975 // Invalidate tickle cache so the next tickle will issue a request
4976 IOLockLock(fActivityLock
);
4977 fDeviceWasActive
= false;
4978 fActivityTicklePowerState
= kInvalidTicklePowerState
;
4979 IOLockUnlock(fActivityLock
);
4981 fIdleTimerMinPowerState
= kPowerStateZero
;
4983 else if (fAdvisoryTickleUsed
)
4985 // Less aggressive mechanism to accelerate idle timer expiration
4986 // before system sleep. May not always allow the driver to wake
4987 // up from system sleep in the min power state.
4991 bool dropTickleDesire
= false;
4993 if (fIdleTimerPeriod
&& !fIdleTimerIgnored
&&
4994 (fIdleTimerMinPowerState
== kPowerStateZero
) &&
4995 (fDeviceDesire
!= kPowerStateZero
))
4997 IOLockLock(fActivityLock
);
4999 if (!fDeviceWasActive
)
5001 // No tickles since the last idle timer expiration.
5002 // Safe to drop the device desire to zero.
5003 dropTickleDesire
= true;
5007 // Was tickled since the last idle timer expiration,
5008 // but not in the last minute.
5009 clock_get_uptime(&now
);
5010 SUB_ABSOLUTETIME(&now
, &fDeviceActiveTimestamp
);
5011 absolutetime_to_nanoseconds(now
, &nsec
);
5012 if (nsec
>= kNoTickleCancelWindow
)
5014 dropTickleDesire
= true;
5018 if (dropTickleDesire
)
5020 // Force the next tickle to raise power state
5021 fDeviceWasActive
= false;
5022 fActivityTicklePowerState
= kInvalidTicklePowerState
;
5025 IOLockUnlock(fActivityLock
);
5028 if (dropTickleDesire
)
5030 // Advisory tickle desire is intentionally untouched since
5031 // it has no effect until system is promoted to full wake.
5033 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
5034 computeDesiredState(kPowerStateZero
, true);
5035 PM_LOG1("%s: tickle desire dropped\n", fName
);
5040 //*********************************************************************************
5041 // [private] ParentChangeTellPriorityClientsPowerDown
5043 // All applications and kernel clients have acknowledged our intention to drop
5044 // power. Here we notify "priority" clients that we are lowering power.
5045 //*********************************************************************************
5047 void IOService::ParentChangeTellPriorityClientsPowerDown( void )
5049 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversWillChange
;
5050 tellChangeDown2(fHeadNotePowerState
);
5053 //*********************************************************************************
5054 // [private] ParentChangeTellCapabilityWillChange
5056 // All (legacy) applications and kernel clients have acknowledged, extra stage for
5057 // root domain to notify apps and drivers about the system capability change.
5058 //*********************************************************************************
5060 void IOService::ParentChangeTellCapabilityWillChange( void )
5062 if (!IS_ROOT_DOMAIN
)
5063 return ParentChangeNotifyInterestedDriversWillChange();
5065 tellSystemCapabilityChange( kIOPM_ParentChangeNotifyInterestedDriversWillChange
);
5068 //*********************************************************************************
5069 // [private] ParentChangeNotifyInterestedDriversWillChange
5071 // All applications and kernel clients have acknowledged our power state change.
5072 // Here we notify interested drivers pre-change.
5073 //*********************************************************************************
5075 void IOService::ParentChangeNotifyInterestedDriversWillChange( void )
5077 notifyAll( kIOPM_ParentChangeSetPowerState
);
5080 //*********************************************************************************
5081 // [private] ParentChangeSetPowerState
5083 // Instruct our controlling driver to program the hardware for the power state
5084 // change. Wait for async completions.
5085 //*********************************************************************************
5087 void IOService::ParentChangeSetPowerState( void )
5089 MS_PUSH( kIOPM_ParentChangeWaitForPowerSettle
);
5090 fMachineState
= kIOPM_DriverThreadCallDone
;
5091 fDriverCallReason
= kDriverCallSetPowerState
;
5093 if (notifyControllingDriver() == false)
5094 notifyControllingDriverDone();
5097 //*********************************************************************************
5098 // [private] ParentChangeWaitForPowerSettle
5100 // Our controlling driver has completed the power state change initiated by our
5101 // parent. Wait for the driver specified settle time to expire.
5102 //*********************************************************************************
5104 void IOService::ParentChangeWaitForPowerSettle( void )
5106 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversDidChange
;
5110 //*********************************************************************************
5111 // [private] ParentChangeNotifyInterestedDriversDidChange
5113 // Power has settled on a power change initiated by our parent. Here we notify
5114 // all our interested drivers post-change.
5115 //*********************************************************************************
5117 void IOService::ParentChangeNotifyInterestedDriversDidChange( void )
5119 notifyAll( kIOPM_ParentChangeTellCapabilityDidChange
);
5122 //*********************************************************************************
5123 // [private] ParentChangeTellCapabilityDidChange
5125 // For root domain to notify capability power-change.
5126 //*********************************************************************************
5128 void IOService::ParentChangeTellCapabilityDidChange( void )
5130 if (!IS_ROOT_DOMAIN
)
5131 return ParentChangeAcknowledgePowerChange();
5133 tellSystemCapabilityChange( kIOPM_ParentChangeAcknowledgePowerChange
);
5136 //*********************************************************************************
5137 // [private] ParentAcknowledgePowerChange
5139 // Acknowledge our power parent that our power change is done.
5140 //*********************************************************************************
5142 void IOService::ParentChangeAcknowledgePowerChange( void )
5144 IORegistryEntry
* nub
;
5147 nub
= fHeadNoteParentConnection
;
5150 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
5153 parent
->acknowledgePowerChange((IOService
*)nub
);
5160 // MARK: Ack and Settle timers
5162 //*********************************************************************************
5163 // [private] settleTimerExpired
5165 // Power has settled after our last change. Notify interested parties that
5166 // there is a new power state.
5167 //*********************************************************************************
5169 void IOService::settleTimerExpired( void )
5172 gIOPMWorkQueue
->signalWorkAvailable();
5175 //*********************************************************************************
5176 // settle_timer_expired
5178 // Holds a retain while the settle timer callout is in flight.
5179 //*********************************************************************************
5182 settle_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5184 IOService
* me
= (IOService
*) arg0
;
5186 if (gIOPMWorkLoop
&& gIOPMWorkQueue
)
5188 gIOPMWorkLoop
->runAction(
5189 OSMemberFunctionCast(IOWorkLoop::Action
, me
, &IOService::settleTimerExpired
),
5195 //*********************************************************************************
5196 // [private] startSettleTimer
5198 // Calculate a power-settling delay in microseconds and start a timer.
5199 //*********************************************************************************
5201 void IOService::startSettleTimer( void )
5204 // This function is broken and serves no useful purpose since it never
5205 // updates fSettleTimeUS to a non-zero value to stall the state machine,
5206 // yet it starts a delay timer. It appears no driver relies on a delay
5207 // from settleUpTime and settleDownTime in the power state table.
5209 AbsoluteTime deadline
;
5210 IOPMPowerStateIndex stateIndex
;
5211 IOPMPowerStateIndex currentOrder
, newOrder
, i
;
5212 uint32_t settleTime
= 0;
5215 PM_ASSERT_IN_GATE();
5217 currentOrder
= StateOrder(fCurrentPowerState
);
5218 newOrder
= StateOrder(fHeadNotePowerState
);
5223 if ( newOrder
< currentOrder
)
5225 while ( i
> newOrder
)
5227 stateIndex
= fPowerStates
[i
].stateOrderToIndex
;
5228 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleDownTime
;
5234 if ( newOrder
> currentOrder
)
5236 while ( i
< newOrder
)
5238 stateIndex
= fPowerStates
[i
+1].stateOrderToIndex
;
5239 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleUpTime
;
5247 clock_interval_to_deadline(settleTime
, kMicrosecondScale
, &deadline
);
5248 pending
= thread_call_enter_delayed(fSettleTimer
, deadline
);
5249 if (pending
) release();
5254 //*********************************************************************************
5255 // [private] ackTimerTick
5257 // The acknowledgement timeout periodic timer has ticked.
5258 // If we are awaiting acks for a power change notification,
5259 // we decrement the timer word of each interested driver which hasn't acked.
5260 // If a timer word becomes zero, we pretend the driver aknowledged.
5261 // If we are waiting for the controlling driver to change the power
5262 // state of the hardware, we decrement its timer word, and if it becomes
5263 // zero, we pretend the driver acknowledged.
5265 // Returns true if the timer tick made it possible to advance to the next
5266 // machine state, false otherwise.
5267 //*********************************************************************************
5270 void IOService::ack_timer_ticked ( void )
5274 #endif /* !__LP64__ */
5276 bool IOService::ackTimerTick( void )
5278 IOPMinformee
* nextObject
;
5281 PM_ASSERT_IN_GATE();
5282 switch (fMachineState
) {
5283 case kIOPM_OurChangeWaitForPowerSettle
:
5284 case kIOPM_ParentChangeWaitForPowerSettle
:
5285 // are we waiting for controlling driver to acknowledge?
5286 if ( fDriverTimer
> 0 )
5288 // yes, decrement timer tick
5290 if ( fDriverTimer
== 0 )
5292 // controlling driver is tardy
5293 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
5294 OUR_PMLog(kPMLogCtrlDriverTardy
, 0, 0);
5295 setProperty(kIOPMTardyAckSPSKey
, kOSBooleanTrue
);
5296 PM_ERROR("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms\n",
5297 fName
, OBFUSCATE(this), fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5299 #if DEBUG && CONFIG_EMBEDDED
5300 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
5301 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5303 if (gIOKitDebug
& kIOLogDebugPower
)
5305 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
5306 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5310 // Unblock state machine and pretend driver has acked.
5315 // still waiting, set timer again
5321 case kIOPM_NotifyChildrenStart
:
5322 // are we waiting for interested parties to acknowledge?
5323 if ( fHeadNotePendingAcks
!= 0 )
5325 // yes, go through the list of interested drivers
5326 nextObject
= fInterestedDrivers
->firstInList();
5327 // and check each one
5328 while ( nextObject
!= NULL
)
5330 if ( nextObject
->timer
> 0 )
5332 nextObject
->timer
--;
5333 // this one should have acked by now
5334 if ( nextObject
->timer
== 0 )
5336 uint64_t nsec
= computeTimeDeltaNS(&nextObject
->startTime
);
5337 OUR_PMLog(kPMLogIntDriverTardy
, 0, 0);
5338 nextObject
->whatObject
->setProperty(kIOPMTardyAckPSCKey
, kOSBooleanTrue
);
5339 PM_ERROR("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) timed out after %d ms\n",
5340 nextObject
->whatObject
->getName(),
5341 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
5342 OBFUSCATE(nextObject
->whatObject
), fName
, fCurrentPowerState
, fHeadNotePowerState
,
5345 // Pretend driver has acked.
5346 fHeadNotePendingAcks
--;
5349 nextObject
= fInterestedDrivers
->nextInList(nextObject
);
5352 // is that the last?
5353 if ( fHeadNotePendingAcks
== 0 )
5355 // yes, we can continue
5358 // no, set timer again
5364 // TODO: aggreggate this
5365 case kIOPM_OurChangeTellClientsPowerDown
:
5366 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
5367 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
5368 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
5369 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
5370 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
5371 case kIOPM_SyncTellClientsPowerDown
:
5372 case kIOPM_SyncTellPriorityClientsPowerDown
:
5373 case kIOPM_SyncNotifyWillChange
:
5374 case kIOPM_TellCapabilityChangeDone
:
5375 // apps didn't respond in time
5376 cleanClientResponses(true);
5377 OUR_PMLog(kPMLogClientTardy
, 0, 1);
5378 // tardy equates to approval
5383 PM_LOG1("%s: unexpected ack timer tick (state = %d)\n",
5384 getName(), fMachineState
);
5390 //*********************************************************************************
5391 // [private] start_watchdog_timer
5392 //*********************************************************************************
5393 void IOService::start_watchdog_timer( void )
5395 AbsoluteTime deadline
;
5397 static int timeout
= -1;
5399 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
))
5402 if (thread_call_isactive(fWatchdogTimer
)) return;
5403 if (timeout
== -1) {
5404 PE_parse_boot_argn("swd_timeout", &timeout
, sizeof(timeout
));
5407 timeout
= WATCHDOG_TIMER_PERIOD
;
5410 clock_interval_to_deadline(timeout
, kSecondScale
, &deadline
);
5413 pending
= thread_call_enter_delayed(fWatchdogTimer
, deadline
);
5414 if (pending
) release();
5418 //*********************************************************************************
5419 // [private] stop_watchdog_timer
5420 // Returns true if watchdog was enabled and stopped now
5421 //*********************************************************************************
5423 bool IOService::stop_watchdog_timer( void )
5427 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
))
5430 pending
= thread_call_cancel(fWatchdogTimer
);
5431 if (pending
) release();
5436 //*********************************************************************************
5437 // reset_watchdog_timer
5438 //*********************************************************************************
5440 void IOService::reset_watchdog_timer( void )
5442 if (stop_watchdog_timer())
5443 start_watchdog_timer();
5447 //*********************************************************************************
5448 // [static] watchdog_timer_expired
5450 // Inside PM work loop's gate.
5451 //*********************************************************************************
5454 IOService::watchdog_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5456 IOService
* me
= (IOService
*) arg0
;
5459 gIOPMWatchDogThread
= current_thread();
5460 getPMRootDomain()->sleepWakeDebugTrig(true);
5461 gIOPMWatchDogThread
= 0;
5462 thread_call_free(me
->fWatchdogTimer
);
5463 me
->fWatchdogTimer
= 0;
5469 IOWorkLoop
* IOService::getIOPMWorkloop( void )
5471 return gIOPMWorkLoop
;
5476 //*********************************************************************************
5477 // [private] start_ack_timer
5478 //*********************************************************************************
5480 void IOService::start_ack_timer( void )
5482 start_ack_timer( ACK_TIMER_PERIOD
, kNanosecondScale
);
5485 void IOService::start_ack_timer ( UInt32 interval
, UInt32 scale
)
5487 AbsoluteTime deadline
;
5490 clock_interval_to_deadline(interval
, scale
, &deadline
);
5493 pending
= thread_call_enter_delayed(fAckTimer
, deadline
);
5494 if (pending
) release();
5496 // Stop watchdog if ack is delayed by more than a sec
5497 if (interval
* scale
> kSecondScale
) {
5498 stop_watchdog_timer();
5502 //*********************************************************************************
5503 // [private] stop_ack_timer
5504 //*********************************************************************************
5506 void IOService::stop_ack_timer( void )
5510 pending
= thread_call_cancel(fAckTimer
);
5511 if (pending
) release();
5513 start_watchdog_timer();
5516 //*********************************************************************************
5517 // [static] actionAckTimerExpired
5519 // Inside PM work loop's gate.
5520 //*********************************************************************************
5523 IOService::actionAckTimerExpired(
5525 void * arg0
, void * arg1
,
5526 void * arg2
, void * arg3
)
5528 IOService
* me
= (IOService
*) target
;
5531 // done will be true if the timer tick unblocks the machine state,
5532 // otherwise no need to signal the work loop.
5534 done
= me
->ackTimerTick();
5535 if (done
&& gIOPMWorkQueue
)
5537 gIOPMWorkQueue
->signalWorkAvailable();
5538 me
->start_watchdog_timer();
5541 return kIOReturnSuccess
;
5544 //*********************************************************************************
5545 // ack_timer_expired
5547 // Thread call function. Holds a retain while the callout is in flight.
5548 //*********************************************************************************
5551 IOService::ack_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5553 IOService
* me
= (IOService
*) arg0
;
5557 gIOPMWorkLoop
->runAction(&actionAckTimerExpired
, me
);
5562 //*********************************************************************************
5563 // [private] start_spindump_timer
5564 //*********************************************************************************
5566 void IOService::start_spindump_timer( const char * delay_type
)
5568 AbsoluteTime deadline
;
5571 if (!fSpinDumpTimer
|| !(kIOKextSpinDump
& gIOKitDebug
))
5574 if (gIOSpinDumpKextName
[0] == '\0' &&
5575 !(PE_parse_boot_argn("swd_kext_name", &gIOSpinDumpKextName
,
5576 sizeof(gIOSpinDumpKextName
))))
5581 if (strncmp(gIOSpinDumpKextName
, fName
, sizeof(gIOSpinDumpKextName
)) != 0)
5584 if (gIOSpinDumpDelayType
[0] == '\0' &&
5585 !(PE_parse_boot_argn("swd_delay_type", &gIOSpinDumpDelayType
,
5586 sizeof(gIOSpinDumpDelayType
))))
5588 strncpy(gIOSpinDumpDelayType
, "SetState", sizeof(gIOSpinDumpDelayType
));
5591 if (strncmp(delay_type
, gIOSpinDumpDelayType
, sizeof(gIOSpinDumpDelayType
)) != 0)
5594 if (gIOSpinDumpDelayDuration
== 0 &&
5595 !(PE_parse_boot_argn("swd_delay_duration", &gIOSpinDumpDelayDuration
,
5596 sizeof(gIOSpinDumpDelayDuration
))))
5598 gIOSpinDumpDelayDuration
= 300;
5601 clock_interval_to_deadline(gIOSpinDumpDelayDuration
, kMillisecondScale
, &deadline
);
5604 pending
= thread_call_enter_delayed(fSpinDumpTimer
, deadline
);
5605 if (pending
) release();
5608 //*********************************************************************************
5609 // [private] stop_spindump_timer
5610 //*********************************************************************************
5612 void IOService::stop_spindump_timer( void )
5616 if (!fSpinDumpTimer
|| !(kIOKextSpinDump
& gIOKitDebug
))
5619 pending
= thread_call_cancel(fSpinDumpTimer
);
5620 if (pending
) release();
5624 //*********************************************************************************
5625 // [static] actionSpinDumpTimerExpired
5627 // Inside PM work loop's gate.
5628 //*********************************************************************************
5631 IOService::actionSpinDumpTimerExpired(
5633 void * arg0
, void * arg1
,
5634 void * arg2
, void * arg3
)
5636 getPMRootDomain()->takeStackshot(false, false, true);
5638 return kIOReturnSuccess
;
5641 //*********************************************************************************
5642 // spindump_timer_expired
5644 // Thread call function. Holds a retain while the callout is in flight.
5645 //*********************************************************************************
5648 IOService::spindump_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5650 IOService
* me
= (IOService
*) arg0
;
5654 gIOPMWorkLoop
->runAction(&actionSpinDumpTimerExpired
, me
);
5660 // MARK: Client Messaging
5662 //*********************************************************************************
5663 // [private] tellSystemCapabilityChange
5664 //*********************************************************************************
5666 void IOService::tellSystemCapabilityChange( uint32_t nextMS
)
5669 fMachineState
= kIOPM_TellCapabilityChangeDone
;
5670 fOutOfBandMessage
= kIOMessageSystemCapabilityChange
;
5674 // Notify app first on pre-change.
5675 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
5679 // Notify kernel clients first on post-change.
5680 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
5683 tellClientsWithResponse( fOutOfBandMessage
);
5686 //*********************************************************************************
5687 // [public] askChangeDown
5689 // Ask registered applications and kernel clients if we can change to a lower
5692 // Subclass can override this to send a different message type. Parameter is
5693 // the destination state number.
5695 // Return true if we don't have to wait for acknowledgements
5696 //*********************************************************************************
5698 bool IOService::askChangeDown( unsigned long stateNum
)
5700 return tellClientsWithResponse( kIOMessageCanDevicePowerOff
);
5703 //*********************************************************************************
5704 // [private] tellChangeDown1
5706 // Notify registered applications and kernel clients that we are definitely
5709 // Return true if we don't have to wait for acknowledgements
5710 //*********************************************************************************
5712 bool IOService::tellChangeDown1( unsigned long stateNum
)
5714 fOutOfBandParameter
= kNotifyApps
;
5715 return tellChangeDown(stateNum
);
5718 //*********************************************************************************
5719 // [private] tellChangeDown2
5721 // Notify priority clients that we are definitely dropping power.
5723 // Return true if we don't have to wait for acknowledgements
5724 //*********************************************************************************
5726 bool IOService::tellChangeDown2( unsigned long stateNum
)
5728 fOutOfBandParameter
= kNotifyPriority
;
5729 return tellChangeDown(stateNum
);
5732 //*********************************************************************************
5733 // [public] tellChangeDown
5735 // Notify registered applications and kernel clients that we are definitely
5738 // Subclass can override this to send a different message type. Parameter is
5739 // the destination state number.
5741 // Return true if we don't have to wait for acknowledgements
5742 //*********************************************************************************
5744 bool IOService::tellChangeDown( unsigned long stateNum
)
5746 return tellClientsWithResponse( kIOMessageDeviceWillPowerOff
);
5749 //*********************************************************************************
5750 // cleanClientResponses
5752 //*********************************************************************************
5754 static void logAppTimeouts( OSObject
* object
, void * arg
)
5756 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5758 unsigned int clientIndex
;
5762 if (OSDynamicCast(_IOServiceInterestNotifier
, object
))
5764 // Discover the 'counter' value or index assigned to this client
5765 // when it was notified, by searching for the array index of the
5766 // client in an array holding the cached interested clients.
5768 clientIndex
= context
->notifyClients
->getNextIndexOfObject(object
, 0);
5770 if ((clientIndex
!= (unsigned int) -1) &&
5771 (flag
= context
->responseArray
->getObject(clientIndex
)) &&
5772 (flag
!= kOSBooleanTrue
))
5774 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
5778 pid
= clientID
->unsigned32BitValue();
5779 proc_name(pid
, name
, sizeof(name
));
5780 clientID
->release();
5783 PM_ERROR(context
->errorLog
, pid
, name
);
5785 // TODO: record message type if possible
5786 IOService::getPMRootDomain()->pmStatsRecordApplicationResponse(
5787 gIOPMStatsResponseTimedOut
,
5788 name
, 0, (30*1000), pid
, object
);
5794 void IOService::cleanClientResponses( bool logErrors
)
5796 if (logErrors
&& fResponseArray
)
5798 switch ( fOutOfBandParameter
) {
5800 case kNotifyCapabilityChangeApps
:
5801 if (fNotifyClientArray
)
5803 IOPMInterestContext context
;
5805 context
.responseArray
= fResponseArray
;
5806 context
.notifyClients
= fNotifyClientArray
;
5807 context
.serialNumber
= fSerialNumber
;
5808 context
.messageType
= kIOMessageCopyClientID
;
5809 context
.notifyType
= kNotifyApps
;
5810 context
.isPreChange
= fIsPreChange
;
5811 context
.enableTracing
= false;
5813 context
.maxTimeRequested
= 0;
5814 context
.stateNumber
= fHeadNotePowerState
;
5815 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5816 context
.changeFlags
= fHeadNoteChangeFlags
;
5817 context
.errorLog
= "PM notification timeout (pid %d, %s)\n";
5819 applyToInterested(gIOAppPowerStateInterest
, logAppTimeouts
, (void *) &context
);
5824 // kNotifyPriority, kNotifyCapabilityChangePriority
5825 // TODO: identify the priority client that has not acked
5826 PM_ERROR("PM priority notification timeout\n");
5827 if (gIOKitDebug
& kIOLogDebugPower
)
5829 panic("PM priority notification timeout");
5837 fResponseArray
->release();
5838 fResponseArray
= NULL
;
5840 if (fNotifyClientArray
)
5842 fNotifyClientArray
->release();
5843 fNotifyClientArray
= NULL
;
5847 //*********************************************************************************
5848 // [protected] tellClientsWithResponse
5850 // Notify registered applications and kernel clients that we are definitely
5853 // Return true if we don't have to wait for acknowledgements
5854 //*********************************************************************************
5856 bool IOService::tellClientsWithResponse( int messageType
)
5858 IOPMInterestContext context
;
5859 bool isRootDomain
= IS_ROOT_DOMAIN
;
5860 uint32_t maxTimeOut
= kMaxTimeRequested
;
5862 PM_ASSERT_IN_GATE();
5863 assert( fResponseArray
== NULL
);
5864 assert( fNotifyClientArray
== NULL
);
5866 if(messageType
== (int)kIOPMMessageLastCallBeforeSleep
)
5867 RD_LOG("tellClientsWithResponse( kIOPMMessageLastCallBeforeSleep, %d )\n",
5868 fOutOfBandParameter
);
5870 RD_LOG("tellClientsWithResponse( %s, %d )\n",
5871 getIOMessageString(messageType
), fOutOfBandParameter
);
5873 fResponseArray
= OSArray::withCapacity( 1 );
5874 if (!fResponseArray
)
5877 fResponseArray
->setCapacityIncrement(8);
5878 if (++fSerialNumber
== 0)
5881 context
.responseArray
= fResponseArray
;
5882 context
.notifyClients
= 0;
5883 context
.serialNumber
= fSerialNumber
;
5884 context
.messageType
= messageType
;
5885 context
.notifyType
= fOutOfBandParameter
;
5886 context
.isPreChange
= fIsPreChange
;
5887 context
.enableTracing
= false;
5889 context
.maxTimeRequested
= 0;
5890 context
.stateNumber
= fHeadNotePowerState
;
5891 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5892 context
.changeFlags
= fHeadNoteChangeFlags
;
5893 context
.messageFilter
= (isRootDomain
) ?
5894 OSMemberFunctionCast(
5897 &IOPMrootDomain::systemMessageFilter
) : 0;
5899 switch ( fOutOfBandParameter
) {
5901 applyToInterested( gIOAppPowerStateInterest
,
5902 pmTellAppWithResponse
, (void *) &context
);
5905 (fMachineState
!= kIOPM_OurChangeTellClientsPowerDown
) &&
5906 (fMachineState
!= kIOPM_SyncTellClientsPowerDown
) &&
5907 (context
.messageType
!= kIOPMMessageLastCallBeforeSleep
))
5909 // Notify capability app for tellChangeDown1()
5910 // but not for askChangeDown().
5911 context
.notifyType
= kNotifyCapabilityChangeApps
;
5912 context
.messageType
= kIOMessageSystemCapabilityChange
;
5913 applyToInterested( gIOAppPowerStateInterest
,
5914 pmTellCapabilityAppWithResponse
, (void *) &context
);
5915 context
.notifyType
= fOutOfBandParameter
;
5916 context
.messageType
= messageType
;
5918 if(context
.messageType
== kIOMessageCanSystemSleep
)
5920 maxTimeOut
= kCanSleepMaxTimeReq
;
5921 if(gCanSleepTimeout
)
5923 maxTimeOut
= (gCanSleepTimeout
*us_per_s
);
5926 context
.maxTimeRequested
= maxTimeOut
;
5927 applyToInterested( gIOGeneralInterest
,
5928 pmTellClientWithResponse
, (void *) &context
);
5932 case kNotifyPriority
:
5933 context
.enableTracing
= isRootDomain
;
5934 applyToInterested( gIOPriorityPowerStateInterest
,
5935 pmTellClientWithResponse
, (void *) &context
);
5939 // Notify capability clients for tellChangeDown2().
5940 context
.notifyType
= kNotifyCapabilityChangePriority
;
5941 context
.messageType
= kIOMessageSystemCapabilityChange
;
5942 applyToInterested( gIOPriorityPowerStateInterest
,
5943 pmTellCapabilityClientWithResponse
, (void *) &context
);
5947 case kNotifyCapabilityChangeApps
:
5948 applyToInterested( gIOAppPowerStateInterest
,
5949 pmTellCapabilityAppWithResponse
, (void *) &context
);
5950 if(context
.messageType
== kIOMessageCanSystemSleep
)
5952 maxTimeOut
= kCanSleepMaxTimeReq
;
5953 if(gCanSleepTimeout
)
5955 maxTimeOut
= (gCanSleepTimeout
*us_per_s
);
5958 context
.maxTimeRequested
= maxTimeOut
;
5961 case kNotifyCapabilityChangePriority
:
5962 context
.enableTracing
= isRootDomain
;
5963 applyToInterested( gIOPriorityPowerStateInterest
,
5964 pmTellCapabilityClientWithResponse
, (void *) &context
);
5967 fNotifyClientArray
= context
.notifyClients
;
5969 // do we have to wait for somebody?
5970 if ( !checkForDone() )
5972 OUR_PMLog(kPMLogStartAckTimer
, context
.maxTimeRequested
, 0);
5973 if (context
.enableTracing
) {
5974 getPMRootDomain()->traceDetail(context
.messageType
, 0, context
.maxTimeRequested
/ 1000);
5976 start_ack_timer( context
.maxTimeRequested
/ 1000, kMillisecondScale
);
5981 // everybody responded
5984 fResponseArray
->release();
5985 fResponseArray
= NULL
;
5987 if (fNotifyClientArray
)
5989 fNotifyClientArray
->release();
5990 fNotifyClientArray
= NULL
;
5996 //*********************************************************************************
5997 // [static private] pmTellAppWithResponse
5999 // We send a message to an application, and we expect a response, so we compute a
6000 // cookie we can identify the response with.
6001 //*********************************************************************************
6003 void IOService::pmTellAppWithResponse( OSObject
* object
, void * arg
)
6005 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6006 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6007 uint32_t msgIndex
, msgRef
, msgType
;
6008 OSNumber
*clientID
= NULL
;
6010 boolean_t proc_suspended
= FALSE
;
6011 OSObject
* waitForReply
= kOSBooleanTrue
;
6012 #if LOG_APP_RESPONSE_TIMES
6016 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
6019 if (context
->us
== getPMRootDomain())
6021 if ((clientID
= copyClientIDForNotification(object
, context
)))
6023 uint32_t clientPID
= clientID
->unsigned32BitValue();
6024 clientID
->release();
6025 proc
= proc_find(clientPID
);
6029 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6034 logClientIDForNotification(object
, context
, "PMTellAppWithResponse - Suspended");
6041 if (context
->messageFilter
&&
6042 !context
->messageFilter(context
->us
, object
, context
, 0, &waitForReply
))
6044 if (kIOLogDebugPower
& gIOKitDebug
)
6046 logClientIDForNotification(object
, context
, "DROP App");
6051 // Create client array (for tracking purposes) only if the service
6052 // has app clients. Usually only root domain does.
6053 if (0 == context
->notifyClients
)
6054 context
->notifyClients
= OSArray::withCapacity( 32 );
6056 msgType
= context
->messageType
;
6057 msgIndex
= context
->responseArray
->getCount();
6058 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6060 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
6061 if (kIOLogDebugPower
& gIOKitDebug
)
6063 logClientIDForNotification(object
, context
, "MESG App");
6066 if (waitForReply
== kOSBooleanTrue
)
6070 clock_get_uptime(&now
);
6071 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
6074 context
->responseArray
->setObject(msgIndex
, num
);
6078 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
6083 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
6084 if (kIOLogDebugPower
& gIOKitDebug
)
6086 logClientIDForNotification(object
, context
, "App response ignored");
6090 if (context
->notifyClients
)
6091 context
->notifyClients
->setObject(msgIndex
, object
);
6093 context
->us
->messageClient(msgType
, object
, (void *)(uintptr_t) msgRef
);
6096 //*********************************************************************************
6097 // [static private] pmTellClientWithResponse
6099 // We send a message to an in-kernel client, and we expect a response,
6100 // so we compute a cookie we can identify the response with.
6101 //*********************************************************************************
6103 void IOService::pmTellClientWithResponse( OSObject
* object
, void * arg
)
6105 IOPowerStateChangeNotification notify
;
6106 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6107 OSObject
* replied
= kOSBooleanTrue
;
6108 _IOServiceInterestNotifier
* notifier
;
6109 uint32_t msgIndex
, msgRef
, msgType
;
6111 AbsoluteTime start
, end
;
6114 if (context
->messageFilter
&&
6115 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6117 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6118 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6120 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6121 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6122 context
->us
->getName(),
6123 getIOMessageString(context
->messageType
),
6124 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6129 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
6130 msgType
= context
->messageType
;
6131 msgIndex
= context
->responseArray
->getCount();
6132 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6134 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6135 if (gIOKitDebug
& kIOLogPower
) {
6136 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
6137 if (OSDynamicCast(IOService
, object
)) {
6138 const char *who
= ((IOService
*) object
)->getName();
6139 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
6141 else if (notifier
) {
6142 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
6145 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
)
6147 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6148 context
->us
->getName(),
6149 getIOMessageString(msgType
),
6150 OBFUSCATE(object
), OBFUSCATE(notifier
->handler
));
6153 if (0 == context
->notifyClients
)
6154 context
->notifyClients
= OSArray::withCapacity( 32 );
6156 notify
.powerRef
= (void *)(uintptr_t) msgRef
;
6157 notify
.returnValue
= 0;
6158 notify
.stateNumber
= context
->stateNumber
;
6159 notify
.stateFlags
= context
->stateFlags
;
6161 if (context
->enableTracing
&& (notifier
!= 0))
6163 getPMRootDomain()->traceDetail(notifier
);
6166 clock_get_uptime(&start
);
6167 retCode
= context
->us
->messageClient(msgType
, object
, (void *) ¬ify
, sizeof(notify
));
6168 clock_get_uptime(&end
);
6170 if (kIOReturnSuccess
== retCode
)
6172 if (0 == notify
.returnValue
) {
6173 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
6174 context
->responseArray
->setObject(msgIndex
, replied
);
6176 replied
= kOSBooleanFalse
;
6177 if ( notify
.returnValue
> context
->maxTimeRequested
)
6179 if (notify
.returnValue
> kPriorityClientMaxWait
)
6181 context
->maxTimeRequested
= kPriorityClientMaxWait
;
6182 PM_ERROR("%s: client %p returned %llu for %s\n",
6183 context
->us
->getName(),
6184 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
6185 (uint64_t) notify
.returnValue
,
6186 getIOMessageString(msgType
));
6189 context
->maxTimeRequested
= notify
.returnValue
;
6192 // Track time taken to ack, by storing the timestamp of
6193 // callback completion
6195 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&end
), sizeof(uint64_t) * 8);
6197 context
->responseArray
->setObject(msgIndex
, num
);
6201 context
->responseArray
->setObject(msgIndex
, replied
);
6205 if (context
->enableTracing
) {
6206 SUB_ABSOLUTETIME(&end
, &start
);
6207 absolutetime_to_nanoseconds(end
, &nsec
);
6209 if ((nsec
> LOG_KEXT_RESPONSE_TIMES
) || (notify
.returnValue
!= 0)) {
6210 getPMRootDomain()->traceAckDelay(notifier
, notify
.returnValue
/1000, NS_TO_MS(nsec
));
6215 // not a client of ours
6216 // so we won't be waiting for response
6217 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
6218 context
->responseArray
->setObject(msgIndex
, replied
);
6220 if (context
->notifyClients
) {
6221 context
->notifyClients
->setObject(msgIndex
, object
);
6226 //*********************************************************************************
6227 // [static private] pmTellCapabilityAppWithResponse
6228 //*********************************************************************************
6230 void IOService::pmTellCapabilityAppWithResponse( OSObject
* object
, void * arg
)
6232 IOPMSystemCapabilityChangeParameters msgArg
;
6233 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6234 OSObject
* replied
= kOSBooleanTrue
;
6235 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6236 uint32_t msgIndex
, msgRef
, msgType
;
6237 #if LOG_APP_RESPONSE_TIMES
6241 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
6244 memset(&msgArg
, 0, sizeof(msgArg
));
6245 if (context
->messageFilter
&&
6246 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, &replied
))
6251 // Create client array (for tracking purposes) only if the service
6252 // has app clients. Usually only root domain does.
6253 if (0 == context
->notifyClients
)
6254 context
->notifyClients
= OSArray::withCapacity( 32 );
6256 msgType
= context
->messageType
;
6257 msgIndex
= context
->responseArray
->getCount();
6258 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6260 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
6261 if (kIOLogDebugPower
& gIOKitDebug
)
6263 // Log client pid/name and client array index.
6264 OSNumber
* clientID
= NULL
;
6265 OSString
* clientIDString
= NULL
;;
6266 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6268 clientIDString
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6271 PM_LOG("%s MESG App(%u) %s, wait %u, %s\n",
6272 context
->us
->getName(),
6273 msgIndex
, getIOMessageString(msgType
),
6274 (replied
!= kOSBooleanTrue
),
6275 clientIDString
? clientIDString
->getCStringNoCopy() : "");
6276 if (clientID
) clientID
->release();
6277 if (clientIDString
) clientIDString
->release();
6280 msgArg
.notifyRef
= msgRef
;
6281 msgArg
.maxWaitForReply
= 0;
6283 if (replied
== kOSBooleanTrue
)
6285 msgArg
.notifyRef
= 0;
6286 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
6287 if (context
->notifyClients
)
6288 context
->notifyClients
->setObject(msgIndex
, kOSBooleanTrue
);
6294 clock_get_uptime(&now
);
6295 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
6298 context
->responseArray
->setObject(msgIndex
, num
);
6302 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
6305 if (context
->notifyClients
)
6306 context
->notifyClients
->setObject(msgIndex
, object
);
6309 context
->us
->messageClient(msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
6312 //*********************************************************************************
6313 // [static private] pmTellCapabilityClientWithResponse
6314 //*********************************************************************************
6316 void IOService::pmTellCapabilityClientWithResponse(
6317 OSObject
* object
, void * arg
)
6319 IOPMSystemCapabilityChangeParameters msgArg
;
6320 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6321 OSObject
* replied
= kOSBooleanTrue
;
6322 _IOServiceInterestNotifier
* notifier
;
6323 uint32_t msgIndex
, msgRef
, msgType
;
6325 AbsoluteTime start
, end
;
6328 memset(&msgArg
, 0, sizeof(msgArg
));
6329 if (context
->messageFilter
&&
6330 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, 0))
6332 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6333 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6335 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6336 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6337 context
->us
->getName(),
6338 getIOMessageString(context
->messageType
),
6339 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6344 if (0 == context
->notifyClients
) {
6345 context
->notifyClients
= OSArray::withCapacity( 32 );
6347 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
6348 msgType
= context
->messageType
;
6349 msgIndex
= context
->responseArray
->getCount();
6350 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6352 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6353 if (gIOKitDebug
& kIOLogPower
) {
6354 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
6355 if (OSDynamicCast(IOService
, object
)) {
6356 const char *who
= ((IOService
*) object
)->getName();
6357 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
6359 else if (notifier
) {
6360 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
6363 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
)
6365 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6366 context
->us
->getName(),
6367 getIOMessageString(msgType
),
6368 OBFUSCATE(object
), OBFUSCATE(notifier
->handler
));
6371 msgArg
.notifyRef
= msgRef
;
6372 msgArg
.maxWaitForReply
= 0;
6374 if (context
->enableTracing
&& (notifier
!= 0))
6376 getPMRootDomain()->traceDetail(notifier
);
6379 clock_get_uptime(&start
);
6380 retCode
= context
->us
->messageClient(
6381 msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
6382 clock_get_uptime(&end
);
6384 if ( kIOReturnSuccess
== retCode
)
6386 if ( 0 == msgArg
.maxWaitForReply
)
6388 // client doesn't want time to respond
6389 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
6390 context
->responseArray
->setObject(msgIndex
, replied
);
6394 replied
= kOSBooleanFalse
;
6395 if ( msgArg
.maxWaitForReply
> context
->maxTimeRequested
)
6397 if (msgArg
.maxWaitForReply
> kCapabilityClientMaxWait
)
6399 context
->maxTimeRequested
= kCapabilityClientMaxWait
;
6400 PM_ERROR("%s: client %p returned %u for %s\n",
6401 context
->us
->getName(),
6402 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
6403 msgArg
.maxWaitForReply
,
6404 getIOMessageString(msgType
));
6407 context
->maxTimeRequested
= msgArg
.maxWaitForReply
;
6410 // Track time taken to ack, by storing the timestamp of
6411 // callback completion
6413 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&end
), sizeof(uint64_t) * 8);
6415 context
->responseArray
->setObject(msgIndex
, num
);
6419 context
->responseArray
->setObject(msgIndex
, replied
);
6423 if (context
->enableTracing
) {
6424 SUB_ABSOLUTETIME(&end
, &start
);
6425 absolutetime_to_nanoseconds(end
, &nsec
);
6427 if ((nsec
> LOG_KEXT_RESPONSE_TIMES
) || (msgArg
.maxWaitForReply
!= 0)) {
6428 getPMRootDomain()->traceAckDelay(notifier
, msgArg
.maxWaitForReply
/1000, NS_TO_MS(nsec
));
6434 // not a client of ours
6435 // so we won't be waiting for response
6436 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
6437 context
->responseArray
->setObject(msgIndex
, replied
);
6439 if (context
->notifyClients
) {
6440 context
->notifyClients
->setObject(msgIndex
, object
);
6445 //*********************************************************************************
6446 // [public] tellNoChangeDown
6448 // Notify registered applications and kernel clients that we are not
6451 // Subclass can override this to send a different message type. Parameter is
6452 // the aborted destination state number.
6453 //*********************************************************************************
6455 void IOService::tellNoChangeDown( unsigned long )
6457 return tellClients( kIOMessageDeviceWillNotPowerOff
);
6460 //*********************************************************************************
6461 // [public] tellChangeUp
6463 // Notify registered applications and kernel clients that we are raising power.
6465 // Subclass can override this to send a different message type. Parameter is
6466 // the aborted destination state number.
6467 //*********************************************************************************
6469 void IOService::tellChangeUp( unsigned long )
6471 return tellClients( kIOMessageDeviceHasPoweredOn
);
6474 //*********************************************************************************
6475 // [protected] tellClients
6477 // Notify registered applications and kernel clients of something.
6478 //*********************************************************************************
6480 void IOService::tellClients( int messageType
)
6482 IOPMInterestContext context
;
6484 RD_LOG("tellClients( %s )\n", getIOMessageString(messageType
));
6486 memset(&context
, 0, sizeof(context
));
6487 context
.messageType
= messageType
;
6488 context
.isPreChange
= fIsPreChange
;
6490 context
.stateNumber
= fHeadNotePowerState
;
6491 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
6492 context
.changeFlags
= fHeadNoteChangeFlags
;
6493 context
.messageFilter
= (IS_ROOT_DOMAIN
) ?
6494 OSMemberFunctionCast(
6497 &IOPMrootDomain::systemMessageFilter
) : 0;
6499 context
.notifyType
= kNotifyPriority
;
6500 applyToInterested( gIOPriorityPowerStateInterest
,
6501 tellKernelClientApplier
, (void *) &context
);
6503 context
.notifyType
= kNotifyApps
;
6504 applyToInterested( gIOAppPowerStateInterest
,
6505 tellAppClientApplier
, (void *) &context
);
6507 applyToInterested( gIOGeneralInterest
,
6508 tellKernelClientApplier
, (void *) &context
);
6511 //*********************************************************************************
6512 // [private] tellKernelClientApplier
6514 // Message a kernel client.
6515 //*********************************************************************************
6517 static void tellKernelClientApplier( OSObject
* object
, void * arg
)
6519 IOPowerStateChangeNotification notify
;
6520 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6522 if (context
->messageFilter
&&
6523 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6525 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6526 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6528 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6529 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6530 context
->us
->getName(),
6531 IOService::getIOMessageString(context
->messageType
),
6532 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6537 notify
.powerRef
= (void *) 0;
6538 notify
.returnValue
= 0;
6539 notify
.stateNumber
= context
->stateNumber
;
6540 notify
.stateFlags
= context
->stateFlags
;
6542 context
->us
->messageClient(context
->messageType
, object
, ¬ify
, sizeof(notify
));
6544 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6545 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6547 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6548 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6549 context
->us
->getName(),
6550 IOService::getIOMessageString(context
->messageType
),
6551 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6555 static OSNumber
* copyClientIDForNotification(
6557 IOPMInterestContext
*context
)
6559 OSNumber
*clientID
= NULL
;
6560 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6564 static void logClientIDForNotification(
6566 IOPMInterestContext
*context
,
6567 const char *logString
)
6569 OSString
*logClientID
= NULL
;
6570 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
6575 logClientID
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6577 PM_LOG("%s %s %s, %s\n",
6578 context
->us
->getName(), logString
,
6579 IOService::getIOMessageString(context
->messageType
),
6580 logClientID
? logClientID
->getCStringNoCopy() : "");
6583 logClientID
->release();
6587 clientID
->release();
6592 static void tellAppClientApplier( OSObject
* object
, void * arg
)
6594 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6595 OSNumber
* clientID
= NULL
;
6597 boolean_t proc_suspended
= FALSE
;
6599 if (context
->us
== IOService::getPMRootDomain())
6601 if ((clientID
= copyClientIDForNotification(object
, context
)))
6603 uint32_t clientPID
= clientID
->unsigned32BitValue();
6604 clientID
->release();
6605 proc
= proc_find(clientPID
);
6609 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6614 logClientIDForNotification(object
, context
, "tellAppClientApplier - Suspended");
6621 if (context
->messageFilter
&&
6622 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6624 if (kIOLogDebugPower
& gIOKitDebug
)
6626 logClientIDForNotification(object
, context
, "DROP App");
6631 if (kIOLogDebugPower
& gIOKitDebug
)
6633 logClientIDForNotification(object
, context
, "MESG App");
6636 context
->us
->messageClient(context
->messageType
, object
, 0);
6639 //*********************************************************************************
6640 // [private] checkForDone
6641 //*********************************************************************************
6643 bool IOService::checkForDone( void )
6648 if (fResponseArray
== NULL
) {
6652 for (i
= 0; ; i
++) {
6653 theFlag
= fResponseArray
->getObject(i
);
6655 if (NULL
== theFlag
) {
6659 if (kOSBooleanTrue
!= theFlag
) {
6666 //*********************************************************************************
6667 // [public] responseValid
6668 //*********************************************************************************
6670 bool IOService::responseValid( uint32_t refcon
, int pid
)
6672 UInt16 serialComponent
;
6673 UInt16 ordinalComponent
;
6675 OSObject
*object
= 0;
6677 serialComponent
= (refcon
>> 16) & 0xFFFF;
6678 ordinalComponent
= (refcon
& 0xFFFF);
6680 if ( serialComponent
!= fSerialNumber
)
6685 if ( fResponseArray
== NULL
)
6690 theFlag
= fResponseArray
->getObject(ordinalComponent
);
6697 if (fNotifyClientArray
)
6698 object
= fNotifyClientArray
->getObject(ordinalComponent
);
6701 if ((num
= OSDynamicCast(OSNumber
, theFlag
)))
6709 clock_get_uptime(&now
);
6710 AbsoluteTime_to_scalar(&start
) = num
->unsigned64BitValue();
6711 SUB_ABSOLUTETIME(&now
, &start
);
6712 absolutetime_to_nanoseconds(now
, &nsec
);
6716 proc_name(pid
, name
, sizeof(name
));
6718 if (nsec
> LOG_APP_RESPONSE_TIMES
)
6720 IOLog("PM response took %d ms (%d, %s)\n", NS_TO_MS(nsec
),
6725 if (nsec
> LOG_APP_RESPONSE_MSG_TRACER
)
6727 // TODO: populate the messageType argument
6728 getPMRootDomain()->pmStatsRecordApplicationResponse(
6729 gIOPMStatsResponseSlow
,
6730 name
, 0, NS_TO_MS(nsec
), pid
, object
);
6734 getPMRootDomain()->pmStatsRecordApplicationResponse(
6735 gIOPMStatsResponsePrompt
,
6736 name
, 0, NS_TO_MS(nsec
), pid
, object
);
6740 getPMRootDomain()->traceAckDelay(object
, 0, NS_TO_MS(nsec
));
6743 if (kIOLogDebugPower
& gIOKitDebug
)
6745 PM_LOG("Ack(%u) %u ms\n",
6746 (uint32_t) ordinalComponent
,
6749 theFlag
= kOSBooleanFalse
;
6752 getPMRootDomain()->pmStatsRecordApplicationResponse(
6753 gIOPMStatsResponsePrompt
,
6754 0, 0, 0, pid
, object
);
6758 if ( kOSBooleanFalse
== theFlag
)
6760 fResponseArray
->replaceObject(ordinalComponent
, kOSBooleanTrue
);
6766 //*********************************************************************************
6767 // [public] allowPowerChange
6769 // Our power state is about to lower, and we have notified applications
6770 // and kernel clients, and one of them has acknowledged. If this is the last to do
6771 // so, and all acknowledgements are positive, we continue with the power change.
6772 //*********************************************************************************
6774 IOReturn
IOService::allowPowerChange( unsigned long refcon
)
6776 IOPMRequest
* request
;
6781 return kIOReturnSuccess
;
6784 request
= acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange
);
6786 return kIOReturnNoMemory
;
6788 request
->fArg0
= (void *) refcon
;
6789 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6790 request
->fArg2
= (void *) 0;
6791 submitPMRequest( request
);
6793 return kIOReturnSuccess
;
6797 IOReturn
IOService::serializedAllowPowerChange2( unsigned long refcon
)
6799 // [deprecated] public
6800 return kIOReturnUnsupported
;
6802 #endif /* !__LP64__ */
6804 //*********************************************************************************
6805 // [public] cancelPowerChange
6807 // Our power state is about to lower, and we have notified applications
6808 // and kernel clients, and one of them has vetoed the change. If this is the last
6809 // client to respond, we abandon the power change.
6810 //*********************************************************************************
6812 IOReturn
IOService::cancelPowerChange( unsigned long refcon
)
6814 IOPMRequest
* request
;
6816 pid_t pid
= proc_selfpid();
6821 return kIOReturnSuccess
;
6825 proc_name(pid
, name
, sizeof(name
));
6826 PM_ERROR("PM notification cancel (pid %d, %s)\n", pid
, name
);
6828 request
= acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange
);
6831 return kIOReturnNoMemory
;
6834 request
->fArg0
= (void *) refcon
;
6835 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6836 request
->fArg2
= (void *) OSString::withCString(name
);
6837 submitPMRequest( request
);
6839 return kIOReturnSuccess
;
6843 IOReturn
IOService::serializedCancelPowerChange2( unsigned long refcon
)
6845 // [deprecated] public
6846 return kIOReturnUnsupported
;
6849 //*********************************************************************************
6850 // PM_Clamp_Timer_Expired
6852 // called when clamp timer expires...set power state to 0.
6853 //*********************************************************************************
6855 void IOService::PM_Clamp_Timer_Expired( void )
6859 //*********************************************************************************
6862 // Set to highest available power state for a minimum of duration milliseconds
6863 //*********************************************************************************
6865 void IOService::clampPowerOn( unsigned long duration
)
6868 #endif /* !__LP64__ */
6870 //*********************************************************************************
6871 // configurePowerStateReport
6873 // Configures the IOStateReport for kPMPowerStateChannel
6874 //*********************************************************************************
6875 IOReturn
IOService::configurePowerStatesReport( IOReportConfigureAction action
, void *result
)
6878 IOReturn rc
= kIOReturnSuccess
;
6884 return kIOReturnUnsupported
;
6886 if (!fNumberOfPowerStates
)
6887 return kIOReturnSuccess
; // For drivers which are in power plane, but haven't called registerPowerDriver()
6892 case kIOReportEnable
:
6898 reportSize
= STATEREPORT_BUFSIZE(fNumberOfPowerStates
);
6899 fReportBuf
= IOMalloc(reportSize
);
6901 rc
= kIOReturnNoMemory
;
6904 memset(fReportBuf
, 0, reportSize
);
6906 STATEREPORT_INIT(fNumberOfPowerStates
, fReportBuf
, reportSize
,
6907 getRegistryEntryID(), kPMPowerStatesChID
, kIOReportCategoryPower
);
6909 for (i
= 0; i
< fNumberOfPowerStates
; i
++) {
6912 if (fPowerStates
[i
].capabilityFlags
& kIOPMPowerOn
)
6913 bits
|= kPMReportPowerOn
;
6914 if (fPowerStates
[i
].capabilityFlags
& kIOPMDeviceUsable
)
6915 bits
|= kPMReportDeviceUsable
;
6916 if (fPowerStates
[i
].capabilityFlags
& kIOPMLowPower
)
6917 bits
|= kPMReportLowPower
;
6919 STATEREPORT_SETSTATEID(fReportBuf
, i
, ((bits
& 0xff) << 8) |
6920 ((StateOrder(fMaxPowerState
) & 0xf) << 4) | (StateOrder(i
) & 0xf));
6922 ts
= mach_absolute_time();
6923 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
6926 case kIOReportDisable
:
6927 if (fReportClientCnt
== 0) {
6928 rc
= kIOReturnBadArgument
;
6931 if (fReportClientCnt
== 1)
6933 IOFree(fReportBuf
, STATEREPORT_BUFSIZE(fNumberOfPowerStates
));
6939 case kIOReportGetDimensions
:
6941 STATEREPORT_UPDATERES(fReportBuf
, kIOReportGetDimensions
, result
);
6950 //*********************************************************************************
6951 // updatePowerStateReport
6953 // Updates the IOStateReport for kPMPowerStateChannel
6954 //*********************************************************************************
6955 IOReturn
IOService::updatePowerStatesReport( IOReportConfigureAction action
, void *result
, void *destination
)
6960 IOReturn rc
= kIOReturnSuccess
;
6961 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
6965 return kIOReturnUnsupported
;
6966 if (!fNumberOfPowerStates
)
6967 return kIOReturnSuccess
;
6969 if ( !result
|| !dest
) return kIOReturnBadArgument
;
6973 case kIOReportCopyChannelData
:
6974 if ( !fReportBuf
) {
6975 rc
= kIOReturnNotOpen
;
6979 ts
= mach_absolute_time();
6980 STATEREPORT_UPDATEPREP(fReportBuf
, ts
, data2cpy
, size2cpy
);
6981 if (size2cpy
> (dest
->getCapacity() - dest
->getLength()) ) {
6982 rc
= kIOReturnOverrun
;
6986 STATEREPORT_UPDATERES(fReportBuf
, kIOReportCopyChannelData
, result
);
6987 dest
->appendBytes(data2cpy
, size2cpy
);
7001 //*********************************************************************************
7002 // configureSimplePowerReport
7004 // Configures the IOSimpleReport for given channel id
7005 //*********************************************************************************
7006 IOReturn
IOService::configureSimplePowerReport(IOReportConfigureAction action
, void *result
)
7009 IOReturn rc
= kIOReturnSuccess
;
7012 return kIOReturnUnsupported
;
7014 if ( !fNumberOfPowerStates
)
7019 case kIOReportEnable
:
7020 case kIOReportDisable
:
7023 case kIOReportGetDimensions
:
7024 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions
, result
);
7032 //*********************************************************************************
7033 // updateSimplePowerReport
7035 // Updates the IOSimpleReport for the given chanel id
7036 //*********************************************************************************
7037 IOReturn
IOService::updateSimplePowerReport( IOReportConfigureAction action
, void *result
, void *destination
)
7041 uint64_t buf
[SIMPLEREPORT_BUFSIZE
/sizeof(uint64_t)+1]; // Force a 8-byte alignment
7042 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
7043 IOReturn rc
= kIOReturnSuccess
;
7048 return kIOReturnUnsupported
;
7049 if ( !result
|| !dest
) return kIOReturnBadArgument
;
7051 if ( !fNumberOfPowerStates
)
7056 case kIOReportCopyChannelData
:
7058 SIMPLEREPORT_INIT(buf
, sizeof(buf
), getRegistryEntryID(), kPMCurrStateChID
, kIOReportCategoryPower
);
7060 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMPowerOn
)
7061 bits
|= kPMReportPowerOn
;
7062 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMDeviceUsable
)
7063 bits
|= kPMReportDeviceUsable
;
7064 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMLowPower
)
7065 bits
|= kPMReportLowPower
;
7068 SIMPLEREPORT_SETVALUE(buf
, ((bits
& 0xff) << 8) | ((StateOrder(fMaxPowerState
) & 0xf) << 4) |
7069 (StateOrder(fCurrentPowerState
) & 0xf));
7071 SIMPLEREPORT_UPDATEPREP(buf
, data2cpy
, size2cpy
);
7072 if (size2cpy
> (dest
->getCapacity() - dest
->getLength())) {
7073 rc
= kIOReturnOverrun
;
7077 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData
, result
);
7078 dest
->appendBytes(data2cpy
, size2cpy
);
7088 return kIOReturnSuccess
;
7095 // MARK: Driver Overrides
7097 //*********************************************************************************
7098 // [public] setPowerState
7100 // Does nothing here. This should be implemented in a subclass driver.
7101 //*********************************************************************************
7103 IOReturn
IOService::setPowerState(
7104 unsigned long powerStateOrdinal
, IOService
* whatDevice
)
7109 //*********************************************************************************
7110 // [public] maxCapabilityForDomainState
7112 // Finds the highest power state in the array whose input power requirement
7113 // is equal to the input parameter. Where a more intelligent decision is
7114 // possible, override this in the subclassed driver.
7115 //*********************************************************************************
7117 IOPMPowerStateIndex
IOService::getPowerStateForDomainFlags( IOPMPowerFlags flags
)
7119 IOPMPowerStateIndex stateIndex
;
7121 if (!fNumberOfPowerStates
)
7122 return kPowerStateZero
;
7124 for ( int order
= fNumberOfPowerStates
- 1; order
>= 0; order
-- )
7126 stateIndex
= fPowerStates
[order
].stateOrderToIndex
;
7128 if ( (flags
& fPowerStates
[stateIndex
].inputPowerFlags
) ==
7129 fPowerStates
[stateIndex
].inputPowerFlags
)
7134 return kPowerStateZero
;
7137 unsigned long IOService::maxCapabilityForDomainState( IOPMPowerFlags domainState
)
7139 return getPowerStateForDomainFlags(domainState
);
7142 //*********************************************************************************
7143 // [public] initialPowerStateForDomainState
7145 // Called to query the power state for the initial power transition.
7146 //*********************************************************************************
7148 unsigned long IOService::initialPowerStateForDomainState( IOPMPowerFlags domainState
)
7150 if (fResetPowerStateOnWake
&& (domainState
& kIOPMRootDomainState
))
7152 // Return lowest power state for any root power domain changes
7153 return kPowerStateZero
;
7156 return getPowerStateForDomainFlags(domainState
);
7159 //*********************************************************************************
7160 // [public] powerStateForDomainState
7162 // This method is not called from PM.
7163 //*********************************************************************************
7165 unsigned long IOService::powerStateForDomainState( IOPMPowerFlags domainState
)
7167 return getPowerStateForDomainFlags(domainState
);
7171 //*********************************************************************************
7172 // [deprecated] didYouWakeSystem
7174 // Does nothing here. This should be implemented in a subclass driver.
7175 //*********************************************************************************
7177 bool IOService::didYouWakeSystem( void )
7181 #endif /* !__LP64__ */
7183 //*********************************************************************************
7184 // [public] powerStateWillChangeTo
7186 // Does nothing here. This should be implemented in a subclass driver.
7187 //*********************************************************************************
7189 IOReturn
IOService::powerStateWillChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
7191 return kIOPMAckImplied
;
7194 //*********************************************************************************
7195 // [public] powerStateDidChangeTo
7197 // Does nothing here. This should be implemented in a subclass driver.
7198 //*********************************************************************************
7200 IOReturn
IOService::powerStateDidChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
7202 return kIOPMAckImplied
;
7205 //*********************************************************************************
7206 // [protected] powerChangeDone
7208 // Called from PM work loop thread.
7209 // Does nothing here. This should be implemented in a subclass policy-maker.
7210 //*********************************************************************************
7212 void IOService::powerChangeDone( unsigned long )
7217 //*********************************************************************************
7218 // [deprecated] newTemperature
7220 // Does nothing here. This should be implemented in a subclass driver.
7221 //*********************************************************************************
7223 IOReturn
IOService::newTemperature( long currentTemp
, IOService
* whichZone
)
7227 #endif /* !__LP64__ */
7229 //*********************************************************************************
7230 // [public] systemWillShutdown
7232 // System shutdown and restart notification.
7233 //*********************************************************************************
7235 void IOService::systemWillShutdown( IOOptionBits specifier
)
7237 IOPMrootDomain
* rootDomain
= IOService::getPMRootDomain();
7239 rootDomain
->acknowledgeSystemWillShutdown( this );
7243 // MARK: PM State Machine
7245 //*********************************************************************************
7246 // [private static] acquirePMRequest
7247 //*********************************************************************************
7250 IOService::acquirePMRequest( IOService
* target
, IOOptionBits requestType
,
7251 IOPMRequest
* active
)
7253 IOPMRequest
* request
;
7257 request
= IOPMRequest::create();
7260 request
->init( target
, requestType
);
7263 IOPMRequest
* root
= active
->getRootRequest();
7264 if (root
) request
->attachRootRequest(root
);
7269 PM_ERROR("%s: No memory for PM request type 0x%x\n",
7270 target
->getName(), (uint32_t) requestType
);
7275 //*********************************************************************************
7276 // [private static] releasePMRequest
7277 //*********************************************************************************
7279 void IOService::releasePMRequest( IOPMRequest
* request
)
7288 //*********************************************************************************
7289 // [private static] submitPMRequest
7290 //*********************************************************************************
7292 void IOService::submitPMRequest( IOPMRequest
* request
)
7295 assert( gIOPMReplyQueue
);
7296 assert( gIOPMRequestQueue
);
7298 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7299 (long)request
->getType(), OBFUSCATE(request
),
7300 OBFUSCATE(request
->getTarget()), request
->getTarget()->getName(),
7301 OBFUSCATE(request
->fArg0
),
7302 OBFUSCATE(request
->fArg1
), OBFUSCATE(request
->fArg2
));
7304 if (request
->isReplyType())
7305 gIOPMReplyQueue
->queuePMRequest( request
);
7307 gIOPMRequestQueue
->queuePMRequest( request
);
7310 void IOService::submitPMRequests( IOPMRequest
** requests
, IOItemCount count
)
7313 assert( count
> 0 );
7314 assert( gIOPMRequestQueue
);
7316 for (IOItemCount i
= 0; i
< count
; i
++)
7318 IOPMRequest
* req
= requests
[i
];
7319 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7320 (long)req
->getType(), OBFUSCATE(req
),
7321 OBFUSCATE(req
->getTarget()), req
->getTarget()->getName(),
7322 OBFUSCATE(req
->fArg0
),
7323 OBFUSCATE(req
->fArg1
), OBFUSCATE(req
->fArg2
));
7326 gIOPMRequestQueue
->queuePMRequestChain( requests
, count
);
7329 //*********************************************************************************
7330 // [private] actionPMRequestQueue
7332 // IOPMRequestQueue::checkForWork() passing a new request to the request target.
7333 //*********************************************************************************
7335 bool IOService::actionPMRequestQueue(
7336 IOPMRequest
* request
,
7337 IOPMRequestQueue
* queue
)
7343 // Work queue will immediately execute the request if the per-service
7344 // request queue is empty. Note pwrMgt is the target's IOServicePM.
7346 more
= gIOPMWorkQueue
->queuePMRequest(request
, pwrMgt
);
7350 // Calling PM without PMinit() is not allowed, fail the request.
7351 // Need to signal more when completing attached requests.
7353 PM_LOG("%s: PM not initialized\n", getName());
7354 PM_LOG1("[- %02x] %p [%p %s] !initialized\n",
7355 request
->getType(), OBFUSCATE(request
),
7356 OBFUSCATE(this), getName());
7358 more
= gIOPMCompletionQueue
->queuePMRequest(request
);
7359 if (more
) gIOPMWorkQueue
->incrementProducerCount();
7365 //*********************************************************************************
7366 // [private] actionPMCompletionQueue
7368 // IOPMCompletionQueue::checkForWork() passing a completed request to the
7370 //*********************************************************************************
7372 bool IOService::actionPMCompletionQueue(
7373 IOPMRequest
* request
,
7374 IOPMCompletionQueue
* queue
)
7376 bool more
= (request
->getNextRequest() != 0);
7377 IOPMRequest
* root
= request
->getRootRequest();
7379 if (root
&& (root
!= request
))
7382 gIOPMWorkQueue
->incrementProducerCount();
7384 releasePMRequest( request
);
7388 //*********************************************************************************
7389 // [private] actionPMWorkQueueRetire
7391 // IOPMWorkQueue::checkForWork() passing a retired request to the request target.
7392 //*********************************************************************************
7394 bool IOService::actionPMWorkQueueRetire( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7396 assert(request
&& queue
);
7398 PM_LOG1("[- %02x] %p [%p %s] state %d, busy %d\n",
7399 request
->getType(), OBFUSCATE(request
),
7400 OBFUSCATE(this), getName(),
7401 fMachineState
, gIOPMBusyRequestCount
);
7403 // Catch requests created by idleTimerExpired()
7404 if (request
->getType() == kIOPMRequestTypeActivityTickle
)
7406 uint32_t tickleFlags
= (uint32_t)(uintptr_t) request
->fArg1
;
7408 if ((tickleFlags
& kTickleTypePowerDrop
) && fIdleTimerPeriod
)
7412 else if (tickleFlags
== (kTickleTypeActivity
| kTickleTypePowerRise
))
7414 // Invalidate any idle power drop that got queued while
7415 // processing this request.
7416 fIdleTimerGeneration
++;
7420 // When the completed request is linked, tell work queue there is
7421 // more work pending.
7423 return (gIOPMCompletionQueue
->queuePMRequest( request
));
7426 //*********************************************************************************
7427 // [private] isPMBlocked
7429 // Check if machine state transition is blocked.
7430 //*********************************************************************************
7432 bool IOService::isPMBlocked( IOPMRequest
* request
, int count
)
7437 if (kIOPM_Finished
== fMachineState
)
7440 if (kIOPM_DriverThreadCallDone
== fMachineState
)
7442 // 5 = kDriverCallInformPreChange
7443 // 6 = kDriverCallInformPostChange
7444 // 7 = kDriverCallSetPowerState
7445 // 8 = kRootDomainInformPreChange
7446 if (fDriverCallBusy
)
7447 reason
= 5 + fDriverCallReason
;
7451 // Waiting on driver's setPowerState() timeout.
7457 // Child or interested driver acks pending.
7458 if (fHeadNotePendingAcks
)
7463 // Waiting on apps or priority power interest clients.
7469 // Waiting on settle timer expiration.
7476 fWaitReason
= reason
;
7482 PM_LOG1("[B %02x] %p [%p %s] state %d, reason %d\n",
7483 request
->getType(), OBFUSCATE(request
),
7484 OBFUSCATE(this), getName(),
7485 fMachineState
, reason
);
7494 //*********************************************************************************
7495 // [private] actionPMWorkQueueInvoke
7497 // IOPMWorkQueue::checkForWork() passing a request to the
7498 // request target for execution.
7499 //*********************************************************************************
7501 bool IOService::actionPMWorkQueueInvoke( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7506 assert(request
&& queue
);
7508 while (isPMBlocked(request
, loop
++) == false)
7510 PM_LOG1("[W %02x] %p [%p %s] state %d\n",
7511 request
->getType(), OBFUSCATE(request
),
7512 OBFUSCATE(this), getName(), fMachineState
);
7514 gIOPMRequest
= request
;
7515 gIOPMWorkInvokeCount
++;
7517 // Every PM machine states must be handled in one of the cases below.
7519 switch ( fMachineState
)
7521 case kIOPM_Finished
:
7522 start_watchdog_timer();
7524 executePMRequest( request
);
7527 case kIOPM_OurChangeTellClientsPowerDown
:
7528 // Root domain might self cancel due to assertions.
7531 bool cancel
= (bool) fDoNotPowerDown
;
7532 getPMRootDomain()->askChangeDownDone(
7533 &fHeadNoteChangeFlags
, &cancel
);
7534 fDoNotPowerDown
= cancel
;
7537 // askChangeDown() done, was it vetoed?
7538 if (!fDoNotPowerDown
)
7540 // no, we can continue
7541 OurChangeTellClientsPowerDown();
7545 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7546 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7547 if (IS_ROOT_DOMAIN
) {
7548 // RootDomain already sent "WillSleep" to its clients
7549 tellChangeUp(fCurrentPowerState
);
7552 tellNoChangeDown(fHeadNotePowerState
);
7554 // mark the change note un-actioned
7555 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7561 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
7562 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7563 if (fDoNotPowerDown
)
7565 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7566 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7567 if (IS_ROOT_DOMAIN
) {
7568 // RootDomain already sent "WillSleep" to its clients
7569 tellChangeUp(fCurrentPowerState
);
7572 tellNoChangeDown(fHeadNotePowerState
);
7574 // mark the change note un-actioned
7575 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7580 OurChangeTellUserPMPolicyPowerDown();
7583 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
7584 // PMRD: LastCallBeforeSleep notify done
7585 // Non-PMRD: tellChangeDown/kNotifyApps done
7586 if (fDoNotPowerDown
)
7588 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7589 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7590 // no, tell clients we're back in the old state
7591 tellChangeUp(fCurrentPowerState
);
7592 // mark the change note un-actioned
7593 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7599 // yes, we can continue
7600 OurChangeTellPriorityClientsPowerDown();
7604 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
7605 OurChangeNotifyInterestedDriversWillChange();
7608 case kIOPM_OurChangeSetPowerState
:
7609 OurChangeSetPowerState();
7612 case kIOPM_OurChangeWaitForPowerSettle
:
7613 OurChangeWaitForPowerSettle();
7616 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
7617 OurChangeNotifyInterestedDriversDidChange();
7620 case kIOPM_OurChangeTellCapabilityDidChange
:
7621 OurChangeTellCapabilityDidChange();
7624 case kIOPM_OurChangeFinish
:
7628 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
7629 ParentChangeTellPriorityClientsPowerDown();
7632 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
7633 ParentChangeNotifyInterestedDriversWillChange();
7636 case kIOPM_ParentChangeSetPowerState
:
7637 ParentChangeSetPowerState();
7640 case kIOPM_ParentChangeWaitForPowerSettle
:
7641 ParentChangeWaitForPowerSettle();
7644 case kIOPM_ParentChangeNotifyInterestedDriversDidChange
:
7645 ParentChangeNotifyInterestedDriversDidChange();
7648 case kIOPM_ParentChangeTellCapabilityDidChange
:
7649 ParentChangeTellCapabilityDidChange();
7652 case kIOPM_ParentChangeAcknowledgePowerChange
:
7653 ParentChangeAcknowledgePowerChange();
7656 case kIOPM_DriverThreadCallDone
:
7657 switch (fDriverCallReason
)
7659 case kDriverCallInformPreChange
:
7660 case kDriverCallInformPostChange
:
7661 notifyInterestedDriversDone();
7663 case kDriverCallSetPowerState
:
7664 notifyControllingDriverDone();
7666 case kRootDomainInformPreChange
:
7667 notifyRootDomainDone();
7670 panic("%s: bad call reason %x",
7671 getName(), fDriverCallReason
);
7675 case kIOPM_NotifyChildrenOrdered
:
7676 notifyChildrenOrdered();
7679 case kIOPM_NotifyChildrenDelayed
:
7680 notifyChildrenDelayed();
7683 case kIOPM_NotifyChildrenStart
:
7684 // pop notifyAll() state saved by notifyInterestedDriversDone()
7689 case kIOPM_SyncTellClientsPowerDown
:
7690 // Root domain might self cancel due to assertions.
7693 bool cancel
= (bool) fDoNotPowerDown
;
7694 getPMRootDomain()->askChangeDownDone(
7695 &fHeadNoteChangeFlags
, &cancel
);
7696 fDoNotPowerDown
= cancel
;
7698 if (!fDoNotPowerDown
)
7700 fMachineState
= kIOPM_SyncTellPriorityClientsPowerDown
;
7701 fOutOfBandParameter
= kNotifyApps
;
7702 tellChangeDown(fHeadNotePowerState
);
7706 // Cancelled by IOPMrootDomain::askChangeDownDone() or
7707 // askChangeDown/kNotifyApps
7708 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7709 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7710 tellNoChangeDown(fHeadNotePowerState
);
7711 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7716 case kIOPM_SyncTellPriorityClientsPowerDown
:
7717 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7718 if (!fDoNotPowerDown
)
7720 fMachineState
= kIOPM_SyncNotifyWillChange
;
7721 fOutOfBandParameter
= kNotifyPriority
;
7722 tellChangeDown(fHeadNotePowerState
);
7726 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7727 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7728 tellChangeUp(fCurrentPowerState
);
7729 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7734 case kIOPM_SyncNotifyWillChange
:
7735 if (kIOPMSyncNoChildNotify
& fHeadNoteChangeFlags
)
7737 fMachineState
= kIOPM_SyncFinish
;
7740 fMachineState
= kIOPM_SyncNotifyDidChange
;
7741 fDriverCallReason
= kDriverCallInformPreChange
;
7745 case kIOPM_SyncNotifyDidChange
:
7746 fIsPreChange
= false;
7748 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
7750 fMachineState
= kIOPM_SyncFinish
;
7754 assert(IS_ROOT_DOMAIN
);
7755 fMachineState
= kIOPM_SyncTellCapabilityDidChange
;
7758 fDriverCallReason
= kDriverCallInformPostChange
;
7762 case kIOPM_SyncTellCapabilityDidChange
:
7763 tellSystemCapabilityChange( kIOPM_SyncFinish
);
7766 case kIOPM_SyncFinish
:
7767 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
7768 ParentChangeAcknowledgePowerChange();
7773 case kIOPM_TellCapabilityChangeDone
:
7776 if (fOutOfBandParameter
== kNotifyCapabilityChangePriority
)
7778 MS_POP(); // tellSystemCapabilityChange()
7781 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
7785 if (fOutOfBandParameter
== kNotifyCapabilityChangeApps
)
7787 MS_POP(); // tellSystemCapabilityChange()
7790 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
7792 tellClientsWithResponse( fOutOfBandMessage
);
7796 panic("PMWorkQueueInvoke: unknown machine state %x",
7802 if (fMachineState
== kIOPM_Finished
)
7804 stop_watchdog_timer();
7813 //*********************************************************************************
7814 // [private] executePMRequest
7815 //*********************************************************************************
7817 void IOService::executePMRequest( IOPMRequest
* request
)
7819 assert( kIOPM_Finished
== fMachineState
);
7821 switch (request
->getType())
7823 case kIOPMRequestTypePMStop
:
7824 handlePMstop( request
);
7827 case kIOPMRequestTypeAddPowerChild1
:
7828 addPowerChild1( request
);
7831 case kIOPMRequestTypeAddPowerChild2
:
7832 addPowerChild2( request
);
7835 case kIOPMRequestTypeAddPowerChild3
:
7836 addPowerChild3( request
);
7839 case kIOPMRequestTypeRegisterPowerDriver
:
7840 handleRegisterPowerDriver( request
);
7843 case kIOPMRequestTypeAdjustPowerState
:
7844 fAdjustPowerScheduled
= false;
7848 case kIOPMRequestTypePowerDomainWillChange
:
7849 handlePowerDomainWillChangeTo( request
);
7852 case kIOPMRequestTypePowerDomainDidChange
:
7853 handlePowerDomainDidChangeTo( request
);
7856 case kIOPMRequestTypeRequestPowerState
:
7857 case kIOPMRequestTypeRequestPowerStateOverride
:
7858 handleRequestPowerState( request
);
7861 case kIOPMRequestTypePowerOverrideOnPriv
:
7862 case kIOPMRequestTypePowerOverrideOffPriv
:
7863 handlePowerOverrideChanged( request
);
7866 case kIOPMRequestTypeActivityTickle
:
7867 handleActivityTickle( request
);
7870 case kIOPMRequestTypeSynchronizePowerTree
:
7871 handleSynchronizePowerTree( request
);
7874 case kIOPMRequestTypeSetIdleTimerPeriod
:
7876 fIdleTimerPeriod
= (uintptr_t) request
->fArg0
;
7877 fNextIdleTimerPeriod
= fIdleTimerPeriod
;
7878 if ((false == fLockedFlags
.PMStop
) && (fIdleTimerPeriod
> 0))
7883 case kIOPMRequestTypeIgnoreIdleTimer
:
7884 fIdleTimerIgnored
= request
->fArg0
? 1 : 0;
7887 case kIOPMRequestTypeQuiescePowerTree
:
7888 gIOPMWorkQueue
->finishQuiesceRequest(request
);
7892 panic("executePMRequest: unknown request type %x", request
->getType());
7896 //*********************************************************************************
7897 // [private] actionPMReplyQueue
7899 // IOPMRequestQueue::checkForWork() passing a reply-type request to the
7901 //*********************************************************************************
7903 bool IOService::actionPMReplyQueue( IOPMRequest
* request
, IOPMRequestQueue
* queue
)
7907 assert( request
&& queue
);
7908 assert( request
->isReplyType() );
7910 PM_LOG1("[A %02x] %p [%p %s] state %d\n",
7911 request
->getType(), OBFUSCATE(request
),
7912 OBFUSCATE(this), getName(), fMachineState
);
7914 switch ( request
->getType() )
7916 case kIOPMRequestTypeAllowPowerChange
:
7917 case kIOPMRequestTypeCancelPowerChange
:
7918 // Check if we are expecting this response.
7919 if (responseValid((uint32_t)(uintptr_t) request
->fArg0
,
7920 (int)(uintptr_t) request
->fArg1
))
7922 if (kIOPMRequestTypeCancelPowerChange
== request
->getType())
7924 // Clients are not allowed to cancel when kIOPMSkipAskPowerDown
7925 // flag is set. Only root domain will set this flag.
7926 // However, there is one exception to this rule. User-space PM
7927 // policy may choose to cancel sleep even after all clients have
7928 // been notified that we will lower power.
7930 if ((fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
7931 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
7932 || ((fHeadNoteChangeFlags
& kIOPMSkipAskPowerDown
) == 0))
7934 fDoNotPowerDown
= true;
7936 OSString
* name
= (OSString
*) request
->fArg2
;
7937 getPMRootDomain()->pmStatsRecordApplicationResponse(
7938 gIOPMStatsResponseCancel
,
7939 name
? name
->getCStringNoCopy() : "", 0,
7940 0, (int)(uintptr_t) request
->fArg1
, 0);
7947 cleanClientResponses(false);
7951 // OSString containing app name in Arg2 must be released.
7952 if (request
->getType() == kIOPMRequestTypeCancelPowerChange
)
7954 OSObject
* obj
= (OSObject
*) request
->fArg2
;
7955 if (obj
) obj
->release();
7959 case kIOPMRequestTypeAckPowerChange
:
7960 more
= handleAcknowledgePowerChange( request
);
7963 case kIOPMRequestTypeAckSetPowerState
:
7964 if (fDriverTimer
== -1)
7966 // driver acked while setPowerState() call is in-flight.
7967 // take this ack, return value from setPowerState() is irrelevant.
7968 OUR_PMLog(kPMLogDriverAcknowledgeSet
,
7969 (uintptr_t) this, fDriverTimer
);
7972 else if (fDriverTimer
> 0)
7974 // expected ack, stop the timer
7978 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
7979 if (nsec
> LOG_SETPOWER_TIMES
) {
7980 getPMRootDomain()->pmStatsRecordApplicationResponse(
7981 gIOPMStatsDriverPSChangeSlow
,
7982 fName
, kDriverCallSetPowerState
, NS_TO_MS(nsec
), getRegistryEntryID(),
7983 NULL
, fHeadNotePowerState
);
7986 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (uintptr_t) this, fDriverTimer
);
7993 OUR_PMLog(kPMLogAcknowledgeErr4
, (uintptr_t) this, 0);
7997 case kIOPMRequestTypeInterestChanged
:
7998 handleInterestChanged( request
);
8002 case kIOPMRequestTypeIdleCancel
:
8003 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
)
8004 || (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
8005 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
8006 || (fMachineState
== kIOPM_SyncTellClientsPowerDown
)
8007 || (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
))
8009 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
8010 PM_LOG2("%s: cancel from machine state %d\n",
8011 getName(), fMachineState
);
8012 fDoNotPowerDown
= true;
8013 // Stop waiting for app replys.
8014 if ((fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
) ||
8015 (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
) ||
8016 (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
) ||
8017 (fMachineState
== kIOPM_SyncTellClientsPowerDown
) )
8018 cleanClientResponses(false);
8023 case kIOPMRequestTypeChildNotifyDelayCancel
:
8024 if (fMachineState
== kIOPM_NotifyChildrenDelayed
)
8026 PM_LOG2("%s: delay notify cancelled\n", getName());
8027 notifyChildrenDelayed();
8032 panic("PMReplyQueue: unknown reply type %x", request
->getType());
8035 more
|= gIOPMCompletionQueue
->queuePMRequest(request
);
8037 gIOPMWorkQueue
->incrementProducerCount();
8042 //*********************************************************************************
8043 // [private] assertPMDriverCall / deassertPMDriverCall
8044 //*********************************************************************************
8046 bool IOService::assertPMDriverCall(
8047 IOPMDriverCallEntry
* entry
,
8048 IOOptionBits options
,
8049 IOPMinformee
* inform
)
8051 IOService
* target
= 0;
8059 if (fLockedFlags
.PMStop
)
8064 if (((options
& kIOPMADC_NoInactiveCheck
) == 0) && isInactive())
8071 if (!inform
->active
)
8075 target
= inform
->whatObject
;
8076 if (target
->isInactive())
8082 entry
->thread
= current_thread();
8083 entry
->target
= target
;
8084 queue_enter(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
8093 void IOService::deassertPMDriverCall( IOPMDriverCallEntry
* entry
)
8095 bool wakeup
= false;
8099 assert( !queue_empty(&fPMDriverCallQueue
) );
8100 queue_remove(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
8101 if (fLockedFlags
.PMDriverCallWait
)
8109 PM_LOCK_WAKEUP(&fPMDriverCallQueue
);
8112 void IOService::waitForPMDriverCall( IOService
* target
)
8114 const IOPMDriverCallEntry
* entry
;
8115 thread_t thread
= current_thread();
8116 AbsoluteTime deadline
;
8123 queue_iterate(&fPMDriverCallQueue
, entry
, const IOPMDriverCallEntry
*, link
)
8125 // Target of interested driver call
8126 if (target
&& (target
!= entry
->target
))
8129 if (entry
->thread
== thread
)
8133 PM_LOG("%s: %s(%s) on PM thread\n",
8134 fName
, __FUNCTION__
, target
? target
->getName() : "");
8135 OSReportWithBacktrace("%s: %s(%s) on PM thread\n",
8136 fName
, __FUNCTION__
, target
? target
->getName() : "");
8148 fLockedFlags
.PMDriverCallWait
= true;
8149 clock_interval_to_deadline(15, kSecondScale
, &deadline
);
8150 waitResult
= PM_LOCK_SLEEP(&fPMDriverCallQueue
, deadline
);
8151 fLockedFlags
.PMDriverCallWait
= false;
8152 if (THREAD_TIMED_OUT
== waitResult
)
8154 PM_ERROR("%s: waitForPMDriverCall timeout\n", fName
);
8161 //*********************************************************************************
8162 // [private] Debug helpers
8163 //*********************************************************************************
8165 const char * IOService::getIOMessageString( uint32_t msg
)
8167 #define MSG_ENTRY(x) {(int) x, #x}
8169 static const IONamedValue msgNames
[] = {
8170 MSG_ENTRY( kIOMessageCanDevicePowerOff
),
8171 MSG_ENTRY( kIOMessageDeviceWillPowerOff
),
8172 MSG_ENTRY( kIOMessageDeviceWillNotPowerOff
),
8173 MSG_ENTRY( kIOMessageDeviceHasPoweredOn
),
8174 MSG_ENTRY( kIOMessageCanSystemPowerOff
),
8175 MSG_ENTRY( kIOMessageSystemWillPowerOff
),
8176 MSG_ENTRY( kIOMessageSystemWillNotPowerOff
),
8177 MSG_ENTRY( kIOMessageCanSystemSleep
),
8178 MSG_ENTRY( kIOMessageSystemWillSleep
),
8179 MSG_ENTRY( kIOMessageSystemWillNotSleep
),
8180 MSG_ENTRY( kIOMessageSystemHasPoweredOn
),
8181 MSG_ENTRY( kIOMessageSystemWillRestart
),
8182 MSG_ENTRY( kIOMessageSystemWillPowerOn
),
8183 MSG_ENTRY( kIOMessageSystemCapabilityChange
),
8184 MSG_ENTRY( kIOPMMessageLastCallBeforeSleep
),
8185 MSG_ENTRY( kIOMessageSystemPagingOff
),
8189 return IOFindNameForValue(msg
, msgNames
);
8194 // MARK: IOPMRequest
8196 //*********************************************************************************
8197 // IOPMRequest Class
8199 // Requests from PM clients, and also used for inter-object messaging within PM.
8200 //*********************************************************************************
8202 OSDefineMetaClassAndStructors( IOPMRequest
, IOCommand
);
8204 IOPMRequest
* IOPMRequest::create( void )
8206 IOPMRequest
* me
= OSTypeAlloc(IOPMRequest
);
8207 if (me
&& !me
->init(0, kIOPMRequestTypeInvalid
))
8215 bool IOPMRequest::init( IOService
* target
, IOOptionBits type
)
8217 if (!IOCommand::init())
8220 fRequestType
= type
;
8226 // Root node and root domain requests does not prevent the power tree from
8227 // becoming quiescent.
8229 fIsQuiesceBlocker
= ((fTarget
!= gIOPMRootNode
) &&
8230 (fTarget
!= IOService::getPMRootDomain()));
8235 void IOPMRequest::reset( void )
8237 assert( fWorkWaitCount
== 0 );
8238 assert( fFreeWaitCount
== 0 );
8240 detachNextRequest();
8241 detachRootRequest();
8243 if (fCompletionAction
&& (fRequestType
== kIOPMRequestTypeQuiescePowerTree
))
8245 // Call the completion on PM work loop context
8246 fCompletionAction(fCompletionTarget
, fCompletionParam
);
8247 fCompletionAction
= 0;
8250 fRequestType
= kIOPMRequestTypeInvalid
;
8259 bool IOPMRequest::attachNextRequest( IOPMRequest
* next
)
8265 // Postpone the execution of the next request after
8267 fRequestNext
= next
;
8268 fRequestNext
->fWorkWaitCount
++;
8269 #if LOG_REQUEST_ATTACH
8270 PM_LOG("Attached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
8271 OBFUSCATE(this), fRequestType
, OBFUSCATE(fRequestNext
),
8272 fRequestNext
->fRequestType
,
8273 (uint32_t) fRequestNext
->fWorkWaitCount
,
8274 fTarget
->getName());
8281 bool IOPMRequest::detachNextRequest( void )
8287 assert(fRequestNext
->fWorkWaitCount
);
8288 if (fRequestNext
->fWorkWaitCount
)
8289 fRequestNext
->fWorkWaitCount
--;
8290 #if LOG_REQUEST_ATTACH
8291 PM_LOG("Detached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
8292 OBFUSCATE(this), fRequestType
, OBFUSCATE(fRequestNext
),
8293 fRequestNext
->fRequestType
,
8294 (uint32_t) fRequestNext
->fWorkWaitCount
,
8295 fTarget
->getName());
8303 bool IOPMRequest::attachRootRequest( IOPMRequest
* root
)
8309 // Delay the completion of the root request after
8311 fRequestRoot
= root
;
8312 fRequestRoot
->fFreeWaitCount
++;
8313 #if LOG_REQUEST_ATTACH
8314 PM_LOG("Attached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8315 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
8316 (uint32_t) fRequestRoot
->fType
,
8317 (uint32_t) fRequestRoot
->fFreeWaitCount
,
8318 fTarget
->getName());
8325 bool IOPMRequest::detachRootRequest( void )
8331 assert(fRequestRoot
->fFreeWaitCount
);
8332 if (fRequestRoot
->fFreeWaitCount
)
8333 fRequestRoot
->fFreeWaitCount
--;
8334 #if LOG_REQUEST_ATTACH
8335 PM_LOG("Detached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8336 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
8337 (uint32_t) fRequestRoot
->fType
,
8338 (uint32_t) fRequestRoot
->fFreeWaitCount
,
8339 fTarget
->getName());
8348 // MARK: IOPMRequestQueue
8350 //*********************************************************************************
8351 // IOPMRequestQueue Class
8353 // Global queues. Queues are created once and never released.
8354 //*********************************************************************************
8356 OSDefineMetaClassAndStructors( IOPMRequestQueue
, IOEventSource
);
8358 IOPMRequestQueue
* IOPMRequestQueue::create( IOService
* inOwner
, Action inAction
)
8360 IOPMRequestQueue
* me
= OSTypeAlloc(IOPMRequestQueue
);
8361 if (me
&& !me
->init(inOwner
, inAction
))
8369 bool IOPMRequestQueue::init( IOService
* inOwner
, Action inAction
)
8371 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
8374 queue_init(&fQueue
);
8375 fLock
= IOLockAlloc();
8376 return (fLock
!= 0);
8379 void IOPMRequestQueue::free( void )
8386 return IOEventSource::free();
8389 void IOPMRequestQueue::queuePMRequest( IOPMRequest
* request
)
8393 queue_enter(&fQueue
, request
, typeof(request
), fCommandChain
);
8394 IOLockUnlock(fLock
);
8395 if (workLoop
) signalWorkAvailable();
8399 IOPMRequestQueue::queuePMRequestChain( IOPMRequest
** requests
, IOItemCount count
)
8403 assert(requests
&& count
);
8409 queue_enter(&fQueue
, next
, typeof(next
), fCommandChain
);
8411 IOLockUnlock(fLock
);
8412 if (workLoop
) signalWorkAvailable();
8415 bool IOPMRequestQueue::checkForWork( void )
8417 Action dqAction
= (Action
) action
;
8418 IOPMRequest
* request
;
8420 int dequeueCount
= 0;
8423 IOLockLock( fLock
);
8425 while (!queue_empty(&fQueue
))
8427 if (dequeueCount
++ >= kMaxDequeueCount
)
8429 // Allow other queues a chance to work
8434 queue_remove_first(&fQueue
, request
, typeof(request
), fCommandChain
);
8435 IOLockUnlock(fLock
);
8436 target
= request
->getTarget();
8438 more
|= (*dqAction
)( target
, request
, this );
8439 IOLockLock( fLock
);
8442 IOLockUnlock( fLock
);
8447 // MARK: IOPMWorkQueue
8449 //*********************************************************************************
8450 // IOPMWorkQueue Class
8452 // Queue of IOServicePM objects, each with a queue of IOPMRequest sharing the
8454 //*********************************************************************************
8456 OSDefineMetaClassAndStructors( IOPMWorkQueue
, IOEventSource
);
8459 IOPMWorkQueue::create( IOService
* inOwner
, Action invoke
, Action retire
)
8461 IOPMWorkQueue
* me
= OSTypeAlloc(IOPMWorkQueue
);
8462 if (me
&& !me
->init(inOwner
, invoke
, retire
))
8470 bool IOPMWorkQueue::init( IOService
* inOwner
, Action invoke
, Action retire
)
8472 if (!invoke
|| !retire
||
8473 !IOEventSource::init(inOwner
, (IOEventSourceAction
)0))
8476 queue_init(&fWorkQueue
);
8478 fInvokeAction
= invoke
;
8479 fRetireAction
= retire
;
8480 fConsumerCount
= fProducerCount
= 0;
8485 bool IOPMWorkQueue::queuePMRequest( IOPMRequest
* request
, IOServicePM
* pwrMgt
)
8487 queue_head_t
* requestQueue
;
8493 assert( onThread() );
8494 assert( queue_next(&request
->fCommandChain
) ==
8495 queue_prev(&request
->fCommandChain
) );
8497 gIOPMBusyRequestCount
++;
8499 if (request
->isQuiesceType())
8501 if ((request
->getTarget() == gIOPMRootNode
) && !fQuiesceStartTime
)
8503 // Attach new quiesce request to all quiesce blockers in the queue
8504 fQuiesceStartTime
= mach_absolute_time();
8505 attachQuiesceRequest(request
);
8506 fQuiesceRequest
= request
;
8509 else if (fQuiesceRequest
&& request
->isQuiesceBlocker())
8511 // Attach the new quiesce blocker to the blocked quiesce request
8512 request
->attachNextRequest(fQuiesceRequest
);
8515 // Add new request to the tail of the per-service request queue.
8516 // Then immediately check the request queue to minimize latency
8517 // if the queue was empty.
8519 requestQueue
= &pwrMgt
->RequestHead
;
8520 empty
= queue_empty(requestQueue
);
8521 queue_enter(requestQueue
, request
, typeof(request
), fCommandChain
);
8524 more
= checkRequestQueue(requestQueue
, &empty
);
8527 // Request just added is blocked, add its target IOServicePM
8528 // to the work queue.
8529 assert( queue_next(&pwrMgt
->WorkChain
) ==
8530 queue_prev(&pwrMgt
->WorkChain
) );
8532 queue_enter(&fWorkQueue
, pwrMgt
, typeof(pwrMgt
), WorkChain
);
8534 PM_LOG3("IOPMWorkQueue: [%u] added %s@%p to queue\n",
8535 fQueueLength
, pwrMgt
->Name
, OBFUSCATE(pwrMgt
));
8542 bool IOPMWorkQueue::checkRequestQueue( queue_head_t
* requestQueue
, bool * empty
)
8544 IOPMRequest
* request
;
8549 assert(!queue_empty(requestQueue
));
8551 request
= (typeof(request
)) queue_first(requestQueue
);
8552 if (request
->isWorkBlocked())
8553 break; // request dispatch blocked on attached request
8555 target
= request
->getTarget();
8558 done
= (*fInvokeAction
)( target
, request
, this );
8562 PM_LOG("PM request 0x%x dropped\n", request
->getType());
8566 break; // PM state machine blocked
8568 assert(gIOPMBusyRequestCount
> 0);
8569 if (gIOPMBusyRequestCount
)
8570 gIOPMBusyRequestCount
--;
8572 if (request
== fQuiesceRequest
)
8574 fQuiesceRequest
= 0;
8577 queue_remove_first(requestQueue
, request
, typeof(request
), fCommandChain
);
8578 more
|= (*fRetireAction
)( target
, request
, this );
8579 done
= queue_empty(requestQueue
);
8586 // Retired a request that may unblock a previously visited request
8587 // that is still waiting on the work queue. Must trigger another
8595 bool IOPMWorkQueue::checkForWork( void )
8597 IOServicePM
* entry
;
8602 #if WORK_QUEUE_STATS
8603 fStatCheckForWork
++;
8606 // Iterate over all IOServicePM entries in the work queue,
8607 // and check each entry's request queue.
8609 while (fConsumerCount
!= fProducerCount
)
8611 PM_LOG3("IOPMWorkQueue: checkForWork %u %u\n",
8612 fProducerCount
, fConsumerCount
);
8614 fConsumerCount
= fProducerCount
;
8616 #if WORK_QUEUE_STATS
8617 if (queue_empty(&fWorkQueue
))
8623 uint32_t cachedWorkCount
= gIOPMWorkInvokeCount
;
8626 __IGNORE_WCASTALIGN(entry
= (typeof(entry
)) queue_first(&fWorkQueue
));
8627 while (!queue_end(&fWorkQueue
, (queue_entry_t
) entry
))
8629 more
|= checkRequestQueue(&entry
->RequestHead
, &empty
);
8631 // Get next entry, points to head if current entry is last.
8632 __IGNORE_WCASTALIGN(next
= (typeof(next
)) queue_next(&entry
->WorkChain
));
8634 // if request queue is empty, remove IOServicePM from work queue.
8637 assert(fQueueLength
);
8638 if (fQueueLength
) fQueueLength
--;
8639 PM_LOG3("IOPMWorkQueue: [%u] removed %s@%p from queue\n",
8640 fQueueLength
, entry
->Name
, OBFUSCATE(entry
));
8641 queue_remove(&fWorkQueue
, entry
, typeof(entry
), WorkChain
);
8646 #if WORK_QUEUE_STATS
8647 if (cachedWorkCount
== gIOPMWorkInvokeCount
)
8655 void IOPMWorkQueue::signalWorkAvailable( void )
8658 IOEventSource::signalWorkAvailable();
8661 void IOPMWorkQueue::incrementProducerCount( void )
8666 void IOPMWorkQueue::attachQuiesceRequest( IOPMRequest
* quiesceRequest
)
8668 IOServicePM
* entry
;
8669 IOPMRequest
* request
;
8671 if (queue_empty(&fWorkQueue
))
8676 queue_iterate(&fWorkQueue
, entry
, typeof(entry
), WorkChain
)
8678 queue_iterate(&entry
->RequestHead
, request
, typeof(request
), fCommandChain
)
8680 // Attach the quiesce request to any request in the queue that
8681 // is not linked to a next request. These requests will block
8682 // the quiesce request.
8684 if (request
->isQuiesceBlocker())
8686 request
->attachNextRequest(quiesceRequest
);
8692 void IOPMWorkQueue::finishQuiesceRequest( IOPMRequest
* quiesceRequest
)
8694 if (fQuiesceRequest
&& (quiesceRequest
== fQuiesceRequest
) &&
8695 (fQuiesceStartTime
!= 0))
8698 fQuiesceFinishTime
= mach_absolute_time();
8703 // MARK: IOPMCompletionQueue
8705 //*********************************************************************************
8706 // IOPMCompletionQueue Class
8707 //*********************************************************************************
8709 OSDefineMetaClassAndStructors( IOPMCompletionQueue
, IOEventSource
);
8711 IOPMCompletionQueue
*
8712 IOPMCompletionQueue::create( IOService
* inOwner
, Action inAction
)
8714 IOPMCompletionQueue
* me
= OSTypeAlloc(IOPMCompletionQueue
);
8715 if (me
&& !me
->init(inOwner
, inAction
))
8723 bool IOPMCompletionQueue::init( IOService
* inOwner
, Action inAction
)
8725 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
8728 queue_init(&fQueue
);
8732 bool IOPMCompletionQueue::queuePMRequest( IOPMRequest
* request
)
8737 // unblock dependent request
8738 more
= request
->detachNextRequest();
8739 queue_enter(&fQueue
, request
, typeof(request
), fCommandChain
);
8743 bool IOPMCompletionQueue::checkForWork( void )
8745 Action dqAction
= (Action
) action
;
8746 IOPMRequest
* request
;
8751 request
= (typeof(request
)) queue_first(&fQueue
);
8752 while (!queue_end(&fQueue
, (queue_entry_t
) request
))
8754 next
= (typeof(next
)) queue_next(&request
->fCommandChain
);
8755 if (!request
->isFreeBlocked())
8757 queue_remove(&fQueue
, request
, typeof(request
), fCommandChain
);
8758 target
= request
->getTarget();
8760 more
|= (*dqAction
)( target
, request
, this );
8769 // MARK: IOServicePM
8771 OSDefineMetaClassAndStructors(IOServicePM
, OSObject
)
8773 //*********************************************************************************
8776 // Serialize IOServicePM for debugging.
8777 //*********************************************************************************
8780 setPMProperty( OSDictionary
* dict
, const char * key
, uint64_t value
)
8782 OSNumber
* num
= OSNumber::withNumber(value
, sizeof(value
) * 8);
8785 dict
->setObject(key
, num
);
8790 IOReturn
IOServicePM::gatedSerialize( OSSerialize
* s
) const
8792 OSDictionary
* dict
;
8794 int powerClamp
= -1;
8797 if (IdleTimerPeriod
)
8800 if (PMActions
.parameter
& kPMActionsFlagLimitPower
)
8804 if (PMActions
.parameter
&
8805 (kPMActionsFlagIsDisplayWrangler
| kPMActionsFlagIsGraphicsDevice
))
8809 #if WORK_QUEUE_STATS
8810 if (gIOPMRootNode
== ControllingDriver
)
8815 dict
= OSDictionary::withDictionary(
8816 PowerClients
, PowerClients
->getCount() + dictSize
);
8818 dict
= OSDictionary::withCapacity(dictSize
);
8822 setPMProperty(dict
, "CurrentPowerState", CurrentPowerState
);
8823 setPMProperty(dict
, "CapabilityFlags", CurrentCapabilityFlags
);
8824 if (NumberOfPowerStates
)
8825 setPMProperty(dict
, "MaxPowerState", NumberOfPowerStates
-1);
8826 if (DesiredPowerState
!= CurrentPowerState
)
8827 setPMProperty(dict
, "DesiredPowerState", DesiredPowerState
);
8828 if (kIOPM_Finished
!= MachineState
)
8829 setPMProperty(dict
, "MachineState", MachineState
);
8830 if (DeviceOverrideEnabled
)
8831 dict
->setObject("PowerOverrideOn", kOSBooleanTrue
);
8832 if (powerClamp
>= 0)
8833 setPMProperty(dict
, "PowerClamp", powerClamp
);
8835 if (IdleTimerPeriod
)
8841 clock_get_uptime(&now
);
8843 // The idle timer period in milliseconds
8844 setPMProperty(dict
, "IdleTimerPeriod", NextIdleTimerPeriod
* 1000ULL);
8846 // Number of tickles since the last idle timer expiration
8847 setPMProperty(dict
, "ActivityTickles", ActivityTickleCount
);
8849 if (AbsoluteTime_to_scalar(&DeviceActiveTimestamp
))
8851 // Milliseconds since the last activity tickle
8853 SUB_ABSOLUTETIME(&delta
, &DeviceActiveTimestamp
);
8854 absolutetime_to_nanoseconds(delta
, &nsecs
);
8855 setPMProperty(dict
, "TimeSinceLastTickle", NS_TO_MS(nsecs
));
8858 if (!IdleTimerStopped
&& AbsoluteTime_to_scalar(&IdleTimerStartTime
))
8860 // Idle timer elapsed time in milliseconds
8862 SUB_ABSOLUTETIME(&delta
, &IdleTimerStartTime
);
8863 absolutetime_to_nanoseconds(delta
, &nsecs
);
8864 setPMProperty(dict
, "IdleTimerElapsedTime", NS_TO_MS(nsecs
));
8868 #if WORK_QUEUE_STATS
8869 if (gIOPMRootNode
== Owner
)
8871 setPMProperty(dict
, "WQ-CheckForWork",
8872 gIOPMWorkQueue
->fStatCheckForWork
);
8873 setPMProperty(dict
, "WQ-ScanEntries",
8874 gIOPMWorkQueue
->fStatScanEntries
);
8875 setPMProperty(dict
, "WQ-QueueEmpty",
8876 gIOPMWorkQueue
->fStatQueueEmpty
);
8877 setPMProperty(dict
, "WQ-NoWorkDone",
8878 gIOPMWorkQueue
->fStatNoWorkDone
);
8882 if (HasAdvisoryDesire
&& !gIOPMAdvisoryTickleEnabled
)
8884 // Don't report advisory tickle when it has no influence
8885 dict
->removeObject(gIOPMPowerClientAdvisoryTickle
);
8888 ok
= dict
->serialize(s
);
8892 return (ok
? kIOReturnSuccess
: kIOReturnNoMemory
);
8895 bool IOServicePM::serialize( OSSerialize
* s
) const
8897 IOReturn ret
= kIOReturnNotReady
;
8899 if (gIOPMWatchDogThread
== current_thread())
8901 // Calling without lock as this data is collected for debug purpose, before reboot.
8902 // The workloop is probably already hung in state machine.
8903 ret
= gatedSerialize(s
);
8905 else if (gIOPMWorkLoop
)
8907 ret
= gIOPMWorkLoop
->runAction(
8908 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOServicePM::gatedSerialize
),
8909 (OSObject
*) this, (void *) s
);
8912 return (kIOReturnSuccess
== ret
);
8915 void IOServicePM::pmPrint(
8918 uintptr_t param2
) const
8920 gPlatform
->PMLog(Name
, event
, param1
, param2
);
8923 void IOServicePM::pmTrace(
8927 uintptr_t param2
) const
8929 uintptr_t nameAsArg
= 0;
8931 assert(event
< KDBG_CODE_MAX
);
8932 assert((eventFunc
& ~KDBG_FUNC_MASK
) == 0);
8934 // Copy the first characters of the name into an uintptr_t.
8935 // NULL termination is not required.
8936 strncpy((char*)&nameAsArg
, Name
, sizeof(nameAsArg
));
8938 IOTimeStampConstant(IODBG_POWER(event
) | eventFunc
, nameAsArg
, (uintptr_t)Owner
->getRegistryEntryID(), (uintptr_t)(OBFUSCATE(param1
)), (uintptr_t)(OBFUSCATE(param2
)));