#include <IOKit/pwr_mgt/IOPowerConnection.h>
#include <IOKit/pwr_mgt/RootDomain.h>
-
// Required for notification instrumentation
#include "IOServicePrivate.h"
pm_vars->responseFlags = NULL;
pm_vars->doNotPowerDown = true;
pm_vars->PMcommandGate = NULL;
- priv->ackTimer = thread_call_allocate(
- (thread_call_func_t)ack_timer_expired,
- (thread_call_param_t)this);
- priv->settleTimer = thread_call_allocate(
- (thread_call_func_t)settle_timer_expired,
- (thread_call_param_t)this);
-
+ priv->ackTimer = thread_call_allocate((thread_call_func_t)ack_timer_expired, (thread_call_param_t)this);
+ priv->settleTimer = thread_call_allocate((thread_call_func_t)settle_timer_expired, (thread_call_param_t)this);
initialized = true;
}
}
// Put ourselves into a usable power state.
// We must be in an "on" power state, as our children must be able to access
// our hardware after joining the power plane.
- temporaryMakeUsable();
+ makeUsable();
// make a nub
connection = new IOPowerConnection;
}
-//******************************************************************************
+//*********************************************************************************
// removePowerChild
//
-//******************************************************************************
+//*********************************************************************************
IOReturn IOService::removePowerChild ( IOPowerConnection * theNub )
{
IORegistryEntry *theChild;
+ OSIterator *iter;
pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogRemoveChild,0,0);
if (priv->head_note_pendingAcks != 0 )
{
// that's one fewer ack to worry about
- OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
+ priv->head_note_pendingAcks -= 1;
// is that the last?
if ( priv->head_note_pendingAcks == 0 )
{
return IOPMNoErr;
}
- // Perhaps the departing child was holding up idle or system sleep - we
- // need to re-evaluate our childrens' requests.
- // Clear and re-calculate our kIOPMChildClamp and kIOPMChildClamp2 bits.
+ // Perhaps the departing child was holding up idle or system sleep - we need to re-evaluate our
+ // childrens' requests. Clear and re-calculate our kIOPMChildClamp and kIOPMChildClamp2 bits.
rebuildChildClampBits();
- // Change state if we can now tolerate lower power
+ if(!priv->clampOn)
+ {
+ // count children
+ iter = getChildIterator(gIOPowerPlane);
+ if ( !iter || !iter->getNextObject() )
+ {
+ // paired to match the makeUsable() call in addPowerChild()
+ changePowerStateToPriv(0);
+ }
+ if(iter) iter->release();
+ }
+
+ // this may be different now
computeDesiredState();
+ // change state if we can now tolerate lower power
changeState();
return IOPMNoErr;
// mark it acked
ackingObject->timer = 0;
// that's one fewer to worry about
- OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
+ priv->head_note_pendingAcks -= 1;
// is that the last?
if ( priv->head_note_pendingAcks == 0 )
{
if ( ((IOPowerConnection *)whichObject)->getAwaitingAck() )
{
// that's one fewer to worry about
- OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
+ priv->head_note_pendingAcks -= 1;
((IOPowerConnection *)whichObject)->setAwaitingAck(false);
theChild = (IOService *)whichObject->copyChildEntry(gIOPowerPlane);
if ( theChild )
void IOService::driver_acked ( void )
{
-
switch (priv->machine_state) {
case kIOPM_OurChangeWaitForPowerSettle:
OurChangeWaitForPowerSettle();
return IOPMNoErr;
}
-//******************************************************************************
-// temporaryMakeUsable
-//
-// Private function, called by IOService::addPowerChild to ensure that the
-// device is temporarily in a usable power state so that attached power
-// children may properly initialize.
-//******************************************************************************
-
-IOReturn IOService::temporaryMakeUsable ( void )
-{
- IOReturn ret = kIOReturnSuccess;
- unsigned long tempDesire;
-
- pm_vars->thePlatform->PMLog( pm_vars->ourName,
- PMlogMakeUsable,
- PMlogMakeUsable,
- priv->deviceDesire);
-
- if ( pm_vars->theControllingDriver == NULL )
- {
- priv->need_to_become_usable = true;
- return IOPMNoErr;
- }
- tempDesire = priv->deviceDesire;
- priv->deviceDesire = pm_vars->theNumberOfPowerStates - 1;
- computeDesiredState();
- if ( inPlane(gIOPowerPlane) && (pm_vars->parentsKnowState) )
- {
- ret = changeState();
- }
- priv->deviceDesire = tempDesire;
- return ret;
-}
-
//*********************************************************************************
// currentCapability
}
if ( pm_vars->myCurrentState > 0 )
{
-
- unsigned long newState = pm_vars->myCurrentState - 1;
-
IOUnlock(priv->activityLock);
- changePowerStateToPriv(newState);
- if ( newState >= priv->ourDesiredPowerState )
- start_PM_idle_timer();
+ changePowerStateToPriv(pm_vars->myCurrentState - 1);
+ start_PM_idle_timer();
return;
}
IOUnlock(priv->activityLock);
// needn't perform the previous change, so we collapse the list a little.
//*********************************************************************************
-IOReturn IOService::enqueuePowerChange (
- unsigned long flags,
- unsigned long whatStateOrdinal,
- unsigned long domainState,
- IOPowerConnection * whichParent,
- unsigned long singleParentState )
+IOReturn IOService::enqueuePowerChange ( unsigned long flags, unsigned long whatStateOrdinal, unsigned long domainState, IOPowerConnection * whichParent, unsigned long singleParentState )
{
long newNote;
long previousNote;
OSObject * next;
IOPowerConnection * connection;
- // To prevent acknowledgePowerChange from finishing the change note and
- // removing it from the queue if
- // some driver calls it, we inflate the number of pending acks so it
- // cannot become zero. We'll fix it later.
-
- if(!acquire_lock()) return IOPMAckImplied;
+ // To prevent acknowledgePowerChange from finishing the change note and removing it from the queue if
+ // some driver calls it, we inflate the number of pending acks so it cannot become zero. We'll fix it later.
- OSAddAtomic(1, (SInt32*)&priv->head_note_pendingAcks);
+ priv->head_note_pendingAcks =1;
+
+ // OK, we will go through the lists of interested drivers and power domain children
+ // and notify each one of this change.
- // OK, we will go through the lists of interested drivers and
- // power domain children and notify each one of this change.
-
nextObject = priv->interestedDrivers->firstInList();
while ( nextObject != NULL ) {
-
- OSAddAtomic(1, (SInt32*)&priv->head_note_pendingAcks);
-
- IOUnlock(priv->our_lock);
-
- inform(nextObject, is_prechange);
-
- if(!acquire_lock())
+ priv->head_note_pendingAcks +=1;
+ if (! inform(nextObject, is_prechange) )
{
- goto exit;
}
-
nextObject = priv->interestedDrivers->nextInList(nextObject);
}
+ if (! acquire_lock() ) {
+ return IOPMNoErr;
+ }
// did they all ack?
if ( priv->head_note_pendingAcks > 1 ) {
// no
// summing their power consumption
pm_vars->thePowerStates[priv->head_note_state].staticPower = 0;
- if ( iter && acquire_lock())
+ if ( iter )
{
while ( (next = iter->getNextObject()) )
{
if ( (connection = OSDynamicCast(IOPowerConnection,next)) )
{
- OSAddAtomic(1, (SInt32*)&priv->head_note_pendingAcks);
-
- IOUnlock(priv->our_lock);
-
+ priv->head_note_pendingAcks +=1;
notifyChild(connection, is_prechange);
-
- if(!acquire_lock())
- {
- goto exit;
- }
}
}
iter->release();
- IOUnlock(priv->our_lock);
}
if (! acquire_lock() ) {
return IOPMNoErr;
}
// now make this real
- OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
-
+ priv->head_note_pendingAcks -= 1;
// is it all acked?
if (priv->head_note_pendingAcks == 0 ) {
// yes, all acked
// not all acked
IOUnlock(priv->our_lock);
-
-exit: // unable to acquire_lock exit case
-
return IOPMWillAckLater;
}
// The child has been detached since we grabbed the child iterator.
// Decrement pending_acks, already incremented in notifyAll,
// to account for this unexpected departure.
-
- if( acquire_lock() )
- {
- OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
- IOUnlock(priv->our_lock);
- }
+ priv->head_note_pendingAcks--;
return true;
}
if ( k == IOPMAckImplied )
{
// yes
- if( acquire_lock() )
- {
- OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
- IOUnlock(priv->our_lock);
- }
-
+ priv->head_note_pendingAcks--;
theNub->setAwaitingAck(false);
childPower = theChild->currentPowerConsumption();
if ( childPower == kIOPMUnknown )
return true;
}
- if ( (k ==IOPMAckImplied) // no, did the return code ack?
- || (k < 0) ) // somebody goofed
+ // no, did the return code ack?
+ if ( k ==IOPMAckImplied )
{
// yes
nextObject->timer = 0;
-
- if( acquire_lock() )
- {
- OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
- IOUnlock(priv->our_lock);
- }
+ priv->head_note_pendingAcks -= 1;
+ return true;
+ }
+ if ( k<0 )
+ {
+ // somebody goofed
+ nextObject->timer = 0;
+ priv-> head_note_pendingAcks -= 1;
return true;
}
{
priv->machine_state = kIOPM_OurChangeWaitForPowerSettle;
- IOLockLock(priv->our_lock);
-
if ( instruct_driver(priv->head_note_state) == IOPMAckImplied )
{
// it's done, carry on
- IOLockUnlock(priv->our_lock);
OurChangeWaitForPowerSettle();
} else {
// it's not, wait for it
pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogStartAckTimer,0,0);
start_ack_timer();
- IOLockUnlock(priv->our_lock);
// execution will resume via ack_timer_ticked()
}
}
{
priv->machine_state = kIOPM_ParentDownWaitForPowerSettle_Delayed;
- IOLockLock(priv->our_lock);
-
if ( instruct_driver(priv->head_note_state) == IOPMAckImplied )
{
// it's done, carry on
- IOLockUnlock(priv->our_lock);
return ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate();
}
// it's not, wait for it
pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogStartAckTimer,0,0);
start_ack_timer();
- IOLockUnlock(priv->our_lock);
return IOPMWillAckLater;
}
{
priv-> machine_state = kIOPM_ParentDownWaitForPowerSettle_Delayed;
- IOLockLock(priv->our_lock);
-
if ( instruct_driver(priv->head_note_state) == IOPMAckImplied )
{
// it's done, carry on
- IOLockUnlock(priv->our_lock);
ParentDownWaitForPowerSettle_Delayed();
} else {
// it's not, wait for it
pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogStartAckTimer,0,0);
start_ack_timer();
- IOLockUnlock(priv->our_lock);
}
}
{
priv->machine_state = kIOPM_ParentUpWaitForSettleTime_Delayed;
- IOLockLock(priv->our_lock);
-
if ( instruct_driver(priv->head_note_state) == IOPMAckImplied )
{
// it did it, carry on
- IOLockUnlock(priv->our_lock);
ParentUpWaitForSettleTime_Delayed();
} else {
// it didn't, wait for it
pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogStartAckTimer,0,0);
start_ack_timer();
- IOLockUnlock(priv->our_lock);
}
}
{
priv->machine_state = kIOPM_ParentUpWaitForSettleTime_Delayed;
- IOLockLock(priv->our_lock);
-
if ( instruct_driver(priv->head_note_state) == IOPMAckImplied )
{
// it did it, carry on
- IOLockUnlock(priv->our_lock);
return ParentUpWaitForSettleTime_Immediate();
}
else {
// it didn't, wait for it
pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogStartAckTimer,0,0);
start_ack_timer();
- IOLockUnlock(priv->our_lock);
return IOPMWillAckLater;
}
}
start_our_change(priv->head_note);
} else {
nub = priv->changeList->changeNote[priv->head_note].parent;
- if (nub) nub->retain(); // might be released by start_parent_change()
if ( start_parent_change(priv->head_note) == IOPMAckImplied )
{
parent = (IOService *)nub->copyParentEntry(gIOPowerPlane);
parent->release();
}
}
- if (nub) nub->release();
}
} else {
IOLockUnlock(priv->queue_lock);
//
//*********************************************************************************
-
-
-void IOService::all_acked( void )
+void IOService::all_acked ( void )
{
switch (priv->machine_state) {
case kIOPM_OurChangeSetPowerState:
{
pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogIntDriverTardy,0,0);
//kprintf("interested driver tardy: %s\n",nextObject->whatObject->getName());
- OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
+ priv->head_note_pendingAcks -= 1;
}
}
nextObject = priv->interestedDrivers->nextInList(nextObject);
case kIOPM_ParentDownSetPowerState_Delayed:
case kIOPM_ParentUpSetPowerState_Delayed:
// one for this child and one to prevent
- OSAddAtomic(2, (SInt32*)&priv->head_note_pendingAcks);
+ priv->head_note_pendingAcks += 2;
// incoming acks from changing our state
IOUnlock(priv->our_lock);
notifyChild(newObject, true);
if (! acquire_lock() )
{
// put it back
- OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
+ --priv->head_note_pendingAcks;
return IOPMNoErr;
}
// are we still waiting for acks?
- OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
- if ( priv->head_note_pendingAcks == 0 )
+ if ( --priv->head_note_pendingAcks == 0 )
{
// no, stop the timer
stop_ack_timer();
case kIOPM_ParentDownAcknowledgeChange_Delayed:
case kIOPM_ParentUpAcknowledgePowerChange_Delayed:
// one for this child and one to prevent
- OSAddAtomic(2, (SInt32*)&priv->head_note_pendingAcks);
+ priv->head_note_pendingAcks += 2;
// incoming acks from changing our state
IOUnlock(priv->our_lock);
notifyChild(newObject, false);
if (! acquire_lock() )
{
// put it back
- OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
+ --priv->head_note_pendingAcks;
return IOPMNoErr;
}
// are we still waiting for acks?
- OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
- if ( priv->head_note_pendingAcks == 0 )
+ if ( --priv->head_note_pendingAcks == 0 )
{
// no, stop the timer
stop_ack_timer();
case kIOPM_ParentDownSetPowerState_Delayed:
case kIOPM_ParentUpSetPowerState_Delayed:
// one for this driver and one to prevent
- OSAddAtomic(2, (SInt32*)&priv->head_note_pendingAcks);
+ priv->head_note_pendingAcks += 2;
// incoming acks from changing our state
IOUnlock(priv->our_lock);
// inform the driver
if (! acquire_lock() )
{
// put it back
- OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
+ --priv->head_note_pendingAcks;
return IOPMNoErr;
}
// are we still waiting for acks?
- OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
- if ( priv->head_note_pendingAcks == 0 )
+ if ( --priv->head_note_pendingAcks == 0 )
{
// no, stop the timer
stop_ack_timer();
case kIOPM_ParentDownAcknowledgeChange_Delayed:
case kIOPM_ParentUpAcknowledgePowerChange_Delayed:
// one for this driver and one to prevent
- OSAddAtomic(2, (SInt32*)&priv->head_note_pendingAcks);
+ priv->head_note_pendingAcks += 2;
// incoming acks from changing our state
IOUnlock(priv->our_lock);
// inform the driver
inform(newObject, false);
if (! acquire_lock() ) {
// put it back
- OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
+ --priv->head_note_pendingAcks;
return IOPMNoErr;
}
// are we still waiting for acks?
- OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
- if ( priv->head_note_pendingAcks == 0 ) {
+ if ( --priv->head_note_pendingAcks == 0 ) {
// no, stop the timer
stop_ack_timer();
IOUnlock(priv->our_lock);
priv->driver_timer = -1;
// yes, instruct it
- IOLockUnlock(priv->our_lock);
OUR_PMLog( kPMLogProgramHardware, (UInt32) this, newState);
delay = pm_vars->theControllingDriver->setPowerState( newState,this );
OUR_PMLog((UInt32) -kPMLogProgramHardware, (UInt32) this, (UInt32) delay);
- IOLockLock(priv->our_lock);
// it finished
if ( delay == IOPMAckImplied )