- do {
- // Is this child already one of our children?
-
- iter = child->getParentIterator( gIOPowerPlane );
- if ( iter )
- {
- IORegistryEntry * entry;
- OSObject * next;
-
- while ((next = iter->getNextObject()))
- {
- if ((entry = OSDynamicCast(IORegistryEntry, next)) &&
- isChild(entry, gIOPowerPlane))
- {
- ok = false;
- break;
- }
- }
- iter->release();
- }
- if (!ok)
- {
- PM_LOG("%s: %s (%p) is already a child\n",
- getName(), child->getName(), OBFUSCATE(child));
- break;
- }
-
- // Add the child to the power plane immediately, but the
- // joining connection is marked as not ready.
- // We want the child to appear in the power plane before
- // returning to the caller, but don't want the caller to
- // block on the PM work loop.
-
- connection = new IOPowerConnection;
- if (!connection)
- break;
-
- // Create a chain of PM requests to perform the bottom-half
- // work from the PM work loop.
-
- requests[0] = acquirePMRequest(
- /* target */ this,
- /* type */ kIOPMRequestTypeAddPowerChild1 );
-
- requests[1] = acquirePMRequest(
- /* target */ child,
- /* type */ kIOPMRequestTypeAddPowerChild2 );
-
- requests[2] = acquirePMRequest(
- /* target */ this,
- /* type */ kIOPMRequestTypeAddPowerChild3 );
-
- if (!requests[0] || !requests[1] || !requests[2])
- break;
-
- requests[0]->attachNextRequest( requests[1] );
- requests[1]->attachNextRequest( requests[2] );
-
- connection->init();
- connection->start(this);
- connection->setAwaitingAck(false);
- connection->setReadyFlag(false);
-
- attachToChild( connection, gIOPowerPlane );
- connection->attachToChild( child, gIOPowerPlane );
-
- // connection needs to be released
- requests[0]->fArg0 = connection;
- requests[1]->fArg0 = connection;
- requests[2]->fArg0 = connection;
-
- submitPMRequest( requests, 3 );
- return kIOReturnSuccess;
- }
- while (false);
-
- if (connection) connection->release();
- if (requests[0]) releasePMRequest(requests[0]);
- if (requests[1]) releasePMRequest(requests[1]);
- if (requests[2]) releasePMRequest(requests[2]);
-
- // Silent failure, to prevent platform drivers from adding the child
- // to the root domain.
-
- return kIOReturnSuccess;
+ do {
+ // Is this child already one of our children?
+
+ iter = child->getParentIterator( gIOPowerPlane );
+ if ( iter )
+ {
+ IORegistryEntry * entry;
+ OSObject * next;
+
+ while ((next = iter->getNextObject()))
+ {
+ if ((entry = OSDynamicCast(IORegistryEntry, next)) &&
+ isChild(entry, gIOPowerPlane))
+ {
+ ok = false;
+ break;
+ }
+ }
+ iter->release();
+ }
+ if (!ok)
+ {
+ PM_LOG("%s: %s (%p) is already a child\n",
+ getName(), child->getName(), OBFUSCATE(child));
+ break;
+ }
+
+ // Add the child to the power plane immediately, but the
+ // joining connection is marked as not ready.
+ // We want the child to appear in the power plane before
+ // returning to the caller, but don't want the caller to
+ // block on the PM work loop.
+
+ connection = new IOPowerConnection;
+ if (!connection)
+ break;
+
+ // Create a chain of PM requests to perform the bottom-half
+ // work from the PM work loop.
+
+ requests[0] = acquirePMRequest(
+ /* target */ this,
+ /* type */ kIOPMRequestTypeAddPowerChild1 );
+
+ requests[1] = acquirePMRequest(
+ /* target */ child,
+ /* type */ kIOPMRequestTypeAddPowerChild2 );
+
+ requests[2] = acquirePMRequest(
+ /* target */ this,
+ /* type */ kIOPMRequestTypeAddPowerChild3 );
+
+ if (!requests[0] || !requests[1] || !requests[2])
+ break;
+
+ requests[0]->attachNextRequest( requests[1] );
+ requests[1]->attachNextRequest( requests[2] );
+
+ connection->init();
+ connection->start(this);
+ connection->setAwaitingAck(false);
+ connection->setReadyFlag(false);
+
+ attachToChild( connection, gIOPowerPlane );
+ connection->attachToChild( child, gIOPowerPlane );
+
+ // connection needs to be released
+ requests[0]->fArg0 = connection;
+ requests[1]->fArg0 = connection;
+ requests[2]->fArg0 = connection;
+
+ submitPMRequest( requests, 3 );
+ return kIOReturnSuccess;
+ }
+ while (false);
+
+ if (connection) connection->release();
+ if (requests[0]) releasePMRequest(requests[0]);
+ if (requests[1]) releasePMRequest(requests[1]);
+ if (requests[2]) releasePMRequest(requests[2]);
+
+ // Silent failure, to prevent platform drivers from adding the child
+ // to the root domain.
+
+ return kIOReturnSuccess;
- {
- // yes, pretend we got one
- theNub->setAwaitingAck(false);
- if (fHeadNotePendingAcks != 0 )
- {
- // that's one fewer ack to worry about
- fHeadNotePendingAcks--;
-
- // is that the last?
- if ( fHeadNotePendingAcks == 0 )
- {
- stop_ack_timer();
-
- // Request unblocked, work queue
- // should re-scan all busy requests.
- gIOPMWorkQueue->incrementProducerCount();
- }
- }
- }
-
- theNub->release();
-
- // A child has gone away, re-scan children desires and clamp bits.
- // The fPendingAdjustPowerRequest helps to reduce redundant parent work.
-
- if (!fAdjustPowerScheduled)
- {
- IOPMRequest * request;
- request = acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState );
- if (request)
- {
- submitPMRequest( request );
- fAdjustPowerScheduled = true;
- }
- }
+ {
+ // yes, pretend we got one
+ theNub->setAwaitingAck(false);
+ if (fHeadNotePendingAcks != 0 )
+ {
+ // that's one fewer ack to worry about
+ fHeadNotePendingAcks--;
+
+ // is that the last?
+ if ( fHeadNotePendingAcks == 0 )
+ {
+ stop_ack_timer();
+
+ // Request unblocked, work queue
+ // should re-scan all busy requests.
+ gIOPMWorkQueue->incrementProducerCount();
+ }
+ }
+ }
+
+ theNub->release();
+
+ // A child has gone away, re-scan children desires and clamp bits.
+ // The fPendingAdjustPowerRequest helps to reduce redundant parent work.
+
+ if (!fAdjustPowerScheduled)
+ {
+ IOPMRequest * request;
+ request = acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState );
+ if (request)
+ {
+ submitPMRequest( request );
+ fAdjustPowerScheduled = true;
+ }
+ }
- return IOPMNotYetInitialized;
-
- if (!powerStates || (numberOfStates < 2))
- {
- OUR_PMLog(kPMLogControllingDriverErr5, numberOfStates, 0);
- return kIOReturnBadArgument;
- }
-
- if (!powerDriver || !powerDriver->initialized)
- {
- OUR_PMLog(kPMLogControllingDriverErr4, 0, 0);
- return kIOReturnBadArgument;
- }
-
- if (powerStates[0].version > kIOPMPowerStateVersion2)
- {
- OUR_PMLog(kPMLogControllingDriverErr1, powerStates[0].version, 0);
- return kIOReturnBadArgument;
- }
-
- do {
- // Make a copy of the supplied power state array.
- powerStatesCopy = IONew(IOPMPSEntry, numberOfStates);
- if (!powerStatesCopy)
+ return IOPMNotYetInitialized;
+
+ if (!powerStates || (numberOfStates < 2))
+ {
+ OUR_PMLog(kPMLogControllingDriverErr5, numberOfStates, 0);
+ return kIOReturnBadArgument;
+ }
+
+ if (!powerDriver || !powerDriver->initialized)
+ {
+ OUR_PMLog(kPMLogControllingDriverErr4, 0, 0);
+ return kIOReturnBadArgument;
+ }
+
+ if (powerStates[0].version > kIOPMPowerStateVersion2)
+ {
+ OUR_PMLog(kPMLogControllingDriverErr1, powerStates[0].version, 0);
+ return kIOReturnBadArgument;
+ }
+
+ do {
+ // Make a copy of the supplied power state array.
+ powerStatesCopy = IONew(IOPMPSEntry, numberOfStates);
+ if (!powerStatesCopy)
- }
-
- // Register powerDriver as interested, unless already done.
- // We don't want to register the default implementation since
- // it does nothing. One ramification of not always registering
- // is the one fewer retain count held.
-
- root = getPlatform()->getProvider();
- assert(root);
- if (!root ||
- ((OSMemberFunctionCast(void (*)(void),
- root, &IOService::powerStateDidChangeTo)) !=
- ((OSMemberFunctionCast(void (*)(void),
- this, &IOService::powerStateDidChangeTo)))) ||
- ((OSMemberFunctionCast(void (*)(void),
- root, &IOService::powerStateWillChangeTo)) !=
- ((OSMemberFunctionCast(void (*)(void),
- this, &IOService::powerStateWillChangeTo)))))
- {
- if (fInterestedDrivers->findItem(powerDriver) == NULL)
- {
- PM_LOCK();
- fInterestedDrivers->appendNewInformee(powerDriver);
- PM_UNLOCK();
- }
- }
-
- // Examine all existing power clients and perform limit check.
+ }
+
+ // Register powerDriver as interested, unless already done.
+ // We don't want to register the default implementation since
+ // it does nothing. One ramification of not always registering
+ // is the one fewer retain count held.
+
+ root = getPlatform()->getProvider();
+ assert(root);
+ if (!root ||
+ ((OSMemberFunctionCast(void (*)(void),
+ root, &IOService::powerStateDidChangeTo)) !=
+ ((OSMemberFunctionCast(void (*)(void),
+ this, &IOService::powerStateDidChangeTo)))) ||
+ ((OSMemberFunctionCast(void (*)(void),
+ root, &IOService::powerStateWillChangeTo)) !=
+ ((OSMemberFunctionCast(void (*)(void),
+ this, &IOService::powerStateWillChangeTo)))))
+ {
+ if (fInterestedDrivers->findItem(powerDriver) == NULL)
+ {
+ PM_LOCK();
+ fInterestedDrivers->appendNewInformee(powerDriver);
+ PM_UNLOCK();
+ }
+ }
+
+ // Examine all existing power clients and perform limit check.
- if ( inPlane(gIOPowerPlane) && fParentsKnowState )
- {
- IOPMPowerStateIndex tempDesire;
- fMaxPowerState = fControllingDriver->maxCapabilityForDomainState(fParentsCurrentPowerFlags);
- // initially change into the state we are already in
- tempDesire = fControllingDriver->initialPowerStateForDomainState(fParentsCurrentPowerFlags);
- adjustPowerState(tempDesire);
- }
- }
- else
- {
- OUR_PMLog(kPMLogControllingDriverErr2, numberOfStates, 0);
+ if ( inPlane(gIOPowerPlane) && fParentsKnowState )
+ {
+ IOPMPowerStateIndex tempDesire;
+ fMaxPowerState = fControllingDriver->maxCapabilityForDomainState(fParentsCurrentPowerFlags);
+ // initially change into the state we are already in
+ tempDesire = fControllingDriver->initialPowerStateForDomainState(fParentsCurrentPowerFlags);
+ adjustPowerState(tempDesire);
+ }
+ }
+ else
+ {
+ OUR_PMLog(kPMLogControllingDriverErr2, numberOfStates, 0);
- if (nsec > LOG_SETPOWER_TIMES)
- PM_LOG("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) async took %d ms\n",
- informee->whatObject->getName(),
- (fDriverCallReason == kDriverCallInformPreChange) ? "Will" : "Did",
- OBFUSCATE(informee->whatObject),
- fName, fCurrentPowerState, fHeadNotePowerState, NS_TO_US(nsec));
-
- uint16_t logType = (fDriverCallReason == kDriverCallInformPreChange)
- ? kIOPMEventTypePSWillChangeTo
- : kIOPMEventTypePSDidChangeTo;
-
- PMEventDetails *details = PMEventDetails::eventDetails(
- logType,
- fName,
- (uintptr_t)this,
- informee->whatObject->getName(),
- 0, 0, 0,
- NS_TO_MS(nsec));
-
- getPMRootDomain()->recordAndReleasePMEvent( details );
+ if (nsec > LOG_SETPOWER_TIMES) {
+ getPMRootDomain()->pmStatsRecordApplicationResponse(
+ gIOPMStatsDriverPSChangeSlow, informee->whatObject->getName(),
+ fDriverCallReason, NS_TO_MS(nsec), 0, NULL, fHeadNotePowerState);
+ }
- result = startPowerChange(
- /* flags */ myChangeFlags,
- /* power state */ maxPowerState,
- /* domain flags */ combinedPowerFlags,
- /* connection */ whichParent,
- /* parent flags */ parentPowerFlags);
- }
-
- // If parent is dropping power, immediately update the parent's
- // capability flags. Any future merging of parent(s) combined
- // power flags should account for this power drop.
-
- if (parentChangeFlags & kIOPMDomainPowerDrop)
- {
- setParentInfo(parentPowerFlags, whichParent, true);
- }
-
- // Parent is expecting an ACK from us. If we did not embark on a state
- // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
- // still required to issue an ACK to our parent.
-
- if (IOPMAckImplied == result)
- {
- IOService * parent;
- parent = (IOService *) whichParent->copyParentEntry(gIOPowerPlane);
- assert(parent);
- if ( parent )
- {
- parent->acknowledgePowerChange( whichParent );
- parent->release();
- }
- }
+ result = startPowerChange(
+ /* flags */ myChangeFlags,
+ /* power state */ maxPowerState,
+ /* domain flags */ combinedPowerFlags,
+ /* connection */ whichParent,
+ /* parent flags */ parentPowerFlags);
+ }
+
+ // If parent is dropping power, immediately update the parent's
+ // capability flags. Any future merging of parent(s) combined
+ // power flags should account for this power drop.
+
+ if (parentChangeFlags & kIOPMDomainPowerDrop)
+ {
+ setParentInfo(parentPowerFlags, whichParent, true);
+ }
+
+ // Parent is expecting an ACK from us. If we did not embark on a state
+ // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
+ // still required to issue an ACK to our parent.
+
+ if (IOPMAckImplied == result)
+ {
+ IOService * parent;
+ parent = (IOService *) whichParent->copyParentEntry(gIOPowerPlane);
+ assert(parent);
+ if ( parent )
+ {
+ parent->acknowledgePowerChange( whichParent );
+ parent->release();
+ }
+ }
- result = startPowerChange(
- /* flags */ myChangeFlags,
- /* power state */ maxPowerState,
- /* domain flags */ fParentsCurrentPowerFlags,
- /* connection */ whichParent,
- /* parent flags */ 0);
- }
-
- // Parent is expecting an ACK from us. If we did not embark on a state
- // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
- // still required to issue an ACK to our parent.
-
- if (IOPMAckImplied == result)
- {
- IOService * parent;
- parent = (IOService *) whichParent->copyParentEntry(gIOPowerPlane);
- assert(parent);
- if ( parent )
- {
- parent->acknowledgePowerChange( whichParent );
- parent->release();
- }
- }
-
- // If the parent registers its power driver late, then this is the
- // first opportunity to tell our parent about our desire. Or if the
+ result = startPowerChange(
+ /* flags */ myChangeFlags,
+ /* power state */ maxPowerState,
+ /* domain flags */ fParentsCurrentPowerFlags,
+ /* connection */ whichParent,
+ /* parent flags */ 0);
+ }
+
+ // Parent is expecting an ACK from us. If we did not embark on a state
+ // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
+ // still required to issue an ACK to our parent.
+
+ if (IOPMAckImplied == result)
+ {
+ IOService * parent;
+ parent = (IOService *) whichParent->copyParentEntry(gIOPowerPlane);
+ assert(parent);
+ if ( parent )
+ {
+ parent->acknowledgePowerChange( whichParent );
+ parent->release();
+ }
+ }
+
+ // If the parent registers its power driver late, then this is the
+ // first opportunity to tell our parent about our desire. Or if the
- else
- {
- // Beyond cancellation point, report the impending state.
- outputPowerFlags =
- fPowerStates[fHeadNotePowerState].outputPowerFlags;
- }
- }
- else if (IS_POWER_RISE)
- {
- // When raising power, must report the output power flags from
- // child's perspective. A child power request may arrive while
- // parent is transitioning upwards. If a request arrives after
- // setParentInfo() has already recorded the output power flags
- // for the next power state, then using the power supplied by
- // fCurrentPowerState is incorrect, and might cause the child
- // to wait when it should not.
-
- outputPowerFlags = childConnection->parentCurrentPowerFlags();
- }
+ else
+ {
+ // Beyond cancellation point, report the impending state.
+ outputPowerFlags =
+ fPowerStates[fHeadNotePowerState].outputPowerFlags;
+ }
+ }
+ else if (IS_POWER_RISE)
+ {
+ // When raising power, must report the output power flags from
+ // child's perspective. A child power request may arrive while
+ // parent is transitioning upwards. If a request arrives after
+ // setParentInfo() has already recorded the output power flags
+ // for the next power state, then using the power supplied by
+ // fCurrentPowerState is incorrect, and might cause the child
+ // to wait when it should not.
+
+ outputPowerFlags = childConnection->parentCurrentPowerFlags();
+ }
- PM_ASSERT_IN_GATE();
- assert(fNotifyChildArray);
- assert(fMachineState == kIOPM_NotifyChildrenOrdered);
-
- // Notify one child, wait for it to ack, then repeat for next child.
- // This is a workaround for some drivers with multiple instances at
- // the same branch in the power tree, but the driver is slow to power
- // up unless the tree ordering is observed. Problem observed only on
- // system wake, not on system sleep.
- //
- // We have the ability to power off in reverse child index order.
- // That works nicely on some machines, but not on all HW configs.
-
- if (fNotifyChildArray->getCount())
- {
- IOPowerConnection * connection;
- connection = (IOPowerConnection *) fNotifyChildArray->getObject(0);
- notifyChild( connection );
- fNotifyChildArray->removeObject(0);
- }
- else
- {
- fNotifyChildArray->release();
- fNotifyChildArray = 0;
+ PM_ASSERT_IN_GATE();
+ assert(fNotifyChildArray);
+ assert(fMachineState == kIOPM_NotifyChildrenOrdered);
+
+ // Notify one child, wait for it to ack, then repeat for next child.
+ // This is a workaround for some drivers with multiple instances at
+ // the same branch in the power tree, but the driver is slow to power
+ // up unless the tree ordering is observed. Problem observed only on
+ // system wake, not on system sleep.
+ //
+ // We have the ability to power off in reverse child index order.
+ // That works nicely on some machines, but not on all HW configs.
+
+ if (fNotifyChildArray->getCount())
+ {
+ IOPowerConnection * connection;
+ connection = (IOPowerConnection *) fNotifyChildArray->getObject(0);
+ notifyChild( connection );
+ fNotifyChildArray->removeObject(0);
+ }
+ else
+ {
+ fNotifyChildArray->release();
+ fNotifyChildArray = 0;
- if (nsec > LOG_SETPOWER_TIMES)
- PM_LOG("%s::setPowerState(%p, %lu -> %lu) took %d ms\n",
- fName, this, fCurrentPowerState, powerState, NS_TO_MS(nsec));
-
- PMEventDetails *details = PMEventDetails::eventDetails(
- kIOPMEventTypeSetPowerStateImmediate, // type
- fName, // who
- (uintptr_t)this, // owner unique
- NULL, // interest name
- (uint8_t)oldPowerState, // old
- (uint8_t)powerState, // new
- 0, // result
- NS_TO_US(nsec)); // usec completion time
-
- getPMRootDomain()->recordAndReleasePMEvent( details );
+ if (nsec > LOG_SETPOWER_TIMES) {
+ getPMRootDomain()->pmStatsRecordApplicationResponse(
+ gIOPMStatsDriverPSChangeSlow,
+ fName, kDriverCallSetPowerState, NS_TO_MS(nsec), 0, NULL, powerState);
+ }
- if (nsec > LOG_SETPOWER_TIMES)
- PM_LOG("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) took %d ms\n",
- driver->getName(),
- (fDriverCallReason == kDriverCallInformPreChange) ? "Will" : "Did",
- driver, fName, fCurrentPowerState, powerState, NS_TO_MS(nsec));
-
- uint16_t logType = (fDriverCallReason == kDriverCallInformPreChange)
- ? kIOPMEventTypePSWillChangeTo
- : kIOPMEventTypePSDidChangeTo;
-
- PMEventDetails *details = PMEventDetails::eventDetails(
- logType, // type
- fName, // who
- (uintptr_t)this, // owner unique
- driver->getName(), // interest name
- (uint8_t)fCurrentPowerState, // old
- (uint8_t)fHeadNotePowerState, // new
- 0, // result
- NS_TO_US(nsec)); // usec completion time
-
- getPMRootDomain()->recordAndReleasePMEvent( details );
+ if (nsec > LOG_SETPOWER_TIMES) {
+ getPMRootDomain()->pmStatsRecordApplicationResponse(
+ gIOPMStatsDriverPSChangeSlow, driver->getName(),
+ fDriverCallReason, NS_TO_MS(nsec), 0, NULL, powerState);
+ }
- if (nsec > LOG_APP_RESPONSE_MSG_TRACER)
- {
- // TODO: populate the messageType argument
- getPMRootDomain()->pmStatsRecordApplicationResponse(
- gIOPMStatsApplicationResponseSlow,
- name, 0, NS_TO_MS(nsec), pid);
- }
+ if (nsec > LOG_APP_RESPONSE_MSG_TRACER)
+ {
+ // TODO: populate the messageType argument
+ getPMRootDomain()->pmStatsRecordApplicationResponse(
+ gIOPMStatsApplicationResponseSlow,
+ name, 0, NS_TO_MS(nsec), pid, object);
+ }
+ else
+ {
+ getPMRootDomain()->pmStatsRecordApplicationResponse(
+ gIOPMStatsApplicationResponsePrompt,
+ name, 0, NS_TO_MS(nsec), pid, object);
- assert( requests );
- assert( count > 0 );
- assert( gIOPMRequestQueue );
-
- for (IOItemCount i = 0; i < count; i++)
- {
- IOPMRequest * req = requests[i];
- PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
- (long)req->getType(), OBFUSCATE(req),
- OBFUSCATE(req->getTarget()), req->getTarget()->getName(),
- OBFUSCATE(req->fArg0),
+ assert( requests );
+ assert( count > 0 );
+ assert( gIOPMRequestQueue );
+
+ for (IOItemCount i = 0; i < count; i++)
+ {
+ IOPMRequest * req = requests[i];
+ PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
+ (long)req->getType(), OBFUSCATE(req),
+ OBFUSCATE(req->getTarget()), req->getTarget()->getName(),
+ OBFUSCATE(req->fArg0),
- break;
- }
-
- // Waiting on driver's setPowerState() timeout.
- if (fDriverTimer)
- {
- reason = 1; break;
- }
-
- // Child or interested driver acks pending.
- if (fHeadNotePendingAcks)
- {
- reason = 2; break;
- }
-
- // Waiting on apps or priority power interest clients.
- if (fResponseArray)
- {
- reason = 3; break;
- }
-
- // Waiting on settle timer expiration.
- if (fSettleTimeUS)
- {
- reason = 4; break;
- }
- } while (false);
-
- fWaitReason = reason;
-
- if (reason)
- {
- if (count)
- {
- PM_LOG1("[B %02x] %p [%p %s] state %d, reason %d\n",
- request->getType(), OBFUSCATE(request),
+ break;
+ }
+
+ // Waiting on driver's setPowerState() timeout.
+ if (fDriverTimer)
+ {
+ reason = 1; break;
+ }
+
+ // Child or interested driver acks pending.
+ if (fHeadNotePendingAcks)
+ {
+ reason = 2; break;
+ }
+
+ // Waiting on apps or priority power interest clients.
+ if (fResponseArray)
+ {
+ reason = 3; break;
+ }
+
+ // Waiting on settle timer expiration.
+ if (fSettleTimeUS)
+ {
+ reason = 4; break;
+ }
+ } while (false);
+
+ fWaitReason = reason;
+
+ if (reason)
+ {
+ if (count)
+ {
+ PM_LOG1("[B %02x] %p [%p %s] state %d, reason %d\n",
+ request->getType(), OBFUSCATE(request),
- if (!fDoNotPowerDown)
- {
- if (IS_ROOT_DOMAIN) {
- PMEventDetails *details = PMEventDetails::eventDetails(
- kIOPMEventTypeAppNotificationsFinished,
- NULL,
- 0,
- 0);
-
- getPMRootDomain()->recordAndReleasePMEvent( details );
- }
-
- // no, we can continue
- OurChangeTellClientsPowerDown();
- }
- else
- {
- if (IS_ROOT_DOMAIN) {
- PMEventDetails *details = PMEventDetails::eventDetails(
- kIOPMEventTypeSleepDone,
- NULL,
- 1, /* reason: 1 == Ask clients succeeded */
- kIOReturnAborted); /* result */
-
- getPMRootDomain()->recordAndReleasePMEvent( details );
- }
+ if (!fDoNotPowerDown)
+ {
+ // no, we can continue
+ OurChangeTellClientsPowerDown();
+ }
+ else
+ {
+ OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState);
+ PM_ERROR("%s: idle cancel, state %u\n", fName, fMachineState);
+ // yes, rescind the warning
+ tellNoChangeDown(fHeadNotePowerState);
+ // mark the change note un-actioned
+ fHeadNoteChangeFlags |= kIOPMNotDone;
+ // and we're done
+ OurChangeFinish();
+ }
+ break;
- if (fDoNotPowerDown)
- {
- OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState);
- PM_ERROR("%s: idle cancel, state %u\n", fName, fMachineState);
- // yes, rescind the warning
- tellNoChangeDown(fHeadNotePowerState);
- // mark the change note un-actioned
- fHeadNoteChangeFlags |= kIOPMNotDone;
- // and we're done
- OurChangeFinish();
- }
- else
- OurChangeTellUserPMPolicyPowerDown();
- break;
-
- case kIOPM_OurChangeTellPriorityClientsPowerDown:
- // PMRD: LastCallBeforeSleep notify done
+ if (fDoNotPowerDown)
+ {
+ OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState);
+ PM_ERROR("%s: idle cancel, state %u\n", fName, fMachineState);
+ // yes, rescind the warning
+ tellNoChangeDown(fHeadNotePowerState);
+ // mark the change note un-actioned
+ fHeadNoteChangeFlags |= kIOPMNotDone;
+ // and we're done
+ OurChangeFinish();
+ }
+ else
+ OurChangeTellUserPMPolicyPowerDown();
+ break;
+
+ case kIOPM_OurChangeTellPriorityClientsPowerDown:
+ // PMRD: LastCallBeforeSleep notify done
- if (fDoNotPowerDown)
- {
- if (IS_ROOT_DOMAIN) {
- PMEventDetails *details = PMEventDetails::eventDetails(
- kIOPMEventTypeSleepDone,
- NULL,
- 2, /* reason: 2 == Client cancelled wake */
- kIOReturnAborted); /* result */
-
- getPMRootDomain()->recordAndReleasePMEvent( details );
- }
- OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState);
- PM_ERROR("%s: idle revert, state %u\n", fName, fMachineState);
- // no, tell clients we're back in the old state
- tellChangeUp(fCurrentPowerState);
- // mark the change note un-actioned
- fHeadNoteChangeFlags |= kIOPMNotDone;
- // and we're done
- OurChangeFinish();
- }
- else
- {
- if (IS_ROOT_DOMAIN) {
- PMEventDetails *details = PMEventDetails::eventDetails(
- kIOPMEventTypeAppNotificationsFinished,
- NULL,
- 2, /* reason: 2 == TellPriorityClientsDone */
- kIOReturnSuccess); /* result */
-
- getPMRootDomain()->recordAndReleasePMEvent( details );
- }
- // yes, we can continue
- OurChangeTellPriorityClientsPowerDown();
- }
- break;
+ if (fDoNotPowerDown)
+ {
+ OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState);
+ PM_ERROR("%s: idle revert, state %u\n", fName, fMachineState);
+ // no, tell clients we're back in the old state
+ tellChangeUp(fCurrentPowerState);
+ // mark the change note un-actioned
+ fHeadNoteChangeFlags |= kIOPMNotDone;
+ // and we're done
+ OurChangeFinish();
+ }
+ else
+ {
+ // yes, we can continue
+ OurChangeTellPriorityClientsPowerDown();
+ }
+ break;
- break;
-
- case kIOPMRequestTypeAckPowerChange:
- more = handleAcknowledgePowerChange( request );
- break;
-
- case kIOPMRequestTypeAckSetPowerState:
- if (fDriverTimer == -1)
- {
- // driver acked while setPowerState() call is in-flight.
- // take this ack, return value from setPowerState() is irrelevant.
- OUR_PMLog(kPMLogDriverAcknowledgeSet,
- (uintptr_t) this, fDriverTimer);
- fDriverTimer = 0;
- }
- else if (fDriverTimer > 0)
- {
- // expected ack, stop the timer
- stop_ack_timer();
+ break;
+
+ case kIOPMRequestTypeAckPowerChange:
+ more = handleAcknowledgePowerChange( request );
+ break;
+
+ case kIOPMRequestTypeAckSetPowerState:
+ if (fDriverTimer == -1)
+ {
+ // driver acked while setPowerState() call is in-flight.
+ // take this ack, return value from setPowerState() is irrelevant.
+ OUR_PMLog(kPMLogDriverAcknowledgeSet,
+ (uintptr_t) this, fDriverTimer);
+ fDriverTimer = 0;
+ }
+ else if (fDriverTimer > 0)
+ {
+ // expected ack, stop the timer
+ stop_ack_timer();
- if (nsec > LOG_SETPOWER_TIMES)
- PM_LOG("%s::setPowerState(%p, %lu -> %lu) async took %d ms\n",
- fName, OBFUSCATE(this), fCurrentPowerState, fHeadNotePowerState, NS_TO_MS(nsec));
-
- PMEventDetails *details = PMEventDetails::eventDetails(
- kIOPMEventTypeSetPowerStateDelayed, // type
- fName, // who
- (uintptr_t)this, // owner unique
- NULL, // interest name
- (uint8_t)getPowerState(), // old
- (uint8_t)fHeadNotePowerState, // new
- 0, // result
- NS_TO_US(nsec)); // usec completion time
-
- getPMRootDomain()->recordAndReleasePMEvent( details );
+ if (nsec > LOG_SETPOWER_TIMES) {
+ getPMRootDomain()->pmStatsRecordApplicationResponse(
+ gIOPMStatsDriverPSChangeSlow,
+ fName, kDriverCallSetPowerState, NS_TO_MS(nsec), 0, NULL, fHeadNotePowerState);
+ }
- OUR_PMLog(kPMLogDriverAcknowledgeSet, (uintptr_t) this, fDriverTimer);
- fDriverTimer = 0;
- more = true;
- }
- else
- {
- // unexpected ack
- OUR_PMLog(kPMLogAcknowledgeErr4, (uintptr_t) this, 0);
- }
- break;
-
- case kIOPMRequestTypeInterestChanged:
- handleInterestChanged( request );
- more = true;
- break;
-
- case kIOPMRequestTypeIdleCancel:
- if ((fMachineState == kIOPM_OurChangeTellClientsPowerDown)
+ OUR_PMLog(kPMLogDriverAcknowledgeSet, (uintptr_t) this, fDriverTimer);
+ fDriverTimer = 0;
+ more = true;
+ }
+ else
+ {
+ // unexpected ack
+ OUR_PMLog(kPMLogAcknowledgeErr4, (uintptr_t) this, 0);
+ }
+ break;
+
+ case kIOPMRequestTypeInterestChanged:
+ handleInterestChanged( request );
+ more = true;
+ break;
+
+ case kIOPMRequestTypeIdleCancel:
+ if ((fMachineState == kIOPM_OurChangeTellClientsPowerDown)
-PMEventDetails* PMEventDetails::eventDetails(uint32_t type,
- const char *ownerName,
- uintptr_t ownerUnique,
- const char *interestName,
- uint8_t oldState,
- uint8_t newState,
- uint32_t result,
- uint32_t elapsedTimeUS) {
-
- PMEventDetails *myself;
- myself = new PMEventDetails;
-
- if(myself) {
- myself->eventType = type;
- myself->ownerName = ownerName;
- myself->ownerUnique = ownerUnique;
- myself->interestName = interestName;
- myself->oldState = oldState;
- myself->newState = newState;
- myself->result = result;
- myself->elapsedTimeUS = elapsedTimeUS;
-
- myself->eventClassifier = kIOPMEventClassDriverEvent;
- }
-
- return myself;
-}
-
-
-PMEventDetails* PMEventDetails::eventDetails(uint32_t type,
- const char *uuid,
- uint32_t reason,
- uint32_t result) {
-
- PMEventDetails *myself;
- myself = new PMEventDetails;
-
- if(myself) {
- myself->eventType = type;
- myself->uuid = uuid;
- myself->reason = reason;
- myself->result = result;
-
- myself->eventClassifier = kIOPMEventClassSystemEvent;
- }
-
- return myself;
-}
-