author | Justin Sobota <jsobota@ti.com> | |
Tue, 12 Feb 2013 22:59:48 +0000 (17:59 -0500) | ||
committer | Justin Sobota <jsobota@ti.com> | |
Tue, 12 Feb 2013 22:59:48 +0000 (17:59 -0500) |
1 | 2 | |||
---|---|---|---|---|
.gitignore | patch | | | | diff2 | | blob | history |
build/buildlib.xs | patch | | diff1 | | diff2 | | blob | history |
docs/RM_SoftwareManifest.pdf | patch | | | | diff2 | | blob | history |
docs/ReleaseNotes_RM.doc | patch | | diff1 | | diff2 | | blob | history |
docs/ReleaseNotes_RM.pdf | patch | | | | diff2 | | blob | history |
package.xdc | patch | | diff1 | | diff2 | | blob | history |
src/rm.c | patch | | diff1 | | diff2 | | blob | history |
diff --cc .gitignore
index 0000000000000000000000000000000000000000,b43267ae6c383b6638a32b181dbd94e21c79ede8..94f53b3d10155a309032d80aabc54507072b7fe3
mode 000000,100644..100644
mode 000000,100644..100644
--- /dev/null
--- 2/.gitignore
+++ b/.gitignore
+ *.swp
+ *~
+ *.bak
++*.orig
+ .dlls
+ .executables
+ .interfaces
+ .libraries
+ .xdcenv.mak
+ Settings.h
+ Settings.xdc
+ build/c66/
+ docs/Doxyfile
+ docs/doxygen/
+ docs/rmDocs.chm
+ lib/
+ makefile
+ package.mak
+ package/
+ packages/
+ rmver.h
diff --cc build/buildlib.xs
Simple merge
diff --cc docs/RM_SoftwareManifest.pdf
index 0000000000000000000000000000000000000000,24528dcf45638e7d4db8f497a18171c0f465f295..7cb930c86d54fc947fa090b90ea0cefc9d8da39f
mode 000000,100644..100644
Binary files differ
mode 000000,100644..100644
Binary files differ
diff --cc docs/ReleaseNotes_RM.doc
index 2279161e4cdf7dd7cab2b6a710c11c19a37cf00d,e7fe5fc3181d4f1eb2599898ba7203b89677bfc7..97cc97c488b4401ff7d34cb82cfd61e05dab4d57
Binary files differ
Binary files differ
diff --cc docs/ReleaseNotes_RM.pdf
index 0000000000000000000000000000000000000000,1e97011436a37230f43861ff4b81345b4b555d5d..ee44920b1458b0c3be637722b20693cf4b3d16e6
mode 000000,100644..100644
Binary files differ
mode 000000,100644..100644
Binary files differ
diff --cc package.xdc
index 34850af45f0f7664251b57c113bd3aa85e086cd6,8e57aabaa6f5a072d364ee0bbfee22b90f774095..50fee562c88030028fc8ffcffe43386a56d738d4
--- 1/package.xdc
--- 2/package.xdc
+++ b/package.xdc
* FILE NAME: package.xdc\r
*\r
* DESCRIPTION: \r
- * This file contains the package specification for the RM LLD library\r
+ * This file contains the package specification for the RM library\r
*\r
- * Copyright (C) 2012, Texas Instruments, Inc.\r
+ * Copyright (C) 2012-2013, Texas Instruments, Inc.\r
*****************************************************************************/\r
\r
- package ti.drv.rm[02, 00, 00, 00] {\r
-package ti.drv.rm[2, 0, 0, 0] {\r
++package ti.drv.rm[02, 00, 00, 01] {\r
module Settings;\r
}\r
- \r
diff --cc src/rm.c
index 607eab17b6ed8d8788bbbcd02cf1abd76bd12e61,96dbf83ab7345f0fa936397e95fc49cc298d7865..c4ffbd8ec9e5c82c9fba6ba79a14cbc78203201d
+++ b/src/rm.c
-/**\r
- * @file rm.c\r
- *\r
- * @brief \r
- * This is the Resource Manager source.\r
- *\r
- * \par\r
- * ============================================================================\r
- * @n (C) Copyright 2012-2013, Texas Instruments, Inc.\r
- * \r
- * Redistribution and use in source and binary forms, with or without \r
- * modification, are permitted provided that the following conditions \r
- * are met:\r
- *\r
- * Redistributions of source code must retain the above copyright \r
- * notice, this list of conditions and the following disclaimer.\r
- *\r
- * Redistributions in binary form must reproduce the above copyright\r
- * notice, this list of conditions and the following disclaimer in the \r
- * documentation and/or other materials provided with the \r
- * distribution.\r
- *\r
- * Neither the name of Texas Instruments Incorporated nor the names of\r
- * its contributors may be used to endorse or promote products derived\r
- * from this software without specific prior written permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- *\r
- * \par\r
-*/\r
-\r
-/* Standard includes */\r
-#include <stdint.h>\r
-#include <string.h>\r
-#include <stdbool.h>\r
-\r
-/* RM external includes */\r
-#include <ti/drv/rm/rm.h>\r
-#include <ti/drv/rm/rmver.h>\r
-#include <ti/drv/rm/rm_services.h>\r
-#include <ti/drv/rm/rm_transport.h>\r
-\r
-/* RM internal includes */\r
-#include <ti/drv/rm/include/rm_loc.h>\r
-#include <ti/drv/rm/include/rm_transportloc.h>\r
-#include <ti/drv/rm/include/rm_nameserverloc.h>\r
-#include <ti/drv/rm/include/rm_dtb_utilloc.h>\r
-#include <ti/drv/rm/include/rm_policyloc.h>\r
-#include <ti/drv/rm/include/rm_treeloc.h>\r
-\r
-/* RM LIBFDT includes */\r
-#include <ti/drv/rm/util/libfdt/libfdt.h>\r
-\r
-/* Tree algorithm includes */\r
-#include <ti/drv/rm/util/tree.h>\r
-\r
-/* RM OSAL layer */\r
-#include <rm_osal.h>\r
-\r
-/**********************************************************************\r
- ************************** Globals ***********************************\r
- **********************************************************************/\r
-\r
-/** @brief Global Variable which describes the RM Version Information */\r
-const char rmVersionStr[] = RM_VERSION_STR ":" __DATE__ ":" __TIME__;\r
-\r
-/**********************************************************************\r
- ************************ Local Functions *****************************\r
- **********************************************************************/\r
-\r
-/* FUNCTION PURPOSE: Initializes a RM inst's transaction sequence number\r
- ***********************************************************************\r
- * DESCRIPTION: The RM instance transaction sequence number can never\r
- * have a value of 0 to avoid conflicts with transactions\r
- * that have a remoteOriginatingId of 0 (transaction ID\r
- * will be used as the remoteOriginatingId for\r
- * transactions that are responses to requests).\r
- */\r
-static uint32_t transactionInitSequenceNum(void)\r
-{\r
- return (1);\r
-}\r
-\r
-/* FUNCTION PURPOSE: Provides a sequence number for new transactions\r
- ***********************************************************************\r
- * DESCRIPTION: Returns a sequence number for a new transaction\r
- * specific to a RM instance. Handles rollover of\r
- * sequence number.\r
- */\r
-static uint32_t transactionGetSequenceNum(Rm_Inst *rmInst)\r
-{\r
- uint32_t sequenceNum = 0;\r
-\r
- if (rmInst->transactionSeqNum + 1 < rmInst->transactionSeqNum) {\r
- /* Rollover */\r
- sequenceNum = rmInst->transactionSeqNum;\r
- rmInst->transactionSeqNum = transactionInitSequenceNum();\r
- }\r
- else {\r
- sequenceNum = rmInst->transactionSeqNum++;\r
- } \r
- return (sequenceNum);\r
-}\r
-\r
-/* FUNCTION PURPOSE: Creates a resource allocator\r
- ***********************************************************************\r
- * DESCRIPTION: Returns a newly Created and initialized resource\r
- * The allocator is also stored in the RM instance\r
- * allocator list. \r
- */\r
-static Rm_Allocator *allocatorAdd(Rm_Inst *rmInst, const char *resourceName)\r
-{\r
- Rm_Allocator *allocators = rmInst->allocators;\r
- Rm_Allocator *newAllocator = NULL;\r
-\r
- newAllocator = Rm_osalMalloc(sizeof(Rm_Allocator));\r
-\r
- if (newAllocator) {\r
- memset((void *)newAllocator, 0, sizeof(Rm_Allocator));\r
- strncpy(newAllocator->resourceName, resourceName, RM_NAME_MAX_CHARS);\r
- newAllocator->allocatorRootEntry = NULL;\r
- newAllocator->nextAllocator = NULL; \r
-\r
- /* Add allocator to end of list */\r
- if (allocators) {\r
- while (allocators->nextAllocator) {\r
- allocators = allocators->nextAllocator;\r
- }\r
- allocators->nextAllocator = newAllocator;\r
- }\r
- else {\r
- rmInst->allocators = newAllocator;\r
- }\r
- }\r
- return (newAllocator);\r
-}\r
-\r
-/* FUNCTION PURPOSE: Deletes a resource allocator\r
- ***********************************************************************\r
- * DESCRIPTION: Deletes a resource allocator based on the given\r
- * resource name. The resource allocator will be\r
- * removed from the RM instance allocator list.\r
- */\r
-static int32_t allocatorDelete(Rm_Inst *rmInst, char *resourceName)\r
-{\r
- Rm_Allocator *allocator = rmInst->allocators;\r
- Rm_Allocator *prevAllocator = NULL;\r
- int32_t retVal = RM_OK;\r
-\r
- while (allocator) {\r
- if (strncmp(allocator->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {\r
- break; \r
- }\r
- prevAllocator = allocator;\r
- allocator = allocator->nextAllocator;\r
- }\r
-\r
- if (allocator) {\r
- if (prevAllocator == NULL) {\r
- rmInst->allocators = allocator->nextAllocator;\r
- }\r
- else {\r
- prevAllocator->nextAllocator = allocator->nextAllocator;\r
- }\r
- Rm_osalFree((void *)allocator, sizeof(Rm_Allocator));\r
- }\r
- else {\r
- retVal = RM_ERROR_RES_ALLOCATOR_DOES_NOT_EXIST;\r
- }\r
- return (retVal);\r
-}\r
-\r
-/* FUNCTION PURPOSE: Adds an owner to an allocator resource\r
- ***********************************************************************\r
- * DESCRIPTION: Adds a RM instance node to a resource node's\r
- * list of owners.\r
- */\r
-static void addOwner(Rm_ResourceNode *node, void *serviceInstNode)\r
-{\r
- Rm_Owner *ownerList = node->ownerList;\r
- Rm_Owner *newOwner = NULL;\r
-\r
- newOwner = Rm_osalMalloc(sizeof(Rm_Owner));\r
-\r
- if (newOwner) {\r
- newOwner->instNameNode = serviceInstNode;\r
- newOwner->nextOwner = NULL; \r
-\r
- /* Add owner entry to end of list */\r
- if (ownerList) {\r
- while (ownerList->nextOwner) {\r
- ownerList = ownerList->nextOwner;\r
- }\r
- ownerList->nextOwner = newOwner;\r
- }\r
- else {\r
- node->ownerList = newOwner;\r
- }\r
-\r
- node->allocationCount++;\r
- newOwner->instNameNode->allocRefCount++;\r
- }\r
-}\r
-\r
-/* FUNCTION PURPOSE: Checks a resource node's ownership\r
- ***********************************************************************\r
- * DESCRIPTION: Returns TRUE if the provided instance node is\r
- * in the list of resource node owners. Otherwise,\r
- * returns FALSE.\r
- */\r
-static bool isOwnedBy(Rm_ResourceNode *node, void *serviceInstNode)\r
-{\r
- Rm_Owner *owner = node->ownerList;\r
-\r
- while (owner) {\r
- if (owner->instNameNode == serviceInstNode) {\r
- return(true); \r
- }\r
- owner = owner->nextOwner;\r
- }\r
- return(false);\r
-}\r
-\r
-/* FUNCTION PURPOSE: Compares two resource node's owners\r
- ***********************************************************************\r
- * DESCRIPTION: Returns TRUE if the owners of two resource nodes \r
- * are equivalent. Otherwise, returns FALSE.\r
- */\r
-static bool compareResourceNodeOwners(Rm_ResourceNode *node1, Rm_ResourceNode *node2)\r
-{\r
- Rm_Owner *node1Owners = node1->ownerList;\r
- Rm_Owner *node2Owners = node2->ownerList;\r
- bool matchedInst;\r
-\r
- if (node1->allocationCount == node2->allocationCount) {\r
- while (node1Owners) {\r
- matchedInst = false;\r
- while (node2Owners) {\r
- if (node1Owners->instNameNode == node2Owners->instNameNode) {\r
- matchedInst = true;\r
- break;\r
- }\r
- node2Owners = node2Owners->nextOwner;\r
- }\r
-\r
- if (matchedInst) {\r
- node2Owners = node2->ownerList;\r
- node1Owners = node1Owners->nextOwner;\r
- }\r
- else {\r
- return(false);\r
- } \r
- }\r
- }\r
- else {\r
- return(false);\r
- } \r
- \r
- return(true);\r
-}\r
-\r
-/* FUNCTION PURPOSE: Deletes an owner from an allocator resource\r
- ***********************************************************************\r
- * DESCRIPTION: Removes a RM instance node from a resource node's\r
- * list of owners.\r
- */\r
-static void deleteOwner(Rm_ResourceNode *node, void *serviceInstNode)\r
-{\r
- Rm_Owner *owner = node->ownerList;\r
- Rm_Owner *prevOwner = NULL;\r
-\r
- while (owner) {\r
- if (owner->instNameNode == serviceInstNode) {\r
- break; \r
- }\r
- prevOwner = owner;\r
- owner = owner->nextOwner;\r
- }\r
-\r
- if (prevOwner == NULL) {\r
- node->ownerList = owner->nextOwner;\r
- }\r
- else {\r
- prevOwner->nextOwner = owner->nextOwner;\r
- }\r
- \r
- node->allocationCount--;\r
- owner->instNameNode->allocRefCount--;\r
- Rm_osalFree((void *)owner, sizeof(Rm_Owner));\r
-}\r
-\r
-/* FUNCTION PURPOSE: Copies the owners of a resource node\r
- ***********************************************************************\r
- * DESCRIPTION: Creates a list of resource owners for the destination\r
- * resource node that is equivalent to the the \r
- * source resource node's owners\r
- */\r
-static void copyOwners(Rm_ResourceNode *dstNode, Rm_ResourceNode *srcNode)\r
-{\r
- Rm_Owner *srcOwnerList = srcNode->ownerList;\r
- Rm_Owner *dstNewOwner;\r
- Rm_Owner *dstPrevOwner;\r
-\r
- dstNode->allocationCount = srcNode->allocationCount;\r
-\r
- while (srcOwnerList) {\r
- dstNewOwner = Rm_osalMalloc(sizeof(Rm_Owner));\r
- dstNewOwner->instNameNode = srcOwnerList->instNameNode;\r
- dstNewOwner->nextOwner = NULL;\r
-\r
- if (dstNode->ownerList == NULL) {\r
- dstNode->ownerList = dstNewOwner;\r
- }\r
- else {\r
- dstPrevOwner->nextOwner = dstNewOwner;\r
- }\r
- dstPrevOwner = dstNewOwner;\r
- srcOwnerList = srcOwnerList->nextOwner;\r
- }\r
-}\r
-\r
-/* FUNCTION PURPOSE: Clears a resource node's owners\r
- ***********************************************************************\r
- * DESCRIPTION: Deletes all owners from the owners list of a \r
- * resource node.\r
- */\r
-static void clearOwners(Rm_ResourceNode *node)\r
-{\r
- Rm_Owner *owner = node->ownerList;\r
- Rm_Owner *nextOwner;\r
-\r
- while (owner) {\r
- nextOwner = owner->nextOwner;\r
- node->allocationCount--;\r
- Rm_osalFree((void *)owner, sizeof(Rm_Owner));\r
- owner = nextOwner;\r
- }\r
-}\r
-\r
-/* FUNCTION PURPOSE: Creates a new resource tree\r
- ***********************************************************************\r
- * DESCRIPTION: Creates a new resource tree using the provided\r
- * resource name and value range. The name and value\r
- * typically originate from the GRL.\r
- */\r
-static int32_t createResourceTree(Rm_Inst *rmInst, const char *resourceName, Rm_ResourceRange *range)\r
-{\r
- Rm_Allocator *allocator = NULL;\r
- Rm_ResourceTree *treeRootEntry = NULL;\r
- Rm_ResourceNode *treeNode = NULL;\r
- Rm_ResourceNode *collidingNode = NULL;\r
-\r
- allocator = allocatorAdd(rmInst, resourceName);\r
- treeRootEntry = Rm_osalMalloc(sizeof(Rm_ResourceTree));\r
- RB_INIT(treeRootEntry);\r
-\r
- while (range != NULL) {\r
- treeNode = rmResourceNodeNew(range->base, range->length);\r
- collidingNode = RB_INSERT(_Rm_AllocatorResourceTree, treeRootEntry, treeNode);\r
-\r
- if (collidingNode) {\r
- Rm_ResourceNode *nextNode = NULL;\r
- \r
- /* Node that was inserted collides with existing node. Destroy tree and return error */\r
- for (treeNode = RB_MIN(_Rm_AllocatorResourceTree, treeRootEntry); treeNode != NULL; treeNode = nextNode) {\r
- nextNode = RB_NEXT(_Rm_AllocatorResourceTree, treeRootEntry, treeNode);\r
- RB_REMOVE(_Rm_AllocatorResourceTree, treeRootEntry, nextNode);\r
- rmResourceNodeFree(treeNode);\r
- }\r
- Rm_osalFree((void *)treeRootEntry, sizeof(Rm_ResourceTree));\r
- allocatorDelete(rmInst, allocator->resourceName);\r
- return (RM_ERROR_GRL_RES_SPECIFIED_MORE_THAN_ONCE);\r
- }\r
- range = range->nextRange;\r
- }\r
- \r
- allocator->allocatorRootEntry = treeRootEntry;\r
- return(RM_OK);\r
-}\r
-\r
-/* FUNCTION PURPOSE: Preallocates a resource\r
- ***********************************************************************\r
- * DESCRIPTION: Called when an allocate request is made but the base \r
- * is unspecified. The preallocation algorithm looks at \r
- * available resources as well as policy permissions to \r
- * determine a resource range that satisfies the request.\r
- * If a valid range is found it will be returned for the \r
- * treeAllocate algorithm to handle.\r
- */\r
-static int32_t treePreAllocate(Rm_Inst *rmInst, Rm_Allocator *allocator, int32_t resourcePolicy,\r
- Rm_AllocatorOpInfo *opInfo)\r
-{\r
- Rm_ResourceNode findNode;\r
- Rm_ResourceNode *matchingNode = NULL;\r
- uint32_t matchingEnd;\r
- uint32_t rangeIndex;\r
- bool resourceFound = false;\r
- Rm_PolicyCheckType policyCheckType;\r
- Rm_PolicyCheckCfg policyCheckCfg;\r
- bool nodePassesPolicy;\r
- int32_t retVal = RM_SERVICE_PROCESSING; \r
-\r
- opInfo->resourceInfo->base = rmPolicyGetResourceBase(rmInst->policy, opInfo->serviceSrcInstNode, \r
- resourcePolicy, opInfo->allocType, \r
- &retVal);\r
- if (retVal != RM_SERVICE_PROCESSING) {\r
- return (retVal);\r
- }\r
-\r
- if (opInfo->resourceInfo->alignment == RM_RESOURCE_ALIGNMENT_UNSPECIFIED) { \r
- /* Get alignment from policy */\r
- opInfo->resourceInfo->alignment = rmPolicyGetResourceAlignment(rmInst->policy, resourcePolicy);\r
- }\r
- \r
- if (opInfo->resourceInfo->alignment == 0) {\r
- opInfo->resourceInfo->alignment = 1;\r
- } \r
-\r
- memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));\r
- findNode.base = opInfo->resourceInfo->base;\r
- findNode.length = opInfo->resourceInfo->length;\r
-\r
- /* Configure policy checking structure */\r
- memset((void *)&policyCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));\r
- if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_INIT_SHIFT)) {\r
- policyCheckType = Rm_policyCheck_INIT;\r
- }\r
- else if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_USE_SHIFT)) {\r
- policyCheckType = Rm_policyCheck_USE;\r
- }\r
- policyCheckCfg.policyDtb = rmInst->policy;\r
- policyCheckCfg.resourceOffset = resourcePolicy;\r
- \r
- do {\r
- matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);\r
- \r
- if (matchingNode) {\r
- nodePassesPolicy = false;\r
- policyCheckCfg.type = policyCheckType;\r
- policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
- policyCheckCfg.resourceBase = findNode.base;\r
- policyCheckCfg.resourceLength = findNode.length;\r
- nodePassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal); \r
- \r
- if (nodePassesPolicy && (matchingNode->allocationCount > 0)) {\r
- /* Check exclusive privileges of instance requesting resource. Requesting\r
- * instance with exclusive privileges can't reserve resource if already owned*/\r
- policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
- policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
- nodePassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
- }\r
- \r
- if (nodePassesPolicy && (matchingNode->allocationCount == 1)) {\r
- /* Check exclusive privileges of instance that currently owns resource */\r
- policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
- policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;\r
- nodePassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
- }\r
-\r
- if (retVal != RM_SERVICE_PROCESSING) {\r
- break;\r
- }\r
-\r
- if (nodePassesPolicy) {\r
- matchingEnd = matchingNode->base + matchingNode->length - 1;\r
- /* Initialize indexer to be first resource value that alignment */\r
- rangeIndex = findNode.base;\r
- if (rangeIndex % opInfo->resourceInfo->alignment) {\r
- rangeIndex += (opInfo->resourceInfo->alignment -\r
- (rangeIndex % opInfo->resourceInfo->alignment));\r
- }\r
- \r
- if ((rangeIndex + opInfo->resourceInfo->length - 1) <= matchingEnd) {\r
- /* Block of unallocated resources within matchingNode that satisfies\r
- * allocate requirements */\r
- opInfo->resourceInfo->base = rangeIndex;\r
- resourceFound = true;\r
- } \r
- }\r
- \r
- if (!resourceFound) {\r
- /* Check next resource node for available resources */\r
- findNode.base = matchingNode->base + matchingNode->length;\r
- }\r
- }\r
- else {\r
- retVal = RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET;\r
- }\r
- } while ((!resourceFound) && \r
- (retVal != RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET));\r
-\r
- return(retVal); \r
-}\r
-\r
-/* FUNCTION PURPOSE: Allocates a resource\r
- ***********************************************************************\r
- * DESCRIPTION: Will attempt to allocate the resource with specified\r
- * base and length from the resource's allocator. The\r
- * allocation algorithm will verify the allocation against\r
- * the policy permissions for the instance requesting the\r
- * allocation. If the policy allows the allocation the \r
- * algorithm will allocate the resource then combine any\r
- * resource nodes that may have become equivalent (in terms\r
- * of ownership) after the allocation.\r
- */\r
-static int32_t treeAllocate(Rm_Inst *rmInst, Rm_Allocator *allocator, int32_t resourcePolicy,\r
- Rm_AllocatorOpInfo *opInfo)\r
-{\r
- Rm_ResourceNode findNode;\r
- Rm_ResourceNode *matchingNode = NULL;\r
- Rm_ResourceNode *leftNode = NULL;\r
- Rm_ResourceNode *rightNode = NULL;\r
- Rm_PolicyCheckType policyCheckType; \r
- Rm_PolicyCheckCfg policyCheckCfg;\r
- bool allocPassesPolicy;\r
- bool combineLeft = false;\r
- bool combineRight = false; \r
- uint32_t findEnd;\r
- uint32_t matchingEnd; \r
- int32_t retVal = RM_SERVICE_PROCESSING;\r
-\r
- memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));\r
- findNode.base = opInfo->resourceInfo->base;\r
- findNode.length = opInfo->resourceInfo->length;\r
- matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);\r
-\r
- /* Prepare privilege checks */\r
- memset((void *)&policyCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));\r
- if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_INIT_SHIFT)) {\r
- policyCheckType = Rm_policyCheck_INIT;\r
- }\r
- else if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_USE_SHIFT)) {\r
- policyCheckType = Rm_policyCheck_USE;\r
- }\r
-\r
- if (matchingNode) {\r
- findEnd = findNode.base + findNode.length - 1;\r
- matchingEnd = matchingNode->base + matchingNode->length - 1;\r
- \r
- if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {\r
- if (opInfo->serviceSrcInstNode == rmPolicyGetLinuxInstNode(rmInst->validInstances)) {\r
- /* Bypass policy checks since Linux Kernel has full privileges */\r
- allocPassesPolicy = true;\r
- }\r
- else {\r
- policyCheckCfg.policyDtb = rmInst->policy;\r
- policyCheckCfg.resourceOffset = resourcePolicy; \r
- policyCheckCfg.type = policyCheckType;\r
- policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
- policyCheckCfg.resourceBase = findNode.base;\r
- policyCheckCfg.resourceLength = findNode.length;\r
- allocPassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
- if (!allocPassesPolicy) {\r
- if (policyCheckType == Rm_policyCheck_INIT) {\r
- retVal = RM_SERVICE_DENIED_INIT_PERM_NOT_GIVEN;\r
- }\r
- else {\r
- retVal = RM_SERVICE_DENIED_USE_PERM_NOT_GIVEN;\r
- }\r
- }\r
-\r
- if (!isOwnedBy(matchingNode, opInfo->serviceSrcInstNode)) {\r
- /* Perform exclusive checks if requesting instance does not already an\r
- * owner of the resource */\r
- if (allocPassesPolicy && (matchingNode->allocationCount > 0)) {\r
- /* Check exclusive privileges of instance requesting resource. Requesting\r
- * instance with exclusive privileges can't reserve resource if already owned*/\r
- policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
- policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;\r
- allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
- if (!allocPassesPolicy) {\r
- retVal = RM_SERVICE_DENIED_EXCLUSIVE_RES_ALLOCD;\r
- }\r
- }\r
- if (allocPassesPolicy && (matchingNode->allocationCount == 1)) {\r
- /* Check exclusive privileges of instance that currently owns resource */\r
- policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;\r
- policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;\r
- allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);\r
- if (!allocPassesPolicy) {\r
- retVal = RM_SERVICE_DENIED_ALLOCD_TO_EXCLUSIVE_INST;\r
- } \r
- } \r
- }\r
- }\r
- \r
- if (allocPassesPolicy) {\r
- if (!isOwnedBy(matchingNode, opInfo->serviceSrcInstNode)) {\r
- /* Handle any possible node combinations if requesting instance is\r
- * not already in resource's owner list. Automatic approval if requesting\r
- * instance is already in owner list. */\r
- if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd)) {\r
- /* findNode range matches matchingNode range\r
- *\r
- * |<--left node-->||<--matched node-->||<--right node-->| => existing node\r
- * |<--alloc request-->| => requested resources\r
- */ \r
- leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
-\r
- if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {\r
- RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
- combineLeft = true;\r
- }\r
- if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {\r
- RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
- combineRight = true;\r
- }\r
-\r
- if (combineLeft && combineRight) {\r
- /* Combine all three nodes into matchingNode */\r
- matchingNode->base = leftNode->base;\r
- matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;\r
-\r
- clearOwners(leftNode);\r
- rmResourceNodeFree(leftNode);\r
- clearOwners(rightNode);\r
- rmResourceNodeFree(rightNode); \r
- }\r
- else if (combineLeft) {\r
- /* Combine left and matching nodes. Reinsert right. */\r
- matchingNode->base = leftNode->base;\r
- matchingNode->length += leftNode->length;\r
-\r
- clearOwners(leftNode);\r
- rmResourceNodeFree(leftNode);\r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode); \r
- }\r
- else if (combineRight) {\r
- /* Combine right and matching nodes. Reinsert left. */\r
- matchingNode->length += rightNode->length;\r
-\r
- clearOwners(rightNode);\r
- rmResourceNodeFree(rightNode);\r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
- }\r
- else {\r
- /* No combine. */\r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
- }\r
-\r
- /* Always reinsert matchingNode */ \r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode); \r
- } \r
- else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {\r
- /* findNode range is subset of matchingNode range and neither boundary is\r
- * equivalent.\r
- *\r
- * |<----------matched node---------->|\r
- * |<---alloc request--->|\r
- */ \r
- RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);\r
- copyOwners(leftNode, matchingNode);\r
- rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);\r
- copyOwners(rightNode, matchingNode);\r
-\r
- matchingNode->base = findNode.base; \r
- matchingNode->length = findNode.length;\r
- addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
-\r
- /* Insert all the nodes */\r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
- } \r
- else { \r
- if (findNode.base == matchingNode->base) {\r
- /* findNode base and matchingNode base are equivalent. May be combine\r
- * possibilities to the left\r
- *\r
- * |<---left node (alloc'd)--->||<----------matched node---------->|\r
- * |<---findNode (alloc req)--->|\r
- */ \r
- leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- /* Add allocating instance to owner list for compare with leftNode */\r
- addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
- \r
- if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {\r
- RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
- /* Combine leftNode and findNode */\r
- leftNode->length += findNode.length;\r
- }\r
- else {\r
- leftNode = rmResourceNodeNew(findNode.base, findNode.length);\r
- copyOwners(leftNode, matchingNode);\r
- }\r
-\r
- /* Account for leftNode in matchingNode */\r
- matchingNode->base = findNode.base + findNode.length;\r
- matchingNode->length = matchingEnd - findEnd; \r
-\r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
- }\r
- else if (findEnd == matchingEnd) {\r
- /* findNode end and matchingNode end are equivalent. May be combine\r
- * possibilities to the right\r
- *\r
- * |<----------matched node---------->||<---right node (alloc'd)--->|\r
- * |<---findNode (alloc req)--->| \r
- */ \r
- rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- /* Add allocating instance to owner list for compare with rightNode */\r
- addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
- \r
- if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {\r
- RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
- /* Combine rightNode and findNode */\r
- rightNode->base = findNode.base;\r
- rightNode->length += findNode.length;\r
- }\r
- else {\r
- rightNode = rmResourceNodeNew(findNode.base, findNode.length);\r
- copyOwners(rightNode, matchingNode);\r
- }\r
-\r
- /* Account for rightNode in matchingNode */\r
- matchingNode->length -= findNode.length; \r
-\r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
- }\r
- /* Remove allocating instance from leftover matchingNode */\r
- deleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- }\r
- }\r
- retVal = RM_SERVICE_APPROVED;\r
- }\r
- }\r
- else {\r
- retVal = RM_SERVICE_DENIED_PARTIAL_ALLOCATION;\r
- }\r
- }\r
- else {\r
- retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;\r
- }\r
-\r
- return(retVal); \r
-}\r
-\r
-/* FUNCTION PURPOSE: Frees a resource\r
- ***********************************************************************\r
- * DESCRIPTION: Will attempt to free the resource with specified\r
- * base and length from the resource's allocator. The\r
- * free algorithm will verify the free request parameters\r
- * match an allocated range for the resource and that the\r
- * range is owned by the instance requesting the free. If\r
- * the free is validated the algorithm will free the \r
- * resource then combine any resource nodes that may have\r
- * become equivalent (in terms of ownership) after the\r
- * allocation.\r
- */\r
-static int32_t treeFree(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
-{\r
- Rm_ResourceNode findNode;\r
- Rm_ResourceNode *matchingNode = NULL;\r
- Rm_ResourceNode *leftNode = NULL;\r
- Rm_ResourceNode *rightNode = NULL;\r
- bool combineLeft = false;\r
- bool combineRight = false;\r
- uint32_t findEnd;\r
- uint32_t matchingEnd;\r
- int32_t retVal;\r
-\r
- memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));\r
- findNode.base = opInfo->resourceInfo->base;\r
- findNode.length = opInfo->resourceInfo->length;\r
- matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);\r
-\r
- if (matchingNode) {\r
- findEnd = findNode.base + findNode.length - 1;\r
- matchingEnd = matchingNode->base + matchingNode->length - 1;\r
- \r
- if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) { \r
- if (matchingNode->allocationCount) {\r
- if (isOwnedBy(matchingNode, opInfo->serviceSrcInstNode)) {\r
- if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))\r
- {\r
- /* Case 1: Free range equals allocated matched node exactly. Attempt to combine \r
- * freed node with nodes to left and right.\r
- *\r
- * |<--left node-->||<---matched node--->||<--right node-->|\r
- * |<---free request--->|\r
- */ \r
- leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- deleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
-\r
- if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {\r
- RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
- combineLeft = true;\r
- }\r
- if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {\r
- RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
- combineRight = true;\r
- }\r
-\r
- if (combineLeft && combineRight) {\r
- /* Combine all three nodes into matchingNode */\r
- matchingNode->base = leftNode->base;\r
- matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;\r
-\r
- clearOwners(leftNode);\r
- rmResourceNodeFree(leftNode);\r
- clearOwners(rightNode);\r
- rmResourceNodeFree(rightNode); \r
- }\r
- else if (combineLeft) {\r
- /* Combine left and matching nodes. Reinsert right. */\r
- matchingNode->base = leftNode->base;\r
- matchingNode->length += leftNode->length;\r
-\r
- clearOwners(leftNode);\r
- rmResourceNodeFree(leftNode);\r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode); \r
- }\r
- else if (combineRight) {\r
- /* Combine right and matching nodes. Reinsert left. */\r
- matchingNode->length += rightNode->length;\r
-\r
- clearOwners(rightNode);\r
- rmResourceNodeFree(rightNode);\r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
- }\r
- else {\r
- /* No combine. */\r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
- }\r
-\r
- /* Always reinsert matchingNode */\r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode); \r
- }\r
- else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {\r
- /* Case 2: Free range is less than range in matched node. Split\r
- * matched node into three nodes.\r
- *\r
- * |<----------matched node---------->|\r
- * |<---free request--->|\r
- *\r
- * Remove instance from AllocatedTo list then add it back in for side nodes for\r
- * proper accounting of allocations in validInstance list\r
- */ \r
- RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- deleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
- \r
- leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);\r
- copyOwners(leftNode, matchingNode);\r
- addOwner(leftNode, opInfo->serviceSrcInstNode);\r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
- \r
- rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);\r
- copyOwners(rightNode, matchingNode);\r
- addOwner(rightNode, opInfo->serviceSrcInstNode);\r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
-\r
- matchingNode->base = findNode.base; \r
- matchingNode->length = findNode.length;\r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- }\r
- else { \r
- if (findNode.base == matchingNode->base) {\r
- /* Case 3: Free range is on left boundary of matched node. Try to \r
- * combine free range with left node.\r
- *\r
- * |<---left node (free)--->||<----------matched node---------->|\r
- * |<---findNode (free req)--->|\r
- */ \r
-\r
- leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- /* Remove freeing instance from owner list for compare with leftNode */\r
- deleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
- \r
- if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {\r
- RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
- /* Combine leftNode and findNode */\r
- leftNode->length += findNode.length;\r
- }\r
- else {\r
- leftNode = rmResourceNodeNew(findNode.base, findNode.length);\r
- copyOwners(leftNode, matchingNode);\r
- }\r
-\r
- /* Remove leftNode range from matchingNode */\r
- matchingNode->base = findNode.base + findNode.length;\r
- matchingNode->length = matchingEnd - findEnd; \r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);\r
- }\r
- else if (findEnd == matchingEnd) {\r
- /* Case 4: Free range is on right boundary of matched node. Try to \r
- * combine free range with right node.\r
- *\r
- * |<----------matched node---------->||<---right node (free)--->|\r
- * |<---findNode (free req)--->|\r
- */ \r
- \r
- rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode); \r
- /* Remove freeing instance from owner list for compare with rightNode */\r
- deleteOwner(matchingNode, opInfo->serviceSrcInstNode);\r
- \r
- if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {\r
- RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
- /* Combine rightNode and findNode */\r
- rightNode->base = findNode.base;\r
- rightNode->length += findNode.length;\r
- }\r
- else {\r
- rightNode = rmResourceNodeNew(findNode.base, findNode.length);\r
- copyOwners(rightNode, matchingNode);\r
- }\r
-\r
- /* Remove rightNode range from matchingNode */\r
- matchingNode->length -= findNode.length; \r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);\r
- }\r
-\r
- /* Add freeing instance back into matchingNode allocations */\r
- addOwner(matchingNode, opInfo->serviceSrcInstNode);\r
- RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);\r
- }\r
-\r
- retVal = RM_SERVICE_APPROVED;\r
- }\r
- else {\r
- retVal = RM_SERVICE_DENIED_RES_NOT_ALLOCD_TO_INST;\r
- }\r
- }\r
- else {\r
- retVal = RM_SERVICE_DENIED_RES_ALREADY_FREE;\r
- }\r
- }\r
- else {\r
- retVal = RM_SERVICE_DENIED_PARTIAL_FREE;\r
- }\r
- }\r
- else {\r
- retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;\r
- }\r
- return(retVal); \r
-}\r
-\r
-/* FUNCTION PURPOSE: Issues a service response to application\r
- ***********************************************************************\r
- * DESCRIPTION: Provides a service response back to the application\r
- * using the service callback function provided to\r
- * the RM instance at the time of the service request.\r
- */\r
-static void serviceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
-{\r
- Rm_ServiceRespInfo serviceResponse;\r
-\r
- /* The responseTransaction will contain the resultant state details of\r
- * the requestTransaction's service request */\r
- serviceResponse.serviceState = transaction->state;\r
- /* Pass back the ID that was provided to the component when it requested\r
- * the service */\r
- serviceResponse.serviceId = transaction->localId;\r
-\r
- /* Service was approved and service was an allocate request. The resource\r
- * data is passed back to the component */\r
- if ((serviceResponse.serviceState == RM_SERVICE_APPROVED) &&\r
- ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||\r
- (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||\r
- (transaction->type == Rm_service_RESOURCE_GET_BY_NAME)))\r
- {\r
- strncpy(serviceResponse.resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);\r
- serviceResponse.resourceBase = transaction->resourceInfo.base;\r
- serviceResponse.resourceLength = transaction->resourceInfo.length;\r
- }\r
-\r
- /* Issue the callback to the requesting component with the response information */\r
- transaction->callback.serviceCallback(&serviceResponse);\r
-\r
- /* Delete the transaction from the transaction queue */\r
- rmTransactionQueueDelete(rmInst, transaction->localId);\r
- return;\r
-}\r
-\r
-/* FUNCTION PURPOSE: Sends RM response packets\r
- ***********************************************************************\r
- * DESCRIPTION: Sends RM response packets to RM instance's that sent\r
- * RM request packets to the RM instance. The response\r
- * is sent via the RM transport API which is plugged\r
- * with an application created transport path.\r
- */\r
-static void transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
-{\r
- Rm_Transport *dstTransport = NULL;\r
- Rm_PacketHandle pktHandle = NULL;\r
-\r
- dstTransport = rmTransportFindRemoteName((Rm_Transport *) rmInst->transports, transaction->pktSrcInstName);\r
-\r
- switch (transaction->type) {\r
- case Rm_service_RESOURCE_ALLOCATE_INIT:\r
- case Rm_service_RESOURCE_ALLOCATE_USE:\r
- case Rm_service_RESOURCE_FREE:\r
- case Rm_service_RESOURCE_GET_BY_NAME:\r
- pktHandle = rmTransportCreateResourceResponsePkt(rmInst, dstTransport->appTransportHandle, \r
- transaction);\r
- break;\r
- case Rm_service_RESOURCE_MAP_TO_NAME:\r
- case Rm_service_RESOURCE_UNMAP_NAME:\r
- pktHandle = rmTransportCreateNsResponsePkt(rmInst, dstTransport->appTransportHandle,\r
- transaction);\r
- break;\r
- }\r
-\r
- if (pktHandle) {\r
- if (rmInst->transportCallouts.rmSendPkt) {\r
- if (rmInst->transportCallouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {\r
- transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;\r
- }\r
- }\r
- else {\r
- transaction->state = RM_ERROR_TRANSPORT_SEND_NOT_REGD;\r
- }\r
- }\r
- rmTransactionQueueDelete(rmInst, transaction->localId);\r
-}\r
-\r
-/* FUNCTION PURPOSE: Sends RM request packets\r
- ***********************************************************************\r
- * DESCRIPTION: Sends RM request packets to RM instance's that are\r
- * capable of forwarding or validating service requests.\r
- * The request is sent via the RM transport API which is\r
- * plugged with an application created transport path.\r
- */\r
-static void transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
-{\r
- Rm_Transport *dstTransport = NULL;\r
- Rm_PacketHandle pktHandle = NULL;\r
-\r
- if (rmInst->registeredWithDelegateOrServer) {\r
- if (rmInst->instType == Rm_instType_CLIENT) {\r
- dstTransport = rmTransportFindRemoteInstType((Rm_Transport *) rmInst->transports, Rm_instType_CLIENT_DELEGATE);\r
-\r
- if (!dstTransport) {\r
- dstTransport = rmTransportFindRemoteInstType((Rm_Transport *) rmInst->transports, Rm_instType_SERVER);\r
- }\r
- } \r
- else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
- dstTransport = rmTransportFindRemoteInstType((Rm_Transport *) rmInst->transports, Rm_instType_SERVER);\r
- }\r
-\r
- switch (transaction->type) {\r
- case Rm_service_RESOURCE_ALLOCATE_INIT:\r
- case Rm_service_RESOURCE_ALLOCATE_USE:\r
- case Rm_service_RESOURCE_FREE:\r
- case Rm_service_RESOURCE_GET_BY_NAME:\r
- pktHandle = rmTransportCreateResourceReqPkt(rmInst, dstTransport->appTransportHandle, transaction);\r
- break;\r
- case Rm_service_RESOURCE_MAP_TO_NAME:\r
- case Rm_service_RESOURCE_UNMAP_NAME:\r
- pktHandle = rmTransportCreateNsRequestPkt(rmInst, dstTransport->appTransportHandle, transaction);\r
- break;\r
- }\r
-\r
- if (pktHandle) {\r
- if (rmInst->transportCallouts.rmSendPkt) { \r
- if (rmInst->transportCallouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {\r
- transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;\r
- }\r
- }\r
- else {\r
- transaction->state = RM_ERROR_TRANSPORT_SEND_NOT_REGD;\r
- } \r
- }\r
-\r
- transaction->hasBeenForwarded = true;\r
- /* Transaction not deleted. Waiting for response from RM CD or Server */\r
- }\r
-}\r
-\r
-/* FUNCTION PURPOSE: Issues an allocator operation\r
- ***********************************************************************\r
- * DESCRIPTION: Issues an allocator preallocate, allocate, or free\r
- * for an RM resource.\r
- */\r
-static int32_t allocatorOperation(Rm_Inst *rmInst, Rm_AllocatorOpInfo *opInfo)\r
-{\r
- Rm_Allocator *allocator = NULL;\r
- int32_t resourceOffsetInPolicy;\r
- int32_t retVal;\r
- \r
- resourceOffsetInPolicy = rmPolicyGetResourceOffset(rmInst->policy, opInfo->resourceInfo->name);\r
- allocator = rmAllocatorFind(rmInst->allocators, opInfo->resourceInfo->name);\r
- \r
- if ((resourceOffsetInPolicy > 0) && allocator) {\r
- if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE) {\r
- retVal = treePreAllocate(rmInst, allocator, resourceOffsetInPolicy, opInfo);\r
- } \r
- else if (opInfo->operation == Rm_allocatorOp_ALLOCATE) {\r
- retVal = treeAllocate(rmInst, allocator, resourceOffsetInPolicy, opInfo);\r
- }\r
- else if (opInfo->operation == Rm_allocatorOp_FREE) {\r
- retVal = treeFree(allocator, opInfo);\r
- } \r
- }\r
- else {\r
- /* Resource could not be found in policy and/or allocator */\r
- retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;\r
- }\r
- return(retVal);\r
-}\r
-\r
-/* FUNCTION PURPOSE: Arbitrates allocation service requests\r
- ***********************************************************************\r
- * DESCRIPTION: Issues a set of allocator operations in order to\r
- * handle a received allocation request. Allocation\r
- * requests are always forwarded to the Server on Client\r
- * CD instances. If a request is made with a NameServer\r
- * name the resource base and length parameters are\r
- * retrieved from the NameServer prior to the allocation\r
- * attempt.\r
- */\r
-static void allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, void *validInstNode,\r
- uint32_t allocType)\r
-{\r
- Rm_AllocatorOpInfo opInfo;\r
- Rm_NameServerObjCfg nameServerObjCfg;\r
- int32_t retVal = transaction->state;\r
-\r
- memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
- \r
- if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
- /* Forward all allocation requests to Server if transport is up. Otherwise, just queue. */\r
- if (rmInst->registeredWithDelegateOrServer) {\r
- transactionForwarder(rmInst, transaction); \r
- } \r
- }\r
- else if (rmInst->instType == Rm_instType_SERVER) {\r
- opInfo.resourceInfo = &transaction->resourceInfo;\r
- opInfo.serviceSrcInstNode = validInstNode;\r
- opInfo.allocType = allocType;\r
-\r
- /* Populated NameServer name has precedence over base */\r
- if (strlen(transaction->resourceInfo.nameServerName) > 0) {\r
- if ((transaction->resourceInfo.base == 0) &&\r
- (transaction->resourceInfo.length == 0) &&\r
- (transaction->resourceInfo.alignment == 0)) {\r
- memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
- nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
- nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;\r
- if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {\r
- strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);\r
- transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;\r
- transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;\r
- } \r
- }\r
- else {\r
- retVal = RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT;\r
- }\r
- }\r
-\r
- if (retVal == RM_SERVICE_PROCESSING) { \r
- if (transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) {\r
- opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE;\r
- retVal = allocatorOperation(rmInst, &opInfo);\r
- }\r
- \r
- if (retVal == RM_SERVICE_PROCESSING) {\r
- opInfo.operation = Rm_allocatorOp_ALLOCATE;\r
- retVal = allocatorOperation(rmInst, &opInfo);\r
- } \r
- }\r
- \r
- transaction->state = retVal;\r
-\r
- if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
- /* Source of allocation was not the server instance, provide the transaction\r
- * to the transaction responder */\r
- transactionResponder(rmInst, transaction);\r
- }\r
- /* Otherwise let the return stack return the transaction to the serviceHandler */ \r
- } \r
-}\r
-\r
-/* FUNCTION PURPOSE: Arbitrates free service requests\r
- ***********************************************************************\r
- * DESCRIPTION: Issues a set of allocator operations in order to\r
- * handle a received free request. Free\r
- * requests are always forwarded to the Server on Client\r
- * CD instances. If a request is made with a NameServer\r
- * name the resource base and length parameters are\r
- * retrieved from the NameServer prior to the free\r
- * attempt.\r
- */\r
-static void freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, void *validInstNode)\r
-{\r
- Rm_AllocatorOpInfo opInfo; \r
- Rm_NameServerObjCfg nameServerObjCfg; \r
- int32_t retVal = transaction->state;\r
-\r
- memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
- \r
- if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
- /* Forward all free requests to Server if transport is up. Otherwise, just queue. */\r
- if (rmInst->registeredWithDelegateOrServer) {\r
- transactionForwarder(rmInst, transaction); \r
- }\r
- }\r
- else if (rmInst->instType == Rm_instType_SERVER) {\r
- opInfo.resourceInfo = &transaction->resourceInfo;\r
- opInfo.serviceSrcInstNode = validInstNode;\r
-\r
- /* Populated NameServer name has precedence over base */\r
- if (strlen(transaction->resourceInfo.nameServerName) > 0) {\r
- if ((transaction->resourceInfo.base == 0) &&\r
- (transaction->resourceInfo.length == 0) &&\r
- (transaction->resourceInfo.alignment == 0)) {\r
- memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
- nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
- nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;\r
- if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {\r
- strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);\r
- transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;\r
- transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;\r
- } \r
- }\r
- else {\r
- retVal = RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT;\r
- } \r
- }\r
- \r
- if(retVal == RM_SERVICE_PROCESSING) { \r
- opInfo.operation = Rm_allocatorOp_FREE;\r
- retVal = allocatorOperation(rmInst, &opInfo);\r
- } \r
-\r
- transaction->state = retVal;\r
-\r
- if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
- /* Source of allocation was not the server instance, provide the transaction\r
- * to the transaction responder */\r
- transactionResponder(rmInst, transaction);\r
- }\r
- /* Otherwise let the return stack return the transaction to the serviceHandler */ \r
- } \r
-}\r
-\r
-/* FUNCTION PURPOSE: Reserves a Linux resource\r
- ***********************************************************************\r
- * DESCRIPTION: Reserves resources for Linux using the base and length\r
- * values retrieved from the Linux DTB via the\r
- * "linux-dtb-alias" properties within the GRL.\r
- */\r
-static int32_t reserveLinuxResource(Rm_Inst *rmInst, Rm_LinuxAlias *linuxAlias, \r
- Rm_LinuxValueRange *linuxValues, Rm_AllocatorOpInfo *opInfo)\r
-{\r
- int32_t retVal = RM_OK;\r
- bool baseFound = false;\r
- bool lengthFound = false;\r
- uint32_t valueIndex = 0;\r
-\r
- while ((linuxValues) && (!baseFound || !lengthFound)) {\r
- if (linuxAlias->baseOffset == valueIndex) {\r
- opInfo->resourceInfo->base = linuxValues->value;\r
- baseFound = true;\r
-\r
- if (linuxAlias->lengthOffset == RM_DTB_UTIL_LINUX_ALIAS_OFFSET_NOT_SET) {\r
- opInfo->resourceInfo->length = 1;\r
- lengthFound = true;\r
- }\r
- }\r
- else if (linuxAlias->lengthOffset == valueIndex) {\r
- opInfo->resourceInfo->length = linuxValues->value;\r
- lengthFound = true;\r
- }\r
-\r
- linuxValues = (Rm_LinuxValueRange *)linuxValues->nextValue;\r
- valueIndex++;\r
- }\r
-\r
- if (!baseFound || !lengthFound) {\r
- retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;\r
- }\r
- else {\r
- /* Allocate resource to Linux */\r
- retVal = allocatorOperation(rmInst, opInfo);\r
- }\r
- return (retVal);\r
-}\r
-\r
-/* FUNCTION PURPOSE: Finds and reserves Linux resources\r
- ***********************************************************************\r
- * DESCRIPTION: Parses the Linux DTB for resources consumed by the\r
- * Linux kernel. If the resource is found via the\r
- * "linux-dtb-alias" property defined in the GRL it is \r
- * reserved.\r
- */\r
-static int32_t findAndReserveLinuxResource(Rm_Inst *rmInst, const char *resourceName, void *linuxDtb, \r
- Rm_LinuxAlias *linuxAlias)\r
-{\r
- Rm_AllocatorOpInfo opInfo;\r
- Rm_ResourceInfo resourceInfo;\r
- uint32_t pathOffset;\r
- uint32_t pathSize;\r
- char *spacePtr;\r
- int32_t propOffset;\r
- int32_t nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
- int32_t prevDepth = RM_DTB_UTIL_STARTING_DEPTH;\r
- int32_t depth;\r
- int32_t propertyLen;\r
- const char *propertyName;\r
- const void *propertyData; \r
- Rm_LinuxValueRange *linuxValueRange;\r
- int32_t retVal = RM_OK; \r
-\r
- memset((void *) &opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
- memset((void *) &resourceInfo, 0, sizeof(Rm_ResourceInfo));\r
-\r
- strncpy(resourceInfo.name, resourceName, RM_NAME_MAX_CHARS);\r
- opInfo.serviceSrcInstNode = rmPolicyGetLinuxInstNode(rmInst->validInstances);\r
- opInfo.operation = Rm_allocatorOp_ALLOCATE;\r
- opInfo.resourceInfo = &resourceInfo; \r
-\r
- while(linuxAlias) {\r
- /* Reset parsing variables */\r
- pathOffset = 0;\r
- pathSize = strlen(linuxAlias->path) + 1;\r
- nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
- prevDepth = RM_DTB_UTIL_STARTING_DEPTH; \r
- resourceInfo.base = 0;\r
- resourceInfo.length = 0;\r
-\r
- spacePtr = strpbrk(linuxAlias->path, " ");\r
- if (spacePtr) {\r
- *spacePtr = '\0';\r
- } \r
- \r
- while(pathOffset < pathSize) {\r
- /* Move through DTB nodes until next alias path node found */\r
- if (strcmp(linuxAlias->path + pathOffset, fdt_get_name(linuxDtb, nodeOffset, NULL))) {\r
- nodeOffset = fdt_next_node(linuxDtb, nodeOffset, &depth);\r
-\r
- if ((depth < prevDepth) || (nodeOffset == -FDT_ERR_NOTFOUND)) {\r
- /* Returning from subnode that matched part of alias path without finding\r
- * resource values */\r
- retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;\r
- break;\r
- }\r
- }\r
- else {\r
- /* Found next alias path node. Move to next node name in path string. */\r
- pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);\r
- spacePtr = strpbrk(linuxAlias->path + pathOffset, " ");\r
- if (spacePtr) {\r
- *spacePtr = '\0';\r
- } \r
- \r
- prevDepth = fdt_node_depth(linuxDtb, nodeOffset);\r
- propOffset = fdt_first_property_offset(linuxDtb, nodeOffset);\r
- while ((propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) &&\r
- (pathOffset < pathSize)) {\r
- propertyData = fdt_getprop_by_offset(linuxDtb, propOffset, \r
- &propertyName, &propertyLen);\r
-\r
- if (strcmp(linuxAlias->path + pathOffset, propertyName) == 0) {\r
- /* Found resource at end of alias path */\r
- pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);\r
- linuxValueRange = rmDtbUtilLinuxExtractValues(propertyData, propertyLen);\r
- retVal = reserveLinuxResource(rmInst, linuxAlias, \r
- linuxValueRange, &opInfo);\r
- rmDtbUtilLinuxFreeValues(linuxValueRange);\r
- }\r
- propOffset = fdt_next_property_offset(linuxDtb, propOffset);\r
- } \r
-\r
- if (propOffset < -FDT_ERR_NOTFOUND) {\r
- retVal = propOffset;\r
- break;\r
- }\r
- }\r
- }\r
-\r
- if (retVal < RM_OK) {\r
- break;\r
- }\r
- linuxAlias = linuxAlias->nextLinuxAlias;\r
- }\r
- return (retVal);\r
-}\r
-\r
-/* FUNCTION PURPOSE: Creates and initializes a resource allocator\r
- ***********************************************************************\r
- * DESCRIPTION: Creates a resource allocator for the provided\r
- * resource name and resource properties retrieved\r
- * from the GRL. Resources will be reserved for \r
- * the Linux kernel if the Linux DTB is provided\r
- * and there are "linux-dtb-alias" properties\r
- * specified in the GRL.\r
- */\r
-static int32_t createAndInitAllocator(Rm_Inst *rmInst, const char *resourceName, \r
- Rm_ResourceProperties *resourceProperties, void *linuxDtb)\r
-{\r
- Rm_ResourceRange *range = NULL;\r
- Rm_ResourceRange *rangeBasePtr = NULL;\r
- Rm_NsAssignment *nsAssignments = NULL;\r
- Rm_NsAssignment *nsAssignmentBasePtr = NULL;\r
- Rm_LinuxAlias *linuxAlias = NULL;\r
- Rm_NameServerObjCfg nameServerObjCfg; \r
- int32_t retVal = RM_OK;\r
-\r
- if (resourceProperties->rangeData && (resourceProperties->rangeLen > 0)) {\r
- range = rangeBasePtr = rmDtbUtilResExtractRange(resourceProperties->rangeData, \r
- resourceProperties->rangeLen);\r
- \r
- if ((retVal = createResourceTree(rmInst, resourceName, range)) >= RM_OK) {\r
- if (resourceProperties->linuxAliasData && resourceProperties->linuxAliasLen) {\r
- if (linuxDtb) {\r
- linuxAlias = rmDtbUtilResExtractLinuxAlias(resourceProperties->linuxAliasData,\r
- resourceProperties->linuxAliasLen, &retVal);\r
- if (linuxAlias) {\r
- retVal = findAndReserveLinuxResource(rmInst, resourceName, linuxDtb, linuxAlias); \r
- }\r
- }\r
- else {\r
- retVal = RM_ERROR_GRL_LINUX_ALIAS_BUT_NO_DTB;\r
- }\r
- }\r
- }\r
- }\r
- \r
- if (retVal >= RM_OK) {\r
- if (resourceProperties->nsAssignData && resourceProperties->nsAssignLen) {\r
- nsAssignments = rmDtbUtilResExtractNsAssignment(resourceProperties->nsAssignData, \r
- resourceProperties->nsAssignLen, &retVal);\r
- if (nsAssignments) {\r
- nsAssignmentBasePtr = nsAssignments;\r
- while (nsAssignments) {\r
- memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
- nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
- nameServerObjCfg.nodeCfg.objName = nsAssignments->nsName;\r
- nameServerObjCfg.nodeCfg.resourceName = (char *)resourceName;\r
- nameServerObjCfg.nodeCfg.resourceBase= nsAssignments->resourceBase;\r
- nameServerObjCfg.nodeCfg.resourceLength = nsAssignments->resourceLength; \r
- rmNameServerAddObject(&nameServerObjCfg);\r
- nsAssignments = nsAssignments->nextNsAssignment;\r
- }\r
- rmDtbUtilResFreeNsAssignmentList(nsAssignmentBasePtr);\r
- }\r
- }\r
- }\r
-\r
- rmDtbUtilResFreeRange(rangeBasePtr);\r
- if (linuxAlias) {\r
- rmDtbUtilResFreeLinuxAlias(linuxAlias);\r
- }\r
- return(retVal);\r
-}\r
-\r
-/* FUNCTION PURPOSE: Recursively parses GRL resource properties\r
- ***********************************************************************\r
- * DESCRIPTION: Recursively parses and stores GRL resource node \r
- * properties using the LIBFDT APIs\r
- */\r
-static int32_t parseResourceProperty(void *globalResourceDtb, int32_t offset, \r
- Rm_ResourceProperties *propertyInfo)\r
-{\r
- int32_t propertyLen;\r
- const char *propertyName;\r
- const void *propertyData;\r
- Rm_ResourcePropType propertyType;\r
- int32_t retVal = RM_OK;\r
-\r
- propertyData = fdt_getprop_by_offset(globalResourceDtb, offset, &propertyName, &propertyLen);\r
- propertyType = rmDtbUtilResGetPropertyType(propertyName);\r
- if (propertyType == Rm_resourcePropType_RESOURCE_RANGE) {\r
- propertyInfo->rangeData = propertyData;\r
- propertyInfo->rangeLen = propertyLen;\r
- }\r
- else if (propertyType == Rm_resourcePropType_NSASSIGNMENT) {\r
- propertyInfo->nsAssignData = propertyData;\r
- propertyInfo->nsAssignLen = propertyLen;\r
- }\r
- else if (propertyType == Rm_resourcePropType_RESOURCE_LINUX_ALIAS) {\r
- propertyInfo->linuxAliasData = propertyData;\r
- propertyInfo->linuxAliasLen = propertyLen;\r
- } \r
- else {\r
- retVal = RM_ERROR_GRL_UNKNOWN_RESOURCE_PROPERTY;\r
- }\r
-\r
- if (retVal == RM_OK) {\r
- offset = fdt_next_property_offset(globalResourceDtb, offset);\r
- if (offset >= 0) {\r
- retVal = parseResourceProperty(globalResourceDtb, offset, propertyInfo);\r
- }\r
- else if (offset != -FDT_ERR_NOTFOUND) {\r
- /* Error returned by LIBFDT */\r
- retVal = offset;\r
- }\r
- }\r
- return (retVal);\r
-}\r
-\r
-/* FUNCTION PURPOSE: Recursively parses GRL resource nodes\r
- ***********************************************************************\r
- * DESCRIPTION: Recursively parses GRL resource nodes looking for\r
- * resource properties to create the resource allocators.\r
- * The LIBFDT APIs are used to parse the GRL.\r
- */\r
-static int32_t parseResourceNode(Rm_Inst *rmInst, void *globalResourceDtb, int32_t nodeOffset, int32_t depth,\r
- void *linuxDtb)\r
-{\r
- const char *resourceName = fdt_get_name(globalResourceDtb, nodeOffset, NULL);\r
- Rm_ResourceProperties resourceProperties;\r
- int32_t retVal = RM_OK;\r
- int32_t offset;\r
-\r
- memset((void *)&resourceProperties, 0, sizeof(Rm_ResourceProperties));\r
- /* Get properties of resource node */\r
- offset = fdt_first_property_offset(globalResourceDtb, nodeOffset);\r
- if (offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) {\r
- retVal = parseResourceProperty(globalResourceDtb, offset, &resourceProperties);\r
- if (retVal < -FDT_ERR_NOTFOUND) {\r
- return (retVal);\r
- }\r
- if (retVal = createAndInitAllocator(rmInst, resourceName, &resourceProperties, linuxDtb) < RM_OK) {\r
- return (retVal);\r
- }\r
- }\r
- else if (offset != -FDT_ERR_NOTFOUND) {\r
- /* Error returned by LIBFDT */\r
- return (offset);\r
- }\r
- \r
- offset = fdt_next_node(globalResourceDtb, nodeOffset, &depth);\r
- if ((offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {\r
- retVal = parseResourceNode(rmInst, globalResourceDtb, offset, depth, linuxDtb);\r
- if (retVal < -FDT_ERR_NOTFOUND) {\r
- return (retVal);\r
- }\r
- }\r
- else if (offset != -FDT_ERR_NOTFOUND) {\r
- /* Error returned by LIBFDT */\r
- return (offset);\r
- }\r
- return (retVal);\r
-}\r
-\r
-/* FUNCTION PURPOSE: Initializes server allocators\r
- ***********************************************************************\r
- * DESCRIPTION: Creates and initializes a server instance's\r
- * resource allocators using the GRL and, if\r
- * provided, Linux DTB.\r
- */\r
-static int32_t initializeAllocators(Rm_Inst *rmInst, void *globalResourceDtb, void *linuxDtb)\r
-{\r
- int32_t nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
- int32_t startDepth = RM_DTB_UTIL_STARTING_DEPTH;\r
- int32_t result = RM_OK;\r
-\r
- /* Recursively parse the Global Resource List, creating an allocator for\r
- * each resource as specified in the node */\r
- result = parseResourceNode(rmInst, globalResourceDtb, nodeOffset, startDepth, linuxDtb);\r
-\r
- return(result);\r
-}\r
-\r
-/**********************************************************************\r
- ********************** Internal Functions ****************************\r
- **********************************************************************/\r
-\r
-/* FUNCTION PURPOSE: Adds a transaction\r
- ***********************************************************************\r
- * DESCRIPTION: Returns a pointer to a newly created transaction.\r
- * The transaction is created based on a new service\r
- * request received via the service API or the\r
- * transport API (service forwarded from another instance)\r
- */\r
-Rm_Transaction *rmTransactionQueueAdd(Rm_Inst *rmInst)\r
-{\r
- Rm_Transaction *transactionQueue = rmInst->transactionQueue;\r
- Rm_Transaction *newTransaction = NULL;\r
-\r
- newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));\r
- if (newTransaction) {\r
- memset((void *)newTransaction, 0, sizeof(Rm_Transaction));\r
-\r
- newTransaction->localId = transactionGetSequenceNum(rmInst);\r
- newTransaction->nextTransaction = NULL; \r
- if (transactionQueue) {\r
- while (transactionQueue->nextTransaction) {\r
- transactionQueue = transactionQueue->nextTransaction;\r
- }\r
- transactionQueue->nextTransaction = newTransaction;\r
- }\r
- else {\r
- rmInst->transactionQueue = newTransaction;\r
- }\r
- }\r
- return (newTransaction);\r
-}\r
-\r
-/* FUNCTION PURPOSE: Finds a transaction\r
- ***********************************************************************\r
- * DESCRIPTION: Returns a pointer to a transaction resident\r
- * in the transaction queue that matches the provided\r
- * transaction ID.\r
- */\r
-Rm_Transaction *rmTransactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)\r
-{\r
- Rm_Transaction *transaction = rmInst->transactionQueue;\r
-\r
- while (transaction) {\r
- if (transaction->localId == transactionId) {\r
- break; \r
- }\r
- transaction = transaction->nextTransaction;\r
- }\r
-\r
- return (transaction);\r
-}\r
-\r
-/* FUNCTION PURPOSE: Deletes a transaction\r
- ***********************************************************************\r
- * DESCRIPTION: Deletes the transaction with the provided transaction\r
- * ID from the instance's transaction queue.\r
- */\r
-int32_t rmTransactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)\r
-{\r
- Rm_Transaction *transaction = rmInst->transactionQueue;\r
- Rm_Transaction *prevTransaction = NULL;\r
- int32_t retVal = RM_OK;\r
-\r
- while (transaction) {\r
- if (transaction->localId == transactionId) {\r
- break; \r
- }\r
-\r
- prevTransaction = transaction;\r
- transaction = transaction->nextTransaction;\r
- }\r
-\r
- if (transaction) {\r
- if (prevTransaction == NULL) {\r
- /* Transaction at start of queue. Map second transaction to start of queue \r
- * as long as more than one transactions. */\r
- rmInst->transactionQueue = transaction->nextTransaction;\r
- }\r
- else {\r
- /* Transaction in middle or end of queue. */\r
- prevTransaction->nextTransaction = transaction->nextTransaction;\r
- }\r
- Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));\r
- }\r
- else {\r
- retVal = RM_ERROR_SERVICE_TRANS_DOES_NOT_EXIST;\r
- } \r
- return (retVal);\r
-}\r
-\r
-/* FUNCTION PURPOSE: Finds an allocator\r
- ***********************************************************************\r
- * DESCRIPTION: Returns a pointer to an allocator that matches the \r
- * provided resource name.\r
- */\r
-Rm_Allocator *rmAllocatorFind(Rm_Allocator *allocatorList, char *resourceName)\r
-{\r
- while (allocatorList) {\r
- if (strncmp(allocatorList->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {\r
- break; \r
- }\r
- allocatorList = allocatorList->nextAllocator;\r
- }\r
-\r
- return (allocatorList);\r
-}\r
-\r
-/* FUNCTION PURPOSE: Processes a transaction\r
- ***********************************************************************\r
- * DESCRIPTION: Processes transactions created from services\r
- * received via the service handle or the transport.\r
- * Transactions will be routed within the RM system\r
- * based on the RM instance type and the type of\r
- * the transaction.\r
- */\r
-void rmTransactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
-{\r
- void *validInstNode;\r
- Rm_PolicyCheckCfg privCheckCfg;\r
- Rm_NameServerObjCfg nameServerObjCfg; \r
- uint32_t allocType = 0; \r
-\r
- /* Handle static transactions originating on this instance. Any other static transactions will be\r
- * stored in transaction queue until all transports are up. */\r
- if (((rmInst->instType == Rm_instType_CLIENT) || (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) &&\r
- (!rmInst->registeredWithDelegateOrServer) && \r
- (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS) == 0)) {\r
- if (rmInst->staticInfo.staticPolicy) {\r
- if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||\r
- (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE)) {\r
- /* Check request against startup policy */\r
- memset((void *)&privCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));\r
-\r
- if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {\r
- privCheckCfg.type = Rm_policyCheck_INIT;\r
- }\r
- else {\r
- privCheckCfg.type = Rm_policyCheck_USE;\r
- }\r
- privCheckCfg.policyDtb = rmInst->staticInfo.staticPolicy;\r
- privCheckCfg.validInstNode = rmPolicyGetValidInstNode(rmInst->staticInfo.staticValidInstTree, \r
- rmInst->instName);\r
- privCheckCfg.resourceOffset = rmPolicyGetResourceOffset(rmInst->staticInfo.staticPolicy,\r
- transaction->resourceInfo.name);\r
- privCheckCfg.resourceBase = transaction->resourceInfo.base;\r
- privCheckCfg.resourceLength = transaction->resourceInfo.length;\r
-\r
- if (rmPolicyCheckPrivilege(&privCheckCfg, &transaction->state)) {\r
- transaction->state = RM_SERVICE_APPROVED_STATIC;\r
- }\r
- else if (transaction->state == RM_SERVICE_PROCESSING) {\r
- /* Privilege check returned false without error */\r
- transaction->state = RM_SERVICE_DENIED_BY_STATIC_POLICY;\r
- }\r
- }\r
- else {\r
- transaction->state = RM_SERVICE_DENIED_INVALID_STATIC_REQUEST;\r
- }\r
- }\r
- else {\r
- transaction->state = RM_ERROR_REQ_FAILED_NO_STATIC_POLICY;\r
- } \r
- }\r
- else {\r
- /* Handle auto-forwarded transactions. These transactions include:\r
- * - All request transactions received on Clients are forwarded to the Client Delegate\r
- * - NameServer requests received on the Client Delegate are forwarded to the Server */\r
- if ((rmInst->instType == Rm_instType_CLIENT) ||\r
- ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
- ((transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||\r
- (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) ||\r
- (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)))) {\r
- \r
- if ((transaction->state != RM_SERVICE_PROCESSING) &&\r
- (transaction->state != RM_SERVICE_APPROVED_STATIC)) {\r
- if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
- /* Transaction did not originate on this instance */\r
- transactionResponder(rmInst, transaction);\r
- }\r
- else {\r
- /* Transaction originated on this instance */\r
- serviceResponder(rmInst, transaction);\r
- }\r
- }\r
- else {\r
- /* Forward request if transport is up. Otherwise, just queue. */\r
- if (rmInst->registeredWithDelegateOrServer) {\r
- transactionForwarder(rmInst, transaction); \r
- } \r
- }\r
- }\r
- else {\r
- /* Validate service's originating instance name */\r
- if (rmInst->instType == Rm_instType_SERVER) {\r
- validInstNode = rmPolicyGetValidInstNode(rmInst->validInstances, transaction->serviceSrcInstName);\r
- if (validInstNode == NULL) {\r
- transaction->state = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;\r
-\r
- /* Send result via responder if transaction did not originate from this instance */\r
- if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
- transactionResponder(rmInst, transaction);\r
- }\r
- }\r
- }\r
-\r
- switch (transaction->type) {\r
- case Rm_service_RESOURCE_ALLOCATE_INIT:\r
- case Rm_service_RESOURCE_ALLOCATE_USE:\r
- case Rm_service_RESOURCE_FREE: \r
- if ((transaction->state != RM_SERVICE_PROCESSING) &&\r
- (transaction->state != RM_SERVICE_APPROVED_STATIC)) {\r
- /* Transaction complete */\r
- if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
- /* Transaction result not destined for this instance */\r
- transactionResponder(rmInst, transaction);\r
- }\r
- else {\r
- /* Transaction result destined for this instance */\r
- serviceResponder(rmInst, transaction); \r
- }\r
- }\r
- else {\r
- /* Complete allocation/free request */\r
- if (transaction->type == Rm_service_RESOURCE_FREE) {\r
- freeHandler(rmInst, transaction, validInstNode);\r
- }\r
- else {\r
- switch (transaction->type) {\r
- case Rm_service_RESOURCE_ALLOCATE_INIT:\r
- RM_policy_SET_PERM(allocType, RM_POLICY_PERM_INIT_SHIFT, 1);\r
- break;\r
- case Rm_service_RESOURCE_ALLOCATE_USE:\r
- RM_policy_SET_PERM(allocType, RM_POLICY_PERM_USE_SHIFT, 1); \r
- break;\r
- }\r
- allocationHandler(rmInst, transaction, validInstNode, allocType);\r
- }\r
- }\r
- break;\r
- case Rm_service_RESOURCE_MAP_TO_NAME:\r
- case Rm_service_RESOURCE_GET_BY_NAME:\r
- case Rm_service_RESOURCE_UNMAP_NAME: \r
- /* NameServer resides on server */\r
- memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));\r
- if (rmInst->nameServer) {\r
- nameServerObjCfg.nameServerTree = rmInst->nameServer;\r
- nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;\r
- if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {\r
- nameServerObjCfg.nodeCfg.resourceName = transaction->resourceInfo.name;\r
- nameServerObjCfg.nodeCfg.resourceBase= transaction->resourceInfo.base;\r
- nameServerObjCfg.nodeCfg.resourceLength = transaction->resourceInfo.length;\r
- transaction->state = rmNameServerAddObject(&nameServerObjCfg);\r
- }\r
- else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {\r
- if ((transaction->state = rmNameServerFindObject(&nameServerObjCfg)) ==\r
- RM_SERVICE_PROCESSING) {\r
- strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);\r
- transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;\r
- transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;\r
- transaction->state = RM_SERVICE_APPROVED;\r
- } \r
- }\r
- else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {\r
- transaction->state = rmNameServerDeleteObject(&nameServerObjCfg);\r
- }\r
- }\r
- else {\r
- transaction->state = RM_ERROR_NAMESERVER_DOES_NOT_EXIST;\r
- }\r
-\r
- /* Send result via responder if transaction did not originate from this instance */\r
- if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {\r
- transactionResponder(rmInst, transaction);\r
- }\r
- break;\r
- }\r
- }\r
- }\r
-\r
- /* Forward any queued requests that weren't forwarded yet */\r
- if (rmInst->registeredWithDelegateOrServer) {\r
- transaction = rmInst->transactionQueue;\r
- while(transaction) {\r
- if (((transaction->state == RM_SERVICE_PROCESSING) ||\r
- (transaction->state == RM_SERVICE_APPROVED_STATIC)) &&\r
- !transaction->hasBeenForwarded) {\r
- transactionForwarder(rmInst, transaction);\r
- }\r
- transaction = transaction->nextTransaction;\r
- }\r
- }\r
-}\r
- \r
-/**********************************************************************\r
- ********************** Application visible APIs **********************\r
- **********************************************************************/\r
-\r
-/* FUNCTION PURPOSE: Display status of managed resources\r
- ***********************************************************************\r
- * DESCRIPTION: Prints the status (allocate/free status, as well as\r
- * owners) for all resources managed by the RM \r
- * instance network. Also, prints the NameServer name\r
- * entries. This function is only available on server\r
- * instances.\r
- */\r
-void Rm_printResourceStatus(Rm_Handle rmServerHandle)\r
-{\r
- Rm_Inst *rmInst = (Rm_Inst *)rmServerHandle;\r
- Rm_Allocator *allocator = rmInst->allocators;\r
- Rm_Owner *owners;\r
- Rm_ResourceTree *treeRoot;\r
- Rm_ResourceNode *treeNode;\r
-\r
- if (rmInst->instType == Rm_instType_SERVER) {\r
- while (allocator != NULL) {\r
- Rm_osalLog("Resource: %s\n", allocator->resourceName);\r
-\r
- treeRoot = allocator->allocatorRootEntry;\r
-\r
- RB_FOREACH(treeNode, _Rm_AllocatorResourceTree, treeRoot) { \r
- Rm_osalLog(" %10d - %10d ", treeNode->base, \r
- treeNode->base + treeNode->length -1);\r
- \r
- if (treeNode->allocationCount == 0) {\r
- Rm_osalLog("NOT ALLOCATED\n");\r
- }\r
- else {\r
- owners = treeNode->ownerList;\r
- Rm_osalLog("allocated to");\r
- while (owners) {\r
- Rm_osalLog(" %s", owners->instNameNode->name);\r
- owners = owners->nextOwner;\r
- }\r
- Rm_osalLog("\n");\r
- }\r
- } \r
- allocator = allocator->nextAllocator;\r
- }\r
- rmNameServerPrintObjects(rmInst->nameServer);\r
- }\r
-}\r
-\r
-/* FUNCTION PURPOSE: Display status of a RM instance\r
- ***********************************************************************\r
- * DESCRIPTION: Prints the current status of various RM instance\r
- * properties such as the state of all transactions\r
- * in the transaction queue and registered transports\r
- */\r
-void Rm_printInstanceStatus(Rm_Handle rmHandle)\r
-{\r
- Rm_Inst *rmInst = (Rm_Inst *)rmHandle;\r
- Rm_Transport *transportList = (Rm_Transport *)rmInst->transports;\r
- Rm_Transaction *transactionQ = rmInst->transactionQueue;\r
-\r
- Rm_osalLog("Instance name: %s\n", rmInst->instName);\r
- if (rmInst->instType == Rm_instType_SERVER) {\r
- Rm_osalLog("Type: Server\n");\r
- }\r
- else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {\r
- Rm_osalLog("Type: Client Delegate\n");\r
- }\r
- else {\r
- Rm_osalLog("Type: Client\n");\r
- }\r
-\r
- if (transportList) {\r
- Rm_osalLog("\nRegistered Transports:\n");\r
- while (transportList) {\r
- Rm_osalLog(" Remote instName: %s\n", transportList->remoteInstName);\r
- if (transportList->remoteInstType == Rm_instType_SERVER) {\r
- Rm_osalLog(" Remote instType: Server\n");\r
- }\r
- else if (transportList->remoteInstType == Rm_instType_CLIENT_DELEGATE) {\r
- Rm_osalLog(" Remote instType: Client Delegate\n");\r
- }\r
- else {\r
- Rm_osalLog(" Remote instType: Client\n");\r
- }\r
- Rm_osalLog(" appTransportHandle: 0x%08x\n", transportList->appTransportHandle);\r
- Rm_osalLog("\n");\r
- transportList = transportList->nextTransport;\r
- }\r
- }\r
-\r
- if (transactionQ) {\r
- Rm_osalLog("\nQueued Service Transactions:\n");\r
- while (transactionQ) {\r
- Rm_osalLog(" Service type: %d\n", transactionQ->type);\r
- Rm_osalLog(" Service ID: %d\n", transactionQ->localId);\r
- Rm_osalLog(" Service srcInstName %s\n", transactionQ->serviceSrcInstName);\r
- Rm_osalLog(" Service state: %d\n", transactionQ->state);\r
- Rm_osalLog(" Resource name: %s\n", transactionQ->resourceInfo.name);\r
- Rm_osalLog(" Resource base: %d\n", transactionQ->resourceInfo.base);\r
- Rm_osalLog(" Resource length: %d\n", transactionQ->resourceInfo.length);\r
- Rm_osalLog(" Resource alignment: %d\n", transactionQ->resourceInfo.alignment);\r
- Rm_osalLog(" Resource NS name: %s\n", transactionQ->resourceInfo.nameServerName);\r
- Rm_osalLog("\n");\r
- transactionQ = transactionQ->nextTransaction;\r
- } \r
- }\r
-}\r
-\r
-/* FUNCTION PURPOSE: RM instance creation and initialization\r
- ***********************************************************************\r
- * DESCRIPTION: Returns a new RM instance created and initialized\r
- * using the parameters provided via the initCfg\r
- * structure.\r
- */\r
-Rm_Handle Rm_init(Rm_InitCfg *initCfg, int32_t *result)\r
-{\r
- Rm_Inst *rmInst;\r
- void *globalResourceDtb = NULL;\r
- void *linuxResourceDtb = NULL;\r
- bool addLinux = false;\r
-\r
- *result = RM_OK;\r
- \r
- if ((initCfg->instName == NULL) ||\r
- ((strlen(initCfg->instName) + 1) > RM_NAME_MAX_CHARS)) {\r
- *result = RM_ERROR_INVALID_INST_NAME;\r
- return (NULL);\r
- }\r
-\r
- if (initCfg->instType >= Rm_instType_LAST) {\r
- *result = RM_ERROR_INVALID_INST_TYPE;\r
- }\r
-\r
- /* Create and initialize instance */\r
- rmInst = Rm_osalMalloc (sizeof(Rm_Inst));\r
- memset ((void *) rmInst, 0, sizeof(Rm_Inst));\r
- rmInst->isLocked = false;\r
- rmInst->registeredWithDelegateOrServer = false;\r
- rmInst->transactionSeqNum = transactionInitSequenceNum();\r
-\r
- rmInst->instType = initCfg->instType; \r
- strncpy (rmInst->instName, initCfg->instName, RM_NAME_MAX_CHARS);\r
-\r
- if (rmInst->instType == Rm_instType_SERVER) {\r
- if (!initCfg->instCfg.serverCfg.globalResourceList ||\r
- !initCfg->instCfg.serverCfg.globalPolicy) {\r
- *result = RM_ERROR_INVALID_SERVER_CONFIGURATION;\r
- Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));\r
- return(NULL);\r
- }\r
-\r
- rmInst->policy = initCfg->instCfg.serverCfg.globalPolicy;\r
- fdt_open_into(rmInst->policy, rmInst->policy, fdt_totalsize(rmInst->policy)); \r
-\r
- if (initCfg->instCfg.serverCfg.linuxDtb) {\r
- linuxResourceDtb = initCfg->instCfg.serverCfg.linuxDtb;\r
- fdt_open_into(linuxResourceDtb, linuxResourceDtb, fdt_totalsize(linuxResourceDtb));\r
- addLinux = true;\r
- }\r
-\r
- /* Create valid instance list from policy. Must be done prior to parsing\r
- * GRL so that Linux resources can be reserved correctly */\r
- rmInst->validInstances = rmPolicyCreateValidInstTree(rmInst->policy, addLinux, result);\r
- /* Validate policy assignment strings */\r
- *result = rmPolicyValidatePolicy(rmInst->policy, rmInst->validInstances); \r
-\r
- rmInst->nameServer = rmNameServerInit();\r
-\r
- globalResourceDtb = initCfg->instCfg.serverCfg.globalResourceList;\r
- fdt_open_into(globalResourceDtb, globalResourceDtb, fdt_totalsize(globalResourceDtb));\r
-\r
- if ((*result = initializeAllocators(rmInst, globalResourceDtb, linuxResourceDtb)) == RM_OK) { \r
- *result = rmPolicyValidatePolicyResourceNames(rmInst->policy, (void *)rmInst->allocators);\r
- }\r
- if (*result < RM_OK) {\r
- Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));\r
- return(NULL);\r
- }\r
- }\r
-\r
- if ((rmInst->instType == Rm_instType_CLIENT) && \r
- (initCfg->instCfg.clientCfg.staticPolicy)) {\r
- rmInst->staticInfo.staticPolicy = initCfg->instCfg.clientCfg.staticPolicy; \r
- }\r
- else if ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
- (initCfg->instCfg.cdCfg.staticPolicy)) { \r
- rmInst->staticInfo.staticPolicy = initCfg->instCfg.cdCfg.staticPolicy; \r
- }\r
- if (rmInst->staticInfo.staticPolicy) {\r
- fdt_open_into(rmInst->staticInfo.staticPolicy, rmInst->staticInfo.staticPolicy, \r
- fdt_totalsize(rmInst->staticInfo.staticPolicy)); \r
- rmInst->staticInfo.staticValidInstTree = rmPolicyCreateValidInstTree(rmInst->staticInfo.staticPolicy, \r
- addLinux, result); \r
- if (*result == RM_OK) {\r
- /* Validate policy assignment strings */\r
- *result = rmPolicyValidatePolicy(rmInst->staticInfo.staticPolicy, rmInst->staticInfo.staticValidInstTree);\r
- }\r
- if (*result != RM_OK) {\r
- if (rmInst->staticInfo.staticValidInstTree) {\r
- rmPolicyFreeValidInstTree(rmInst->staticInfo.staticValidInstTree);\r
- }\r
- Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));\r
- rmInst = NULL;\r
- }\r
- }\r
- return ((Rm_Handle) rmInst);\r
-}\r
-\r
-/* FUNCTION PURPOSE: Returns RM version information\r
- ***********************************************************************\r
- */\r
-uint32_t Rm_getVersion (void)\r
-{\r
- return RM_VERSION_ID;\r
-}\r
-\r
-/* FUNCTION PURPOSE: Returns RM version string\r
- ***********************************************************************\r
- */\r
-const char* Rm_getVersionStr (void)\r
-{\r
- return rmVersionStr;\r
-}\r
-\r
+/**
+ * @file rm.c
+ *
+ * @brief
- * This is the Resource Manager Low Level Driver file.
++ * This is the Resource Manager source.
+ *
+ * \par
+ * ============================================================================
- * @n (C) Copyright 2012, Texas Instruments, Inc.
++ * @n (C) Copyright 2012-2013, Texas Instruments, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \par
+*/
+
- /* c99 include */
++/* Standard includes */
+#include <stdint.h>
- #include <stdlib.h>
++#include <string.h>
++#include <stdbool.h>
+
- /* RM includes */
++/* RM external includes */
+#include <ti/drv/rm/rm.h>
- #include <ti/drv/rm/rm_public_lld.h>
- #include <ti/drv/rm/resource_table_defs.h>
- #include <ti/drv/rm/include/rm_pvt.h>
++#include <ti/drv/rm/rmver.h>
++#include <ti/drv/rm/rm_services.h>
++#include <ti/drv/rm/rm_transport.h>
++
++/* RM internal includes */
++#include <ti/drv/rm/include/rm_loc.h>
++#include <ti/drv/rm/include/rm_transportloc.h>
++#include <ti/drv/rm/include/rm_nameserverloc.h>
++#include <ti/drv/rm/include/rm_dtb_utilloc.h>
++#include <ti/drv/rm/include/rm_policyloc.h>
++#include <ti/drv/rm/include/rm_treeloc.h>
++
++/* RM LIBFDT includes */
++#include <ti/drv/rm/util/libfdt/libfdt.h>
++
++/* Tree algorithm includes */
++#include <ti/drv/rm/util/tree.h>
+
+/* RM OSAL layer */
+#include <rm_osal.h>
+
- /* CSL includes */
- #include <ti/csl/csl_qm_queue.h>
-
+/**********************************************************************
+ ************************** Globals ***********************************
+ **********************************************************************/
+
- /* Place QMSS PDSP permissions array */
- #pragma DATA_SECTION (rmQmssPdspFirmwarePerms, ".rm");
- #pragma DATA_ALIGN (rmQmssPdspFirmwarePerms, 128)
- Rm_Perms rmQmssPdspFirmwarePerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_QMSS_FIRMWARE_PDSPS, Rm_Perms)];
-
- /* Place QMSS queue permissions array */
- #pragma DATA_SECTION (rmQmssQueuePerms, ".rm");
- #pragma DATA_ALIGN (rmQmssQueuePerms, 128)
- Rm_Perms rmQmssQueuePerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_QMSS_QUEUES, Rm_Perms)];
-
- /* Place QMSS memory region permissions array */
- #pragma DATA_SECTION (rmQmssMemRegionPerms, ".rm");
- #pragma DATA_ALIGN (rmQmssMemRegionPerms, 128)
- Rm_Perms rmQmssMemRegionPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_QMSS_MEM_REGIONS, Rm_Perms)];
-
- /* Place QMSS Linking RAM permissions array */
- #pragma DATA_SECTION (rmQmssLinkingRamPerms, ".rm");
- #pragma DATA_ALIGN (rmQmssLinkingRamPerms, 128)
- Rm_qmssLinkingRamPerms rmQmssLinkingRamPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_QMSS_LINKING_RAM_RANGES, Rm_qmssLinkingRamPerms)];
-
- /* Place QMSS accumulator channel permissions array */
- #pragma DATA_SECTION (rmQmssAccumChPerms, ".rm");
- #pragma DATA_ALIGN (rmQmssAccumChPerms, 128)
- Rm_Perms rmQmssAccumChPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_QMSS_ACCUM_CH, Rm_Perms)];
-
- /* Place QMSS QOS cluster permissions array */
- #pragma DATA_SECTION (rmQmssQosClusterPerms, ".rm");
- #pragma DATA_ALIGN (rmQmssQosClusterPerms, 128)
- Rm_Perms rmQmssQosClusterPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_QMSS_QOS_CLUSTER, Rm_Perms)];
-
- /* Place QMSS QOS queue permissions array */
- #pragma DATA_SECTION (rmQmssQosQueuePerms, ".rm");
- #pragma DATA_ALIGN (rmQmssQosQueuePerms, 128)
- Rm_Perms rmQmssQosQueuePerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_QMSS_QOS_QUEUES, Rm_Perms)];
-
- /* Place CPPI SRIO TX channel permissions array */
- #pragma DATA_SECTION (rmCppiSrioTxChPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiSrioTxChPerms, 128)
- Rm_Perms rmCppiSrioTxChPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_SRIO_TX_CH, Rm_Perms)];
-
- #ifdef QMSS_MAX_AIF_QUEUE
- /* Place CPPI AIF TX channel permissions array */
- #pragma DATA_SECTION (rmCppiAifTxChPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiAifTxChPerms, 128)
- Rm_Perms rmCppiAifTxChPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_AIF_TX_CH, Rm_Perms)];
- #endif
-
- #ifdef QMSS_MAX_FFTC_A_QUEUE
- /* Place CPPI FFTC A TX channel permissions array */
- #pragma DATA_SECTION (rmCppiFftcATxChPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiFftcATxChPerms, 128)
- Rm_Perms rmCppiFftcATxChPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_FFTC_A_TX_CH, Rm_Perms)];
- #endif
-
- #ifdef QMSS_MAX_FFTC_B_QUEUE
- /* Place CPPI FFTC B TX channel permissions array */
- #pragma DATA_SECTION (rmCppiFftcBTxChPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiFftcBTxChPerms, 128)
- Rm_Perms rmCppiFftcBTxChPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_FFTC_B_TX_CH, Rm_Perms)];
- #endif
-
- #ifdef QMSS_MAX_PASS_QUEUE
- /* Place CPPI PASS TX channel permissions array */
- #pragma DATA_SECTION (rmCppiPassTxChPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiPassTxChPerms, 128)
- Rm_Perms rmCppiPassTxChPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_PASS_TX_CH, Rm_Perms)];
- #endif
-
- /* Place CPPI QMSS TX channel permissions array */
- #pragma DATA_SECTION (rmCppiQmssTxChPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiQmssTxChPerms, 128)
- Rm_Perms rmCppiQmssTxChPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_QMSS_TX_CH, Rm_Perms)];
-
- #ifdef QMSS_MAX_FFTC_C_QUEUE
- /* Place CPPI FFTC C TX channel permissions array */
- #pragma DATA_SECTION (rmCppiFftcCTxChPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiFftcCTxChPerms, 128)
- Rm_Perms rmCppiFftcCTxChPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_FFTC_C_TX_CH, Rm_Perms)];
- #endif
-
- #ifdef QMSS_MAX_BCP_QUEUE
- /* Place CPPI BCP TX channel permissions array */
- #pragma DATA_SECTION (rmCppiBcpTxChPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiBcpTxChPerms, 128)
- Rm_Perms rmCppiBcpTxChPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_BCP_TX_CH, Rm_Perms)];
- #endif
-
- /* Place CPPI SRIO RX channel permissions array */
- #pragma DATA_SECTION (rmCppiSrioRxChPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiSrioRxChPerms, 128)
- Rm_Perms rmCppiSrioRxChPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_SRIO_RX_CH, Rm_Perms)];
-
- #ifdef QMSS_MAX_AIF_QUEUE
- /* Place CPPI AIF RX channel permissions array */
- #pragma DATA_SECTION (rmCppiAifRxChPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiAifRxChPerms, 128)
- Rm_Perms rmCppiAifRxChPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_AIF_RX_CH, Rm_Perms)];
- #endif
-
- #ifdef QMSS_MAX_FFTC_A_QUEUE
- /* Place CPPI FFTC A RX channel permissions array */
- #pragma DATA_SECTION (rmCppiFftcARxChPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiFftcARxChPerms, 128)
- Rm_Perms rmCppiFftcARxChPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_FFTC_A_RX_CH, Rm_Perms)];
- #endif
-
- #ifdef QMSS_MAX_FFTC_B_QUEUE
- /* Place CPPI FFTC B RX channel permissions array */
- #pragma DATA_SECTION (rmCppiFftcBRxChPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiFftcBRxChPerms, 128)
- Rm_Perms rmCppiFftcBRxChPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_FFTC_B_RX_CH, Rm_Perms)];
- #endif
-
- #ifdef QMSS_MAX_PASS_QUEUE
- /* Place CPPI PASS RX channel permissions array */
- #pragma DATA_SECTION (rmCppiPassRxChPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiPassRxChPerms, 128)
- Rm_Perms rmCppiPassRxChPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_PASS_RX_CH, Rm_Perms)];
- #endif
-
- /* Place CPPI QMSS RX channel permissions array */
- #pragma DATA_SECTION (rmCppiQmssRxChPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiQmssRxChPerms, 128)
- Rm_Perms rmCppiQmssRxChPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_QMSS_RX_CH, Rm_Perms)];
-
- #ifdef QMSS_MAX_FFTC_C_QUEUE
- /* Place CPPI FFTC C RX channel permissions array */
- #pragma DATA_SECTION (rmCppiFftcCRxChPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiFftcCRxChPerms, 128)
- Rm_Perms rmCppiFftcCRxChPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_FFTC_C_RX_CH, Rm_Perms)];
- #endif
-
- #ifdef QMSS_MAX_BCP_QUEUE
- /* Place CPPI BCP RX channel permissions array */
- #pragma DATA_SECTION (rmCppiBcpRxChPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiBcpRxChPerms, 128)
- Rm_Perms rmCppiBcpRxChPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_BCP_RX_CH, Rm_Perms)];
- #endif
-
- /* Place CPPI SRIO flow permissions array */
- #pragma DATA_SECTION (rmCppiSrioFlowPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiSrioFlowPerms, 128)
- Rm_Perms rmCppiSrioFlowPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_SRIO_FLOW, Rm_Perms)];
-
- #ifdef QMSS_MAX_AIF_QUEUE
- /* Place CPPI AIF flow permissions array */
- #pragma DATA_SECTION (rmCppiAifFlowPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiAifFlowPerms, 128)
- Rm_Perms rmCppiAifFlowPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_AIF_FLOW, Rm_Perms)];
- #endif
-
- #ifdef QMSS_MAX_FFTC_A_QUEUE
- /* Place CPPI FFTC A flow permissions array */
- #pragma DATA_SECTION (rmCppiFftcAFlowPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiFftcAFlowPerms, 128)
- Rm_Perms rmCppiFftcAFlowPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_FFTC_A_FLOW, Rm_Perms)];
- #endif
-
- #ifdef QMSS_MAX_FFTC_B_QUEUE
- /* Place CPPI FFTC B flow permissions array */
- #pragma DATA_SECTION (rmCppiFftcBFlowPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiFftcBFlowPerms, 128)
- Rm_Perms rmCppiFftcBFlowPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_FFTC_B_FLOW, Rm_Perms)];
- #endif
-
- #ifdef QMSS_MAX_PASS_QUEUE
- /* Place CPPI PASS flow permissions array */
- #pragma DATA_SECTION (rmCppiPassFlowPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiPassFlowPerms, 128)
- Rm_Perms rmCppiPassFlowPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_PASS_FLOW, Rm_Perms)];
- #endif
-
- /* Place CPPI QMSS flow permissions array */
- #pragma DATA_SECTION (rmCppiQmssFlowPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiQmssFlowPerms, 128)
- Rm_Perms rmCppiQmssFlowPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_QMSS_FLOW, Rm_Perms)];
-
- #ifdef QMSS_MAX_FFTC_C_QUEUE
- /* Place CPPI FFTC C flow permissions array */
- #pragma DATA_SECTION (rmCppiFftcCFlowPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiFftcCFlowPerms, 128)
- Rm_Perms rmCppiFftcCFlowPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_FFTC_C_FLOW, Rm_Perms)];
- #endif
-
- #ifdef QMSS_MAX_BCP_QUEUE
- /* Place CPPI BCP flow permissions array */
- #pragma DATA_SECTION (rmCppiBcpFlowPerms, ".rm");
- #pragma DATA_ALIGN (rmCppiBcpFlowPerms, 128)
- Rm_Perms rmCppiBcpFlowPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_CPPI_BCP_FLOW, Rm_Perms)];
- #endif
-
- /* Place PA lookup table permissions array */
- #pragma DATA_SECTION (rmPaLutPerms, ".rm");
- #pragma DATA_ALIGN (rmPaLutPerms, 128)
- Rm_Perms rmPaLutPerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_PA_LUT, Rm_Perms)];
-
- /* Rm_init/Rm_start synchronization object. Initialized to 0. */
- #pragma DATA_SECTION (rmGSyncObj, ".rm");
- #pragma DATA_ALIGN (rmGSyncObj, 128)
- Rm_Sync_Obj rmGSyncObj =
++/** @brief Global Variable which describes the RM Version Information */
++const char rmVersionStr[] = RM_VERSION_STR ":" __DATE__ ":" __TIME__;
++
++/**********************************************************************
++ ************************ Local Functions *****************************
++ **********************************************************************/
++
++/* FUNCTION PURPOSE: Initializes a RM inst's transaction sequence number
++ ***********************************************************************
++ * DESCRIPTION: The RM instance transaction sequence number can never
++ * have a value of 0 to avoid conflicts with transactions
++ * that have a remoteOriginatingId of 0 (transaction ID
++ * will be used as the remoteOriginatingId for
++ * transactions that are responses to requests).
++ */
++static uint32_t transactionInitSequenceNum(void)
+{
- {
- RM_PERMISSION_TABLE_NOT_VALID,
++ return (1);
++}
++
++/* FUNCTION PURPOSE: Provides a sequence number for new transactions
++ ***********************************************************************
++ * DESCRIPTION: Returns a sequence number for a new transaction
++ * specific to a RM instance. Handles rollover of
++ * sequence number.
++ */
++static uint32_t transactionGetSequenceNum(Rm_Inst *rmInst)
++{
++ uint32_t sequenceNum = 0;
++
++ if (rmInst->transactionSeqNum + 1 < rmInst->transactionSeqNum) {
++ /* Rollover */
++ sequenceNum = rmInst->transactionSeqNum;
++ rmInst->transactionSeqNum = transactionInitSequenceNum();
+ }
- };
++ else {
++ sequenceNum = rmInst->transactionSeqNum++;
++ }
++ return (sequenceNum);
++}
+
- /* Create, populate, and place RM global permissions object */
- #pragma DATA_SECTION (rmGPermsObj, ".rm");
- #pragma DATA_ALIGN (rmGPermsObj, 128)
- Rm_GlobalPermissionsObj rmGPermsObj =
++/* FUNCTION PURPOSE: Creates a resource allocator
++ ***********************************************************************
++ * DESCRIPTION: Returns a newly Created and initialized resource
++ * The allocator is also stored in the RM instance
++ * allocator list.
++ */
++static Rm_Allocator *allocatorAdd(Rm_Inst *rmInst, const char *resourceName)
+{
- {
- /* qmssPdspFirmwarePerms */
- &rmQmssPdspFirmwarePerms[0],
- /* Pointer: qmssQueuePerms */
- &rmQmssQueuePerms[0],
- /* Pointer: qmssMemRegionPerms */
- &rmQmssMemRegionPerms[0],
- /* qmssLinkRamControlPerms */
- {
- 0u,
- 0u,
- },
- /* Pointer: qmssLinkRamPerms */
- &rmQmssLinkingRamPerms[0],
- /* Pointer: qmssAccumChPerms */
- &rmQmssAccumChPerms[0],
- /* qmssQosPdspTimerPerms */
- {
- 0u,
- 0u,
- },
- /* Pointer: qmssQosClusterPerms */
- &rmQmssQosClusterPerms[0],
- /* Pointer: qmssQosQueuePerms */
- &rmQmssQosQueuePerms[0],
- /* Pointer array: cppiTxChPerms - Must be in same order as DMA objects */
- {
- { &rmCppiSrioTxChPerms[0],
- #ifdef QMSS_MAX_AIF_QUEUE
- &rmCppiAifTxChPerms[0],
- #endif
- #ifdef QMSS_MAX_FFTC_A_QUEUE
- &rmCppiFftcATxChPerms[0],
- #endif
- #ifdef QMSS_MAX_FFTC_B_QUEUE
- &rmCppiFftcBTxChPerms[0],
- #endif
- #ifdef QMSS_MAX_PASS_QUEUE
- &rmCppiPassTxChPerms[0],
- #endif
- &rmCppiQmssTxChPerms[0],
- #ifdef QMSS_MAX_FFTC_C_QUEUE
- &rmCppiFftcCTxChPerms[0],
- #endif
- #ifdef QMSS_MAX_BCP_QUEUE
- &rmCppiBcpTxChPerms[0]
- #endif
- }
- },
- /* Pointer array: cppiRxChPerms - Must be in same order as DMA objects */
- {
- { &rmCppiSrioRxChPerms[0],
- #ifdef QMSS_MAX_AIF_QUEUE
- &rmCppiAifRxChPerms[0],
- #endif
- #ifdef QMSS_MAX_FFTC_A_QUEUE
- &rmCppiFftcARxChPerms[0],
- #endif
- #ifdef QMSS_MAX_FFTC_B_QUEUE
- &rmCppiFftcBRxChPerms[0],
- #endif
- #ifdef QMSS_MAX_PASS_QUEUE
- &rmCppiPassRxChPerms[0],
- #endif
- &rmCppiQmssRxChPerms[0],
- #ifdef QMSS_MAX_FFTC_C_QUEUE
- &rmCppiFftcCRxChPerms[0],
- #endif
- #ifdef QMSS_MAX_BCP_QUEUE
- &rmCppiBcpRxChPerms[0]
- #endif
- }
- },
- /* Pointer array: cppiFlowPerms - Must be in same order as DMA objects */
- {
- { &rmCppiSrioFlowPerms[0],
- #ifdef QMSS_MAX_AIF_QUEUE
- &rmCppiAifFlowPerms[0],
- #endif
- #ifdef QMSS_MAX_FFTC_A_QUEUE
- &rmCppiFftcAFlowPerms[0],
- #endif
- #ifdef QMSS_MAX_FFTC_B_QUEUE
- &rmCppiFftcBFlowPerms[0],
- #endif
- #ifdef QMSS_MAX_PASS_QUEUE
- &rmCppiPassFlowPerms[0],
- #endif
- &rmCppiQmssFlowPerms[0],
- #ifdef QMSS_MAX_FFTC_C_QUEUE
- &rmCppiFftcCFlowPerms[0],
- #endif
- #ifdef QMSS_MAX_BCP_QUEUE
- &rmCppiBcpFlowPerms[0]
- #endif
++ Rm_Allocator *allocators = rmInst->allocators;
++ Rm_Allocator *newAllocator = NULL;
++
++ newAllocator = Rm_osalMalloc(sizeof(Rm_Allocator));
++
++ if (newAllocator) {
++ memset((void *)newAllocator, 0, sizeof(Rm_Allocator));
++ strncpy(newAllocator->resourceName, resourceName, RM_NAME_MAX_CHARS);
++ newAllocator->allocatorRootEntry = NULL;
++ newAllocator->nextAllocator = NULL;
++
++ /* Add allocator to end of list */
++ if (allocators) {
++ while (allocators->nextAllocator) {
++ allocators = allocators->nextAllocator;
+ }
- },
- /* paFirmwarePerms */
- {
- 0u,
- 0u,
- },
- /* Pointer: paLutPerms */
- &rmPaLutPerms[0],
- }
- };
-
- /** @brief Global Variable (should be local per DSP) containing LLD RM permission checkers */
- Rm_LldPermCallouts rmPermissionCheckers =
++ allocators->nextAllocator = newAllocator;
++ }
++ else {
++ rmInst->allocators = newAllocator;
++ }
++ }
++ return (newAllocator);
++}
++
++/* FUNCTION PURPOSE: Deletes a resource allocator
++ ***********************************************************************
++ * DESCRIPTION: Deletes a resource allocator based on the given
++ * resource name. The resource allocator will be
++ * removed from the RM instance allocator list.
++ */
++static int32_t allocatorDelete(Rm_Inst *rmInst, char *resourceName)
+{
- Rm_initPermissionChecker,
- Rm_usePermissionChecker,
- };
++ Rm_Allocator *allocator = rmInst->allocators;
++ Rm_Allocator *prevAllocator = NULL;
++ int32_t retVal = RM_OK;
+
- /** @brief Global Variable which describes the RM LLD Version Information */
- const char rmLldVersionStr[] = RM_LLD_VERSION_STR ":" __DATE__ ":" __TIME__;
++ while (allocator) {
++ if (strncmp(allocator->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {
++ break;
++ }
++ prevAllocator = allocator;
++ allocator = allocator->nextAllocator;
++ }
+
- /**********************************************************************
- ********************** Internal Functions *********************************
- **********************************************************************/
++ if (allocator) {
++ if (prevAllocator == NULL) {
++ rmInst->allocators = allocator->nextAllocator;
++ }
++ else {
++ prevAllocator->nextAllocator = allocator->nextAllocator;
++ }
++ Rm_osalFree((void *)allocator, sizeof(Rm_Allocator));
++ }
++ else {
++ retVal = RM_ERROR_RES_ALLOCATOR_DOES_NOT_EXIST;
++ }
++ return (retVal);
++}
+
- /**
- * @b Description
- * @n
- * Initialize the permission tables. All resources are intialized to deny all initialization
- * and usage permissions.
- *
++/* FUNCTION PURPOSE: Adds an owner to an allocator resource
++ ***********************************************************************
++ * DESCRIPTION: Adds a RM instance node to a resource node's
++ * list of owners.
+ */
- void Rm_permissionTableInit(void)
++static void addOwner(Rm_ResourceNode *node, void *serviceInstNode)
+{
- uint16_t resourceIndex;
- Rm_Perms *resArrayPtr;
- uint16_t dmaNum;
- uint16_t dmaTxCh[RM_CPPI_MAX_DMAS] = {RM_CPPI_SRIO_TX_CH,
- #ifdef QMSS_MAX_AIF_QUEUE
- RM_CPPI_AIF_TX_CH,
- #endif
- #ifdef QMSS_MAX_FFTC_A_QUEUE
- RM_CPPI_FFTC_A_TX_CH,
- #endif
- #ifdef QMSS_MAX_FFTC_B_QUEUE
- RM_CPPI_FFTC_B_TX_CH,
- #endif
- #ifdef QMSS_MAX_PASS_QUEUE
- RM_CPPI_PASS_TX_CH,
- #endif
- RM_CPPI_QMSS_TX_CH,
- #ifdef QMSS_MAX_FFTC_C_QUEUE
- RM_CPPI_FFTC_C_TX_CH,
- #endif
- #ifdef QMSS_MAX_BCP_QUEUE
- RM_CPPI_BCP_TX_CH
- #endif
- };
- uint16_t dmaRxCh[RM_CPPI_MAX_DMAS] = {RM_CPPI_SRIO_RX_CH,
- #ifdef QMSS_MAX_AIF_QUEUE
- RM_CPPI_AIF_RX_CH,
- #endif
- #ifdef QMSS_MAX_FFTC_A_QUEUE
- RM_CPPI_FFTC_A_RX_CH,
- #endif
- #ifdef QMSS_MAX_FFTC_B_QUEUE
- RM_CPPI_FFTC_B_RX_CH,
- #endif
- #ifdef QMSS_MAX_PASS_QUEUE
- RM_CPPI_PASS_RX_CH,
- #endif
- RM_CPPI_QMSS_RX_CH,
- #ifdef QMSS_MAX_FFTC_C_QUEUE
- RM_CPPI_FFTC_C_RX_CH,
- #endif
- #ifdef QMSS_MAX_BCP_QUEUE
- RM_CPPI_BCP_RX_CH
- #endif
- };
- uint16_t dmaFlow[RM_CPPI_MAX_DMAS] = {RM_CPPI_SRIO_FLOW,
- #ifdef QMSS_MAX_AIF_QUEUE
- RM_CPPI_AIF_FLOW,
- #endif
- #ifdef QMSS_MAX_FFTC_A_QUEUE
- RM_CPPI_FFTC_A_FLOW,
- #endif
- #ifdef QMSS_MAX_FFTC_B_QUEUE
- RM_CPPI_FFTC_B_FLOW,
- #endif
- #ifdef QMSS_MAX_PASS_QUEUE
- RM_CPPI_PASS_FLOW,
- #endif
- RM_CPPI_QMSS_FLOW,
- #ifdef QMSS_MAX_FFTC_C_QUEUE
- RM_CPPI_FFTC_C_FLOW,
- #endif
- #ifdef QMSS_MAX_BCP_QUEUE
- RM_CPPI_BCP_FLOW
- #endif
- };
-
- /* QMSS Linking RAM Control */
- rmGPermsObj.obj.qmssLinkRamControlPerms.initPerms = 0;
- rmGPermsObj.obj.qmssLinkRamControlPerms.usePerms = 0;
-
- /* QMSS QOS PDSP Timer */
- rmGPermsObj.obj.qmssQosPdspTimerPerms.initPerms = 0;
- rmGPermsObj.obj.qmssQosPdspTimerPerms.usePerms = 0;
-
- /* PA Firmware */
- rmGPermsObj.obj.paFirmwarePerms.initPerms = 0;
- rmGPermsObj.obj.paFirmwarePerms.usePerms = 0;
-
- /* Writeback the values that were initialized in the global object itself */
- Rm_osalEndMemAccess ((void *) &rmGPermsObj, sizeof (Rm_GlobalPermissionsObj));
-
- /* QMSS PDSP Firmware */
- for (resourceIndex = 0; resourceIndex < RM_QMSS_FIRMWARE_PDSPS; resourceIndex++)
- {
- rmGPermsObj.obj.qmssPdspFirmwarePerms[resourceIndex].initPerms = 0;
- rmGPermsObj.obj.qmssPdspFirmwarePerms[resourceIndex].usePerms = 0;
++ Rm_Owner *ownerList = node->ownerList;
++ Rm_Owner *newOwner = NULL;
++
++ newOwner = Rm_osalMalloc(sizeof(Rm_Owner));
++
++ if (newOwner) {
++ newOwner->instNameNode = serviceInstNode;
++ newOwner->nextOwner = NULL;
++
++ /* Add owner entry to end of list */
++ if (ownerList) {
++ while (ownerList->nextOwner) {
++ ownerList = ownerList->nextOwner;
++ }
++ ownerList->nextOwner = newOwner;
++ }
++ else {
++ node->ownerList = newOwner;
++ }
++
++ node->allocationCount++;
++ newOwner->instNameNode->allocRefCount++;
+ }
- /* Writeback the qmssPdspFirmwarePerms array */
- Rm_osalEndMemAccess ((void *) rmGPermsObj.obj.qmssPdspFirmwarePerms, sizeof (Rm_Perms)*RM_QMSS_FIRMWARE_PDSPS);
++}
+
- /* QMSS queues */
- for (resourceIndex = 0; resourceIndex < RM_QMSS_QUEUES; resourceIndex++)
- {
- rmGPermsObj.obj.qmssQueuePerms[resourceIndex].initPerms = 0;
- rmGPermsObj.obj.qmssQueuePerms[resourceIndex].usePerms = 0;
++/* FUNCTION PURPOSE: Checks a resource node's ownership
++ ***********************************************************************
++ * DESCRIPTION: Returns TRUE if the provided instance node is
++ * in the list of resource node owners. Otherwise,
++ * returns FALSE.
++ */
++static bool isOwnedBy(Rm_ResourceNode *node, void *serviceInstNode)
++{
++ Rm_Owner *owner = node->ownerList;
++
++ while (owner) {
++ if (owner->instNameNode == serviceInstNode) {
++ return(true);
++ }
++ owner = owner->nextOwner;
+ }
- /* Writeback the qmssQueuePerms array */
- Rm_osalEndMemAccess ((void *) rmGPermsObj.obj.qmssQueuePerms, sizeof (Rm_Perms)*RM_QMSS_QUEUES);
++ return(false);
++}
+
- /* QMSS memory regions */
- for (resourceIndex = 0; resourceIndex < RM_QMSS_MEM_REGIONS; resourceIndex++)
- {
- rmGPermsObj.obj.qmssMemRegionPerms[resourceIndex].initPerms = 0;
- rmGPermsObj.obj.qmssMemRegionPerms[resourceIndex].usePerms = 0;
++/* FUNCTION PURPOSE: Compares two resource node's owners
++ ***********************************************************************
++ * DESCRIPTION: Returns TRUE if the owners of two resource nodes
++ * are equivalent. Otherwise, returns FALSE.
++ */
++static bool compareResourceNodeOwners(Rm_ResourceNode *node1, Rm_ResourceNode *node2)
++{
++ Rm_Owner *node1Owners = node1->ownerList;
++ Rm_Owner *node2Owners = node2->ownerList;
++ bool matchedInst;
++
++ if (node1->allocationCount == node2->allocationCount) {
++ while (node1Owners) {
++ matchedInst = false;
++ while (node2Owners) {
++ if (node1Owners->instNameNode == node2Owners->instNameNode) {
++ matchedInst = true;
++ break;
++ }
++ node2Owners = node2Owners->nextOwner;
++ }
++
++ if (matchedInst) {
++ node2Owners = node2->ownerList;
++ node1Owners = node1Owners->nextOwner;
++ }
++ else {
++ return(false);
++ }
++ }
+ }
- /* Writeback the qmssMemRegionPerms array */
- Rm_osalEndMemAccess ((void *) rmGPermsObj.obj.qmssMemRegionPerms, sizeof (Rm_Perms)*RM_QMSS_MEM_REGIONS);
++ else {
++ return(false);
++ }
++
++ return(true);
++}
+
- /* QMSS Linking RAM */
- for (resourceIndex = 0; resourceIndex < RM_QMSS_LINKING_RAM_RANGES; resourceIndex++)
- {
- rmGPermsObj.obj.qmssLinkRamPerms[resourceIndex].startIndex = RM_QMSS_LINKING_RAM_RANGE_INIT;
- rmGPermsObj.obj.qmssLinkRamPerms[resourceIndex].endIndex = RM_QMSS_LINKING_RAM_RANGE_INIT;
- rmGPermsObj.obj.qmssLinkRamPerms[resourceIndex].rangePerms.initPerms = 0;
- rmGPermsObj.obj.qmssLinkRamPerms[resourceIndex].rangePerms.usePerms = 0;
++/* FUNCTION PURPOSE: Deletes an owner from an allocator resource
++ ***********************************************************************
++ * DESCRIPTION: Removes a RM instance node from a resource node's
++ * list of owners.
++ */
++static void deleteOwner(Rm_ResourceNode *node, void *serviceInstNode)
++{
++ Rm_Owner *owner = node->ownerList;
++ Rm_Owner *prevOwner = NULL;
++
++ while (owner) {
++ if (owner->instNameNode == serviceInstNode) {
++ break;
++ }
++ prevOwner = owner;
++ owner = owner->nextOwner;
+ }
- /* Writeback the qmssLinkRamPerms array */
- Rm_osalEndMemAccess ((void *) rmGPermsObj.obj.qmssLinkRamPerms, sizeof (Rm_Perms)*RM_QMSS_LINKING_RAM_RANGES);
+
- /* QMSS accumulator channels */
- for (resourceIndex = 0; resourceIndex < RM_QMSS_ACCUM_CH; resourceIndex++)
- {
- rmGPermsObj.obj.qmssAccumChPerms[resourceIndex].initPerms = 0;
- rmGPermsObj.obj.qmssAccumChPerms[resourceIndex].usePerms = 0;
++ if (prevOwner == NULL) {
++ node->ownerList = owner->nextOwner;
+ }
- /* Writeback the qmssAccumChPerms array */
- Rm_osalEndMemAccess ((void *) rmGPermsObj.obj.qmssAccumChPerms, sizeof (Rm_Perms)*RM_QMSS_ACCUM_CH);
++ else {
++ prevOwner->nextOwner = owner->nextOwner;
++ }
++
++ node->allocationCount--;
++ owner->instNameNode->allocRefCount--;
++ Rm_osalFree((void *)owner, sizeof(Rm_Owner));
++}
+
- /* QMSS QOS Clusters */
- for (resourceIndex = 0; resourceIndex < RM_QMSS_QOS_CLUSTER; resourceIndex++)
- {
- rmGPermsObj.obj.qmssQosClusterPerms[resourceIndex].initPerms = 0;
- rmGPermsObj.obj.qmssQosClusterPerms[resourceIndex].usePerms = 0;
++/* FUNCTION PURPOSE: Copies the owners of a resource node
++ ***********************************************************************
++ * DESCRIPTION: Creates a list of resource owners for the destination
++ * resource node that is equivalent to the the
++ * source resource node's owners
++ */
++static void copyOwners(Rm_ResourceNode *dstNode, Rm_ResourceNode *srcNode)
++{
++ Rm_Owner *srcOwnerList = srcNode->ownerList;
++ Rm_Owner *dstNewOwner;
++ Rm_Owner *dstPrevOwner;
++
++ dstNode->allocationCount = srcNode->allocationCount;
++
++ while (srcOwnerList) {
++ dstNewOwner = Rm_osalMalloc(sizeof(Rm_Owner));
++ dstNewOwner->instNameNode = srcOwnerList->instNameNode;
++ dstNewOwner->nextOwner = NULL;
++
++ if (dstNode->ownerList == NULL) {
++ dstNode->ownerList = dstNewOwner;
++ }
++ else {
++ dstPrevOwner->nextOwner = dstNewOwner;
++ }
++ dstPrevOwner = dstNewOwner;
++ srcOwnerList = srcOwnerList->nextOwner;
+ }
- /* Writeback the qmssQosClusterPerms array */
- Rm_osalEndMemAccess ((void *) rmGPermsObj.obj.qmssQosClusterPerms, sizeof (Rm_Perms)*RM_QMSS_QOS_CLUSTER);
++}
+
- /* QMSS QOS Queues */
- for (resourceIndex = 0; resourceIndex < RM_QMSS_QOS_QUEUES; resourceIndex++)
- {
- rmGPermsObj.obj.qmssQosQueuePerms[resourceIndex].initPerms = 0;
- rmGPermsObj.obj.qmssQosQueuePerms[resourceIndex].usePerms = 0;
++/* FUNCTION PURPOSE: Clears a resource node's owners
++ ***********************************************************************
++ * DESCRIPTION: Deletes all owners from the owners list of a
++ * resource node.
++ */
++static void clearOwners(Rm_ResourceNode *node)
++{
++ Rm_Owner *owner = node->ownerList;
++ Rm_Owner *nextOwner;
++
++ while (owner) {
++ nextOwner = owner->nextOwner;
++ node->allocationCount--;
++ Rm_osalFree((void *)owner, sizeof(Rm_Owner));
++ owner = nextOwner;
+ }
- /* Writeback the qmssQosQueuePerms array */
- Rm_osalEndMemAccess ((void *) rmGPermsObj.obj.qmssQosQueuePerms, sizeof (Rm_Perms)*RM_QMSS_QOS_QUEUES);
++}
+
- /* CPPI DMA transmit channels */
- for (dmaNum = 0; dmaNum < RM_CPPI_MAX_DMAS; dmaNum++)
- {
- resArrayPtr = rmGPermsObj.obj.cppiTxChPerms.dmaPermPtrs[dmaNum];
-
- for (resourceIndex = 0; resourceIndex < dmaTxCh[dmaNum]; resourceIndex++)
- {
- resArrayPtr[resourceIndex].initPerms = 0;
- resArrayPtr[resourceIndex].usePerms = 0;
++/* FUNCTION PURPOSE: Creates a new resource tree
++ ***********************************************************************
++ * DESCRIPTION: Creates a new resource tree using the provided
++ * resource name and value range. The name and value
++ * typically originate from the GRL.
++ */
++static int32_t createResourceTree(Rm_Inst *rmInst, const char *resourceName, Rm_ResourceRange *range)
++{
++ Rm_Allocator *allocator = NULL;
++ Rm_ResourceTree *treeRootEntry = NULL;
++ Rm_ResourceNode *treeNode = NULL;
++ Rm_ResourceNode *collidingNode = NULL;
++
++ allocator = allocatorAdd(rmInst, resourceName);
++ treeRootEntry = Rm_osalMalloc(sizeof(Rm_ResourceTree));
++ RB_INIT(treeRootEntry);
++
++ while (range != NULL) {
++ treeNode = rmResourceNodeNew(range->base, range->length);
++ collidingNode = RB_INSERT(_Rm_AllocatorResourceTree, treeRootEntry, treeNode);
++
++ if (collidingNode) {
++ Rm_ResourceNode *nextNode = NULL;
++
++ /* Node that was inserted collides with existing node. Destroy tree and return error */
++ for (treeNode = RB_MIN(_Rm_AllocatorResourceTree, treeRootEntry); treeNode != NULL; treeNode = nextNode) {
++ nextNode = RB_NEXT(_Rm_AllocatorResourceTree, treeRootEntry, treeNode);
++ RB_REMOVE(_Rm_AllocatorResourceTree, treeRootEntry, nextNode);
++ rmResourceNodeFree(treeNode);
++ }
++ Rm_osalFree((void *)treeRootEntry, sizeof(Rm_ResourceTree));
++ allocatorDelete(rmInst, allocator->resourceName);
++ return (RM_ERROR_GRL_RES_SPECIFIED_MORE_THAN_ONCE);
+ }
++ range = range->nextRange;
++ }
++
++ allocator->allocatorRootEntry = treeRootEntry;
++ return(RM_OK);
++}
++
++/* FUNCTION PURPOSE: Preallocates a resource
++ ***********************************************************************
++ * DESCRIPTION: Called when an allocate request is made but the base
++ * is unspecified. The preallocation algorithm looks at
++ * available resources as well as policy permissions to
++ * determine a resource range that satisfies the request.
++ * If a valid range is found it will be returned for the
++ * treeAllocate algorithm to handle.
++ */
++static int32_t treePreAllocate(Rm_Inst *rmInst, Rm_Allocator *allocator, int32_t resourcePolicy,
++ Rm_AllocatorOpInfo *opInfo)
++{
++ Rm_ResourceNode findNode;
++ Rm_ResourceNode *matchingNode = NULL;
++ uint32_t matchingEnd;
++ uint32_t rangeIndex;
++ bool resourceFound = false;
++ Rm_PolicyCheckType policyCheckType;
++ Rm_PolicyCheckCfg policyCheckCfg;
++ bool nodePassesPolicy;
++ int32_t retVal = RM_SERVICE_PROCESSING;
++
++ opInfo->resourceInfo->base = rmPolicyGetResourceBase(rmInst->policy, opInfo->serviceSrcInstNode,
++ resourcePolicy, opInfo->allocType,
++ &retVal);
++ if (retVal != RM_SERVICE_PROCESSING) {
++ return (retVal);
++ }
+
- /* Writeback each of the transmit channel arrays */
- Rm_osalEndMemAccess ((void *) resArrayPtr, sizeof (Rm_Perms)*dmaTxCh[dmaNum]);
++ if (opInfo->resourceInfo->alignment == RM_RESOURCE_ALIGNMENT_UNSPECIFIED) {
++ /* Get alignment from policy */
++ opInfo->resourceInfo->alignment = rmPolicyGetResourceAlignment(rmInst->policy, resourcePolicy);
+ }
++
++ if (opInfo->resourceInfo->alignment == 0) {
++ opInfo->resourceInfo->alignment = 1;
++ }
+
- /* CPPI DMA receive channels */
- for (dmaNum = 0; dmaNum < RM_CPPI_MAX_DMAS; dmaNum++)
- {
- resArrayPtr = rmGPermsObj.obj.cppiRxChPerms.dmaPermPtrs[dmaNum];
++ memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));
++ findNode.base = opInfo->resourceInfo->base;
++ findNode.length = opInfo->resourceInfo->length;
++
++ /* Configure policy checking structure */
++ memset((void *)&policyCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));
++ if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_INIT_SHIFT)) {
++ policyCheckType = Rm_policyCheck_INIT;
++ }
++ else if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_USE_SHIFT)) {
++ policyCheckType = Rm_policyCheck_USE;
++ }
++ policyCheckCfg.policyDtb = rmInst->policy;
++ policyCheckCfg.resourceOffset = resourcePolicy;
++
++ do {
++ matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
+
- for (resourceIndex = 0; resourceIndex < dmaRxCh[dmaNum]; resourceIndex++)
- {
- resArrayPtr[resourceIndex].initPerms = 0;
- resArrayPtr[resourceIndex].usePerms = 0;
++ if (matchingNode) {
++ nodePassesPolicy = false;
++ policyCheckCfg.type = policyCheckType;
++ policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
++ policyCheckCfg.resourceBase = findNode.base;
++ policyCheckCfg.resourceLength = findNode.length;
++ nodePassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
++
++ if (nodePassesPolicy && (matchingNode->allocationCount > 0)) {
++ /* Check exclusive privileges of instance requesting resource. Requesting
++ * instance with exclusive privileges can't reserve resource if already owned*/
++ policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
++ policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
++ nodePassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
++ }
++
++ if (nodePassesPolicy && (matchingNode->allocationCount == 1)) {
++ /* Check exclusive privileges of instance that currently owns resource */
++ policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
++ policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;
++ nodePassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
++ }
++
++ if (retVal != RM_SERVICE_PROCESSING) {
++ break;
++ }
++
++ if (nodePassesPolicy) {
++ matchingEnd = matchingNode->base + matchingNode->length - 1;
++ /* Initialize indexer to be first resource value that alignment */
++ rangeIndex = findNode.base;
++ if (rangeIndex % opInfo->resourceInfo->alignment) {
++ rangeIndex += (opInfo->resourceInfo->alignment -
++ (rangeIndex % opInfo->resourceInfo->alignment));
++ }
++
++ if ((rangeIndex + opInfo->resourceInfo->length - 1) <= matchingEnd) {
++ /* Block of unallocated resources within matchingNode that satisfies
++ * allocate requirements */
++ opInfo->resourceInfo->base = rangeIndex;
++ resourceFound = true;
++ }
++ }
++
++ if (!resourceFound) {
++ /* Check next resource node for available resources */
++ findNode.base = matchingNode->base + matchingNode->length;
++ }
+ }
++ else {
++ retVal = RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET;
++ }
++ } while ((!resourceFound) &&
++ (retVal != RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET));
+
- /* Writeback each of the receive channel arrays */
- Rm_osalEndMemAccess ((void *) resArrayPtr, sizeof (Rm_Perms)*dmaRxCh[dmaNum]);
- }
++ return(retVal);
++}
+
- /* CPPI DMA flows */
- for (dmaNum = 0; dmaNum < RM_CPPI_MAX_DMAS; dmaNum++)
- {
- resArrayPtr = rmGPermsObj.obj.cppiFlowPerms.dmaPermPtrs[dmaNum];
++/* FUNCTION PURPOSE: Allocates a resource
++ ***********************************************************************
++ * DESCRIPTION: Will attempt to allocate the resource with specified
++ * base and length from the resource's allocator. The
++ * allocation algorithm will verify the allocation against
++ * the policy permissions for the instance requesting the
++ * allocation. If the policy allows the allocation the
++ * algorithm will allocate the resource then combine any
++ * resource nodes that may have become equivalent (in terms
++ * of ownership) after the allocation.
++ */
++static int32_t treeAllocate(Rm_Inst *rmInst, Rm_Allocator *allocator, int32_t resourcePolicy,
++ Rm_AllocatorOpInfo *opInfo)
++{
++ Rm_ResourceNode findNode;
++ Rm_ResourceNode *matchingNode = NULL;
++ Rm_ResourceNode *leftNode = NULL;
++ Rm_ResourceNode *rightNode = NULL;
++ Rm_PolicyCheckType policyCheckType;
++ Rm_PolicyCheckCfg policyCheckCfg;
++ bool allocPassesPolicy;
++ bool combineLeft = false;
++ bool combineRight = false;
++ uint32_t findEnd;
++ uint32_t matchingEnd;
++ int32_t retVal = RM_SERVICE_PROCESSING;
++
++ memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));
++ findNode.base = opInfo->resourceInfo->base;
++ findNode.length = opInfo->resourceInfo->length;
++ matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
++
++ /* Prepare privilege checks */
++ memset((void *)&policyCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));
++ if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_INIT_SHIFT)) {
++ policyCheckType = Rm_policyCheck_INIT;
++ }
++ else if (RM_policy_GET_PERM(opInfo->allocType, RM_POLICY_PERM_USE_SHIFT)) {
++ policyCheckType = Rm_policyCheck_USE;
++ }
++
++ if (matchingNode) {
++ findEnd = findNode.base + findNode.length - 1;
++ matchingEnd = matchingNode->base + matchingNode->length - 1;
+
- for (resourceIndex = 0; resourceIndex < dmaFlow[dmaNum]; resourceIndex++)
- {
- resArrayPtr[resourceIndex].initPerms = 0;
- resArrayPtr[resourceIndex].usePerms = 0;
++ if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {
++ if (opInfo->serviceSrcInstNode == rmPolicyGetLinuxInstNode(rmInst->validInstances)) {
++ /* Bypass policy checks since Linux Kernel has full privileges */
++ allocPassesPolicy = true;
++ }
++ else {
++ policyCheckCfg.policyDtb = rmInst->policy;
++ policyCheckCfg.resourceOffset = resourcePolicy;
++ policyCheckCfg.type = policyCheckType;
++ policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
++ policyCheckCfg.resourceBase = findNode.base;
++ policyCheckCfg.resourceLength = findNode.length;
++ allocPassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
++ if (!allocPassesPolicy) {
++ if (policyCheckType == Rm_policyCheck_INIT) {
++ retVal = RM_SERVICE_DENIED_INIT_PERM_NOT_GIVEN;
++ }
++ else {
++ retVal = RM_SERVICE_DENIED_USE_PERM_NOT_GIVEN;
++ }
++ }
++
++ if (!isOwnedBy(matchingNode, opInfo->serviceSrcInstNode)) {
++ /* Perform exclusive checks if requesting instance does not already an
++ * owner of the resource */
++ if (allocPassesPolicy && (matchingNode->allocationCount > 0)) {
++ /* Check exclusive privileges of instance requesting resource. Requesting
++ * instance with exclusive privileges can't reserve resource if already owned*/
++ policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
++ policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
++ allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
++ if (!allocPassesPolicy) {
++ retVal = RM_SERVICE_DENIED_EXCLUSIVE_RES_ALLOCD;
++ }
++ }
++ if (allocPassesPolicy && (matchingNode->allocationCount == 1)) {
++ /* Check exclusive privileges of instance that currently owns resource */
++ policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
++ policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;
++ allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
++ if (!allocPassesPolicy) {
++ retVal = RM_SERVICE_DENIED_ALLOCD_TO_EXCLUSIVE_INST;
++ }
++ }
++ }
++ }
++
++ if (allocPassesPolicy) {
++ if (!isOwnedBy(matchingNode, opInfo->serviceSrcInstNode)) {
++ /* Handle any possible node combinations if requesting instance is
++ * not already in resource's owner list. Automatic approval if requesting
++ * instance is already in owner list. */
++ if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd)) {
++ /* findNode range matches matchingNode range
++ *
++ * |<--left node-->||<--matched node-->||<--right node-->| => existing node
++ * |<--alloc request-->| => requested resources
++ */
++ leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ addOwner(matchingNode, opInfo->serviceSrcInstNode);
++
++ if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {
++ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
++ combineLeft = true;
++ }
++ if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {
++ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
++ combineRight = true;
++ }
++
++ if (combineLeft && combineRight) {
++ /* Combine all three nodes into matchingNode */
++ matchingNode->base = leftNode->base;
++ matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;
++
++ clearOwners(leftNode);
++ rmResourceNodeFree(leftNode);
++ clearOwners(rightNode);
++ rmResourceNodeFree(rightNode);
++ }
++ else if (combineLeft) {
++ /* Combine left and matching nodes. Reinsert right. */
++ matchingNode->base = leftNode->base;
++ matchingNode->length += leftNode->length;
++
++ clearOwners(leftNode);
++ rmResourceNodeFree(leftNode);
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
++ }
++ else if (combineRight) {
++ /* Combine right and matching nodes. Reinsert left. */
++ matchingNode->length += rightNode->length;
++
++ clearOwners(rightNode);
++ rmResourceNodeFree(rightNode);
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
++ }
++ else {
++ /* No combine. */
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
++ }
++
++ /* Always reinsert matchingNode */
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ }
++ else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {
++ /* findNode range is subset of matchingNode range and neither boundary is
++ * equivalent.
++ *
++ * |<----------matched node---------->|
++ * |<---alloc request--->|
++ */
++ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);
++ copyOwners(leftNode, matchingNode);
++ rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);
++ copyOwners(rightNode, matchingNode);
++
++ matchingNode->base = findNode.base;
++ matchingNode->length = findNode.length;
++ addOwner(matchingNode, opInfo->serviceSrcInstNode);
++
++ /* Insert all the nodes */
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
++ }
++ else {
++ if (findNode.base == matchingNode->base) {
++ /* findNode base and matchingNode base are equivalent. May be combine
++ * possibilities to the left
++ *
++ * |<---left node (alloc'd)--->||<----------matched node---------->|
++ * |<---findNode (alloc req)--->|
++ */
++ leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ /* Add allocating instance to owner list for compare with leftNode */
++ addOwner(matchingNode, opInfo->serviceSrcInstNode);
++
++ if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {
++ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
++ /* Combine leftNode and findNode */
++ leftNode->length += findNode.length;
++ }
++ else {
++ leftNode = rmResourceNodeNew(findNode.base, findNode.length);
++ copyOwners(leftNode, matchingNode);
++ }
++
++ /* Account for leftNode in matchingNode */
++ matchingNode->base = findNode.base + findNode.length;
++ matchingNode->length = matchingEnd - findEnd;
++
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
++ }
++ else if (findEnd == matchingEnd) {
++ /* findNode end and matchingNode end are equivalent. May be combine
++ * possibilities to the right
++ *
++ * |<----------matched node---------->||<---right node (alloc'd)--->|
++ * |<---findNode (alloc req)--->|
++ */
++ rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ /* Add allocating instance to owner list for compare with rightNode */
++ addOwner(matchingNode, opInfo->serviceSrcInstNode);
++
++ if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {
++ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
++ /* Combine rightNode and findNode */
++ rightNode->base = findNode.base;
++ rightNode->length += findNode.length;
++ }
++ else {
++ rightNode = rmResourceNodeNew(findNode.base, findNode.length);
++ copyOwners(rightNode, matchingNode);
++ }
++
++ /* Account for rightNode in matchingNode */
++ matchingNode->length -= findNode.length;
++
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
++ }
++ /* Remove allocating instance from leftover matchingNode */
++ deleteOwner(matchingNode, opInfo->serviceSrcInstNode);
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ }
++ }
++ retVal = RM_SERVICE_APPROVED;
++ }
+ }
++ else {
++ retVal = RM_SERVICE_DENIED_PARTIAL_ALLOCATION;
++ }
++ }
++ else {
++ retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;
++ }
+
- /* Writeback each of the flow arrays */
- Rm_osalEndMemAccess ((void *) resArrayPtr, sizeof (Rm_Perms)*dmaFlow[dmaNum]);
- }
++ return(retVal);
++}
+
- /* PA Lookup tables */
- for (resourceIndex = 0; resourceIndex < RM_PA_LUT; resourceIndex++)
- {
- rmGPermsObj.obj.paLutPerms[resourceIndex].initPerms = 0;
- rmGPermsObj.obj.paLutPerms[resourceIndex].usePerms = 0;
++/* FUNCTION PURPOSE: Frees a resource
++ ***********************************************************************
++ * DESCRIPTION: Will attempt to free the resource with specified
++ * base and length from the resource's allocator. The
++ * free algorithm will verify the free request parameters
++ * match an allocated range for the resource and that the
++ * range is owned by the instance requesting the free. If
++ * the free is validated the algorithm will free the
++ * resource then combine any resource nodes that may have
++ * become equivalent (in terms of ownership) after the
++ * allocation.
++ */
++static int32_t treeFree(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)
++{
++ Rm_ResourceNode findNode;
++ Rm_ResourceNode *matchingNode = NULL;
++ Rm_ResourceNode *leftNode = NULL;
++ Rm_ResourceNode *rightNode = NULL;
++ bool combineLeft = false;
++ bool combineRight = false;
++ uint32_t findEnd;
++ uint32_t matchingEnd;
++ int32_t retVal;
++
++ memset((void *)&findNode, 0, sizeof(Rm_ResourceNode));
++ findNode.base = opInfo->resourceInfo->base;
++ findNode.length = opInfo->resourceInfo->length;
++ matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
++
++ if (matchingNode) {
++ findEnd = findNode.base + findNode.length - 1;
++ matchingEnd = matchingNode->base + matchingNode->length - 1;
++
++ if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {
++ if (matchingNode->allocationCount) {
++ if (isOwnedBy(matchingNode, opInfo->serviceSrcInstNode)) {
++ if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))
++ {
++ /* Case 1: Free range equals allocated matched node exactly. Attempt to combine
++ * freed node with nodes to left and right.
++ *
++ * |<--left node-->||<---matched node--->||<--right node-->|
++ * |<---free request--->|
++ */
++ leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ deleteOwner(matchingNode, opInfo->serviceSrcInstNode);
++
++ if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {
++ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
++ combineLeft = true;
++ }
++ if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {
++ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
++ combineRight = true;
++ }
++
++ if (combineLeft && combineRight) {
++ /* Combine all three nodes into matchingNode */
++ matchingNode->base = leftNode->base;
++ matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;
++
++ clearOwners(leftNode);
++ rmResourceNodeFree(leftNode);
++ clearOwners(rightNode);
++ rmResourceNodeFree(rightNode);
++ }
++ else if (combineLeft) {
++ /* Combine left and matching nodes. Reinsert right. */
++ matchingNode->base = leftNode->base;
++ matchingNode->length += leftNode->length;
++
++ clearOwners(leftNode);
++ rmResourceNodeFree(leftNode);
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
++ }
++ else if (combineRight) {
++ /* Combine right and matching nodes. Reinsert left. */
++ matchingNode->length += rightNode->length;
++
++ clearOwners(rightNode);
++ rmResourceNodeFree(rightNode);
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
++ }
++ else {
++ /* No combine. */
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
++ }
++
++ /* Always reinsert matchingNode */
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ }
++ else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {
++ /* Case 2: Free range is less than range in matched node. Split
++ * matched node into three nodes.
++ *
++ * |<----------matched node---------->|
++ * |<---free request--->|
++ *
++ * Remove instance from AllocatedTo list then add it back in for side nodes for
++ * proper accounting of allocations in validInstance list
++ */
++ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ deleteOwner(matchingNode, opInfo->serviceSrcInstNode);
++
++ leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);
++ copyOwners(leftNode, matchingNode);
++ addOwner(leftNode, opInfo->serviceSrcInstNode);
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
++
++ rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);
++ copyOwners(rightNode, matchingNode);
++ addOwner(rightNode, opInfo->serviceSrcInstNode);
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
++
++ matchingNode->base = findNode.base;
++ matchingNode->length = findNode.length;
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ }
++ else {
++ if (findNode.base == matchingNode->base) {
++ /* Case 3: Free range is on left boundary of matched node. Try to
++ * combine free range with left node.
++ *
++ * |<---left node (free)--->||<----------matched node---------->|
++ * |<---findNode (free req)--->|
++ */
++
++ leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ /* Remove freeing instance from owner list for compare with leftNode */
++ deleteOwner(matchingNode, opInfo->serviceSrcInstNode);
++
++ if (leftNode && compareResourceNodeOwners(leftNode, matchingNode)) {
++ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
++ /* Combine leftNode and findNode */
++ leftNode->length += findNode.length;
++ }
++ else {
++ leftNode = rmResourceNodeNew(findNode.base, findNode.length);
++ copyOwners(leftNode, matchingNode);
++ }
++
++ /* Remove leftNode range from matchingNode */
++ matchingNode->base = findNode.base + findNode.length;
++ matchingNode->length = matchingEnd - findEnd;
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
++ }
++ else if (findEnd == matchingEnd) {
++ /* Case 4: Free range is on right boundary of matched node. Try to
++ * combine free range with right node.
++ *
++ * |<----------matched node---------->||<---right node (free)--->|
++ * |<---findNode (free req)--->|
++ */
++
++ rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ /* Remove freeing instance from owner list for compare with rightNode */
++ deleteOwner(matchingNode, opInfo->serviceSrcInstNode);
++
++ if (rightNode && compareResourceNodeOwners(rightNode, matchingNode)) {
++ RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
++ /* Combine rightNode and findNode */
++ rightNode->base = findNode.base;
++ rightNode->length += findNode.length;
++ }
++ else {
++ rightNode = rmResourceNodeNew(findNode.base, findNode.length);
++ copyOwners(rightNode, matchingNode);
++ }
++
++ /* Remove rightNode range from matchingNode */
++ matchingNode->length -= findNode.length;
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
++ }
++
++ /* Add freeing instance back into matchingNode allocations */
++ addOwner(matchingNode, opInfo->serviceSrcInstNode);
++ RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
++ }
++
++ retVal = RM_SERVICE_APPROVED;
++ }
++ else {
++ retVal = RM_SERVICE_DENIED_RES_NOT_ALLOCD_TO_INST;
++ }
++ }
++ else {
++ retVal = RM_SERVICE_DENIED_RES_ALREADY_FREE;
++ }
++ }
++ else {
++ retVal = RM_SERVICE_DENIED_PARTIAL_FREE;
++ }
+ }
- /* Writeback the paLutPerms array */
- Rm_osalEndMemAccess ((void *) rmGPermsObj.obj.paLutPerms, sizeof (Rm_Perms)*RM_PA_LUT);
-
++ else {
++ retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;
++ }
++ return(retVal);
+}
+
- /**
- * @b Description
- * @n
- * Sets a list of entries in a permissions array to the specified permissions
- *
- * @param[in] resourceEntry
- * The resource entry from the application defined resource table containing
- * a range of resources and the permissions to assign to them.
- *
- * @param[in] rmPermsArray
- * The permissions array for the resource specified in the resourceEntry.
- *
- * @param[in] len
- * Full length of permissions array for writeback after the permissions have been
- * transferred.
++/* FUNCTION PURPOSE: Issues a service response to application
++ ***********************************************************************
++ * DESCRIPTION: Provides a service response back to the application
++ * using the service callback function provided to
++ * the RM instance at the time of the service request.
+ */
- void Rm_setTablePermissions (const Rm_Resource *resourceEntry, Rm_Perms *rmPermsArray, uint32_t len)
++static void serviceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
+{
- uint32_t index;
-
- /* Scan through the resource range filling in the specified permission */
- for (index = resourceEntry->resourceStart; index < resourceEntry->resourceEnd + 1; index++)
++ Rm_ServiceRespInfo serviceResponse;
++
++ /* The responseTransaction will contain the resultant state details of
++ * the requestTransaction's service request */
++ serviceResponse.serviceState = transaction->state;
++ /* Pass back the ID that was provided to the component when it requested
++ * the service */
++ serviceResponse.serviceId = transaction->localId;
++
++ /* Service was approved and service was an allocate request. The resource
++ * data is passed back to the component */
++ if ((serviceResponse.serviceState == RM_SERVICE_APPROVED) &&
++ ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
++ (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
++ (transaction->type == Rm_service_RESOURCE_GET_BY_NAME)))
+ {
- rmPermsArray[index].initPerms = resourceEntry->resourceInitFlags;
- rmPermsArray[index].usePerms = resourceEntry->resourceUseFlags;
++ strncpy(serviceResponse.resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
++ serviceResponse.resourceBase = transaction->resourceInfo.base;
++ serviceResponse.resourceLength = transaction->resourceInfo.length;
+ }
+
- Rm_osalEndMemAccess ((void *)rmPermsArray, sizeof (Rm_Perms)* len);
++ /* Issue the callback to the requesting component with the response information */
++ transaction->callback.serviceCallback(&serviceResponse);
++
++ /* Delete the transaction from the transaction queue */
++ rmTransactionQueueDelete(rmInst, transaction->localId);
++ return;
+}
+
- /**
- * @b Description
- * @n
- * Takes an application specified resource table as input and transfers all
- * resource permissions specified within into the internal resource
- * permission tables. Upon completion of permission transfer a global
- * synchronization object is written to sync with slave cores.
- *
- * @param[in] rmResourceTable
- * Application defined resource table containing all resources that should
- * have permissions set for the DSPs
- *
- * @retval
- * Success - RM_OK
- * @retval
- * Failure - RM_ERROR_PERMISSION_TABLE_POPULATION_FAILED
++/* FUNCTION PURPOSE: Sends RM response packets
++ ***********************************************************************
++ * DESCRIPTION: Sends RM response packets to RM instance's that sent
++ * RM request packets to the RM instance. The response
++ * is sent via the RM transport API which is plugged
++ * with an application created transport path.
+ */
- Rm_Result Rm_populatePermissionTable(const Rm_Resource *rmResourceTable)
++static void transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
+{
- const Rm_Resource *resourceEntry;
- uint16_t linkRamIndex;
++ Rm_Transport *dstTransport = NULL;
++ Rm_PacketHandle pktHandle = NULL;
++
++ dstTransport = rmTransportFindRemoteName((Rm_Transport *) rmInst->transports, transaction->pktSrcInstName);
++
++ switch (transaction->type) {
++ case Rm_service_RESOURCE_ALLOCATE_INIT:
++ case Rm_service_RESOURCE_ALLOCATE_USE:
++ case Rm_service_RESOURCE_FREE:
++ case Rm_service_RESOURCE_GET_BY_NAME:
++ pktHandle = rmTransportCreateResourceResponsePkt(rmInst, dstTransport->appTransportHandle,
++ transaction);
++ break;
++ case Rm_service_RESOURCE_MAP_TO_NAME:
++ case Rm_service_RESOURCE_UNMAP_NAME:
++ pktHandle = rmTransportCreateNsResponsePkt(rmInst, dstTransport->appTransportHandle,
++ transaction);
++ break;
++ }
+
- /* Verify resource table can be read by verifying magic number is contained
- * in first entry of the resource table */
- resourceEntry = rmResourceTable;
-
- /* Invalidate the resource */
- Rm_osalBeginMemAccess ((void *) resourceEntry, sizeof (Rm_Resource));
- if (resourceEntry->resourceId != RM_RESOURCE_MAGIC_NUMBER)
- {
- return RM_ERROR_PERMISSION_TABLE_POPULATION_FAILED;
++ if (pktHandle) {
++ if (rmInst->transportCallouts.rmSendPkt) {
++ if (rmInst->transportCallouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {
++ transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
++ }
++ }
++ else {
++ transaction->state = RM_ERROR_TRANSPORT_SEND_NOT_REGD;
++ }
+ }
++ rmTransactionQueueDelete(rmInst, transaction->localId);
++}
+
- /* Magic number is visible start parsing the resource table and transferring
- * permissions to the internal permissions tables */
++/* FUNCTION PURPOSE: Sends RM request packets
++ ***********************************************************************
++ * DESCRIPTION: Sends RM request packets to RM instance's that are
++ * capable of forwarding or validating service requests.
++ * The request is sent via the RM transport API which is
++ * plugged with an application created transport path.
++ */
++static void transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)
++{
++ Rm_Transport *dstTransport = NULL;
++ Rm_PacketHandle pktHandle = NULL;
+
- /* Parse resource table until last entry field is encountered */
- while (resourceEntry->resourceId != RM_RESOURCE_FINAL_ENTRY)
- {
- /* Invalidate the resource */
- Rm_osalBeginMemAccess ((void *) resourceEntry, sizeof (Rm_Resource));
-
- /* Populate a permission table based on the resourceId */
- switch (resourceEntry->resourceId)
- {
- case RM_RESOURCE_MAGIC_NUMBER:
- break;
-
- case RM_RESOURCE_QMSS_FIRMWARE_PDSP:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_QMSS_FIRMWARE_PDSPS, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.qmssPdspFirmwarePerms, RM_QMSS_FIRMWARE_PDSPS);
- break;
-
- case RM_RESOURCE_QMSS_QUEUE:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_QMSS_QUEUES, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.qmssQueuePerms, RM_QMSS_QUEUES);
- break;
-
- case RM_RESOURCE_QMSS_MEMORY_REGION:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_QMSS_MEM_REGIONS, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.qmssMemRegionPerms, RM_QMSS_MEM_REGIONS);
- break;
-
- case RM_RESOURCE_QMSS_LINKING_RAM_CONTROL:
- rmGPermsObj.obj.qmssLinkRamControlPerms.initPerms = resourceEntry->resourceInitFlags;
- rmGPermsObj.obj.qmssLinkRamControlPerms.usePerms = resourceEntry->resourceUseFlags;
- break;
-
- case RM_RESOURCE_QMSS_LINKING_RAM:
- /* Expect Linking RAM ranges to be presented in order */
-
- /* Find next available unused Linking RAM permissions entry */
- for (linkRamIndex = 0; linkRamIndex < RM_QMSS_LINKING_RAM_RANGES; linkRamIndex++)
- {
- if ((rmGPermsObj.obj.qmssLinkRamPerms[linkRamIndex].startIndex == RM_QMSS_LINKING_RAM_RANGE_INIT) &&
- (rmGPermsObj.obj.qmssLinkRamPerms[linkRamIndex].endIndex == RM_QMSS_LINKING_RAM_RANGE_INIT))
- {
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_QMSS_LINKING_RAM_RANGE_INIT,
- RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- /* Populate the entry with the Linking RAM resource data */
- rmGPermsObj.obj.qmssLinkRamPerms[linkRamIndex].startIndex = resourceEntry->resourceStart;
- rmGPermsObj.obj.qmssLinkRamPerms[linkRamIndex].endIndex = resourceEntry->resourceEnd;
- rmGPermsObj.obj.qmssLinkRamPerms[linkRamIndex].rangePerms.initPerms = resourceEntry->resourceInitFlags;
- rmGPermsObj.obj.qmssLinkRamPerms[linkRamIndex].rangePerms.usePerms = resourceEntry->resourceUseFlags;
-
- Rm_osalEndMemAccess ((void *)&rmGPermsObj.obj.qmssLinkRamPerms[0], sizeof (Rm_Perms)* RM_QMSS_LINKING_RAM_RANGES);
-
- /* Leave search loop */
- break;
- }
- }
- break;
-
- case RM_RESOURCE_QMSS_ACCUMULATOR_CH:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_QMSS_ACCUM_CH, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.qmssAccumChPerms, RM_QMSS_ACCUM_CH);
- break;
-
- case RM_RESOURCE_QMSS_QOS_PDSP_TIMER:
- rmGPermsObj.obj.qmssQosPdspTimerPerms.initPerms = resourceEntry->resourceInitFlags;
- rmGPermsObj.obj.qmssQosPdspTimerPerms.usePerms = resourceEntry->resourceUseFlags;
- break;
-
- case RM_RESOURCE_QMSS_QOS_CLUSTER:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_QMSS_QOS_CLUSTER, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.qmssQosClusterPerms, RM_QMSS_QOS_CLUSTER);
- break;
-
- case RM_RESOURCE_QMSS_QOS_QUEUE:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_QMSS_QOS_QUEUES, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.qmssQosQueuePerms, RM_QMSS_QOS_QUEUES);
- break;
-
- case RM_RESOURCE_CPPI_SRIO_TX_CH:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_SRIO_TX_CH, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiTxChPerms.dmaPermPtrs[RM_CPPI_SRIO_DMA_ID], RM_CPPI_SRIO_TX_CH);
- break;
-
- case RM_RESOURCE_CPPI_SRIO_RX_CH:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_SRIO_RX_CH, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiRxChPerms.dmaPermPtrs[RM_CPPI_SRIO_DMA_ID], RM_CPPI_SRIO_RX_CH);
- break;
-
- case RM_RESOURCE_CPPI_SRIO_FLOW:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_SRIO_FLOW, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiFlowPerms.dmaPermPtrs[RM_CPPI_SRIO_DMA_ID], RM_CPPI_SRIO_FLOW);
- break;
-
- #ifdef QMSS_MAX_AIF_QUEUE
- case RM_RESOURCE_CPPI_AIF_TX_CH:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_AIF_TX_CH, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiTxChPerms.dmaPermPtrs[RM_CPPI_AIF_DMA_ID], RM_CPPI_AIF_TX_CH);
- break;
-
- case RM_RESOURCE_CPPI_AIF_RX_CH:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_AIF_RX_CH, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiRxChPerms.dmaPermPtrs[RM_CPPI_AIF_DMA_ID], RM_CPPI_AIF_RX_CH);
- break;
-
- case RM_RESOURCE_CPPI_AIF_FLOW:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_AIF_FLOW, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiFlowPerms.dmaPermPtrs[RM_CPPI_AIF_DMA_ID], RM_CPPI_AIF_FLOW);
- break;
- #endif
-
- #ifdef QMSS_MAX_FFTC_A_QUEUE
- case RM_RESOURCE_CPPI_FFTC_A_TX_CH:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_FFTC_A_TX_CH, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiTxChPerms.dmaPermPtrs[RM_CPPI_FFTC_A_DMA_ID], RM_CPPI_FFTC_A_TX_CH);
- break;
-
- case RM_RESOURCE_CPPI_FFTC_A_RX_CH:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_FFTC_A_RX_CH, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiRxChPerms.dmaPermPtrs[RM_CPPI_FFTC_A_DMA_ID], RM_CPPI_FFTC_A_RX_CH);
- break;
-
- case RM_RESOURCE_CPPI_FFTC_A_FLOW:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_FFTC_A_FLOW, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiFlowPerms.dmaPermPtrs[RM_CPPI_FFTC_A_DMA_ID], RM_CPPI_FFTC_A_FLOW);
- break;
- #endif
-
- #ifdef QMSS_MAX_FFTC_B_QUEUE
- case RM_RESOURCE_CPPI_FFTC_B_TX_CH:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_FFTC_B_TX_CH, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiTxChPerms.dmaPermPtrs[RM_CPPI_FFTC_B_DMA_ID], RM_CPPI_FFTC_B_TX_CH);
- break;
-
- case RM_RESOURCE_CPPI_FFTC_B_RX_CH:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_FFTC_B_RX_CH, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiRxChPerms.dmaPermPtrs[RM_CPPI_FFTC_B_DMA_ID], RM_CPPI_FFTC_B_RX_CH);
- break;
-
- case RM_RESOURCE_CPPI_FFTC_B_FLOW:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_FFTC_B_FLOW, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiFlowPerms.dmaPermPtrs[RM_CPPI_FFTC_B_DMA_ID], RM_CPPI_FFTC_B_FLOW);
- break;
- #endif
-
- #ifdef QMSS_MAX_PASS_QUEUE
- case RM_RESOURCE_CPPI_PASS_TX_CH:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_PASS_TX_CH, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiTxChPerms.dmaPermPtrs[RM_CPPI_PASS_DMA_ID], RM_CPPI_PASS_TX_CH);
- break;
-
- case RM_RESOURCE_CPPI_PASS_RX_CH:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_PASS_RX_CH, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiRxChPerms.dmaPermPtrs[RM_CPPI_PASS_DMA_ID], RM_CPPI_PASS_RX_CH);
- break;
-
- case RM_RESOURCE_CPPI_PASS_FLOW:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_PASS_FLOW, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiFlowPerms.dmaPermPtrs[RM_CPPI_PASS_DMA_ID], RM_CPPI_PASS_FLOW);
- break;
- #endif
-
- case RM_RESOURCE_CPPI_QMSS_TX_CH:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_QMSS_TX_CH, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiTxChPerms.dmaPermPtrs[RM_CPPI_QMSS_DMA_ID], RM_CPPI_QMSS_TX_CH);
- break;
-
- case RM_RESOURCE_CPPI_QMSS_RX_CH:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_QMSS_RX_CH, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiRxChPerms.dmaPermPtrs[RM_CPPI_QMSS_DMA_ID], RM_CPPI_QMSS_RX_CH);
- break;
-
- case RM_RESOURCE_CPPI_QMSS_FLOW:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_QMSS_FLOW, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiFlowPerms.dmaPermPtrs[RM_CPPI_QMSS_DMA_ID], RM_CPPI_QMSS_FLOW);
- break;
-
- #ifdef QMSS_MAX_FFTC_C_QUEUE
- case RM_RESOURCE_CPPI_FFTC_C_TX_CH:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_FFTC_C_TX_CH, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiTxChPerms.dmaPermPtrs[RM_CPPI_FFTC_C_DMA_ID], RM_CPPI_FFTC_C_TX_CH);
- break;
-
- case RM_RESOURCE_CPPI_FFTC_C_RX_CH:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_FFTC_C_RX_CH, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiRxChPerms.dmaPermPtrs[RM_CPPI_FFTC_C_DMA_ID], RM_CPPI_FFTC_C_RX_CH);
- break;
-
- case RM_RESOURCE_CPPI_FFTC_C_FLOW:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_FFTC_C_FLOW, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiFlowPerms.dmaPermPtrs[RM_CPPI_FFTC_C_DMA_ID], RM_CPPI_FFTC_C_FLOW);
- break;
- #endif
-
- #ifdef QMSS_MAX_BCP_QUEUE
- case RM_RESOURCE_CPPI_BCP_TX_CH:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_BCP_TX_CH, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiTxChPerms.dmaPermPtrs[RM_CPPI_BCP_DMA_ID], RM_CPPI_BCP_TX_CH);
- break;
-
- case RM_RESOURCE_CPPI_BCP_RX_CH:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_BCP_RX_CH, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiRxChPerms.dmaPermPtrs[RM_CPPI_BCP_DMA_ID], RM_CPPI_BCP_RX_CH);
- break;
-
- case RM_RESOURCE_CPPI_BCP_FLOW:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_CPPI_BCP_FLOW, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.cppiFlowPerms.dmaPermPtrs[RM_CPPI_BCP_DMA_ID], RM_CPPI_BCP_FLOW);
- break;
- #endif
-
- case RM_RESOURCE_PA_FIRMWARE:
- rmGPermsObj.obj.paFirmwarePerms.initPerms = resourceEntry->resourceInitFlags;
- rmGPermsObj.obj.paFirmwarePerms.usePerms = resourceEntry->resourceUseFlags;
- break;
-
- case RM_RESOURCE_PA_LUT_ENTRY:
- RM_RANGE_CHECK (resourceEntry->resourceStart, resourceEntry->resourceEnd, RM_PA_LUT, RM_ERROR_PERMISSION_TABLE_ENTRY_FAILURE);
- Rm_setTablePermissions (resourceEntry, rmGPermsObj.obj.paLutPerms, RM_PA_LUT);
- break;
-
- default:
- return RM_ERROR_PERMISSION_TABLE_POPULATION_FAILED;
++ if (rmInst->registeredWithDelegateOrServer) {
++ if (rmInst->instType == Rm_instType_CLIENT) {
++ dstTransport = rmTransportFindRemoteInstType((Rm_Transport *) rmInst->transports, Rm_instType_CLIENT_DELEGATE);
+
++ if (!dstTransport) {
++ dstTransport = rmTransportFindRemoteInstType((Rm_Transport *) rmInst->transports, Rm_instType_SERVER);
++ }
++ }
++ else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
++ dstTransport = rmTransportFindRemoteInstType((Rm_Transport *) rmInst->transports, Rm_instType_SERVER);
+ }
+
- resourceEntry++;
- };
++ switch (transaction->type) {
++ case Rm_service_RESOURCE_ALLOCATE_INIT:
++ case Rm_service_RESOURCE_ALLOCATE_USE:
++ case Rm_service_RESOURCE_FREE:
++ case Rm_service_RESOURCE_GET_BY_NAME:
++ pktHandle = rmTransportCreateResourceReqPkt(rmInst, dstTransport->appTransportHandle, transaction);
++ break;
++ case Rm_service_RESOURCE_MAP_TO_NAME:
++ case Rm_service_RESOURCE_UNMAP_NAME:
++ pktHandle = rmTransportCreateNsRequestPkt(rmInst, dstTransport->appTransportHandle, transaction);
++ break;
++ }
+
- /* Write synchronization object so that slave cores know permissions table is
- * populated and valid */
- rmGSyncObj.obj.globalSyncObj = RM_PERMISSION_TABLE_VALID;
-
- /* Writeback Sync Object */
- Rm_osalEndMemAccess ((void *) &rmGSyncObj, sizeof (Rm_Sync_Obj));
++ if (pktHandle) {
++ if (rmInst->transportCallouts.rmSendPkt) {
++ if (rmInst->transportCallouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {
++ transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
++ }
++ }
++ else {
++ transaction->state = RM_ERROR_TRANSPORT_SEND_NOT_REGD;
++ }
++ }
+
- return RM_OK;
++ transaction->hasBeenForwarded = true;
++ /* Transaction not deleted. Waiting for response from RM CD or Server */
++ }
+}
+
- /**
- * @b Description
- * @n
- * This function is called on slave DSPs after the master DSP has populated
- * the internal permission tables. This function invalidates all internal
- * global permission tables so that no further invalidates are required
- * when LLDs perform resource permission checks
- *
++/* FUNCTION PURPOSE: Issues an allocator operation
++ ***********************************************************************
++ * DESCRIPTION: Issues an allocator preallocate, allocate, or free
++ * for an RM resource.
+ */
- void Rm_updatePermissionTables(void)
++static int32_t allocatorOperation(Rm_Inst *rmInst, Rm_AllocatorOpInfo *opInfo)
+{
- uint16_t dmaIndex;
- const uint16_t dmaTxCh[RM_CPPI_MAX_DMAS] = {RM_CPPI_SRIO_TX_CH,
- #ifdef QMSS_MAX_AIF_QUEUE
- RM_CPPI_AIF_TX_CH,
- #endif
- #ifdef QMSS_MAX_FFTC_A_QUEUE
- RM_CPPI_FFTC_A_TX_CH,
- #endif
- #ifdef QMSS_MAX_FFTC_B_QUEUE
- RM_CPPI_FFTC_B_TX_CH,
- #endif
- #ifdef QMSS_MAX_PASS_QUEUE
- RM_CPPI_PASS_TX_CH,
- #endif
- RM_CPPI_QMSS_TX_CH,
- #ifdef QMSS_MAX_FFTC_C_QUEUE
- RM_CPPI_FFTC_C_TX_CH,
- #endif
- #ifdef QMSS_MAX_BCP_QUEUE
- RM_CPPI_BCP_TX_CH
- #endif
- };
- const uint16_t dmaRxCh[RM_CPPI_MAX_DMAS] = {RM_CPPI_SRIO_RX_CH,
- #ifdef QMSS_MAX_AIF_QUEUE
- RM_CPPI_AIF_RX_CH,
- #endif
- #ifdef QMSS_MAX_FFTC_A_QUEUE
- RM_CPPI_FFTC_A_RX_CH,
- #endif
- #ifdef QMSS_MAX_FFTC_B_QUEUE
- RM_CPPI_FFTC_B_RX_CH,
- #endif
- #ifdef QMSS_MAX_PASS_QUEUE
- RM_CPPI_PASS_RX_CH,
- #endif
- RM_CPPI_QMSS_RX_CH,
- #ifdef QMSS_MAX_FFTC_C_QUEUE
- RM_CPPI_FFTC_C_RX_CH,
- #endif
- #ifdef QMSS_MAX_BCP_QUEUE
- RM_CPPI_BCP_RX_CH
- #endif
- };
- const uint16_t dmaFlow[RM_CPPI_MAX_DMAS] = {RM_CPPI_SRIO_FLOW,
- #ifdef QMSS_MAX_AIF_QUEUE
- RM_CPPI_AIF_FLOW,
- #endif
- #ifdef QMSS_MAX_FFTC_A_QUEUE
- RM_CPPI_FFTC_A_FLOW,
- #endif
- #ifdef QMSS_MAX_FFTC_B_QUEUE
- RM_CPPI_FFTC_B_FLOW,
- #endif
- #ifdef QMSS_MAX_PASS_QUEUE
- RM_CPPI_PASS_FLOW,
- #endif
- RM_CPPI_QMSS_FLOW,
- #ifdef QMSS_MAX_FFTC_C_QUEUE
- RM_CPPI_FFTC_C_FLOW,
- #endif
- #ifdef QMSS_MAX_BCP_QUEUE
- RM_CPPI_BCP_FLOW
- #endif
- };
++ Rm_Allocator *allocator = NULL;
++ int32_t resourceOffsetInPolicy;
++ int32_t retVal;
+
- /* Invalidate all permission tables so no further invalidates are required
- * on slave cores */
-
- /* Global permissions object */
- Rm_osalBeginMemAccess ((void *) &rmGPermsObj, sizeof (Rm_GlobalPermissionsObj));
++ resourceOffsetInPolicy = rmPolicyGetResourceOffset(rmInst->policy, opInfo->resourceInfo->name);
++ allocator = rmAllocatorFind(rmInst->allocators, opInfo->resourceInfo->name);
+
- /* QMSS Permission Tables */
-
- /* QMSS PDSPs */
- Rm_osalBeginMemAccess ((void *)rmGPermsObj.obj.qmssPdspFirmwarePerms, sizeof (Rm_Perms) * RM_QMSS_FIRMWARE_PDSPS);
- /* QMSS Queues */
- Rm_osalBeginMemAccess ((void *)rmGPermsObj.obj.qmssQueuePerms, sizeof (Rm_Perms) * RM_QMSS_QUEUES);
- /* QMSS Memory Regions */
- Rm_osalBeginMemAccess ((void *)rmGPermsObj.obj.qmssMemRegionPerms, sizeof (Rm_Perms) * RM_QMSS_MEM_REGIONS);
- /* QMSS Linking RAM */
- Rm_osalBeginMemAccess ((void *)rmGPermsObj.obj.qmssLinkRamPerms, sizeof (Rm_qmssLinkingRamPerms) * RM_QMSS_LINKING_RAM_RANGES);
- /* QMSS Accumulator Channels */
- Rm_osalBeginMemAccess ((void *)rmGPermsObj.obj.qmssAccumChPerms, sizeof (Rm_Perms) * RM_QMSS_ACCUM_CH);
- /* QMSS QOS Clusters */
- Rm_osalBeginMemAccess ((void *)rmGPermsObj.obj.qmssQosClusterPerms, sizeof (Rm_Perms) * RM_QMSS_QOS_CLUSTER);
- /* QMSS QOS Queues */
- Rm_osalBeginMemAccess ((void *)rmGPermsObj.obj.qmssQosQueuePerms, sizeof (Rm_Perms) * RM_QMSS_QOS_QUEUES);
-
- /* CPPI Permission Tables */
-
- /* CPPI DMA Transmit Channels */
- for (dmaIndex = 0; dmaIndex < RM_CPPI_MAX_DMAS; dmaIndex++)
- {
- Rm_osalBeginMemAccess ((void *)rmGPermsObj.obj.cppiTxChPerms.dmaPermPtrs[dmaIndex], sizeof (Rm_Perms)*dmaTxCh[dmaIndex]);
++ if ((resourceOffsetInPolicy > 0) && allocator) {
++ if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE) {
++ retVal = treePreAllocate(rmInst, allocator, resourceOffsetInPolicy, opInfo);
++ }
++ else if (opInfo->operation == Rm_allocatorOp_ALLOCATE) {
++ retVal = treeAllocate(rmInst, allocator, resourceOffsetInPolicy, opInfo);
++ }
++ else if (opInfo->operation == Rm_allocatorOp_FREE) {
++ retVal = treeFree(allocator, opInfo);
++ }
+ }
- /* CPPI DMA Receive Channels */
- for (dmaIndex = 0; dmaIndex < RM_CPPI_MAX_DMAS; dmaIndex++)
- {
- Rm_osalBeginMemAccess ((void *)rmGPermsObj.obj.cppiRxChPerms.dmaPermPtrs[dmaIndex], sizeof (Rm_Perms)*dmaRxCh[dmaIndex]);
++ else {
++ /* Resource could not be found in policy and/or allocator */
++ retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
+ }
- /* CPPI DMA Receive Flows */
- for (dmaIndex = 0; dmaIndex < RM_CPPI_MAX_DMAS; dmaIndex++)
- {
- Rm_osalBeginMemAccess ((void *)rmGPermsObj.obj.cppiFlowPerms.dmaPermPtrs[dmaIndex], sizeof (Rm_Perms)*dmaFlow[dmaIndex]);
++ return(retVal);
++}
++
++/* FUNCTION PURPOSE: Arbitrates allocation service requests
++ ***********************************************************************
++ * DESCRIPTION: Issues a set of allocator operations in order to
++ * handle a received allocation request. Allocation
++ * requests are always forwarded to the Server on Client
++ * CD instances. If a request is made with a NameServer
++ * name the resource base and length parameters are
++ * retrieved from the NameServer prior to the allocation
++ * attempt.
++ */
++static void allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, void *validInstNode,
++ uint32_t allocType)
++{
++ Rm_AllocatorOpInfo opInfo;
++ Rm_NameServerObjCfg nameServerObjCfg;
++ int32_t retVal = transaction->state;
++
++ memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
++
++ if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
++ /* Forward all allocation requests to Server if transport is up. Otherwise, just queue. */
++ if (rmInst->registeredWithDelegateOrServer) {
++ transactionForwarder(rmInst, transaction);
++ }
+ }
++ else if (rmInst->instType == Rm_instType_SERVER) {
++ opInfo.resourceInfo = &transaction->resourceInfo;
++ opInfo.serviceSrcInstNode = validInstNode;
++ opInfo.allocType = allocType;
++
++ /* Populated NameServer name has precedence over base */
++ if (strlen(transaction->resourceInfo.nameServerName) > 0) {
++ if ((transaction->resourceInfo.base == 0) &&
++ (transaction->resourceInfo.length == 0) &&
++ (transaction->resourceInfo.alignment == 0)) {
++ memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
++ nameServerObjCfg.nameServerTree = rmInst->nameServer;
++ nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
++ if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {
++ strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
++ transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
++ transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
++ }
++ }
++ else {
++ retVal = RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT;
++ }
++ }
+
- /* PA permission tables */
++ if (retVal == RM_SERVICE_PROCESSING) {
++ if (transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) {
++ opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE;
++ retVal = allocatorOperation(rmInst, &opInfo);
++ }
++
++ if (retVal == RM_SERVICE_PROCESSING) {
++ opInfo.operation = Rm_allocatorOp_ALLOCATE;
++ retVal = allocatorOperation(rmInst, &opInfo);
++ }
++ }
++
++ transaction->state = retVal;
+
- /* PA Firmware invalidated as part of global permissions object invalidate */
- /* PA LUTs */
- Rm_osalBeginMemAccess ((void *)rmGPermsObj.obj.paLutPerms, sizeof (Rm_Perms) * RM_PA_LUT);
++ if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
++ /* Source of allocation was not the server instance, provide the transaction
++ * to the transaction responder */
++ transactionResponder(rmInst, transaction);
++ }
++ /* Otherwise let the return stack return the transaction to the serviceHandler */
++ }
+}
+
- /**
- * @b Description
- * @n
- * This function extracts the initialization permission for a DSP from a resource
- * permission element.
- *
- * @param[in] resourcePermissions
- * A permissions structure element to extract the per DSP initialization permission
- *
- * @retval
- * Success - RM_INIT_PERMISSION_APPROVED
- * @retval
- * Failure - RM_INIT_PERMISSION_DENIED
++/* FUNCTION PURPOSE: Arbitrates free service requests
++ ***********************************************************************
++ * DESCRIPTION: Issues a set of allocator operations in order to
++ * handle a received free request. Free
++ * requests are always forwarded to the Server on Client
++ * CD instances. If a request is made with a NameServer
++ * name the resource base and length parameters are
++ * retrieved from the NameServer prior to the free
++ * attempt.
+ */
- Rm_Result Rm_getInitPermissions (Rm_Perms *resourcePermissions)
++static void freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, void *validInstNode)
+{
- /* Check the init permissions for the calling DSP */
- if (!(RM_GET_PERMISSIONS(resourcePermissions->initPerms)))
- {
- return RM_INIT_PERMISSION_DENIED;
++ Rm_AllocatorOpInfo opInfo;
++ Rm_NameServerObjCfg nameServerObjCfg;
++ int32_t retVal = transaction->state;
++
++ memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
++
++ if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
++ /* Forward all free requests to Server if transport is up. Otherwise, just queue. */
++ if (rmInst->registeredWithDelegateOrServer) {
++ transactionForwarder(rmInst, transaction);
++ }
+ }
-
- return RM_INIT_PERMISSION_APPROVED;
++ else if (rmInst->instType == Rm_instType_SERVER) {
++ opInfo.resourceInfo = &transaction->resourceInfo;
++ opInfo.serviceSrcInstNode = validInstNode;
++
++ /* Populated NameServer name has precedence over base */
++ if (strlen(transaction->resourceInfo.nameServerName) > 0) {
++ if ((transaction->resourceInfo.base == 0) &&
++ (transaction->resourceInfo.length == 0) &&
++ (transaction->resourceInfo.alignment == 0)) {
++ memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
++ nameServerObjCfg.nameServerTree = rmInst->nameServer;
++ nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
++ if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {
++ strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
++ transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
++ transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
++ }
++ }
++ else {
++ retVal = RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT;
++ }
++ }
++
++ if(retVal == RM_SERVICE_PROCESSING) {
++ opInfo.operation = Rm_allocatorOp_FREE;
++ retVal = allocatorOperation(rmInst, &opInfo);
++ }
++
++ transaction->state = retVal;
++
++ if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
++ /* Source of allocation was not the server instance, provide the transaction
++ * to the transaction responder */
++ transactionResponder(rmInst, transaction);
++ }
++ /* Otherwise let the return stack return the transaction to the serviceHandler */
++ }
+}
+
- /**
- * @b Description
- * @n
- * This function extracts the usage permission for a DSP from a resource
- * permission element.
- *
- * @param[in] resourcePermissions
- * A permissions structure element to extract the per DSP usage permission
- *
- * @retval
- * Success - RM_INIT_PERMISSION_APPROVED
- * @retval
- * Failure - RM_INIT_PERMISSION_DENIED
++/* FUNCTION PURPOSE: Reserves a Linux resource
++ ***********************************************************************
++ * DESCRIPTION: Reserves resources for Linux using the base and length
++ * values retrieved from the Linux DTB via the
++ * "linux-dtb-alias" properties within the GRL.
+ */
- Rm_Result Rm_getUsePermissions (Rm_Perms *resourcePermissions)
++static int32_t reserveLinuxResource(Rm_Inst *rmInst, Rm_LinuxAlias *linuxAlias,
++ Rm_LinuxValueRange *linuxValues, Rm_AllocatorOpInfo *opInfo)
+{
- /* Check the use permissions for the calling DSP */
- if (!(RM_GET_PERMISSIONS(resourcePermissions->usePerms)))
- {
- return RM_USE_PERMISSION_DENIED;
++ int32_t retVal = RM_OK;
++ bool baseFound = false;
++ bool lengthFound = false;
++ uint32_t valueIndex = 0;
++
++ while ((linuxValues) && (!baseFound || !lengthFound)) {
++ if (linuxAlias->baseOffset == valueIndex) {
++ opInfo->resourceInfo->base = linuxValues->value;
++ baseFound = true;
++
++ if (linuxAlias->lengthOffset == RM_DTB_UTIL_LINUX_ALIAS_OFFSET_NOT_SET) {
++ opInfo->resourceInfo->length = 1;
++ lengthFound = true;
++ }
++ }
++ else if (linuxAlias->lengthOffset == valueIndex) {
++ opInfo->resourceInfo->length = linuxValues->value;
++ lengthFound = true;
++ }
++
++ linuxValues = (Rm_LinuxValueRange *)linuxValues->nextValue;
++ valueIndex++;
++ }
++
++ if (!baseFound || !lengthFound) {
++ retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;
++ }
++ else {
++ /* Allocate resource to Linux */
++ retVal = allocatorOperation(rmInst, opInfo);
+ }
-
- return RM_USE_PERMISSION_APPROVED;
++ return (retVal);
+}
+
- /**
- * @b Description
- * @n
- * This function searches the list of linking RAM address ranges to find one that has
- * the requested linking RAM address within it. If found the function returns the permissions
- * for this range. Otherwise it returns denied.
- *
- * @param[in] isInitCheck
- * True - Permissions check is for initialization
- * False - Permissions check is for usage
- *
- * @param[in] linkRamPermArray
- * Internal array of linking RAM ranges and their permissions
- *
- * @param[in] linkRamResData
- * Linking RAM addresses to check for initialization or usage permissions
- *
- * @retval
- * Success - RM_INIT_PERMISSION_APPROVED
- * @retval
- * Failure - RM_INIT_PERMISSION_DENIED
++/* FUNCTION PURPOSE: Finds and reserves Linux resources
++ ***********************************************************************
++ * DESCRIPTION: Parses the Linux DTB for resources consumed by the
++ * Linux kernel. If the resource is found via the
++ * "linux-dtb-alias" property defined in the GRL it is
++ * reserved.
+ */
- Rm_Result Rm_getLinkRamPermissions (Bool isInitCheck, Rm_qmssLinkingRamPerms *linkRamPermArray, Rm_ResourceInfo *linkRamResData)
++static int32_t findAndReserveLinuxResource(Rm_Inst *rmInst, const char *resourceName, void *linuxDtb,
++ Rm_LinuxAlias *linuxAlias)
+{
- Rm_Result retVal;
- uint16_t linkRamIndex;
++ Rm_AllocatorOpInfo opInfo;
++ Rm_ResourceInfo resourceInfo;
++ uint32_t pathOffset;
++ uint32_t pathSize;
++ char *spacePtr;
++ int32_t propOffset;
++ int32_t nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
++ int32_t prevDepth = RM_DTB_UTIL_STARTING_DEPTH;
++ int32_t depth;
++ int32_t propertyLen;
++ const char *propertyName;
++ const void *propertyData;
++ Rm_LinuxValueRange *linuxValueRange;
++ int32_t retVal = RM_OK;
++
++ memset((void *) &opInfo, 0, sizeof(Rm_AllocatorOpInfo));
++ memset((void *) &resourceInfo, 0, sizeof(Rm_ResourceInfo));
++
++ strncpy(resourceInfo.name, resourceName, RM_NAME_MAX_CHARS);
++ opInfo.serviceSrcInstNode = rmPolicyGetLinuxInstNode(rmInst->validInstances);
++ opInfo.operation = Rm_allocatorOp_ALLOCATE;
++ opInfo.resourceInfo = &resourceInfo;
++
++ while(linuxAlias) {
++ /* Reset parsing variables */
++ pathOffset = 0;
++ pathSize = strlen(linuxAlias->path) + 1;
++ nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
++ prevDepth = RM_DTB_UTIL_STARTING_DEPTH;
++ resourceInfo.base = 0;
++ resourceInfo.length = 0;
++
++ spacePtr = strpbrk(linuxAlias->path, " ");
++ if (spacePtr) {
++ *spacePtr = '\0';
++ }
++
++ while(pathOffset < pathSize) {
++ /* Move through DTB nodes until next alias path node found */
++ if (strcmp(linuxAlias->path + pathOffset, fdt_get_name(linuxDtb, nodeOffset, NULL))) {
++ nodeOffset = fdt_next_node(linuxDtb, nodeOffset, &depth);
++
++ if ((depth < prevDepth) || (nodeOffset == -FDT_ERR_NOTFOUND)) {
++ /* Returning from subnode that matched part of alias path without finding
++ * resource values */
++ retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;
++ break;
++ }
++ }
++ else {
++ /* Found next alias path node. Move to next node name in path string. */
++ pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);
++ spacePtr = strpbrk(linuxAlias->path + pathOffset, " ");
++ if (spacePtr) {
++ *spacePtr = '\0';
++ }
++
++ prevDepth = fdt_node_depth(linuxDtb, nodeOffset);
++ propOffset = fdt_first_property_offset(linuxDtb, nodeOffset);
++ while ((propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) &&
++ (pathOffset < pathSize)) {
++ propertyData = fdt_getprop_by_offset(linuxDtb, propOffset,
++ &propertyName, &propertyLen);
++
++ if (strcmp(linuxAlias->path + pathOffset, propertyName) == 0) {
++ /* Found resource at end of alias path */
++ pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);
++ linuxValueRange = rmDtbUtilLinuxExtractValues(propertyData, propertyLen);
++ retVal = reserveLinuxResource(rmInst, linuxAlias,
++ linuxValueRange, &opInfo);
++ rmDtbUtilLinuxFreeValues(linuxValueRange);
++ }
++ propOffset = fdt_next_property_offset(linuxDtb, propOffset);
++ }
+
- /* Initialize the return value based on type of check boolean */
- if (isInitCheck)
- {
- retVal = RM_INIT_PERMISSION_DENIED;
- }
- else
- {
- retVal = RM_USE_PERMISSION_DENIED;
++ if (propOffset < -FDT_ERR_NOTFOUND) {
++ retVal = propOffset;
++ break;
++ }
++ }
++ }
++
++ if (retVal < RM_OK) {
++ break;
++ }
++ linuxAlias = linuxAlias->nextLinuxAlias;
+ }
-
- for (linkRamIndex = 0; linkRamIndex < RM_QMSS_LINKING_RAM_RANGES; linkRamIndex++)
- {
- if ((linkRamResData->res_info.linkRamData.linkRamStartIndex >= linkRamPermArray[linkRamIndex].startIndex) &&
- (linkRamResData->res_info.linkRamData.linkRamEndIndex <= linkRamPermArray[linkRamIndex].endIndex))
- {
- /* Check the use permissions for the calling DSP */
- if (isInitCheck)
- {
- if (RM_GET_PERMISSIONS(linkRamPermArray[linkRamIndex].rangePerms.initPerms))
- {
- retVal = RM_USE_PERMISSION_APPROVED;
++ return (retVal);
++}
++
++/* FUNCTION PURPOSE: Creates and initializes a resource allocator
++ ***********************************************************************
++ * DESCRIPTION: Creates a resource allocator for the provided
++ * resource name and resource properties retrieved
++ * from the GRL. Resources will be reserved for
++ * the Linux kernel if the Linux DTB is provided
++ * and there are "linux-dtb-alias" properties
++ * specified in the GRL.
++ */
++static int32_t createAndInitAllocator(Rm_Inst *rmInst, const char *resourceName,
++ Rm_ResourceProperties *resourceProperties, void *linuxDtb)
++{
++ Rm_ResourceRange *range = NULL;
++ Rm_ResourceRange *rangeBasePtr = NULL;
++ Rm_NsAssignment *nsAssignments = NULL;
++ Rm_NsAssignment *nsAssignmentBasePtr = NULL;
++ Rm_LinuxAlias *linuxAlias = NULL;
++ Rm_NameServerObjCfg nameServerObjCfg;
++ int32_t retVal = RM_OK;
++
++ if (resourceProperties->rangeData && (resourceProperties->rangeLen > 0)) {
++ range = rangeBasePtr = rmDtbUtilResExtractRange(resourceProperties->rangeData,
++ resourceProperties->rangeLen);
++
++ if ((retVal = createResourceTree(rmInst, resourceName, range)) >= RM_OK) {
++ if (resourceProperties->linuxAliasData && resourceProperties->linuxAliasLen) {
++ if (linuxDtb) {
++ linuxAlias = rmDtbUtilResExtractLinuxAlias(resourceProperties->linuxAliasData,
++ resourceProperties->linuxAliasLen, &retVal);
++ if (linuxAlias) {
++ retVal = findAndReserveLinuxResource(rmInst, resourceName, linuxDtb, linuxAlias);
++ }
++ }
++ else {
++ retVal = RM_ERROR_GRL_LINUX_ALIAS_BUT_NO_DTB;
+ }
+ }
- else
- {
- if (RM_GET_PERMISSIONS(linkRamPermArray[linkRamIndex].rangePerms.usePerms))
- {
- retVal = RM_USE_PERMISSION_APPROVED;
++ }
++ }
++
++ if (retVal >= RM_OK) {
++ if (resourceProperties->nsAssignData && resourceProperties->nsAssignLen) {
++ nsAssignments = rmDtbUtilResExtractNsAssignment(resourceProperties->nsAssignData,
++ resourceProperties->nsAssignLen, &retVal);
++ if (nsAssignments) {
++ nsAssignmentBasePtr = nsAssignments;
++ while (nsAssignments) {
++ memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
++ nameServerObjCfg.nameServerTree = rmInst->nameServer;
++ nameServerObjCfg.nodeCfg.objName = nsAssignments->nsName;
++ nameServerObjCfg.nodeCfg.resourceName = (char *)resourceName;
++ nameServerObjCfg.nodeCfg.resourceBase= nsAssignments->resourceBase;
++ nameServerObjCfg.nodeCfg.resourceLength = nsAssignments->resourceLength;
++ rmNameServerAddObject(&nameServerObjCfg);
++ nsAssignments = nsAssignments->nextNsAssignment;
+ }
++ rmDtbUtilResFreeNsAssignmentList(nsAssignmentBasePtr);
+ }
- break;
+ }
+ }
+
++ rmDtbUtilResFreeRange(rangeBasePtr);
++ if (linuxAlias) {
++ rmDtbUtilResFreeLinuxAlias(linuxAlias);
++ }
++ return(retVal);
++}
++
++/* FUNCTION PURPOSE: Recursively parses GRL resource properties
++ ***********************************************************************
++ * DESCRIPTION: Recursively parses and stores GRL resource node
++ * properties using the LIBFDT APIs
++ */
++static int32_t parseResourceProperty(void *globalResourceDtb, int32_t offset,
++ Rm_ResourceProperties *propertyInfo)
++{
++ int32_t propertyLen;
++ const char *propertyName;
++ const void *propertyData;
++ Rm_ResourcePropType propertyType;
++ int32_t retVal = RM_OK;
++
++ propertyData = fdt_getprop_by_offset(globalResourceDtb, offset, &propertyName, &propertyLen);
++ propertyType = rmDtbUtilResGetPropertyType(propertyName);
++ if (propertyType == Rm_resourcePropType_RESOURCE_RANGE) {
++ propertyInfo->rangeData = propertyData;
++ propertyInfo->rangeLen = propertyLen;
++ }
++ else if (propertyType == Rm_resourcePropType_NSASSIGNMENT) {
++ propertyInfo->nsAssignData = propertyData;
++ propertyInfo->nsAssignLen = propertyLen;
++ }
++ else if (propertyType == Rm_resourcePropType_RESOURCE_LINUX_ALIAS) {
++ propertyInfo->linuxAliasData = propertyData;
++ propertyInfo->linuxAliasLen = propertyLen;
++ }
++ else {
++ retVal = RM_ERROR_GRL_UNKNOWN_RESOURCE_PROPERTY;
++ }
++
++ if (retVal == RM_OK) {
++ offset = fdt_next_property_offset(globalResourceDtb, offset);
++ if (offset >= 0) {
++ retVal = parseResourceProperty(globalResourceDtb, offset, propertyInfo);
++ }
++ else if (offset != -FDT_ERR_NOTFOUND) {
++ /* Error returned by LIBFDT */
++ retVal = offset;
++ }
++ }
+ return (retVal);
+}
+
- /**********************************************************************
- **********APIs visible to other LLDs internally via call table *******************
- **********************************************************************/
++/* FUNCTION PURPOSE: Recursively parses GRL resource nodes
++ ***********************************************************************
++ * DESCRIPTION: Recursively parses GRL resource nodes looking for
++ * resource properties to create the resource allocators.
++ * The LIBFDT APIs are used to parse the GRL.
++ */
++static int32_t parseResourceNode(Rm_Inst *rmInst, void *globalResourceDtb, int32_t nodeOffset, int32_t depth,
++ void *linuxDtb)
++{
++ const char *resourceName = fdt_get_name(globalResourceDtb, nodeOffset, NULL);
++ Rm_ResourceProperties resourceProperties;
++ int32_t retVal = RM_OK;
++ int32_t offset;
++
++ memset((void *)&resourceProperties, 0, sizeof(Rm_ResourceProperties));
++ /* Get properties of resource node */
++ offset = fdt_first_property_offset(globalResourceDtb, nodeOffset);
++ if (offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) {
++ retVal = parseResourceProperty(globalResourceDtb, offset, &resourceProperties);
++ if (retVal < -FDT_ERR_NOTFOUND) {
++ return (retVal);
++ }
++ if (retVal = createAndInitAllocator(rmInst, resourceName, &resourceProperties, linuxDtb) < RM_OK) {
++ return (retVal);
++ }
++ }
++ else if (offset != -FDT_ERR_NOTFOUND) {
++ /* Error returned by LIBFDT */
++ return (offset);
++ }
++
++ offset = fdt_next_node(globalResourceDtb, nodeOffset, &depth);
++ if ((offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && (depth >= RM_DTB_UTIL_STARTING_DEPTH)) {
++ retVal = parseResourceNode(rmInst, globalResourceDtb, offset, depth, linuxDtb);
++ if (retVal < -FDT_ERR_NOTFOUND) {
++ return (retVal);
++ }
++ }
++ else if (offset != -FDT_ERR_NOTFOUND) {
++ /* Error returned by LIBFDT */
++ return (offset);
++ }
++ return (retVal);
++}
+
- /**
- * @b Description
- * @n
- * This function is used by LLDs to check initialization permissions for a resource
- *
- * @param[in] resourceData
- * Structure containing resource information such as resource type and the
- * resource value to be checked
- *
- * @retval
- * Success - RM_INIT_PERMISSION_APPROVED
- * @retval
- * Failure - RM_INIT_PERMISSION_DENIED
++/* FUNCTION PURPOSE: Initializes server allocators
++ ***********************************************************************
++ * DESCRIPTION: Creates and initializes a server instance's
++ * resource allocators using the GRL and, if
++ * provided, Linux DTB.
+ */
- Rm_Result Rm_initPermissionChecker (Rm_ResourceInfo *resourceData)
++static int32_t initializeAllocators(Rm_Inst *rmInst, void *globalResourceDtb, void *linuxDtb)
+{
- switch (resourceData->resourceType)
- {
- case Rm_resource_QMSS_FIRMWARE_PDSP:
- return (Rm_getInitPermissions(&rmGPermsObj.obj.qmssPdspFirmwarePerms[resourceData->res_info.pdspNum]));
-
- case Rm_resource_QMSS_QUEUE:
- return (Rm_getInitPermissions(&rmGPermsObj.obj.qmssQueuePerms[resourceData->res_info.queNum]));
-
- case Rm_resource_QMSS_MEMORY_REGION:
- return (Rm_getInitPermissions(&rmGPermsObj.obj.qmssMemRegionPerms[resourceData->res_info.memRegion]));
++ int32_t nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
++ int32_t startDepth = RM_DTB_UTIL_STARTING_DEPTH;
++ int32_t result = RM_OK;
+
- case Rm_resource_QMSS_LINKING_RAM_CONTROL:
- return (Rm_getInitPermissions(&rmGPermsObj.obj.qmssLinkRamControlPerms));
-
- case Rm_resource_QMSS_LINKING_RAM:
- return (Rm_getLinkRamPermissions (TRUE, &rmGPermsObj.obj.qmssLinkRamPerms[0], resourceData));
-
- case Rm_resource_QMSS_ACCUM_CH:
- return (Rm_getInitPermissions(&rmGPermsObj.obj.qmssAccumChPerms[resourceData->res_info.accumCh]));
++ /* Recursively parse the Global Resource List, creating an allocator for
++ * each resource as specified in the node */
++ result = parseResourceNode(rmInst, globalResourceDtb, nodeOffset, startDepth, linuxDtb);
+
- case Rm_resource_QMSS_QOS_TIMER:
- return (Rm_getInitPermissions(&rmGPermsObj.obj.qmssQosPdspTimerPerms));
++ return(result);
++}
+
- case Rm_resource_QMSS_QOS_CLUSTER:
- return (Rm_getInitPermissions(&rmGPermsObj.obj.qmssQosClusterPerms[resourceData->res_info.qosCluster]));
++/**********************************************************************
++ ********************** Internal Functions ****************************
++ **********************************************************************/
+
- case Rm_resource_QMSS_QOS_QUEUE:
- return (Rm_getInitPermissions(&rmGPermsObj.obj.qmssQosQueuePerms[resourceData->res_info.qosQueue]));
-
- case Rm_resource_CPPI_TX_CH:
- {
- Rm_Perms *txChPermsArray = rmGPermsObj.obj.cppiTxChPerms.dmaPermPtrs[resourceData->res_info.cpDmaData.dmaNum];
- return (Rm_getInitPermissions(&txChPermsArray[resourceData->res_info.cpDmaData.cppiChNumOrFlowId]));
- }
-
- case Rm_resource_CPPI_RX_CH:
- {
- Rm_Perms *rxChPermsArray = rmGPermsObj.obj.cppiRxChPerms.dmaPermPtrs[resourceData->res_info.cpDmaData.dmaNum];
- return (Rm_getInitPermissions(&rxChPermsArray[resourceData->res_info.cpDmaData.cppiChNumOrFlowId]));
- }
-
- case Rm_resource_CPPI_RX_FLOW:
- {
- Rm_Perms *flowPermsArray = rmGPermsObj.obj.cppiFlowPerms.dmaPermPtrs[resourceData->res_info.cpDmaData.dmaNum];
- return (Rm_getInitPermissions(&flowPermsArray[resourceData->res_info.cpDmaData.cppiChNumOrFlowId]));
++/* FUNCTION PURPOSE: Adds a transaction
++ ***********************************************************************
++ * DESCRIPTION: Returns a pointer to a newly created transaction.
++ * The transaction is created based on a new service
++ * request received via the service API or the
++ * transport API (service forwarded from another instance)
++ */
++Rm_Transaction *rmTransactionQueueAdd(Rm_Inst *rmInst)
++{
++ Rm_Transaction *transactionQueue = rmInst->transactionQueue;
++ Rm_Transaction *newTransaction = NULL;
++
++ newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));
++ if (newTransaction) {
++ memset((void *)newTransaction, 0, sizeof(Rm_Transaction));
++
++ newTransaction->localId = transactionGetSequenceNum(rmInst);
++ newTransaction->nextTransaction = NULL;
++ if (transactionQueue) {
++ while (transactionQueue->nextTransaction) {
++ transactionQueue = transactionQueue->nextTransaction;
+ }
-
- case Rm_resource_PA_FIRMWARE:
- return (Rm_getInitPermissions(&rmGPermsObj.obj.paFirmwarePerms));
-
- case Rm_resource_PA_LUT:
- return (Rm_getInitPermissions(&rmGPermsObj.obj.paLutPerms[resourceData->res_info.lutEntry]));
-
- default:
- return (RM_INIT_PERMISSION_DENIED);
++ transactionQueue->nextTransaction = newTransaction;
++ }
++ else {
++ rmInst->transactionQueue = newTransaction;
++ }
+ }
++ return (newTransaction);
+}
+
- /**
- * @b Description
- * @n
- * This function is used by LLDs to check usage permissions for a resource
- *
- * @param[in] resourceData
- * Structure containing resource information such as resource type and the
- * resource value to be checked
- *
- * @retval
- * Success - RM_INIT_PERMISSION_APPROVED
- * @retval
- * Failure - RM_INIT_PERMISSION_DENIED
++/* FUNCTION PURPOSE: Finds a transaction
++ ***********************************************************************
++ * DESCRIPTION: Returns a pointer to a transaction resident
++ * in the transaction queue that matches the provided
++ * transaction ID.
+ */
- Rm_Result Rm_usePermissionChecker (Rm_ResourceInfo *resourceData)
++Rm_Transaction *rmTransactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)
+{
- switch (resourceData->resourceType)
- {
- case Rm_resource_QMSS_FIRMWARE_PDSP:
- return (Rm_getUsePermissions(&rmGPermsObj.obj.qmssPdspFirmwarePerms[resourceData->res_info.pdspNum]));
-
- case Rm_resource_QMSS_QUEUE:
- return (Rm_getUsePermissions(&rmGPermsObj.obj.qmssQueuePerms[resourceData->res_info.queNum]));
-
- case Rm_resource_QMSS_MEMORY_REGION:
- return (Rm_getUsePermissions(&rmGPermsObj.obj.qmssMemRegionPerms[resourceData->res_info.memRegion]));
++ Rm_Transaction *transaction = rmInst->transactionQueue;
+
- case Rm_resource_QMSS_LINKING_RAM_CONTROL:
- return (Rm_getUsePermissions(&rmGPermsObj.obj.qmssLinkRamControlPerms));
-
- case Rm_resource_QMSS_LINKING_RAM:
- return (Rm_getLinkRamPermissions(FALSE, &rmGPermsObj.obj.qmssLinkRamPerms[0], resourceData));
-
- case Rm_resource_QMSS_ACCUM_CH:
- return (Rm_getUsePermissions(&rmGPermsObj.obj.qmssAccumChPerms[resourceData->res_info.accumCh]));
++ while (transaction) {
++ if (transaction->localId == transactionId) {
++ break;
++ }
++ transaction = transaction->nextTransaction;
++ }
+
- case Rm_resource_QMSS_QOS_TIMER:
- return (Rm_getUsePermissions(&rmGPermsObj.obj.qmssQosPdspTimerPerms));
++ return (transaction);
++}
+
- case Rm_resource_QMSS_QOS_CLUSTER:
- return (Rm_getUsePermissions(&rmGPermsObj.obj.qmssQosClusterPerms[resourceData->res_info.qosCluster]));
++/* FUNCTION PURPOSE: Deletes a transaction
++ ***********************************************************************
++ * DESCRIPTION: Deletes the transaction with the provided transaction
++ * ID from the instance's transaction queue.
++ */
++int32_t rmTransactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)
++{
++ Rm_Transaction *transaction = rmInst->transactionQueue;
++ Rm_Transaction *prevTransaction = NULL;
++ int32_t retVal = RM_OK;
+
- case Rm_resource_QMSS_QOS_QUEUE:
- return (Rm_getUsePermissions(&rmGPermsObj.obj.qmssQosQueuePerms[resourceData->res_info.qosQueue]));
-
- case Rm_resource_CPPI_TX_CH:
- {
- Rm_Perms *txChPermsArray = rmGPermsObj.obj.cppiTxChPerms.dmaPermPtrs[resourceData->res_info.cpDmaData.dmaNum];
- return (Rm_getUsePermissions(&txChPermsArray[resourceData->res_info.cpDmaData.cppiChNumOrFlowId]));
- }
-
- case Rm_resource_CPPI_RX_CH:
- {
- Rm_Perms *rxChPermsArray = rmGPermsObj.obj.cppiRxChPerms.dmaPermPtrs[resourceData->res_info.cpDmaData.dmaNum];
- return (Rm_getUsePermissions(&rxChPermsArray[resourceData->res_info.cpDmaData.cppiChNumOrFlowId]));
++ while (transaction) {
++ if (transaction->localId == transactionId) {
++ break;
++ }
++
++ prevTransaction = transaction;
++ transaction = transaction->nextTransaction;
++ }
++
++ if (transaction) {
++ if (prevTransaction == NULL) {
++ /* Transaction at start of queue. Map second transaction to start of queue
++ * as long as more than one transactions. */
++ rmInst->transactionQueue = transaction->nextTransaction;
++ }
++ else {
++ /* Transaction in middle or end of queue. */
++ prevTransaction->nextTransaction = transaction->nextTransaction;
++ }
++ Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));
++ }
++ else {
++ retVal = RM_ERROR_SERVICE_TRANS_DOES_NOT_EXIST;
++ }
++ return (retVal);
++}
++
++/* FUNCTION PURPOSE: Finds an allocator
++ ***********************************************************************
++ * DESCRIPTION: Returns a pointer to an allocator that matches the
++ * provided resource name.
++ */
++Rm_Allocator *rmAllocatorFind(Rm_Allocator *allocatorList, char *resourceName)
++{
++ while (allocatorList) {
++ if (strncmp(allocatorList->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {
++ break;
++ }
++ allocatorList = allocatorList->nextAllocator;
++ }
++
++ return (allocatorList);
++}
++
++/* FUNCTION PURPOSE: Processes a transaction
++ ***********************************************************************
++ * DESCRIPTION: Processes transactions created from services
++ * received via the service handle or the transport.
++ * Transactions will be routed within the RM system
++ * based on the RM instance type and the type of
++ * the transaction.
++ */
++void rmTransactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction)
++{
++ void *validInstNode;
++ Rm_PolicyCheckCfg privCheckCfg;
++ Rm_NameServerObjCfg nameServerObjCfg;
++ uint32_t allocType = 0;
++
++ /* Handle static transactions originating on this instance. Any other static transactions will be
++ * stored in transaction queue until all transports are up. */
++ if (((rmInst->instType == Rm_instType_CLIENT) || (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) &&
++ (!rmInst->registeredWithDelegateOrServer) &&
++ (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS) == 0)) {
++ if (rmInst->staticInfo.staticPolicy) {
++ if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
++ (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE)) {
++ /* Check request against startup policy */
++ memset((void *)&privCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));
++
++ if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
++ privCheckCfg.type = Rm_policyCheck_INIT;
++ }
++ else {
++ privCheckCfg.type = Rm_policyCheck_USE;
++ }
++ privCheckCfg.policyDtb = rmInst->staticInfo.staticPolicy;
++ privCheckCfg.validInstNode = rmPolicyGetValidInstNode(rmInst->staticInfo.staticValidInstTree,
++ rmInst->instName);
++ privCheckCfg.resourceOffset = rmPolicyGetResourceOffset(rmInst->staticInfo.staticPolicy,
++ transaction->resourceInfo.name);
++ privCheckCfg.resourceBase = transaction->resourceInfo.base;
++ privCheckCfg.resourceLength = transaction->resourceInfo.length;
++
++ if (rmPolicyCheckPrivilege(&privCheckCfg, &transaction->state)) {
++ transaction->state = RM_SERVICE_APPROVED_STATIC;
++ }
++ else if (transaction->state == RM_SERVICE_PROCESSING) {
++ /* Privilege check returned false without error */
++ transaction->state = RM_SERVICE_DENIED_BY_STATIC_POLICY;
++ }
+ }
-
- case Rm_resource_CPPI_RX_FLOW:
- {
- Rm_Perms *flowPermsArray = rmGPermsObj.obj.cppiFlowPerms.dmaPermPtrs[resourceData->res_info.cpDmaData.dmaNum];
- return (Rm_getUsePermissions(&flowPermsArray[resourceData->res_info.cpDmaData.cppiChNumOrFlowId]));
++ else {
++ transaction->state = RM_SERVICE_DENIED_INVALID_STATIC_REQUEST;
+ }
-
- case Rm_resource_PA_FIRMWARE:
- return (Rm_getUsePermissions(&rmGPermsObj.obj.paFirmwarePerms));
-
- case Rm_resource_PA_LUT:
- return (Rm_getUsePermissions(&rmGPermsObj.obj.paLutPerms[resourceData->res_info.lutEntry]));
-
- default:
- return (RM_USE_PERMISSION_DENIED);
++ }
++ else {
++ transaction->state = RM_ERROR_REQ_FAILED_NO_STATIC_POLICY;
++ }
+ }
- }
++ else {
++ /* Handle auto-forwarded transactions. These transactions include:
++ * - All request transactions received on Clients are forwarded to the Client Delegate
++ * - NameServer requests received on the Client Delegate are forwarded to the Server */
++ if ((rmInst->instType == Rm_instType_CLIENT) ||
++ ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&
++ ((transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||
++ (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) ||
++ (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)))) {
++
++ if ((transaction->state != RM_SERVICE_PROCESSING) &&
++ (transaction->state != RM_SERVICE_APPROVED_STATIC)) {
++ if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
++ /* Transaction did not originate on this instance */
++ transactionResponder(rmInst, transaction);
++ }
++ else {
++ /* Transaction originated on this instance */
++ serviceResponder(rmInst, transaction);
++ }
++ }
++ else {
++ /* Forward request if transport is up. Otherwise, just queue. */
++ if (rmInst->registeredWithDelegateOrServer) {
++ transactionForwarder(rmInst, transaction);
++ }
++ }
++ }
++ else {
++ /* Validate service's originating instance name */
++ if (rmInst->instType == Rm_instType_SERVER) {
++ validInstNode = rmPolicyGetValidInstNode(rmInst->validInstances, transaction->serviceSrcInstName);
++ if (validInstNode == NULL) {
++ transaction->state = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
++
++ /* Send result via responder if transaction did not originate from this instance */
++ if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
++ transactionResponder(rmInst, transaction);
++ }
++ }
++ }
++
++ switch (transaction->type) {
++ case Rm_service_RESOURCE_ALLOCATE_INIT:
++ case Rm_service_RESOURCE_ALLOCATE_USE:
++ case Rm_service_RESOURCE_FREE:
++ if ((transaction->state != RM_SERVICE_PROCESSING) &&
++ (transaction->state != RM_SERVICE_APPROVED_STATIC)) {
++ /* Transaction complete */
++ if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
++ /* Transaction result not destined for this instance */
++ transactionResponder(rmInst, transaction);
++ }
++ else {
++ /* Transaction result destined for this instance */
++ serviceResponder(rmInst, transaction);
++ }
++ }
++ else {
++ /* Complete allocation/free request */
++ if (transaction->type == Rm_service_RESOURCE_FREE) {
++ freeHandler(rmInst, transaction, validInstNode);
++ }
++ else {
++ switch (transaction->type) {
++ case Rm_service_RESOURCE_ALLOCATE_INIT:
++ RM_policy_SET_PERM(allocType, RM_POLICY_PERM_INIT_SHIFT, 1);
++ break;
++ case Rm_service_RESOURCE_ALLOCATE_USE:
++ RM_policy_SET_PERM(allocType, RM_POLICY_PERM_USE_SHIFT, 1);
++ break;
++ }
++ allocationHandler(rmInst, transaction, validInstNode, allocType);
++ }
++ }
++ break;
++ case Rm_service_RESOURCE_MAP_TO_NAME:
++ case Rm_service_RESOURCE_GET_BY_NAME:
++ case Rm_service_RESOURCE_UNMAP_NAME:
++ /* NameServer resides on server */
++ memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
++ if (rmInst->nameServer) {
++ nameServerObjCfg.nameServerTree = rmInst->nameServer;
++ nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
++ if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {
++ nameServerObjCfg.nodeCfg.resourceName = transaction->resourceInfo.name;
++ nameServerObjCfg.nodeCfg.resourceBase= transaction->resourceInfo.base;
++ nameServerObjCfg.nodeCfg.resourceLength = transaction->resourceInfo.length;
++ transaction->state = rmNameServerAddObject(&nameServerObjCfg);
++ }
++ else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
++ if ((transaction->state = rmNameServerFindObject(&nameServerObjCfg)) ==
++ RM_SERVICE_PROCESSING) {
++ strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
++ transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
++ transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
++ transaction->state = RM_SERVICE_APPROVED;
++ }
++ }
++ else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {
++ transaction->state = rmNameServerDeleteObject(&nameServerObjCfg);
++ }
++ }
++ else {
++ transaction->state = RM_ERROR_NAMESERVER_DOES_NOT_EXIST;
++ }
+
- /* */
++ /* Send result via responder if transaction did not originate from this instance */
++ if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
++ transactionResponder(rmInst, transaction);
++ }
++ break;
++ }
++ }
++ }
+
++ /* Forward any queued requests that weren't forwarded yet */
++ if (rmInst->registeredWithDelegateOrServer) {
++ transaction = rmInst->transactionQueue;
++ while(transaction) {
++ if (((transaction->state == RM_SERVICE_PROCESSING) ||
++ (transaction->state == RM_SERVICE_APPROVED_STATIC)) &&
++ !transaction->hasBeenForwarded) {
++ transactionForwarder(rmInst, transaction);
++ }
++ transaction = transaction->nextTransaction;
++ }
++ }
++}
++
+/**********************************************************************
- *********************** Application visible APIs ***************************
++ ********************** Application visible APIs **********************
+ **********************************************************************/
+
- /** @addtogroup RM_LLD_FUNCTION
- @{
- */
-
- /**
- * @b Description
- * @n
- * This function initializes the Resource Manager low level driver
- * This function is called once in the system to setup the Resource Manager
- * low level driver by mapping the application defined resource table to internal
- * permission tables. After mapping is complete a global synchronization object
- * is written to sync with slave cores
- *
- * @param[in] rmResourceTable
- * Resource table defined by application. Used to populate internal permission
- * tables.
- *
- * @post
- * RM LLD global permissions are set.
- *
- * @retval
- * Success - RM_OK
- * @retval
- * Failure - RM_ERROR_PERMISSION_TABLE_POPULATION_FAILED
++/* FUNCTION PURPOSE: Display status of managed resources
++ ***********************************************************************
++ * DESCRIPTION: Prints the status (allocate/free status, as well as
++ * owners) for all resources managed by the RM
++ * instance network. Also, prints the NameServer name
++ * entries. This function is only available on server
++ * instances.
+ */
- Rm_Result Rm_init (const Rm_Resource *rmResourceTable)
++void Rm_printResourceStatus(Rm_Handle rmServerHandle)
+{
- void *key;
- Rm_Result ret_val = RM_ERROR;
-
- /* Check permission structure sizes to make sure they're evenly
- * divisible into a cache line. This generates no object code when
- * optimizer is on. If failes, assert will occur at compile time */
- RM_COMPILE_TIME_SIZE_CHECK((RM_MAX_CACHE_ALIGN/sizeof(Rm_Perms)) * sizeof(Rm_Perms) == RM_MAX_CACHE_ALIGN);
- RM_COMPILE_TIME_SIZE_CHECK((RM_MAX_CACHE_ALIGN/sizeof(Rm_qmssLinkingRamPerms)) * \
- sizeof(Rm_qmssLinkingRamPerms) == RM_MAX_CACHE_ALIGN);
-
- /* Begin Critical Section before accessing shared resources. */
- key = Rm_osalCsEnter ();
-
- /* Initialize the permissions table */
- Rm_permissionTableInit();
++ Rm_Inst *rmInst = (Rm_Inst *)rmServerHandle;
++ Rm_Allocator *allocator = rmInst->allocators;
++ Rm_Owner *owners;
++ Rm_ResourceTree *treeRoot;
++ Rm_ResourceNode *treeNode;
+
- if (!rmResourceTable)
- {
- /* End Critical Section */
- Rm_osalCsExit (key);
- return RM_ERROR_PERMISSION_TABLE_POPULATION_FAILED;
- }
++ if (rmInst->instType == Rm_instType_SERVER) {
++ while (allocator != NULL) {
++ Rm_osalLog("Resource: %s\n", allocator->resourceName);
+
- ret_val = Rm_populatePermissionTable(rmResourceTable);
++ treeRoot = allocator->allocatorRootEntry;
+
- /* End Critical Section */
- Rm_osalCsExit (key);
- return ret_val;
++ RB_FOREACH(treeNode, _Rm_AllocatorResourceTree, treeRoot) {
++ Rm_osalLog(" %10d - %10d ", treeNode->base,
++ treeNode->base + treeNode->length -1);
++
++ if (treeNode->allocationCount == 0) {
++ Rm_osalLog("NOT ALLOCATED\n");
++ }
++ else {
++ owners = treeNode->ownerList;
++ Rm_osalLog("allocated to");
++ while (owners) {
++ Rm_osalLog(" %s", owners->instNameNode->name);
++ owners = owners->nextOwner;
++ }
++ Rm_osalLog("\n");
++ }
++ }
++ allocator = allocator->nextAllocator;
++ }
++ rmNameServerPrintObjects(rmInst->nameServer);
++ }
+}
+
- /**
- * @b Description
- * @n
- * This function waits for the Resource Manager master to populate the
- * global permissions table based on a global sync object. Once the
- * global sync object has been written by the master core this function
- * will invalidate all permissions tables. Since the permissions table are
- * static, and will not change through the system up-time, a single
- * invalidation at the start will suffice.
- *
- * This function can be called on all core besides that which called
- * Rm_init. Calling this function on said cores will act as a blocking
- * synchronization point.
- *
- * @retval
- * Success - RM_OK
- * @retval
- * Failure - RM_FAILURE
++/* FUNCTION PURPOSE: Display status of a RM instance
++ ***********************************************************************
++ * DESCRIPTION: Prints the current status of various RM instance
++ * properties such as the state of all transactions
++ * in the transaction queue and registered transports
+ */
- Rm_Result Rm_start (void)
++void Rm_printInstanceStatus(Rm_Handle rmHandle)
+{
- /* Loop until the global sync object signals the permissions table has been
- * populated and valid */
- do
- {
- /* Invalidate the global sync object */
- Rm_osalBeginMemAccess ((void *) &rmGSyncObj, sizeof (Rm_Sync_Obj));
- } while (rmGSyncObj.obj.globalSyncObj != RM_PERMISSION_TABLE_VALID);
++ Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
++ Rm_Transport *transportList = (Rm_Transport *)rmInst->transports;
++ Rm_Transaction *transactionQ = rmInst->transactionQueue;
+
- /* Master core finished populating the permission tables. Must invalidate
- * all tables to see latest permissions */
- Rm_updatePermissionTables();
++ Rm_osalLog("Instance name: %s\n", rmInst->instName);
++ if (rmInst->instType == Rm_instType_SERVER) {
++ Rm_osalLog("Type: Server\n");
++ }
++ else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
++ Rm_osalLog("Type: Client Delegate\n");
++ }
++ else {
++ Rm_osalLog("Type: Client\n");
++ }
++
++ if (transportList) {
++ Rm_osalLog("\nRegistered Transports:\n");
++ while (transportList) {
++ Rm_osalLog(" Remote instName: %s\n", transportList->remoteInstName);
++ if (transportList->remoteInstType == Rm_instType_SERVER) {
++ Rm_osalLog(" Remote instType: Server\n");
++ }
++ else if (transportList->remoteInstType == Rm_instType_CLIENT_DELEGATE) {
++ Rm_osalLog(" Remote instType: Client Delegate\n");
++ }
++ else {
++ Rm_osalLog(" Remote instType: Client\n");
++ }
++ Rm_osalLog(" appTransportHandle: 0x%08x\n", transportList->appTransportHandle);
++ Rm_osalLog("\n");
++ transportList = transportList->nextTransport;
++ }
++ }
+
- return RM_OK;
++ if (transactionQ) {
++ Rm_osalLog("\nQueued Service Transactions:\n");
++ while (transactionQ) {
++ Rm_osalLog(" Service type: %d\n", transactionQ->type);
++ Rm_osalLog(" Service ID: %d\n", transactionQ->localId);
++ Rm_osalLog(" Service srcInstName %s\n", transactionQ->serviceSrcInstName);
++ Rm_osalLog(" Service state: %d\n", transactionQ->state);
++ Rm_osalLog(" Resource name: %s\n", transactionQ->resourceInfo.name);
++ Rm_osalLog(" Resource base: %d\n", transactionQ->resourceInfo.base);
++ Rm_osalLog(" Resource length: %d\n", transactionQ->resourceInfo.length);
++ Rm_osalLog(" Resource alignment: %d\n", transactionQ->resourceInfo.alignment);
++ Rm_osalLog(" Resource NS name: %s\n", transactionQ->resourceInfo.nameServerName);
++ Rm_osalLog("\n");
++ transactionQ = transactionQ->nextTransaction;
++ }
++ }
+}
+
- /**
- * @b Description
- * @n
- * This function returns an RM handle to the application to provide
- * to LLDs that want to use the RM.
- *
- * @retval
- * Success - RM Handle. Used an an input parameter for LLD startCfg functions.
- * @retval
- * Failure - NULL
++/* FUNCTION PURPOSE: RM instance creation and initialization
++ ***********************************************************************
++ * DESCRIPTION: Returns a new RM instance created and initialized
++ * using the parameters provided via the initCfg
++ * structure.
+ */
- Rm_Handle Rm_getHandle(void)
++Rm_Handle Rm_init(Rm_InitCfg *initCfg, int32_t *result)
+{
- return ((void *) &rmPermissionCheckers);
++ Rm_Inst *rmInst;
++ void *globalResourceDtb = NULL;
++ void *linuxResourceDtb = NULL;
++ bool addLinux = false;
++
++ *result = RM_OK;
++
++ if ((initCfg->instName == NULL) ||
++ ((strlen(initCfg->instName) + 1) > RM_NAME_MAX_CHARS)) {
++ *result = RM_ERROR_INVALID_INST_NAME;
++ return (NULL);
++ }
++
++ if (initCfg->instType >= Rm_instType_LAST) {
++ *result = RM_ERROR_INVALID_INST_TYPE;
++ }
++
++ /* Create and initialize instance */
++ rmInst = Rm_osalMalloc (sizeof(Rm_Inst));
++ memset ((void *) rmInst, 0, sizeof(Rm_Inst));
++ rmInst->isLocked = false;
++ rmInst->registeredWithDelegateOrServer = false;
++ rmInst->transactionSeqNum = transactionInitSequenceNum();
++
++ rmInst->instType = initCfg->instType;
++ strncpy (rmInst->instName, initCfg->instName, RM_NAME_MAX_CHARS);
++
++ if (rmInst->instType == Rm_instType_SERVER) {
++ if (!initCfg->instCfg.serverCfg.globalResourceList ||
++ !initCfg->instCfg.serverCfg.globalPolicy) {
++ *result = RM_ERROR_INVALID_SERVER_CONFIGURATION;
++ Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
++ return(NULL);
++ }
++
++ rmInst->policy = initCfg->instCfg.serverCfg.globalPolicy;
++ fdt_open_into(rmInst->policy, rmInst->policy, fdt_totalsize(rmInst->policy));
++
++ if (initCfg->instCfg.serverCfg.linuxDtb) {
++ linuxResourceDtb = initCfg->instCfg.serverCfg.linuxDtb;
++ fdt_open_into(linuxResourceDtb, linuxResourceDtb, fdt_totalsize(linuxResourceDtb));
++ addLinux = true;
++ }
++
++ /* Create valid instance list from policy. Must be done prior to parsing
++ * GRL so that Linux resources can be reserved correctly */
++ rmInst->validInstances = rmPolicyCreateValidInstTree(rmInst->policy, addLinux, result);
++ /* Validate policy assignment strings */
++ *result = rmPolicyValidatePolicy(rmInst->policy, rmInst->validInstances);
++
++ rmInst->nameServer = rmNameServerInit();
++
++ globalResourceDtb = initCfg->instCfg.serverCfg.globalResourceList;
++ fdt_open_into(globalResourceDtb, globalResourceDtb, fdt_totalsize(globalResourceDtb));
++
++ if ((*result = initializeAllocators(rmInst, globalResourceDtb, linuxResourceDtb)) == RM_OK) {
++ *result = rmPolicyValidatePolicyResourceNames(rmInst->policy, (void *)rmInst->allocators);
++ }
++ if (*result < RM_OK) {
++ Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
++ return(NULL);
++ }
++ }
++
++ if ((rmInst->instType == Rm_instType_CLIENT) &&
++ (initCfg->instCfg.clientCfg.staticPolicy)) {
++ rmInst->staticInfo.staticPolicy = initCfg->instCfg.clientCfg.staticPolicy;
++ }
++ else if ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&
++ (initCfg->instCfg.cdCfg.staticPolicy)) {
++ rmInst->staticInfo.staticPolicy = initCfg->instCfg.cdCfg.staticPolicy;
++ }
++ if (rmInst->staticInfo.staticPolicy) {
++ fdt_open_into(rmInst->staticInfo.staticPolicy, rmInst->staticInfo.staticPolicy,
++ fdt_totalsize(rmInst->staticInfo.staticPolicy));
++ rmInst->staticInfo.staticValidInstTree = rmPolicyCreateValidInstTree(rmInst->staticInfo.staticPolicy,
++ addLinux, result);
++ if (*result == RM_OK) {
++ /* Validate policy assignment strings */
++ *result = rmPolicyValidatePolicy(rmInst->staticInfo.staticPolicy, rmInst->staticInfo.staticValidInstTree);
++ }
++ if (*result != RM_OK) {
++ if (rmInst->staticInfo.staticValidInstTree) {
++ rmPolicyFreeValidInstTree(rmInst->staticInfo.staticValidInstTree);
++ }
++ Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
++ rmInst = NULL;
++ }
++ }
++ return ((Rm_Handle) rmInst);
+}
+
- /**
- * @b Description
- * @n
- * The function is used to get the version information of the RM LLD.
- *
- * @retval
- * Version Information.
++/* FUNCTION PURPOSE: Returns RM version information
++ ***********************************************************************
+ */
+uint32_t Rm_getVersion (void)
+{
- return RM_LLD_VERSION_ID;
++ return RM_VERSION_ID;
+}
+
- /**
- * @b Description
- * @n
- * The function is used to get the version string for the RM LLD.
- *
- * @retval
- * Version String.
++/* FUNCTION PURPOSE: Returns RM version string
++ ***********************************************************************
+ */
+const char* Rm_getVersionStr (void)
+{
- return rmLldVersionStr;
++ return rmVersionStr;
+}
+
- /**
- @}
- */