/*
- * Copyright (c) 1998-2016 Apple Inc. All rights reserved.
+ * Copyright (c) 1998-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <IOKit/IOMessage.h>
#include <IOKit/IOPlatformExpert.h>
#include <IOKit/IOService.h>
+#include <IOKit/IOUserServer.h>
#include <IOKit/IOEventSource.h>
#include <IOKit/IOWorkLoop.h>
#include <IOKit/IOCommand.h>
#include "IOServicePMPrivate.h"
#include "IOKitKernelInternal.h"
-
+#if USE_SETTLE_TIMER
static void settle_timer_expired(thread_call_param_t, thread_call_param_t);
+#endif
static void idle_timer_expired(thread_call_param_t, thread_call_param_t);
static void tellKernelClientApplier(OSObject * object, void * arg);
static void tellAppClientApplier(OSObject * object, void * arg);
+static const char * getNotificationPhaseString(uint32_t phase);
static uint64_t
computeTimeDeltaNS( const AbsoluteTime * start )
static IOService * gIOPMRootNode = NULL;
static IOPlatformExpert * gPlatform = NULL;
+// log setPowerStates and powerStateChange longer than (ns):
+static uint64_t gIOPMSetPowerStateLogNS =
+#if defined(__i386__) || defined(__x86_64__)
+ (300ULL * 1000ULL * 1000ULL)
+#else
+ (50ULL * 1000ULL * 1000ULL)
+#endif
+;
const OSSymbol * gIOPMPowerClientDevice = NULL;
const OSSymbol * gIOPMPowerClientDriver = NULL;
return type;
}
-static IOPMRequestTag
-getPMRequestTag( void )
-{
- IOPMRequestTag tag = 0;
- if (gIOPMRequest &&
- (gIOPMRequest->getType() == kIOPMRequestTypeRequestPowerStateOverride)) {
- tag = gIOPMRequest->fRequestTag;
- }
- return tag;
-}
-
SYSCTL_UINT(_kern, OID_AUTO, pmtimeout, CTLFLAG_RW | CTLFLAG_LOCKED, &gCanSleepTimeout, 0, "Power Management Timeout");
//******************************************************************************
#define ns_per_us 1000
#define k30Seconds (30*us_per_s)
#define k5Seconds ( 5*us_per_s)
-#if CONFIG_EMBEDDED
+#if !defined(XNU_TARGET_OS_OSX)
#define kCanSleepMaxTimeReq k5Seconds
-#else
+#else /* defined(XNU_TARGET_OS_OSX) */
#define kCanSleepMaxTimeReq k30Seconds
-#endif
+#endif /* defined(XNU_TARGET_OS_OSX) */
#define kMaxTimeRequested k30Seconds
#define kMinAckTimeoutTicks (10*1000000)
#define kIOPMTardyAckSPSKey "IOPMTardyAckSetPowerState"
#define IS_POWER_DROP (StateOrder(fHeadNotePowerState) < StateOrder(fCurrentPowerState))
#define IS_POWER_RISE (StateOrder(fHeadNotePowerState) > StateOrder(fCurrentPowerState))
-// log setPowerStates longer than (ns):
-#if defined(__i386__) || defined(__x86_64__)
-#define LOG_SETPOWER_TIMES (300ULL * 1000ULL * 1000ULL)
-#else
-#define LOG_SETPOWER_TIMES (50ULL * 1000ULL * 1000ULL)
-#endif
// log app responses longer than (ns):
#define LOG_APP_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
// use message tracer to log messages longer than (ns):
fMachineState = fSavedMachineState; \
fSavedMachineState = kIOPM_BadMachineState; } while (false)
-#define PM_ACTION_0(a) \
+#define PM_ACTION_TICKLE(a) \
do { if (fPMActions.a) { \
(fPMActions.a)(fPMActions.target, this, &fPMActions); } \
} while (false)
-#define PM_ACTION_2(a, x, y) \
+#define PM_ACTION_CHANGE(a, x, y) \
do { if (fPMActions.a) { \
- (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y, \
- getPMRequestTag()); } \
+ (fPMActions.a)(fPMActions.target, this, &fPMActions, gIOPMRequest, x, y); } \
} while (false)
-#define PM_ACTION_3(a, x, y, z) \
+#define PM_ACTION_CLIENT(a, x, y, z) \
do { if (fPMActions.a) { \
(fPMActions.a)(fPMActions.target, this, &fPMActions, x, y, z); } \
} while (false)
if (gIOPMRequestQueue && gIOPMReplyQueue && gIOPMCompletionQueue) {
gIOPMInitialized = true;
}
+
+#if (DEVELOPMENT || DEBUG)
+ uint32_t setPowerStateLogMS = 0;
+ if (PE_parse_boot_argn("setpowerstate_log", &setPowerStateLogMS, sizeof(setPowerStateLogMS))) {
+ gIOPMSetPowerStateLogNS = setPowerStateLogMS * 1000000ULL;
+ }
+#endif
}
if (!gIOPMInitialized) {
return;
fAckTimer = thread_call_allocate(
&IOService::ack_timer_expired, (thread_call_param_t)this);
+#if USE_SETTLE_TIMER
fSettleTimer = thread_call_allocate(
&settle_timer_expired, (thread_call_param_t)this);
+#endif
fIdleTimer = thread_call_allocate(
&idle_timer_expired, (thread_call_param_t)this);
fDriverCallEntry = thread_call_allocate(
fBlockedArray->release();
fBlockedArray = NULL;
}
-
+#if USE_SETTLE_TIMER
if (fSettleTimer) {
thread_call_cancel(fSettleTimer);
thread_call_free(fSettleTimer);
fSettleTimer = NULL;
}
+#endif
if (fAckTimer) {
thread_call_cancel(fAckTimer);
thread_call_free(fAckTimer);
fNotifyClientArray->release();
fNotifyClientArray = NULL;
}
+ if (fReportBuf && fNumberOfPowerStates) {
+ IOFree(fReportBuf, STATEREPORT_BUFSIZE(fNumberOfPowerStates));
+ fReportBuf = NULL;
+ }
if (fPowerStates && fNumberOfPowerStates) {
IODelete(fPowerStates, IOPMPSEntry, fNumberOfPowerStates);
fNumberOfPowerStates = 0;
IOService * parent;
IOPMPowerFlags powerFlags;
bool knowsState;
- unsigned long powerState;
- unsigned long tempDesire;
+ IOPMPowerStateIndex powerState;
+ IOPMPowerStateIndex tempDesire;
PM_ASSERT_IN_GATE();
parent = (IOService *) connection->getParentEntry(gIOPowerPlane);
fPreviousRequestPowerFlags = (IOPMPowerFlags)(-1);
adjustPowerState(tempDesire);
}
-
- getPMRootDomain()->tagPowerPlaneService(this, &fPMActions);
}
//*********************************************************************************
powerStatesCopy[i].outputPowerFlags = powerStates[i].outputPowerCharacter;
powerStatesCopy[i].inputPowerFlags = powerStates[i].inputPowerRequirement;
powerStatesCopy[i].staticPower = powerStates[i].staticPower;
+#if USE_SETTLE_TIMER
powerStatesCopy[i].settleUpTime = powerStates[i].settleUpTime;
powerStatesCopy[i].settleDownTime = powerStates[i].settleDownTime;
+#endif
if (powerStates[i].version >= kIOPMPowerStateVersion2) {
stateOrder = powerStates[i].stateOrder;
} else {
void
IOService::handleRegisterPowerDriver( IOPMRequest * request )
{
- IOService * powerDriver = (IOService *) request->fArg0;
- IOPMPSEntry * powerStates = (IOPMPSEntry *) request->fArg1;
- unsigned long numberOfStates = (unsigned long) request->fArg2;
- unsigned long i, stateIndex;
- unsigned long lowestPowerState;
- IOService * root;
- OSIterator * iter;
+ IOService * powerDriver = (IOService *) request->fArg0;
+ IOPMPSEntry * powerStates = (IOPMPSEntry *) request->fArg1;
+ IOPMPowerStateIndex numberOfStates = (IOPMPowerStateIndex) request->fArg2;
+ IOPMPowerStateIndex i, stateIndex;
+ IOPMPowerStateIndex lowestPowerState;
+ IOService * root;
+ OSIterator * iter;
PM_ASSERT_IN_GATE();
assert(powerStates);
assert(numberOfStates > 1);
if (!fNumberOfPowerStates) {
- OUR_PMLog(kPMLogControllingDriver,
- (unsigned long) numberOfStates,
- (unsigned long) kIOPMPowerStateVersion1);
+ OUR_PMLog(kPMLogControllingDriver, numberOfStates, kIOPMPowerStateVersion1);
fPowerStates = powerStates;
fNumberOfPowerStates = numberOfStates;
iter->release();
}
+ // Populate IOPMActions for a few special services
+ getPMRootDomain()->tagPowerPlaneService(this, &fPMActions, fNumberOfPowerStates - 1);
+
if (inPlane(gIOPowerPlane) && fParentsKnowState) {
IOPMPowerStateIndex tempDesire;
fMaxPowerState = fControllingDriver->maxCapabilityForDomainState(fParentsCurrentPowerFlags);
if (fInsertInterestSet) {
while ((driver = (IOService *) fInsertInterestSet->getAnyObject())) {
if (list->findItem(driver) == NULL) {
- informee = list->appendNewInformee(driver);
+ list->appendNewInformee(driver);
}
fInsertInterestSet->removeObject(driver);
}
IOService::handleAcknowledgePowerChange( IOPMRequest * request )
{
IOPMinformee * informee;
- unsigned long childPower = kIOPMUnknown;
+ IOPMPowerStateIndex childPower = kIOPMUnknown;
IOService * theChild;
IOService * whichObject;
bool all_acked = false;
if (informee->timer != 0) {
if (informee->timer > 0) {
uint64_t nsec = computeTimeDeltaNS(&informee->startTime);
- if (nsec > LOG_SETPOWER_TIMES) {
+ if (nsec > gIOPMSetPowerStateLogNS) {
getPMRootDomain()->pmStatsRecordApplicationResponse(
gIOPMStatsDriverPSChangeSlow, informee->whatObject->getName(),
fDriverCallReason, NS_TO_MS(nsec), informee->whatObject->getRegistryEntryID(),
- NULL, fHeadNotePowerState);
+ NULL, fHeadNotePowerState, true);
}
}
//*********************************************************************************
void
-IOService::adjustPowerState( uint32_t clamp )
+IOService::adjustPowerState( IOPMPowerStateIndex clamp )
{
PM_ASSERT_IN_GATE();
computeDesiredState(clamp, false);
if (nr) {
submitPMRequest(nr);
}
+
+ // For display wrangler or any other delay-eligible (dark wake clamped)
+ // drivers attached to root domain in the power plane.
nr = acquirePMRequest(getPMRootDomain(), kIOPMRequestTypeChildNotifyDelayCancel);
if (nr) {
submitPMRequest(nr);
PM_ASSERT_IN_GATE();
if (fControllingDriver && fParentsKnowState && inPlane(gIOPowerPlane) &&
(fCurrentPowerState == fHighestPowerState)) {
- IOOptionBits options = (uintptr_t) request->fArg0;
+ IOPMPowerChangeFlags options = (IOPMPowerChangeFlags)(uintptr_t) request->fArg0;
startPowerChange(
/* flags */ kIOPMSelfInitiated | kIOPMSynchronize |
IOPowerConnection * connection;
IOPMPowerStateIndex maxPowerState;
IOPMPowerFlags combinedPowerFlags;
- bool savedParentsKnowState;
IOReturn result = IOPMAckImplied;
PM_ASSERT_IN_GATE();
goto exit_no_ack;
}
- savedParentsKnowState = fParentsKnowState;
-
// Combine parents' output power flags.
combinedPowerFlags = 0;
//*********************************************************************************
// [public] temporaryPowerClampOn
//
-// A power domain wants to clamp its power on till it has children which
-// will thendetermine the power domain state.
+// A power domain wants to be clamped to max power until it has children which
+// will then determine the power domain state.
//
// We enter the highest state until addPowerChild is called.
//*********************************************************************************
}
gIOPMPowerClientDevice->retain();
- request->fRequestTag = tag;
+ request->fTag = tag;
request->fArg0 = (void *) ordinal;
request->fArg1 = (void *) gIOPMPowerClientDevice;
request->fArg2 = NULL;
// Prevent needless downwards power transitions by clamping power
// until the scheduled request is executed.
+ //
+ // TODO: review fOverrideMaxPowerState
if (gIOPMWorkLoop->inGate() && (ordinal < fNumberOfPowerStates)) {
fTempClampPowerState = StateMax(fTempClampPowerState, ordinal);
fTempClampCount++;
+ request->fArg2 = (void *)(uintptr_t) true;
+
+ // Place a power state ceiling to prevent any transition to a
+ // power state higher than fOverrideMaxPowerState.
fOverrideMaxPowerState = ordinal;
- request->fArg2 = (void *) (uintptr_t) true;
}
submitPMRequest( request );
return IOPMNoErr;
}
+//*********************************************************************************
+// Tagged form of changePowerStateTo()
+//*********************************************************************************
+
+IOReturn
+IOService::changePowerStateWithTagTo( IOPMPowerStateIndex ordinal, IOPMRequestTag tag )
+{
+ OUR_PMLog(kPMLogChangeStateTo, ordinal, tag);
+ return requestPowerState(gIOPMPowerClientDriver, ordinal, tag);
+}
+
+//*********************************************************************************
+// Tagged form of changePowerStateToPriv()
+//*********************************************************************************
+
+IOReturn
+IOService::changePowerStateWithTagToPriv( unsigned long ordinal, IOPMRequestTag tag )
+{
+ OUR_PMLog(kPMLogChangeStateToPriv, ordinal, tag);
+ return requestPowerState(gIOPMPowerClientDevice, ordinal, tag);
+}
+
//*********************************************************************************
// [public] changePowerStateForRootDomain
//
IOReturn
IOService::requestPowerState(
const OSSymbol * client,
- uint32_t state )
+ IOPMPowerStateIndex state,
+ IOPMRequestTag tag )
{
IOPMRequest * request;
- if (!client) {
+ if (!client || (state > UINT_MAX)) {
return kIOReturnBadArgument;
}
if (!initialized) {
}
client->retain();
+ request->fTag = tag;
request->fArg0 = (void *)(uintptr_t) state;
request->fArg1 = (void *) client;
request->fArg2 = NULL;
if (gIOPMWorkLoop->inGate() && (state < fNumberOfPowerStates)) {
fTempClampPowerState = StateMax(fTempClampPowerState, state);
fTempClampCount++;
- request->fArg2 = (void *) (uintptr_t) true;
+ request->fArg2 = (void *)(uintptr_t) true;
}
submitPMRequest( request );
void
IOService::handleRequestPowerState( IOPMRequest * request )
{
- const OSSymbol * client = (const OSSymbol *) request->fArg1;
- uint32_t state = (uint32_t)(uintptr_t) request->fArg0;
+ const OSSymbol * client = (const OSSymbol *) request->fArg1;
+ IOPMPowerStateIndex state = (IOPMPowerStateIndex) request->fArg0;
PM_ASSERT_IN_GATE();
if (request->fArg2) {
//*********************************************************************************
void
-IOService::updatePowerClient( const OSSymbol * client, uint32_t powerState )
+IOService::updatePowerClient( const OSSymbol * client, IOPMPowerStateIndex powerState )
{
IOPMPowerStateIndex oldPowerState = kPowerStateZero;
+ if (powerState > UINT_MAX) {
+ assert(false);
+ return;
+ }
+
if (!fPowerClients) {
fPowerClients = OSDictionary::withCapacity(4);
}
}
}
- PM_ACTION_3(actionUpdatePowerClient, client, oldPowerState, powerState);
+ PM_ACTION_CLIENT(actionUpdatePowerClient, client, oldPowerState, powerState);
}
}
}
}
-uint32_t
+IOPMPowerStateIndex
IOService::getPowerStateForClient( const OSSymbol * client )
{
- uint32_t powerState = kPowerStateZero;
+ IOPMPowerStateIndex powerState = kPowerStateZero;
if (fPowerClients && client) {
OSNumber * num = (OSNumber *) fPowerClients->getObject(client);
OSIterator * iter;
OSObject * next;
IOPowerConnection * connection;
- uint32_t desiredState = kPowerStateZero;
- uint32_t newPowerState = kPowerStateZero;
+ IOPMPowerStateIndex desiredState = kPowerStateZero;
+ IOPMPowerStateIndex newPowerState = kPowerStateZero;
bool hasChildren = false;
// Desired power state is always 0 without a controlling driver.
desiredState = getPowerStateForClient(client);
assert(desiredState < fNumberOfPowerStates);
PM_LOG1(" %u %s\n",
- desiredState, client->getCStringNoCopy());
+ (uint32_t) desiredState, client->getCStringNoCopy());
newPowerState = StateMax(newPowerState, desiredState);
PM_LOG1(" temp %u, clamp %u, current %u, new %u\n",
(uint32_t) localClamp, (uint32_t) fTempClampPowerState,
- (uint32_t) fCurrentPowerState, newPowerState);
+ (uint32_t) fCurrentPowerState, (uint32_t) newPowerState);
if (!computeOnly) {
// Restart idle timer if possible when device desire has increased.
fActivityTickleCount++;
clock_get_uptime(&fDeviceActiveTimestamp);
- PM_ACTION_0(actionActivityTickle);
+ PM_ACTION_TICKLE(actionActivityTickle);
// Record the last tickle power state.
// This helps to filter out redundant tickles as
void
IOService::handleActivityTickle( IOPMRequest * request )
{
- uint32_t ticklePowerState = (uint32_t)(uintptr_t) request->fArg0;
- uint32_t tickleFlags = (uint32_t)(uintptr_t) request->fArg1;
- uint32_t tickleGeneration = (uint32_t)(uintptr_t) request->fArg2;
- bool adjustPower = false;
+ IOPMPowerStateIndex ticklePowerState = (IOPMPowerStateIndex) request->fArg0;
+ IOPMPowerStateIndex tickleFlags = (IOPMPowerStateIndex) request->fArg1;
+ uint32_t tickleGeneration = (uint32_t)(uintptr_t) request->fArg2;
+ bool adjustPower = false;
PM_ASSERT_IN_GATE();
if (fResetPowerStateOnWake && (tickleGeneration != gIOPMTickleGeneration)) {
if (tickleFlags & kTickleTypeActivity) {
IOPMPowerStateIndex deviceDesireOrder = StateOrder(fDeviceDesire);
- uint32_t idleTimerGeneration = ticklePowerState; // kTickleTypePowerDrop
+ IOPMPowerStateIndex idleTimerGeneration = ticklePowerState; // kTickleTypePowerDrop
if (tickleFlags & kTickleTypePowerRise) {
if ((StateOrder(ticklePowerState) > deviceDesireOrder) &&
OUR_PMLog(kPMLogSetIdleTimerPeriod, period, fIdleTimerPeriod);
+ if (period > INT_MAX) {
+ return kIOReturnBadArgument;
+ }
+
IOPMRequest * request =
acquirePMRequest( this, kIOPMRequestTypeSetIdleTimerPeriod );
if (!request) {
SInt32 idle_in = 0;
boolean_t pending;
- if (!initialized || !fIdleTimerPeriod) {
+ if (!initialized || !fIdleTimerPeriod ||
+ ((unsigned int) fCurrentPowerState != fCurrentPowerState)) {
return;
}
clock_get_uptime(&uptime);
// Subclasses may modify idle sleep algorithm
- idle_in = nextIdleTimeout(uptime, fDeviceActiveTimestamp, fCurrentPowerState);
+ idle_in = nextIdleTimeout(uptime, fDeviceActiveTimestamp, (unsigned int) fCurrentPowerState);
// Check for out-of range responses
if (idle_in > maxTimeout) {
// use standard implementation
idle_in = IOService::nextIdleTimeout(uptime,
fDeviceActiveTimestamp,
- fCurrentPowerState);
+ (unsigned int) fCurrentPowerState);
} else if (idle_in < minTimeout) {
idle_in = fIdleTimerPeriod;
}
return kPowerStateZero;
}
- return fCurrentPowerState;
+ return (UInt32) fCurrentPowerState;
}
#ifndef __LP64__
IOPowerConnection * parentConnection,
IOPMPowerFlags parentFlags )
{
- uint32_t savedPMActionsParam;
+ uint32_t savedPMActionsState;
PM_ASSERT_IN_GATE();
assert( fMachineState == kIOPM_Finished );
}
fIsPreChange = true;
- savedPMActionsParam = fPMActions.parameter;
- PM_ACTION_2(actionPowerChangeOverride, &powerState, &changeFlags);
+ savedPMActionsState = fPMActions.state;
+ PM_ACTION_CHANGE(actionPowerChangeOverride, &powerState, &changeFlags);
// rdar://problem/55040032
// Schedule a power adjustment after removing the power clamp
// automatically request parent power when necessary.
if (!fAdjustPowerScheduled &&
((changeFlags & kIOPMSelfInitiated) == 0) &&
- ((fPMActions.parameter & kPMActionsFlagLimitPower) == 0) &&
- ((savedPMActionsParam & kPMActionsFlagLimitPower) != 0)) {
+ ((fPMActions.state & kPMActionsStatePowerClamped) == 0) &&
+ ((savedPMActionsState & kPMActionsStatePowerClamped) != 0)) {
IOPMRequest * request = acquirePMRequest(this, kIOPMRequestTypeAdjustPowerState);
if (request) {
submitPMRequest(request);
IOPMinformee * informee;
IOPMinformeeList * list = fInterestedDrivers;
DriverCallParam * param;
- IOItemCount count;
- IOItemCount skipCnt = 0;
+ unsigned long numItems;
+ uint32_t count;
+ uint32_t skipCnt = 0;
PM_ASSERT_IN_GATE();
assert( fDriverCallParamCount == 0 );
fHeadNotePendingAcks = 0;
- count = list->numberOfItems();
- if (!count) {
- goto done; // no interested drivers
+ numItems = list->numberOfItems();
+ if (!numItems || ((uint32_t) numItems != numItems)) {
+ goto done; // interested drivers count out of range
}
+ count = (uint32_t) numItems;
+
// Allocate an array of interested drivers and their return values
// for the callout thread. Everything else is still "owned" by the
// PM work loop, which can run to process acknowledgePowerChange()
{
assert( fDriverCallBusy == false );
- // Only for root domain in the will-change phase
+ // Only for root domain in the will-change phase.
+ // On a power up, don't notify children right after the interested drivers.
+ // Perform setPowerState() first, then notify the children.
if (!IS_ROOT_DOMAIN || (fMachineState != kIOPM_OurChangeSetPowerState)) {
notifyChildren();
return;
if (assertPMDriverCall(&callEntry, kIOPMDriverCallMethodSetPowerState)) {
OUR_PMLogFuncStart(kPMLogProgramHardware, (uintptr_t) this, powerState);
clock_get_uptime(&fDriverCallStartTime);
- result = fControllingDriver->setPowerState( powerState, this );
+
+ if (reserved && reserved->uvars && reserved->uvars->userServer) {
+ result = reserved->uvars->userServer->serviceSetPowerState(fControllingDriver, this, fHeadNotePowerArrayEntry->capabilityFlags, powerState);
+ } else {
+ result = fControllingDriver->setPowerState( powerState, this );
+ }
clock_get_uptime(&end);
OUR_PMLogFuncEnd(kPMLogProgramHardware, (uintptr_t) this, (UInt32) result);
SUB_ABSOLUTETIME(&end, &fDriverCallStartTime);
absolutetime_to_nanoseconds(end, &nsec);
- if (nsec > LOG_SETPOWER_TIMES) {
+ if (nsec > gIOPMSetPowerStateLogNS) {
getPMRootDomain()->pmStatsRecordApplicationResponse(
gIOPMStatsDriverPSChangeSlow,
fName, kDriverCallSetPowerState, NS_TO_MS(nsec), getRegistryEntryID(),
SUB_ABSOLUTETIME(&end, &informee->startTime);
absolutetime_to_nanoseconds(end, &nsec);
- if (nsec > LOG_SETPOWER_TIMES) {
+ if (nsec > gIOPMSetPowerStateLogNS) {
getPMRootDomain()->pmStatsRecordApplicationResponse(
gIOPMStatsDriverPSChangeSlow, driver->getName(),
fDriverCallReason, NS_TO_MS(nsec), driver->getRegistryEntryID(),
// Do not inform driver and clients about this request completion,
// except for the originator (root domain).
- PM_ACTION_2(actionPowerChangeDone,
+ PM_ACTION_CHANGE(actionPowerChangeDone,
fHeadNotePowerState, fHeadNoteChangeFlags);
if (getPMRequestType() == kIOPMRequestTypeSynchronizePowerTree) {
PM_LOCK();
if (fReportBuf) {
ts = mach_absolute_time();
- STATEREPORT_SETSTATE(fReportBuf, fCurrentPowerState, ts);
+ STATEREPORT_SETSTATE(fReportBuf, (uint16_t) fCurrentPowerState, ts);
}
PM_UNLOCK();
#if PM_VARS_SUPPORT
fPMVars->myCurrentState = fCurrentPowerState;
#endif
OUR_PMLog(kPMLogChangeDone, fCurrentPowerState, prevPowerState);
- PM_ACTION_2(actionPowerChangeDone,
- fHeadNotePowerState, fHeadNoteChangeFlags);
+ PM_ACTION_CHANGE(actionPowerChangeDone,
+ prevPowerState, fHeadNoteChangeFlags);
actionCalled = true;
powerStatePtr = &fPowerStates[fCurrentPowerState];
PM_LOCK();
if (fReportBuf) {
ts = mach_absolute_time();
- STATEREPORT_SETSTATE(fReportBuf, fCurrentPowerState, ts);
+ STATEREPORT_SETSTATE(fReportBuf, (uint16_t) fCurrentPowerState, ts);
}
PM_UNLOCK();
#if PM_VARS_SUPPORT
#endif
OUR_PMLog(kPMLogChangeDone, fCurrentPowerState, prevPowerState);
- PM_ACTION_2(actionPowerChangeDone,
- fHeadNotePowerState, fHeadNoteChangeFlags);
+ PM_ACTION_CHANGE(actionPowerChangeDone,
+ prevPowerState, fHeadNoteChangeFlags);
actionCalled = true;
powerStatePtr = &fPowerStates[fCurrentPowerState];
}
if (!actionCalled) {
- PM_ACTION_2(actionPowerChangeDone,
+ PM_ACTION_CHANGE(actionPowerChangeDone,
fHeadNotePowerState, fHeadNoteChangeFlags);
}
}
// Change started, but may not complete...
// Can be canceled (power drop) or deferred (power rise).
- PM_ACTION_2(actionPowerChangeStart, fHeadNotePowerState, &fHeadNoteChangeFlags);
+ PM_ACTION_CHANGE(actionPowerChangeStart, fHeadNotePowerState, &fHeadNoteChangeFlags);
// Two separate paths, depending if power is being raised or lowered.
// Lowering power is subject to approval by clients of this service.
return;
}
- PM_ACTION_2(actionPowerChangeStart, fHeadNotePowerState, &fHeadNoteChangeFlags);
+ PM_ACTION_CHANGE(actionPowerChangeStart, fHeadNotePowerState, &fHeadNoteChangeFlags);
if (fHeadNoteChangeFlags & kIOPMNotDone) {
OurChangeFinish();
return OurChangeFinish();
}
+ if (!IS_POWER_DROP) {
+ // Notify root domain immediately after notifying interested
+ // drivers and power children.
+ getPMRootDomain()->willTellSystemCapabilityDidChange();
+ }
+
getPMRootDomain()->tracePoint( IS_POWER_DROP ?
kIOPMTracePointSleepCapabilityClients :
kIOPMTracePointWakeCapabilityClients );
// Power domain is forcing us to lower power
if (StateOrder(fHeadNotePowerState) < StateOrder(fCurrentPowerState)) {
- PM_ACTION_2(actionPowerChangeStart, fHeadNotePowerState, &fHeadNoteChangeFlags);
+ PM_ACTION_CHANGE(actionPowerChangeStart, fHeadNotePowerState, &fHeadNoteChangeFlags);
// Tell apps and kernel clients
fInitialPowerChange = false;
if (fHeadNoteChangeFlags & kIOPMDomainDidChange) {
if (StateOrder(fHeadNotePowerState) > StateOrder(fCurrentPowerState)) {
- PM_ACTION_2(actionPowerChangeStart,
+ PM_ACTION_CHANGE(actionPowerChangeStart,
fHeadNotePowerState, &fHeadNoteChangeFlags);
// Parent did change up - start our change up
void
IOService::settleTimerExpired( void )
{
+#if USE_SETTLE_TIMER
fSettleTimeUS = 0;
gIOPMWorkQueue->signalWorkAvailable();
+#endif
}
//*********************************************************************************
// Holds a retain while the settle timer callout is in flight.
//*********************************************************************************
+#if USE_SETTLE_TIMER
static void
settle_timer_expired( thread_call_param_t arg0, thread_call_param_t arg1 )
{
}
me->release();
}
+#endif
//*********************************************************************************
// [private] startSettleTimer
void
IOService::startSettleTimer( void )
{
-#if NOT_USEFUL
+#if USE_SETTLE_TIMER
// This function is broken and serves no useful purpose since it never
// updates fSettleTimeUS to a non-zero value to stall the state machine,
// yet it starts a delay timer. It appears no driver relies on a delay
PM_ERROR("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms\n",
fName, OBFUSCATE(this), fCurrentPowerState, fHeadNotePowerState, NS_TO_MS(nsec));
-#if DEBUG || DEVELOPMENT || CONFIG_EMBEDDED
- uint32_t panic_allowed = -1;
- PE_parse_boot_argn("setpowerstate_panic", &panic_allowed, sizeof(panic_allowed));
- if (panic_allowed != 0) {
+#if DEBUG || DEVELOPMENT || !defined(XNU_TARGET_OS_OSX)
+ bool panic_allowed = false;
+ uint32_t setpowerstate_panic = -1;
+ PE_parse_boot_argn("setpowerstate_panic", &setpowerstate_panic, sizeof(setpowerstate_panic));
+ panic_allowed = setpowerstate_panic != 0;
+#ifdef CONFIG_XNUPOST
+ uint64_t kernel_post_args = 0;
+ PE_parse_boot_argn("kernPOST", &kernel_post_args, sizeof(kernel_post_args));
+ if (kernel_post_args != 0) {
+ panic_allowed = false;
+ }
+#endif /* CONFIG_XNUPOST */
+ if (panic_allowed) {
// rdar://problem/48743340 - excluding AppleSEPManager from panic
const char *whitelist = "AppleSEPManager";
if (strncmp(fName, whitelist, strlen(whitelist))) {
fName, this, fCurrentPowerState, fHeadNotePowerState, NS_TO_MS(nsec));
}
} else {
- PM_ERROR("setPowerState panic disabled by setpowerstate_panic boot-arg\n");
+#ifdef CONFIG_XNUPOST
+ if (kernel_post_args != 0) {
+ PM_ERROR("setPowerState panic disabled by kernPOST boot-arg\n");
+ }
+#endif /* CONFIG_XNUPOST */
+ if (setpowerstate_panic != 0) {
+ PM_ERROR("setPowerState panic disabled by setpowerstate_panic boot-arg\n");
+ }
}
-#else
+#else /* !(DEBUG || DEVELOPMENT || !defined(XNU_TARGET_OS_OSX)) */
if (gIOKitDebug & kIOLogDebugPower) {
panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
fName, this, fCurrentPowerState, fHeadNotePowerState, NS_TO_MS(nsec));
function_addr = OSMemberFunctionCast(const void *, fControllingDriver, &IOService::setPowerState);
kext = OSKext::lookupKextWithAddress((vm_address_t)function_addr);
if (kext) {
+#if __has_feature(ptrauth_calls)
+ function_addr = (const void*)VM_KERNEL_STRIP_PTR(function_addr);
+#endif /* __has_feature(ptrauth_calls) */
const char *bundleID = kext->getIdentifierCString();
const char *apple_prefix = "com.apple";
const char *kernel_prefix = "__kernel__";
}
kext->release();
}
- // Unblock state machine and pretend driver has acked.
- done = true;
}
-#endif
+#endif /* !(DEBUG || DEVELOPMENT || !defined(XNU_TARGET_OS_OSX)) */
+ // Unblock state machine and pretend driver has acked.
+ done = true;
getPMRootDomain()->reset_watchdog_timer(this, 0);
} else {
// still waiting, set timer again
void
IOService::tellSystemCapabilityChange( uint32_t nextMS )
{
+ assert(IS_ROOT_DOMAIN);
+
MS_PUSH( nextMS );
fMachineState = kIOPM_TellCapabilityChangeDone;
fOutOfBandMessage = kIOMessageSystemCapabilityChange;
assert( fResponseArray == NULL );
assert( fNotifyClientArray == NULL );
- if (messageType == (int)kIOPMMessageLastCallBeforeSleep) {
- RD_LOG("tellClientsWithResponse( kIOPMMessageLastCallBeforeSleep, %d )\n",
- fOutOfBandParameter);
- } else {
- RD_LOG("tellClientsWithResponse( %s, %d )\n",
- getIOMessageString(messageType), fOutOfBandParameter);
- }
+ RD_LOG("tellClientsWithResponse( %s, %s )\n", getIOMessageString(messageType),
+ getNotificationPhaseString(fOutOfBandParameter));
fResponseArray = OSArray::withCapacity( 1 );
if (!fResponseArray) {
context.messageFilter = (isRootDomain) ?
OSMemberFunctionCast(
IOPMMessageFilter,
- this,
+ (IOPMrootDomain *)this,
&IOPMrootDomain::systemMessageFilter) : NULL;
switch (fOutOfBandParameter) {
break;
case kNotifyCapabilityChangeApps:
+ context.enableTracing = isRootDomain;
applyToInterested( gIOAppPowerStateInterest,
pmTellCapabilityAppWithResponse, (void *) &context );
if (context.messageType == kIOMessageCanSystemSleep) {
fNotifyClientArray = context.notifyClients;
if (context.skippedInDark) {
- IOLog("tellClientsWithResponse(%s, %d) %d of %d skipped in dark\n",
- getIOMessageString(messageType), fOutOfBandParameter,
+ IOLog("tellClientsWithResponse(%s, %s) %d of %d skipped in dark\n",
+ getIOMessageString(messageType), getNotificationPhaseString(fOutOfBandParameter),
context.skippedInDark, context.skippedInDark + context.notSkippedInDark);
}
IOReturn retCode;
AbsoluteTime start, end;
uint64_t nsec;
+ bool enableTracing;
if (context->messageFilter &&
!context->messageFilter(context->us, object, context, NULL, NULL)) {
- if ((kIOLogDebugPower & gIOKitDebug) &&
- (OSDynamicCast(_IOServiceInterestNotifier, object))) {
- _IOServiceInterestNotifier *n = (_IOServiceInterestNotifier *) object;
- PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
- context->us->getName(),
- getIOMessageString(context->messageType),
- OBFUSCATE(object), OBFUSCATE(n->handler));
- }
+ getPMRootDomain()->traceFilteredNotification(object);
return;
}
+ // Besides interest notifiers this applier function can also be invoked against
+ // IOService clients of context->us, so notifier can be NULL. But for tracing
+ // purposes the IOService clients can be ignored but each will still consume
+ // an entry in the responseArray and also advance msgIndex.
notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
msgType = context->messageType;
msgIndex = context->responseArray->getCount();
msgRef = ((context->serialNumber & 0xFFFF) << 16) + (msgIndex & 0xFFFF);
+ enableTracing = context->enableTracing && (notifier != NULL);
IOServicePM * pwrMgt = context->us->pwrMgt;
if (gIOKitDebug & kIOLogPower) {
OUR_PMLog(kPMLogClientNotify, (uintptr_t) notifier->handler, 0);
}
}
- if ((kIOLogDebugPower & gIOKitDebug) && notifier) {
- PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
- context->us->getName(),
- getIOMessageString(msgType),
- OBFUSCATE(object), OBFUSCATE(notifier->handler));
- }
if (NULL == context->notifyClients) {
- context->notifyClients = OSArray::withCapacity( 32 );
+ context->notifyClients = OSArray::withCapacity(32);
+ assert(context->notifyClients != NULL);
}
notify.powerRef = (void *)(uintptr_t) msgRef;
notify.stateNumber = context->stateNumber;
notify.stateFlags = context->stateFlags;
- if (context->enableTracing && (notifier != NULL)) {
- getPMRootDomain()->traceDetail(notifier, true);
+ clock_get_uptime(&start);
+ if (enableTracing) {
+ getPMRootDomain()->traceNotification(notifier, true, start, msgIndex);
}
- clock_get_uptime(&start);
retCode = context->us->messageClient(msgType, object, (void *) ¬ify, sizeof(notify));
- clock_get_uptime(&end);
- if (context->enableTracing && (notifier != NULL)) {
- getPMRootDomain()->traceDetail(notifier, false);
+ clock_get_uptime(&end);
+ if (enableTracing) {
+ getPMRootDomain()->traceNotification(notifier, false, end);
}
-
if (kIOReturnSuccess == retCode) {
if (0 == notify.returnValue) {
OUR_PMLog(kPMLogClientAcknowledge, msgRef, (uintptr_t) object);
(uint64_t) notify.returnValue,
getIOMessageString(msgType));
} else {
- context->maxTimeRequested = notify.returnValue;
+ context->maxTimeRequested = (typeof(context->maxTimeRequested))notify.returnValue;
}
}
//
}
}
- if (context->enableTracing) {
+ if (enableTracing) {
SUB_ABSOLUTETIME(&end, &start);
absolutetime_to_nanoseconds(end, &nsec);
if ((nsec > LOG_KEXT_RESPONSE_TIMES) || (notify.returnValue != 0)) {
- getPMRootDomain()->traceAckDelay(notifier, notify.returnValue / 1000, NS_TO_MS(nsec));
+ getPMRootDomain()->traceNotificationResponse(notifier, NS_TO_MS(nsec), (uint32_t) notify.returnValue);
}
}
} else {
// Create client array (for tracking purposes) only if the service
// has app clients. Usually only root domain does.
if (NULL == context->notifyClients) {
- context->notifyClients = OSArray::withCapacity( 32 );
+ context->notifyClients = OSArray::withCapacity(32);
+ assert(context->notifyClients != NULL);
}
msgType = context->messageType;
IOReturn retCode;
AbsoluteTime start, end;
uint64_t nsec;
+ bool enableTracing;
memset(&msgArg, 0, sizeof(msgArg));
if (context->messageFilter &&
!context->messageFilter(context->us, object, context, &msgArg, NULL)) {
- if ((kIOLogDebugPower & gIOKitDebug) &&
- (OSDynamicCast(_IOServiceInterestNotifier, object))) {
- _IOServiceInterestNotifier *n = (_IOServiceInterestNotifier *) object;
- PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
- context->us->getName(),
- getIOMessageString(context->messageType),
- OBFUSCATE(object), OBFUSCATE(n->handler));
- }
+ getPMRootDomain()->traceFilteredNotification(object);
return;
}
if (NULL == context->notifyClients) {
- context->notifyClients = OSArray::withCapacity( 32 );
+ context->notifyClients = OSArray::withCapacity(32);
+ assert(context->notifyClients != NULL);
}
+
notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
msgType = context->messageType;
msgIndex = context->responseArray->getCount();
msgRef = ((context->serialNumber & 0xFFFF) << 16) + (msgIndex & 0xFFFF);
+ enableTracing = context->enableTracing && (notifier != NULL);
IOServicePM * pwrMgt = context->us->pwrMgt;
if (gIOKitDebug & kIOLogPower) {
OUR_PMLog(kPMLogClientNotify, (uintptr_t) notifier->handler, 0);
}
}
- if ((kIOLogDebugPower & gIOKitDebug) && notifier) {
- PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
- context->us->getName(),
- getIOMessageString(msgType),
- OBFUSCATE(object), OBFUSCATE(notifier->handler));
- }
msgArg.notifyRef = msgRef;
msgArg.maxWaitForReply = 0;
- if (context->enableTracing && (notifier != NULL)) {
- getPMRootDomain()->traceDetail(notifier, true);
+ clock_get_uptime(&start);
+ if (enableTracing) {
+ getPMRootDomain()->traceNotification(notifier, true, start, msgIndex);
}
- clock_get_uptime(&start);
- retCode = context->us->messageClient(
- msgType, object, (void *) &msgArg, sizeof(msgArg));
+ retCode = context->us->messageClient(msgType, object, (void *) &msgArg, sizeof(msgArg));
+
clock_get_uptime(&end);
- if (context->enableTracing && (notifier != NULL)) {
- getPMRootDomain()->traceDetail(notifier, false);
+ if (enableTracing) {
+ getPMRootDomain()->traceNotification(notifier, false, end, msgIndex);
}
if (kIOReturnSuccess == retCode) {
}
}
- if (context->enableTracing) {
+ if (enableTracing) {
SUB_ABSOLUTETIME(&end, &start);
absolutetime_to_nanoseconds(end, &nsec);
if ((nsec > LOG_KEXT_RESPONSE_TIMES) || (msgArg.maxWaitForReply != 0)) {
- getPMRootDomain()->traceAckDelay(notifier, msgArg.maxWaitForReply / 1000, NS_TO_MS(nsec));
+ getPMRootDomain()->traceNotificationResponse(notifier, NS_TO_MS(nsec), msgArg.maxWaitForReply);
}
}
} else {
context.messageFilter = (IS_ROOT_DOMAIN) ?
OSMemberFunctionCast(
IOPMMessageFilter,
- this,
+ (IOPMrootDomain *)this,
&IOPMrootDomain::systemMessageFilter) : NULL;
- context.notifyType = kNotifyPriority;
+ context.notifyType = kNotifyPriority;
applyToInterested( gIOPriorityPowerStateInterest,
tellKernelClientApplier, (void *) &context );
- context.notifyType = kNotifyApps;
+ context.notifyType = kNotifyApps;
applyToInterested( gIOAppPowerStateInterest,
tellAppClientApplier, (void *) &context );
{
IOPowerStateChangeNotification notify;
IOPMInterestContext * context = (IOPMInterestContext *) arg;
+ bool enableTracing = context->enableTracing;
if (context->messageFilter &&
!context->messageFilter(context->us, object, context, NULL, NULL)) {
- if ((kIOLogDebugPower & gIOKitDebug) &&
- (OSDynamicCast(_IOServiceInterestNotifier, object))) {
- _IOServiceInterestNotifier *n = (_IOServiceInterestNotifier *) object;
- PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
- context->us->getName(),
- IOService::getIOMessageString(context->messageType),
- OBFUSCATE(object), OBFUSCATE(n->handler));
- }
+ IOService::getPMRootDomain()->traceFilteredNotification(object);
return;
}
notify.stateNumber = context->stateNumber;
notify.stateFlags = context->stateFlags;
- if (context->enableTracing && object) {
- IOService::getPMRootDomain()->traceDetail(object, true);
- }
- context->us->messageClient(context->messageType, object, ¬ify, sizeof(notify));
- if (context->enableTracing && object) {
- IOService::getPMRootDomain()->traceDetail(object, false);
+ if (enableTracing) {
+ IOService::getPMRootDomain()->traceNotification(object, true);
}
+ context->us->messageClient(context->messageType, object, ¬ify, sizeof(notify));
-
- if ((kIOLogDebugPower & gIOKitDebug) &&
- (OSDynamicCast(_IOServiceInterestNotifier, object))) {
- _IOServiceInterestNotifier *n = (_IOServiceInterestNotifier *) object;
- PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
- context->us->getName(),
- IOService::getIOMessageString(context->messageType),
- OBFUSCATE(object), OBFUSCATE(n->handler));
+ if (enableTracing) {
+ IOService::getPMRootDomain()->traceNotification(object, false);
}
}
name, 0, NS_TO_MS(nsec), pid, object);
}
} else {
- getPMRootDomain()->traceAckDelay(object, 0, NS_TO_MS(nsec));
+ getPMRootDomain()->traceNotificationAck(object, NS_TO_MS(nsec));
}
if (kIOLogDebugPower & gIOKitDebug) {
IOReturn rc = kIOReturnSuccess;
size_t reportSize;
unsigned long i;
- uint64_t ts;
+ uint64_t ts;
if (!pwrMgt) {
return kIOReturnUnsupported;
if (!fNumberOfPowerStates) {
return kIOReturnSuccess; // For drivers which are in power plane, but haven't called registerPowerDriver()
}
+
+ if (fNumberOfPowerStates > INT16_MAX) {
+ return kIOReturnOverrun;
+ }
PM_LOCK();
switch (action) {
}
memset(fReportBuf, 0, reportSize);
- STATEREPORT_INIT(fNumberOfPowerStates, fReportBuf, reportSize,
+ STATEREPORT_INIT((uint16_t) fNumberOfPowerStates, fReportBuf, reportSize,
getRegistryEntryID(), kPMPowerStatesChID, kIOReportCategoryPower);
for (i = 0; i < fNumberOfPowerStates; i++) {
((StateOrder(fMaxPowerState) & 0xf) << 4) | (StateOrder(i) & 0xf));
}
ts = mach_absolute_time();
- STATEREPORT_SETSTATE(fReportBuf, fCurrentPowerState, ts);
+ STATEREPORT_SETSTATE(fReportBuf, (uint16_t) fCurrentPowerState, ts);
break;
case kIOReportDisable:
PM_UNLOCK();
- return kIOReturnSuccess;
+ return rc;
}
return kPowerStateZero;
}
- for (int order = fNumberOfPowerStates - 1; order >= 0; order--) {
+ for (long order = fNumberOfPowerStates - 1; order >= 0; order--) {
stateIndex = fPowerStates[order].stateOrderToIndex;
if ((flags & fPowerStates[stateIndex].inputPowerFlags) ==
reason = 3; break;
}
+#if USE_SETTLE_TIMER
// Waiting on settle timer expiration.
if (fSettleTimeUS) {
reason = 4; break;
}
+#endif
} while (false);
fWaitReason = reason;
case kIOPM_TellCapabilityChangeDone:
if (fIsPreChange) {
if (fOutOfBandParameter == kNotifyCapabilityChangePriority) {
- MS_POP(); // tellSystemCapabilityChange()
+ MS_POP(); // MS passed to tellSystemCapabilityChange()
continue;
}
fOutOfBandParameter = kNotifyCapabilityChangePriority;
} else {
if (fOutOfBandParameter == kNotifyCapabilityChangeApps) {
- MS_POP(); // tellSystemCapabilityChange()
+ MS_POP(); // MS passed to tellSystemCapabilityChange()
continue;
}
fOutOfBandParameter = kNotifyCapabilityChangeApps;
case kIOPMRequestTypeSetIdleTimerPeriod:
{
- fIdleTimerPeriod = (uintptr_t) request->fArg0;
+ fIdleTimerPeriod = (typeof(fIdleTimerPeriod))(uintptr_t) request->fArg0;
fNextIdleTimerPeriod = fIdleTimerPeriod;
if ((false == fLockedFlags.PMStop) && (fIdleTimerPeriod > 0)) {
restartIdleTimer();
getPMRootDomain()->reset_watchdog_timer(this, 0);
uint64_t nsec = computeTimeDeltaNS(&fDriverCallStartTime);
- if (nsec > LOG_SETPOWER_TIMES) {
+ if (nsec > gIOPMSetPowerStateLogNS) {
getPMRootDomain()->pmStatsRecordApplicationResponse(
gIOPMStatsDriverPSChangeSlow,
fName, kDriverCallSetPowerState, NS_TO_MS(nsec), getRegistryEntryID(),
- NULL, fHeadNotePowerState);
+ NULL, fHeadNotePowerState, true);
}
OUR_PMLog(kPMLogDriverAcknowledgeSet, (uintptr_t) this, fDriverTimer);
return IOFindNameForValue(msg, msgNames);
}
+static const char *
+getNotificationPhaseString( uint32_t phase )
+{
+#define PHASE_ENTRY(x) {(int) x, #x}
+
+ static const IONamedValue phaseNames[] = {
+ PHASE_ENTRY( kNotifyApps ),
+ PHASE_ENTRY( kNotifyPriority ),
+ PHASE_ENTRY( kNotifyCapabilityChangeApps ),
+ PHASE_ENTRY( kNotifyCapabilityChangePriority ),
+ { 0, NULL }
+ };
+
+ return IOFindNameForValue(phase, phaseNames);
+}
// MARK: -
// MARK: IOPMRequest
void
IOPMRequestQueue::queuePMRequest( IOPMRequest * request )
{
+ uint64_t now = mach_continuous_time();
+
assert(request);
+ request->setTimestamp(now);
IOLockLock(fLock);
queue_enter(&fQueue, request, typeof(request), fCommandChain);
IOLockUnlock(fLock);
IOPMRequestQueue::queuePMRequestChain( IOPMRequest ** requests, IOItemCount count )
{
IOPMRequest * next;
+ uint64_t now = mach_continuous_time();
assert(requests && count);
IOLockLock(fLock);
while (count--) {
next = *requests;
+ next->setTimestamp(now);
requests++;
queue_enter(&fQueue, next, typeof(next), fCommandChain);
}
dictSize += 4;
}
- if (PMActions.parameter & kPMActionsFlagLimitPower) {
+ if (PMActions.state & kPMActionsStatePowerClamped) {
dictSize += 1;
powerClamp = 0;
- if (PMActions.parameter &
- (kPMActionsFlagIsDisplayWrangler | kPMActionsFlagIsGraphicsDevice)) {
+ if (PMActions.flags &
+ (kPMActionsFlagIsDisplayWrangler | kPMActionsFlagIsGraphicsDriver)) {
powerClamp++;
}
}
// NULL termination is not required.
strncpy((char*)&nameAsArg, Name, sizeof(nameAsArg));
+#if defined(XNU_TARGET_OS_OSX)
+ KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, IODBG_POWER(event) | eventFunc, nameAsArg,
+ (uintptr_t)Owner->getRegistryEntryID(), (uintptr_t)(OBFUSCATE(param1)),
+ (uintptr_t)(OBFUSCATE(param2)), 0);
+#else
IOTimeStampConstant(IODBG_POWER(event) | eventFunc, nameAsArg, (uintptr_t)Owner->getRegistryEntryID(), (uintptr_t)(OBFUSCATE(param1)), (uintptr_t)(OBFUSCATE(param2)));
+#endif
}