kernel/eka/drivers/resourceman/resourcecontrol_extended.cpp
changeset 0 a41df078684a
child 4 56f325a607ea
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/resourceman/resourcecontrol_extended.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,943 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\drivers\resourceman\resourcecontrol_extended.cpp
+// 
+//
+
+#include <drivers/resourcecontrol.h>
+		
+extern DPowerResourceController* PowerResourceController;
+/**
+@internalComponent
+@prototype 9.5
+
+Reserves the client level from pool to be used for updating resource client level in dependency resource.
+
+@param aCount Number of client levels to reserve from pool
+
+@return KErrNone On success 
+@return KErrNoMemory Not enough memory to grow the pool
+*/
+TInt DPowerResourceController::ReserveClientLevelPoolCount(TUint16 aCount)
+	{
+	if(aCount < iResourceLevelPoolCount) 
+		iResourceLevelPoolCount = (TUint16)(iResourceLevelPoolCount - aCount);
+	else
+		{
+		TUint allocCount = (iStaticResDependencyCount / 2) + aCount;
+		// coverity[alloc_fn]
+		SPowerResourceClientLevel* pCL = new SPowerResourceClientLevel[allocCount];
+		if(!pCL)
+			return KErrNoMemory;
+		for(TUint count = 0;count<(TUint)(allocCount);count++)
+			LIST_PUSH(iResourceLevelPool, &pCL[count], iNextInList);
+		iResourceLevelPoolCount= (TUint16)(iResourceLevelPoolCount + (iStaticResDependencyCount / 2));
+#ifdef PRM_INSTRUMENTATION_MACRO
+		TUint size = allocCount * 4;
+		PRM_MEMORY_USAGE_TRACE
+#endif
+		}
+	return KErrNone;
+	}
+
+/**
+@internalComponent
+@prototype 9.5
+
+Return a client level object from pool.
+
+@param aLevelPtr Pointer to update the client level object.
+
+@return None 
+*/
+void DPowerResourceController::RemoveClientLevelFromPool(SPowerResourceClientLevel *&aLevelPtr)
+	{
+	LIST_POP(iResourceLevelPool, aLevelPtr, iNextInList);
+	return;
+	}
+
+/**
+Update with number of dependent resources for the specified resource. 
+*/
+TInt DPowerResourceController::GetNumDependentsForResource(TUint aResourceId, TUint* aNumResources)
+	{
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetNumDependentsForResource"));
+	
+	if(!(aResourceId & KIdMaskResourceWithDependencies))
+		return KErrNotSupported;
+	SNode* pN;
+	if(aResourceId & KIdMaskDynamic)
+		{
+		DDynamicPowerResourceD* pDR = iDynamicResDependencyList[(TUint16)(aResourceId & ID_INDEX_BIT_MASK)];		
+		if(!pDR)														
+			return KErrNotFound;
+		pN = pDR->iDependencyList;
+		}
+	else
+		{
+		if((aResourceId & ID_INDEX_BIT_MASK) > iStaticResDependencyCount)
+			return KErrNotFound;
+		DStaticPowerResourceD* pDR = iStaticResDependencyArray[(TUint16)(aResourceId & ID_INDEX_BIT_MASK) - 1];
+		pN = pDR->iDependencyList;
+		}
+	*aNumResources = 0;
+	for(;pN != NULL; pN = pN->iNext)
+		(*aNumResources)++;
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetNumDependentsForResource"));
+	return KErrNone;
+	}
+
+/**
+Update the specified array with dependent resource Id's of the specified resource. 
+*/
+TInt DPowerResourceController::GetDependentsIdForResource(TUint aResourceId, TAny* aInfo, TUint* aNumDepResources)
+	{
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetDependentsIdForResource"));
+
+	if(!(aResourceId & KIdMaskResourceWithDependencies))
+		return KErrNotSupported;
+	
+	if(!aInfo || !*aNumDepResources)
+		{
+		return KErrArgument;
+		}
+
+	TDes8 *pInfo = (TDes8*)aInfo;
+	
+	if((TUint)(pInfo->MaxLength() - pInfo->Length()) < (sizeof(SResourceDependencyInfo)*(*aNumDepResources)))
+		return KErrArgument;
+     
+	SResourceDependencyInfo sResDepInfo;
+	
+	SNode* pN;
+	if(aResourceId & KIdMaskDynamic)
+		{
+		DDynamicPowerResourceD* pDR = iDynamicResDependencyList[(TUint16)(aResourceId & ID_INDEX_BIT_MASK)];
+		if(!pDR)
+			return KErrNotFound;
+		pN = pDR->iDependencyList;
+		}
+	else
+		{
+		if((aResourceId & ID_INDEX_BIT_MASK) > iStaticResDependencyCount)
+			return KErrNotFound;
+		DStaticPowerResourceD* pDR = iStaticResDependencyArray[(TUint16)(aResourceId & ID_INDEX_BIT_MASK) -1];
+		pN = pDR->iDependencyList;
+		}
+	TUint count = 0;
+	TUint resCount = 0;
+
+	for(; pN != NULL; pN = pN->iNext)
+		{
+		resCount++;
+		if(count == *aNumDepResources)
+			continue;
+		sResDepInfo.iResourceId = pN->iResource->iResourceId;
+		sResDepInfo.iDependencyPriority = pN->iPriority;
+		pInfo->Append(TPckgC<SResourceDependencyInfo>(sResDepInfo));
+		}
+	*aNumDepResources = resCount;
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetDependentsIdForResource"));
+	return KErrNone;
+	}
+
+/**
+Registers resource dependency. This could be between 2 dynamic resource or between
+dynamic and static resource.
+*/
+TInt DPowerResourceController::RegisterResourceDependency(SPowerResourceClient* aClientPtr, SResourceDependencyInfo* aInfo1, 
+														              SResourceDependencyInfo* aInfo2)
+	{
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DExtendedResourceController::RegisterResourceDependency"));
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId1 = 0x%x, ResourceId2 = 0x%x", 
+		                             aClientPtr->iClientId, aInfo1->iResourceId, aInfo2->iResourceId));
+		                             
+	if(iDfcQDependencyLock)
+		{
+		__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterResourceDependency::Resource In Use"));
+		return KErrInUse;
+		}
+	
+	TInt r = KErrNone;
+	//One of the resource must be dynamic resource
+	if(!(aInfo1->iResourceId & KIdMaskDynamic) && !(aInfo2->iResourceId & KIdMaskDynamic))
+		return KErrNotSupported;
+	//Both the resources should have dependency resource bit set in its id. 
+	if(!(aInfo1->iResourceId & KIdMaskResourceWithDependencies) || !(aInfo2->iResourceId & KIdMaskResourceWithDependencies))
+		return KErrNotSupported;
+	
+	DDynamicPowerResourceD* pR1 = NULL;
+	DDynamicPowerResourceD* pR2 = NULL;
+	SNode* pN1 = NULL;
+	SNode* pN2 = NULL;
+	//Retrieve resource1 from the corresponding list.
+	if(aInfo1->iResourceId & KIdMaskDynamic)
+		{
+		pR1 = iDynamicResDependencyList[(TUint16)(aInfo1->iResourceId & ID_INDEX_BIT_MASK)];
+		if(!pR1)
+			return KErrNotFound;
+		pN1 = pR1->iDependencyList;
+		}
+	else 
+		{
+		if((aInfo1->iResourceId & ID_INDEX_BIT_MASK) > iStaticResDependencyCount)
+			return KErrNotFound;
+		pR1 = (DDynamicPowerResourceD*)iStaticResDependencyArray[(TUint16)(aInfo1->iResourceId & ID_INDEX_BIT_MASK) - 1];
+		pN1 = ((DStaticPowerResourceD*)pR1)->iDependencyList;
+		}
+	//Retrieve resource2 from the corresponding list.
+	if(aInfo2->iResourceId & KIdMaskDynamic)
+		{
+		pR2 = iDynamicResDependencyList[(TUint16)(aInfo2->iResourceId & ID_INDEX_BIT_MASK)];
+		if(!pR2)
+			return KErrNotFound;
+		pN2 = pR2->iDependencyList;
+		}
+	else
+		{
+		if((aInfo2->iResourceId & ID_INDEX_BIT_MASK) > iStaticResDependencyCount)
+			return KErrNotFound;
+		pR2 = (DDynamicPowerResourceD*)iStaticResDependencyArray[(TUint16)(aInfo2->iResourceId & ID_INDEX_BIT_MASK) - 1];
+		pN2 = ((DStaticPowerResourceD*)pR2)->iDependencyList;
+		}
+
+	//Only long latency resource is allowed to have dependents.
+	if(!pR1->LatencySet())
+		pR1->iFlags |= KLongLatencySet;
+	if(!pR2->LatencySet())
+		pR2->iFlags |= KLongLatencySet;
+	
+	//Check for closed loop
+	//NOTE: Panics, if any closed loop is encountered
+	if(pN1)
+		CheckForDependencyLoop((DStaticPowerResourceD*)pR1, pR1->iResourceId, pR2->iResourceId);
+
+	if(pN2)
+		CheckForDependencyLoop((DStaticPowerResourceD*)pR2, pR2->iResourceId, pR1->iResourceId);
+
+	//Check whether the passed priority already exists.Code will return with KErrAlreadyExists, if it exists.
+	CHECK_IF_PRIORITY_ALREADY_EXISTS(pN1, aInfo2->iDependencyPriority)
+	CHECK_IF_PRIORITY_ALREADY_EXISTS(pN2, aInfo1->iDependencyPriority)
+	UnLock();
+	//Allocate nodes
+	// coverity[alloc_fn]
+	SNode* pSN1 = new (SNode);
+	// coverity[alloc_fn]
+	SNode* pSN2 = new (SNode);
+	Lock();
+	if(!pSN1 || !pSN2)
+		return KErrNoMemory;
+	//Add the link
+	pSN1->iResource = (DStaticPowerResourceD*)pR1;
+	pSN1->iPropagatedLevel = 0;
+	pSN1->iPriority = aInfo1->iDependencyPriority;
+	pSN1->iVisited = EFalse;
+	pSN1->iNext = NULL;
+
+	pSN2->iResource = (DStaticPowerResourceD*)pR2;
+	pSN2->iPropagatedLevel = 0;
+	pSN2->iPriority = aInfo2->iDependencyPriority;
+	pSN2->iVisited = EFalse;
+	pSN2->iNext = NULL;
+
+	if(aInfo1->iResourceId & KIdMaskDynamic) //Dynamic resource
+		// coverity[memory_leak]
+		ADD_DEPENDENCY_NODE(pSN2, ((DDynamicPowerResourceD*)pR1)->iDependencyList)
+	else
+		((DStaticPowerResourceD*)pR1)->AddNode(pSN2);
+	
+	//Add the second node
+	if(aInfo2->iResourceId & KIdMaskDynamic) //Dynamic resource
+		// coverity[memory_leak]
+		ADD_DEPENDENCY_NODE(pSN1, ((DDynamicPowerResourceD*)pR2)->iDependencyList)
+	else
+		((DStaticPowerResourceD*)pR2)->AddNode(pSN1);
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DExtendedResourceController::RegisterResourceDependency"));
+#ifdef PRM_INSTRUMENTATION_MACRO
+	PRM_REGISTER_RESOURCE_DEPENDENCY_TRACE
+#endif
+	return r;
+	}
+
+/**
+Registers dynamic resource. 
+*/
+TInt DPowerResourceController::RegisterDynamicResource(SPowerResourceClient* aClientPtr, DDynamicPowerResource* aPDRes, 
+													                 TUint* aDynamicResourceId)
+	{
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DExtendedResourceController::RegisterDynamicResource"));
+	TInt r = KErrNone;
+	//Check for dynamic resource
+	if(!(aPDRes->iResourceId & KIdMaskDynamic))
+		return KErrNotSupported;
+	//check for count
+	else if(aPDRes->LockCount() != 0) 
+		return KErrAlreadyExists;
+	
+	TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
+	req->ReqType() = TPowerRequest::ERegisterDynamicResource;
+	req->Resource() = (DStaticPowerResource*)aPDRes;
+	UnLock();
+	req->SendReceive(iMsgQ);
+	Lock();
+	if(req->ReturnCode() == KErrNone)
+		{
+		*aDynamicResourceId = req->ResourceId();
+		aPDRes-> iOwnerId = aClientPtr->iClientId;
+		aPDRes->Lock();
+		//Increment dynamic resource count in client
+		aClientPtr->iDynamicResCount++;
+		}
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DExtendedResourceController::RegisterDynamicResource, resource ID = 0x%x", 
+		                                                                                  aDynamicResourceId));
+#ifdef PRM_INSTRUMENTATION_MACRO
+	PRM_REGISTER_DYNAMIC_RESOURCE_TRACE
+#endif
+	return r;
+	}
+
+/**
+Deregisters dynamic resource.
+*/
+TInt DPowerResourceController::DeregisterDynamicResource(SPowerResourceClient* aClientPtr, TUint aResourceId, 
+														 TInt* aPDefLevel)
+	{
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DExtendedResourceController::DeregisterDynamicResource"));
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("aClientId = 0x%x, aDynamicResourceId = 0x%x, Default Level = %d", 
+		                               aClientPtr->iClientId, aResourceId, aPDefLevel ? *aPDefLevel : 0));
+	TInt r = KErrNone;
+	DDynamicPowerResource* pDR = NULL;
+	//Check for dynamic resource bit
+	if(!(aResourceId & KIdMaskDynamic))
+		return KErrNotSupported;
+
+	//Get the resource from appropriate container
+	if(aResourceId & KIdMaskResourceWithDependencies)
+		{
+		pDR = iDynamicResDependencyList[(TUint16)(aResourceId & ID_INDEX_BIT_MASK)];		
+		if(!pDR)														
+			return KErrNotFound;
+		}
+	else
+		{
+		pDR = iDynamicResourceList[(TUint16)(aResourceId & ID_INDEX_BIT_MASK)];		
+		if(!pDR)														
+			return KErrNotFound;
+		}
+	//Client which registered the dynamic resource is only allowed to deregister. 
+	if(aClientPtr->iClientId != pDR->iOwnerId)
+		{
+		__KTRACE_OPT(KRESMANAGER, Kern::Printf("Client attempting to deregister a dynamic resource which is not the owner!"));
+		return KErrAccessDenied;
+		}
+	// Don't allow to deregister if the some other operation is in progress or if the resource is shared and
+	// another client holds requirement on this resource
+	if((pDR->LockCount() > RESOURCE_NOT_IN_OPERATION) || pDR->InUse())
+		{
+		return KErrInUse;
+		}
+	TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
+	req->ResourceCb() = NULL;
+	req->ReturnCode() = KErrNone;
+	req->RequiresChange() = EFalse;
+	pDR->UnLock(); //Marked as deleted so that no other operation will be taking place.
+	req->ReqType() = TPowerRequest::ESetDefaultLevel;
+	//Handle dynamic resource with dependencies
+	if(aResourceId & KIdMaskResourceWithDependencies)
+		{
+		for(SNode* pNode = ((DDynamicPowerResourceD*)pDR)->iDependencyList; pNode != NULL; pNode = pNode->iNext)
+			{
+			if((TUint)pNode->iResource->iLevelOwnerId == aResourceId)
+				{
+				req->ResourceId() = pNode->iResource->iResourceId;
+				req->ClientId() = aResourceId;
+				req->Level() = pNode->iResource->iCachedLevel;
+				req->Resource() = pNode->iResource; 
+				((DDynamicPowerResourceD*)(pNode->iResource))->Lock();
+				UnLock();
+				req->SendReceive(iMsgQDependency);
+				Lock();
+				}
+			//Remove entry from resource dependency list
+			for(SNode* pSN = pNode->iResource->iDependencyList; pSN != NULL; pSN = pSN->iNext)
+				{
+				if(pSN->iResource->iResourceId == aResourceId)
+					{
+					LIST_REMOVE(pNode->iResource->iDependencyList, pSN, iNext, SNode);
+					UnLock();
+					delete pSN;
+					Lock();
+					break;
+					}
+				}
+			//Remove from dependent resource "resource client level" list
+			for(SPowerResourceClientLevel* pL = ((DDynamicPowerResourceD*)(pNode->iResource))->iResourceClientList; 
+			                                                                pL != NULL; pL = pL->iNextInList)
+				{
+				if(pL->iClientId == aResourceId)
+					{
+					LIST_REMOVE(((DDynamicPowerResourceD*)(pNode->iResource))->iResourceClientList, pL, iNextInList, 
+						                                                                SPowerResourceClientLevel);
+					//Move to free pool
+					LIST_PUSH(iResourceLevelPool, pL, iNextInList);
+					iResourceLevelPoolCount++;
+					}
+				}
+			((DDynamicPowerResource*)(pNode->iResource))->UnLock();
+			}
+		//Move the resource to default level
+		req->ClientId() = -1;
+		req->ResourceId() = aResourceId;
+		req->Resource() = pDR;
+		if(aPDefLevel)
+			req->Level() = *aPDefLevel; //Set the resource to the passed level
+		else
+			req->Level() = pDR->iDefaultLevel; //Set the resource level to default level
+		UnLock();
+		req->SendReceive(iMsgQDependency);
+		}
+	else
+		{
+		UnLock();
+		req->ResourceId() = aResourceId;
+		req->ClientId() = KDynamicResourceDeRegistering;
+		req->Resource() = pDR;
+		req->ResourceCb() = NULL;
+		if(aPDefLevel)
+			req->Level() = *aPDefLevel; //Set the resource to the passed level
+		else
+			req->Level() = pDR->iDefaultLevel; //Set the resource level to default level
+		if(pDR->LatencySet())
+			{
+			r = req->SendReceive(iMsgQ);
+			}
+		else
+			{
+			//Call custom function for custom sense resource
+			if(pDR->Sense() == DStaticPowerResource::ECustom)
+				{
+				if(!pDR->iCustomFunction)
+					Panic(ECustomFunctionNotSet);
+				pDR->iCustomFunction(req->ClientId(), *(aClientPtr->iName), aResourceId,
+				                     EDynamicResourceDeregister, req->Level(),
+				                     (TAny*)&pDR->iClientList, NULL);
+				}
+			//Not checking for error condition as the resource needs to be moved to default state
+			if(aPDefLevel)
+				{
+				//If the resource change to requested level fails trying to change it to default level.
+				req->ReqType() = TPowerRequest::EChange;
+				r = pDR->DoRequest(*req);
+				if(r != KErrNone)
+					{
+					req->ReqType() = TPowerRequest::ESetDefaultLevel;
+					req->Level() = pDR->iDefaultLevel;
+					pDR->DoRequest(*req);
+					}
+				}
+			else
+				pDR->DoRequest(*req);
+			//Send notifications. Passing -2 in clientId to indicate that this dynamic resource is deregistering
+			CompleteNotifications(KDynamicResourceDeRegistering, pDR, req->Level(),KErrNone, req->ClientId());
+			}
+		}
+	Lock();
+	//Remove client level
+	SPowerResourceClientLevel *pCL;
+	SPowerResourceClient *pC;
+	for(SDblQueLink* pRC = pDR->iClientList.First(); pRC != &pDR->iClientList.iA; pRC = pRC->iNext)
+		{
+		pCL = (SPowerResourceClientLevel*)pRC;
+		if(pCL->iClientId & USER_SIDE_CLIENT_BIT_MASK)
+			pC = iUserSideClientList[(TUint16)(pCL->iClientId & ID_INDEX_BIT_MASK)];								
+		else																										
+			pC = iClientList[(TUint16)(pCL->iClientId & ID_INDEX_BIT_MASK)];										
+		LIST_REMOVE(pC->iLevelList, pCL, iNextInList, SPowerResourceClientLevel);
+		LIST_PUSH(iClientLevelPool, pCL, iNextInList);
+		if(pC->iUnderFlowClCount > 0)
+			{
+			pC->iUnderFlowClCount--;
+			iClientLevelPoolCount++;
+			}
+		else
+			pC->iReservedCl++;
+		}
+	//Decrement dynamic resource count in client
+	aClientPtr->iDynamicResCount--;
+	if(aResourceId & KIdMaskResourceWithDependencies)
+		{
+		iDynamicResDependencyList.Remove((DDynamicPowerResourceD*)pDR, (TUint16)(pDR->iResourceId & ID_INDEX_BIT_MASK));
+		iDynamicResDependencyCount--;
+		}
+	else
+		{
+		iDynamicResourceList.Remove(pDR, (TUint16)(pDR->iResourceId & ID_INDEX_BIT_MASK));
+		iDynamicResourceCount--;
+		}
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DExtendedResourceController::DeregisterDynamicResource"));
+#ifdef PRM_INSTRUMENTATION_MACRO
+	TInt level = req->Level();
+	PRM_DEREGISTER_DYNAMIC_RESOURCE_TRACE
+#endif
+	return r;
+	}
+
+/**
+@publishedPartner
+@prototype 9.6
+Default implementation, PSL re-implements this if features supported.
+*/
+TInt DPowerResourceController::DoRegisterStaticResourcesDependency(DStaticPowerResourceD**& aStaticResourceDArray, 
+																    TUint16& aStaticResourceDCount)
+	{
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("DExtendedResourceController::DoRegisterStaticResourcesDependency default \
+		                                                               implementation"));
+	aStaticResourceDArray = NULL;
+	aStaticResourceDCount = 0;
+	return KErrNone;
+	}
+
+/**
+This function checks for any closed loop dependency, if so panics.
+*/
+void DPowerResourceController::CheckForDependencyLoop(DStaticPowerResourceD* pR, TUint aParentResId, TUint aTargetResId)
+	{
+	SNode *pN;
+
+	if(pR->iResourceId & KIdMaskDynamic)
+		pN = ((DDynamicPowerResourceD*)pR)->iDependencyList;
+	else
+		pN = pR->iDependencyList;
+
+	for(; pN != NULL; pN = pN->iNext)
+		{
+		if(pN->iResource->iResourceId == aParentResId)
+			continue;
+		if(pN->iVisited || (pN->iResource->iResourceId == aTargetResId))
+			{
+			__KTRACE_OPT(KRESMANAGER, Kern::Printf("Loop encountered\n"));
+			DPowerResourceController::Panic(DPowerResourceController::EClosedLoopDependencies);
+			}
+		pN->iVisited = ETrue;
+		CheckForDependencyLoop(pN->iResource, pR->iResourceId, aTargetResId);
+		pN->iVisited = EFalse;
+		}
+	}
+
+/**
+This is called from the controller thread to handle the dependency resource state change operation.
+*/
+TInt DPowerResourceController::HandleDependencyResourceStateChange(SPowerResourceClient* pC, TPowerRequest& aRequest)
+	{
+	DStaticPowerResourceD* pR = (DStaticPowerResourceD*)aRequest.Resource();
+	if(aRequest.ReqType() == TPowerRequest::EChange) //Handle resource change operation
+		{
+		if(aRequest.Resource()->Usage()) //Shared resource
+			{
+			Lock();
+			aRequest.ReturnCode() = CheckLevelAndAddClient(pC, &aRequest);
+			UnLock();
+			if((aRequest.ReturnCode()!= KErrNone) || (!aRequest.RequiresChange()))
+				{
+				aRequest.Level() = pR->iCachedLevel; //If no change then send the current level back.
+				return aRequest.ReturnCode();
+				}
+			}
+		else if(pR->iClientList.IsEmpty())
+			{
+			Lock();
+			if(pC->iReservedCl==0 && !iClientLevelPoolCount)
+				{
+				__KTRACE_OPT(KRESMANAGER, Kern::Printf("Reserved Client Level exhausted and its free pool empty"));
+                aRequest.ReturnCode() = KErrUnderflow;
+				UNLOCK_RETURN(KErrUnderflow);
+				}
+			SPowerResourceClientLevel* pSCL=NULL;
+			LIST_POP(iClientLevelPool, pSCL, iNextInList);
+			pSCL->iClientId=pC->iClientId;
+			pSCL->iResourceId=aRequest.ResourceId();
+			pSCL->iLevel=aRequest.Level();
+			LIST_PUSH(pC->iLevelList, pSCL, iNextInList); //Add to client
+			pR->iClientList.Add(pSCL); //Add in resource
+			if(pC->iReservedCl==0)
+				{
+				iClientLevelPoolCount--;
+				pC->iUnderFlowClCount++;
+				}
+            else
+			   pC->iReservedCl--;
+			if(pR->iCachedLevel == aRequest.Level())
+				{
+				pR->iLevelOwnerId = aRequest.ClientId();
+				if(pR->iIdleListEntry)
+					pR->iIdleListEntry->iLevelOwnerId = aRequest.ClientId();
+				aRequest.ReturnCode() = KErrNone;
+				UNLOCK_RETURN(KErrNone);
+				}
+			UnLock();
+			}
+		else
+			{
+			//Update the level in the client list.
+			SPowerResourceClientLevel* pSCL = (SPowerResourceClientLevel*)pR->iClientList.First();
+			pSCL->iLevel = aRequest.Level();
+			}
+	//Call appropriate resource's handle change propagation function
+	if(pR->iResourceId & KIdMaskDynamic)
+		aRequest.ReturnCode() = ((DDynamicPowerResourceD*)pR)->HandleChangePropagation(aRequest, EChangeStart, pC->iClientId, *(pC->iName));
+	else
+		aRequest.ReturnCode() = pR->HandleChangePropagation(aRequest, EChangeStart,pC->iClientId, *(pC->iName));
+	return aRequest.ReturnCode();
+	}
+	if(aRequest.ClientId() == -1) //Special where the resource needs to set to default level, when dynamic resource deregisters
+		{
+		//If resource is asked to change to certain value, instead of default then 
+		//try to set it to that value. If not able to set then try to set it to default level.
+		if(aRequest.Level() != pR->iDefaultLevel)
+			aRequest.ReqType() = TPowerRequest::EChange;
+		aRequest.ReturnCode() = pR->DoRequest(aRequest);
+		if((aRequest.ReturnCode() != KErrNone) && (aRequest.ReqType() == TPowerRequest::EChange))
+			{
+			aRequest.ReqType() = TPowerRequest::ESetDefaultLevel;
+			aRequest.Level() = pR->iDefaultLevel;
+			pR->DoRequest(aRequest);
+			}
+		//Set clientId to -2, indicating that the resource is deregistered.
+		CompleteNotifications(KDynamicResourceDeRegistering, pR, aRequest.Level(), KErrNone, aRequest.ClientId());
+		return KErrNone;
+		}
+	//Handle custom sense resource
+	if(aRequest.Resource()->Sense() == DStaticPowerResource::ECustom)
+		{
+		if(pR->iResourceId & KIdMaskDynamic)
+		    {
+			aRequest.RequiresChange() = ((DDynamicPowerResourceD*)pR)->iDepCustomFunction(aRequest.ClientId(), *(pC->iName), aRequest.ResourceId(), 
+			                                                                              EClientRelinquishLevel, aRequest.Level(), (TAny*)&pR->iClientList,
+			                                                                              (TAny*)&((DDynamicPowerResourceD*)pR)->iResourceClientList, NULL);
+			}
+		else
+		    {
+			aRequest.RequiresChange() = pR->iDepCustomFunction(aRequest.ClientId(), *(pC->iName), aRequest.ResourceId(),
+			                                                   EClientRelinquishLevel, aRequest.Level(), (TAny*)&pR->iClientList,
+			                                                   (TAny*)&pR->iResourceClientList, NULL);
+		    }
+		}
+	else
+		{
+		SPowerResourceClientLevel* pL = NULL;
+		SPowerResourceClientLevel* pMCL = NULL;
+		TInt maxLevel = KMinTInt;
+		//Find the maximum level from client
+		for(SDblQueLink* pCL = pR->iClientList.First(); pCL != &pR->iClientList.iA; pCL = pCL->iNext)
+			{
+			pL = (SPowerResourceClientLevel*)pCL;
+			if(pL->iClientId == (TUint)aRequest.ClientId())
+				continue;
+			if(pMCL == NULL)
+				{	
+				maxLevel = pL->iLevel;
+				pMCL = pL;
+				continue;
+				}
+			if(((pR->Sense() == DStaticPowerResource::ENegative) && (pL->iLevel < maxLevel)) || 
+				                    ((pR->Sense() == DStaticPowerResource::EPositive) && (pL->iLevel > maxLevel)))
+				{
+				maxLevel = pL->iLevel;
+				pMCL = pL;
+				}
+			}	
+		//Find the maximum level from resource client level
+		if(pR->iResourceId & KIdMaskDynamic)
+			pL = ((DDynamicPowerResourceD*)pR)->iResourceClientList;
+		else
+			pL = pR->iResourceClientList;
+		for(; pL != NULL; pL = pL->iNextInList)
+			{
+			if(pL->iClientId == (TUint)aRequest.ClientId())
+				continue;
+			if(pMCL == NULL)
+					{
+				maxLevel = pL->iLevel;
+				pMCL = pL;
+				continue;
+				}
+			if(((pR->Sense() == DStaticPowerResource::ENegative) && (pL->iLevel < maxLevel)) || 
+				           ((pR->Sense() == DStaticPowerResource::EPositive) && (pL->iLevel > maxLevel)))
+				{
+				maxLevel = pL->iLevel;
+				pMCL = pL;
+				}
+			}
+		if(pMCL == NULL)
+			{
+			aRequest.ClientId() = -1;
+			aRequest.Level() = pR->iDefaultLevel;
+			}
+		else
+			{
+			aRequest.ClientId() = pMCL->iClientId;
+			aRequest.Level() = maxLevel;
+			}
+		}
+	if((aRequest.Level() == pR->iCachedLevel) && !aRequest.RequiresChange()) //No need to change the resource just update the owner 
+		{
+		pR->iLevelOwnerId = aRequest.ClientId();
+		if(pR->iIdleListEntry)
+			pR->iIdleListEntry->iLevelOwnerId = aRequest.ClientId();
+		aRequest.ReturnCode() = KErrNone;
+		return KErrNone;
+		}
+	aRequest.ReqType() = TPowerRequest::EChange; //Make the change otherwise PSL set to default level
+
+	const TDesC8 *name;
+	if(aRequest.ClientId() == -1)
+		name = &KNoClient;
+	else
+		{
+		if(aRequest.ClientId() & (1 << RESOURCE_BIT_IN_ID_CHECK))										
+			{																							
+			DStaticPowerResourceD* pResource;												
+			if(aRequest.ClientId() & KIdMaskDynamic)										
+				pResource = (DStaticPowerResourceD*)iDynamicResDependencyList[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK)];
+			else																						
+				pResource = iStaticResDependencyArray[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK)  - 1];	
+			name = pResource->iName;																	
+			}																							
+		else																							
+			{																							
+			SPowerResourceClient* pClient;																
+			if(aRequest.ClientId() & USER_SIDE_CLIENT_BIT_MASK)										
+				pClient = iUserSideClientList[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK)];	
+			else // coverity[returned_null]
+				pClient = iClientList[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK)];			
+			name = pClient->iName;				
+			}
+		}
+
+	if(pR->iResourceId & KIdMaskDynamic)
+		aRequest.ReturnCode() = ((DDynamicPowerResourceD*)pR)->HandleChangePropagation(aRequest, EChangeStart, aRequest.ClientId(), *name);
+	else
+		aRequest.ReturnCode() = pR->HandleChangePropagation(aRequest, EChangeStart, aRequest.ClientId(), *name);
+	if(aRequest.ReturnCode() == KErrPermissionDenied) //Update the ownerId alone
+		{
+		pR->iLevelOwnerId = aRequest.ClientId();
+		if(pR->iIdleListEntry)
+			pR->iIdleListEntry->iLevelOwnerId = aRequest.ClientId();
+		}
+	return KErrNone;
+	}
+
+/**
+Deregisters resource dependency.
+*/
+TInt DPowerResourceController::DeregisterResourceDependency(SPowerResourceClient* aClientPtr, TUint aResId1, TUint aResId2)
+	{
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::DeregisterResourceDependency"));
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId1 = 0x%x, ResourceId2 = 0x%x", 
+		                                                                  aClientPtr->iClientId, aResId1, aResId2));
+	if(iDfcQDependencyLock)
+		{
+		__KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterResourceDependency::Resource In Use"));
+		UNLOCK_RETURN(KErrInUse);
+		}
+	DDynamicPowerResourceD *pDR1 = NULL;
+	DDynamicPowerResourceD *pDR2 = NULL;
+	SNode* pN1 = NULL;
+	SNode* pN2 = NULL;
+	SPowerResourceClientLevel* pCL1 = NULL;
+	SPowerResourceClientLevel* pCL2 = NULL;
+	//Get first resource from list
+	if(!(aResId1 & KIdMaskResourceWithDependencies) || !(aResId2 & KIdMaskResourceWithDependencies))
+		UNLOCK_RETURN(KErrAccessDenied);
+
+	if(aResId1 & KIdMaskDynamic)
+		{
+		pDR1 = iDynamicResDependencyList[(TUint16)(aResId1 & ID_INDEX_BIT_MASK)];	
+		if(!pDR1)															
+			UNLOCK_RETURN(KErrNotFound);
+		pN1 = pDR1->iDependencyList;
+		pCL1 = pDR1->iResourceClientList;
+		}
+	else
+		{
+		if((aResId1 & ID_INDEX_BIT_MASK) > iStaticResDependencyCount)			
+			UNLOCK_RETURN(KErrNotFound);			
+		pDR1 = (DDynamicPowerResourceD*)iStaticResDependencyArray[(aResId1 & ID_INDEX_BIT_MASK) - 1];
+		pN1 = ((DStaticPowerResourceD*)pDR1)->iDependencyList;
+		pCL1 = ((DStaticPowerResourceD*)pDR1)->iResourceClientList;
+		}
+
+	//Get second resource from list
+	if(aResId2 & KIdMaskDynamic)
+		{
+		pDR2 = iDynamicResDependencyList[(TUint16)(aResId2 & ID_INDEX_BIT_MASK)];	
+		if(!pDR2)															
+			UNLOCK_RETURN(KErrNotFound);
+		pN2 = pDR2->iDependencyList;
+		pCL2 = pDR2->iResourceClientList;
+		}
+	else
+		{
+		if((aResId2 & ID_INDEX_BIT_MASK)> iStaticResDependencyCount)			
+				UNLOCK_RETURN(KErrNotFound);			
+		pDR2 = (DDynamicPowerResourceD*)iStaticResDependencyArray[(TUint16)(aResId2 & ID_INDEX_BIT_MASK) - 1];
+		pN2 = ((DStaticPowerResourceD*)pDR2)->iDependencyList;
+		pCL2 = ((DStaticPowerResourceD*)pDR2)->iResourceClientList;
+		}
+
+	//Check whether dependency exist between the two
+	SNode* pN = NULL;
+	for(pN = pN1; pN != NULL; pN = pN->iNext)
+		{
+		if(pN->iResource->iResourceId == pDR2->iResourceId)
+			break;
+		}
+	if(pN == NULL)
+		UNLOCK_RETURN(KErrNotFound);
+	pN1 = pN; //Storing for later use.
+	for(pN = pN2; pN != NULL; pN = pN->iNext)
+		{
+		if(pN->iResource->iResourceId == pDR1->iResourceId)
+			break;
+		}
+	if(pN == NULL)
+		return KErrNotFound;
+	pN2 = pN; //Storing for later use
+	//Remove the dependency link from both the resource
+	if(aResId1 & KIdMaskDynamic)
+		{
+		LIST_REMOVE(pDR1->iDependencyList, pN1, iNext, SNode);
+		}
+	else
+		{
+		LIST_REMOVE(((DStaticPowerResourceD*)pDR1)->iDependencyList, pN1, iNext, SNode);
+		}
+
+	if(aResId2 & KIdMaskDynamic)
+		{	
+		LIST_REMOVE(pDR2->iDependencyList, pN2, iNext, SNode);
+		}
+	else
+		{	
+		LIST_REMOVE(((DStaticPowerResourceD*)pDR2)->iDependencyList, pN2, iNext, SNode);
+		}
+
+	//Remove the resource client level from each resource
+	for(; pCL1 != NULL; pCL1 = pCL1->iNextInList)
+		{
+		if(pCL1->iClientId == pDR2->iResourceId)
+			{
+			if(aResId1 & KIdMaskDynamic)
+				{	
+				LIST_REMOVE(pDR1->iResourceClientList, pCL1, iNextInList, SPowerResourceClientLevel);
+				}	
+			else
+				{
+				LIST_REMOVE(((DStaticPowerResourceD*)pDR1)->iResourceClientList, pCL1, iNextInList, 
+					                                            SPowerResourceClientLevel);
+				}
+			LIST_PUSH(iResourceLevelPool, pCL1, iNextInList);
+			iResourceLevelPoolCount++;
+			break;
+			}
+		}
+	for(; pCL2 != NULL; pCL2 = pCL2->iNextInList)
+		{
+		if(pCL2->iClientId == pDR1->iResourceId)
+			{
+			if(aResId2 & KIdMaskDynamic)
+				{	
+				LIST_REMOVE(pDR2->iResourceClientList, pCL2, iNextInList, SPowerResourceClientLevel);
+				}
+			else
+				{
+				LIST_REMOVE(((DStaticPowerResourceD*)pDR2)->iResourceClientList, pCL2, iNextInList, 
+					                                              SPowerResourceClientLevel);
+				}
+			LIST_PUSH(iResourceLevelPool, pCL2, iNextInList);
+			iResourceLevelPoolCount++;
+			break;
+			}
+		}
+
+	TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
+	req->ResourceCb() = NULL;
+	req->ReqType() = TPowerRequest::ESetDefaultLevel;
+	req->RequiresChange() = EFalse;
+	req->ReturnCode() = KErrNone;
+	if((TUint)pDR1->iLevelOwnerId == pDR2->iResourceId)
+		{
+		//Ask to change to default level. Process this in the RC thread;
+		req->ResourceId() = pDR1->iResourceId;
+		req->ClientId() = pDR2->iResourceId;
+		req->Resource() = pDR1;
+		req->Level() = pDR1->iDefaultLevel;
+		if(aResId1 & KIdMaskDynamic)
+			pDR1->Lock();
+		UnLock();
+		req->SendReceive(iMsgQDependency);
+		Lock();
+		if(aResId1 & KIdMaskDynamic)
+			pDR1->UnLock();
+		}
+	if((TUint)pDR2->iLevelOwnerId == pDR1->iResourceId)
+		{
+		//Ask to change to default level. Process this in the RC thread.
+		req->ResourceId() = pDR2->iResourceId;
+		req->ClientId() = pDR1->iResourceId;
+		req->Resource() = pDR2;
+		req->Level() = pDR2->iDefaultLevel;
+		if(aResId2 & KIdMaskDynamic)
+			pDR2->Lock();
+		UnLock();
+		req->SendReceive(iMsgQDependency);
+		Lock();
+		if(aResId2 & KIdMaskDynamic)
+			pDR2->UnLock();
+		}
+	__KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::DeregisterResourceDependency"));
+#ifdef PRM_INSTRUMENTATION_MACRO
+	PRM_DEREGISTER_RESOURCE_DEPENDENCY_TRACE
+#endif
+	UnLock();
+	delete pN1;
+	delete pN2;
+	return KErrNone;
+	}
+
+/**
+This function takes care of resource state change of static dependency resource.
+This propagates the change to all of its dependents.
+This function takes Originator name and id as parameter as this needs to be passed for custom sense function.
+*/
+TInt DStaticPowerResourceD::HandleChangePropagation(TPowerRequest aRequest, TPropagation aProp, TUint aOriginatorId, const TDesC8& aOriginatorName)
+	{
+	static TUint16 clientLevelCount = 0;
+	DStaticPowerResourceD* pDR = (DStaticPowerResourceD*)aRequest.Resource();
+	TInt result = KErrNone;
+	TInt resState;
+	TPowerRequest depRequest;
+	depRequest.ReqType() = TPowerRequest::EChange;
+	depRequest.ResourceCb() = NULL;
+	depRequest.ReturnCode() = KErrNone;
+	depRequest.RequiresChange() = EFalse;
+	DStaticPowerResourceD* pDepRes = NULL;
+	TBool traceEnabled = EFalse;
+#ifdef PRM_INSTRUMENTATION_MACRO
+	traceEnabled = ETrue;
+#endif
+	HANDLE_CHANGE_PROPAGATION(PowerResourceController, DStaticPowerResourceD*, traceEnabled, aOriginatorId, aOriginatorName)
+	}
+
+