c18b64502b7888f432a9c2ebaba34bc7989ef140
[keystone-rtos/rm-lld.git] / src / rm_allocator.c
1 /**
2  *   @file  rm_allocator.c
3  *
4  *   @brief   
5  *      This is the Resource Manager allocator source.
6  *
7  *  \par
8  *  ============================================================================
9  *  @n   (C) Copyright 2012-2013, Texas Instruments, Inc.
10  * 
11  *  Redistribution and use in source and binary forms, with or without 
12  *  modification, are permitted provided that the following conditions 
13  *  are met:
14  *
15  *    Redistributions of source code must retain the above copyright 
16  *    notice, this list of conditions and the following disclaimer.
17  *
18  *    Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the 
20  *    documentation and/or other materials provided with the   
21  *    distribution.
22  *
23  *    Neither the name of Texas Instruments Incorporated nor the names of
24  *    its contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
28  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
29  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
31  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
32  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
33  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
36  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
37  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38  *
39  *  \par
40 */
42 /* RM external includes */
43 #include <ti/drv/rm/rm.h>
45 /* RM internal includes */
46 #include <ti/drv/rm/include/rm_loc.h>
47 #include <ti/drv/rm/include/rm_allocatorloc.h>
48 #include <ti/drv/rm/include/rm_dtb_utilloc.h>
49 #include <ti/drv/rm/include/rm_policyloc.h>
50 #include <ti/drv/rm/include/rm_treeloc.h>
52 /* RM LIBFDT includes */
53 #include <ti/drv/rm/util/libfdt/libfdt.h>
55 /* Tree algorithm includes */
56 #include <ti/drv/rm/util/tree.h>
58 /* RM OSAL layer */
59 #include <rm_osal.h>
61 /**********************************************************************
62  ************************ Local Functions *****************************
63  **********************************************************************/
65 /* FUNCTION PURPOSE: Creates a resource allocator
66  ***********************************************************************
67  * DESCRIPTION: Returns a newly Created and initialized resource
68  *              The allocator is also stored in the RM instance
69  *              allocator list.            
70  */
71 static Rm_Allocator *allocatorAdd(Rm_Handle rmHandle, const char *resourceName)
72 {
73     Rm_Inst      *rmInst = (Rm_Inst *)rmHandle;
74     Rm_Allocator *allocators   = rmAllocatorGetAllocatorList(rmHandle);
75     Rm_Allocator *newAllocator = NULL;
77     newAllocator = Rm_osalMalloc(sizeof(*allocators));
79     if (newAllocator) {
80         memset((void *)newAllocator, 0, sizeof(*newAllocator));
81         strncpy(newAllocator->resourceName, resourceName, RM_NAME_MAX_CHARS);
82         newAllocator->allocatorRootEntry = NULL;
83         newAllocator->nextAllocator = NULL;  
85         /* Add allocator to end of list */
86         if (allocators) {
87             while (allocators->nextAllocator) {
88                 allocators = allocators->nextAllocator;
89             }
90             allocators->nextAllocator = newAllocator;
91             RM_SS_OBJ_WB(allocators, Rm_Allocator);
92         }
93         else {
94             if ((rmInst->instType == Rm_instType_SERVER) ||
95                 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
96                 rmInst->u.server.allocators = newAllocator;
97             }
98             else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
99                 rmInst->u.cd.allocators = newAllocator;
100             }            
101         }
102     }
103     return (newAllocator);
106 /* FUNCTION PURPOSE: Checks a resource node's ownership
107  ***********************************************************************
108  * DESCRIPTION: Returns the owner reference count if the provided
109  *              instance node is in the list of resource node owners.  Otherwise,
110  *              returns 0.
111  */
112 static int allocatorResNodeIsOwnedBy(Rm_Handle rmHandle, Rm_ResourceNode *node, Rm_PolicyValidInstNode *serviceInstNode)
114     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;
115     Rm_Owner *owner = node->ownerList;
117     while (owner) {
118         RM_SS_OBJ_INV(owner, Rm_Owner);
119         if (owner->instNameNode == serviceInstNode) {
120             return(owner->refCnt);           
121         }
122         owner = owner->nextOwner;
123     }
124     return(0);
127 /* FUNCTION PURPOSE: Increments an owner's refCnt
128  ***********************************************************************
129  * DESCRIPTION: Increments a resource owner's reference count
130  */
131 static void allocatorResNodeOwnerRefCntInc(Rm_Handle rmHandle, Rm_ResourceNode *node, Rm_PolicyValidInstNode *serviceInstNode)
133     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;
134     Rm_Owner *owner = node->ownerList;
136     while (owner) {
137         RM_SS_OBJ_INV(owner, Rm_Owner);
138         if (owner->instNameNode == serviceInstNode) {
139             owner->refCnt++;
140             RM_SS_OBJ_WB(owner, Rm_Owner);
141             break;
142         }
143         owner = owner->nextOwner;
144     }
147 /* FUNCTION PURPOSE: Decrements an owner's refCnt
148  ***********************************************************************
149  * DESCRIPTION: Decrements a resource owner's reference count
150  */
151 static void allocatorResNodeOwnerRefCntDec(Rm_Handle rmHandle, Rm_ResourceNode *node, Rm_PolicyValidInstNode *serviceInstNode)
153     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;
154     Rm_Owner *owner = node->ownerList;
156     while (owner) {
157         RM_SS_OBJ_INV(owner, Rm_Owner);
158         if (owner->instNameNode == serviceInstNode) {
159             owner->refCnt--;
160             RM_SS_OBJ_WB(owner, Rm_Owner);
161             break;
162         }
163         owner = owner->nextOwner;
164     }
167 /* FUNCTION PURPOSE: Returns an owner's refCnt
168  ***********************************************************************
169  * DESCRIPTION: Returns a resource owner's reference count
170  */
171 static uint16_t allocatorResNodeOwnerGetRefCnt(Rm_Handle rmHandle, Rm_ResourceNode *node, Rm_PolicyValidInstNode *serviceInstNode)
173     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;
174     Rm_Owner *owner = node->ownerList;
176     while (owner) {
177         RM_SS_OBJ_INV(owner, Rm_Owner);
178         if (owner->instNameNode == serviceInstNode) {
179             return (owner->refCnt);
180         }
181         owner = owner->nextOwner;
182     }
184     return(0);
187 /* FUNCTION PURPOSE: Adds an owner to an allocator resource
188  ***********************************************************************
189  * DESCRIPTION: Adds a RM instance node to a resource node's
190  *              list of owners.  If the owner is already present that
191  *              owner's reference count is incremented
192  */
193 static void allocatorResNodeOwnerAdd(Rm_Handle rmHandle, Rm_ResourceNode *node, Rm_PolicyValidInstNode *serviceInstNode)
195     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;    
196     Rm_Owner *ownerList = node->ownerList;
197     Rm_Owner *newOwner = NULL;
199     if (allocatorResNodeIsOwnedBy(rmHandle, node, serviceInstNode)) {
200         allocatorResNodeOwnerRefCntInc(rmHandle, node, serviceInstNode);
201     }
202     else {
203         newOwner = Rm_osalMalloc(sizeof(*newOwner));
205         if (newOwner) {
206             newOwner->instNameNode = serviceInstNode;
207             newOwner->refCnt = 0;
208             newOwner->nextOwner = NULL;  
210             /* Add owner entry to end of list */
211             if (ownerList) {
212                 RM_SS_OBJ_INV(ownerList, Rm_Owner);
213                 while (ownerList->nextOwner) {
214                     ownerList = ownerList->nextOwner;
215                     RM_SS_OBJ_INV(ownerList, Rm_Owner);
216                 }
217                 ownerList->nextOwner = newOwner;
218                 RM_SS_OBJ_WB(ownerList, Rm_Owner);
219             }
220             else {
221                 node->ownerList = newOwner;
222             }
224             node->allocationCount++;
225             newOwner->refCnt++;
226             newOwner->instNameNode->allocRefCount++;
227             RM_SS_OBJ_WB(newOwner, Rm_Owner);
228             RM_SS_OBJ_WB(newOwner->instNameNode, Rm_PolicyValidInstNode);
229         }
230     }
233 /* FUNCTION PURPOSE: Compares two resource node's boundaries
234  ***********************************************************************
235  * DESCRIPTION: Returns TRUE if the resource nodes are neighbors from
236  *              a base+length perspective.  Otherwise, returns FALSE.
237  */
238 static int allocatorResNodeBoundaryCompare(Rm_ResourceNode *node1, Rm_ResourceNode *node2)
240     uint32_t node1End = node1->base + node1->length - 1;
241     uint32_t node2End = node2->base + node2->length - 1;
243     if (node1 && node2) {
244         if (node1->base < node2->base) {
245             if (node1End == (node2->base - 1)) {
246                 return(RM_TRUE);
247             }
248         }
249         else if (node2->base < node1->base) {
250             if (node2End == (node1->base - 1)) {
251                 return(RM_TRUE);
252             }     
253         }
254     }
255     return(RM_FALSE);
258 /* FUNCTION PURPOSE: Compares two resource node's owners
259  ***********************************************************************
260  * DESCRIPTION: Returns TRUE if the owners of two resource nodes 
261  *              are equivalent.  Otherwise, returns FALSE.
262  */
263 static int allocatorResNodeOwnerCompare(Rm_Handle rmHandle, Rm_ResourceNode *node1, Rm_ResourceNode *node2)
265     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;    
266     Rm_Owner *node1Owners = node1->ownerList;
267     Rm_Owner *node2Owners = node2->ownerList;
268     int       matchedInst;
270     if (rmInst->instType == Rm_instType_SHARED_SERVER) {
271         while(node2Owners) {
272             Rm_osalBeginMemAccess((void *)node2Owners, sizeof(*node2Owners));
273             node2Owners = node2Owners->nextOwner;
274         }
275         node2Owners = node2->ownerList;
276     }
278     if (node1->allocationCount == node2->allocationCount) {
279         while (node1Owners) {
280             RM_SS_OBJ_INV(node1Owners, Rm_Owner);
281             matchedInst = RM_FALSE;
282             while (node2Owners) {
283                 if ((node1Owners->instNameNode == node2Owners->instNameNode) &&
284                     (node1Owners->refCnt == node2Owners->refCnt)) {
285                     matchedInst = RM_TRUE;
286                     break;
287                 }
288                 node2Owners = node2Owners->nextOwner;
289             }
291             if (matchedInst) {
292                 node2Owners = node2->ownerList;
293                 node1Owners = node1Owners->nextOwner;
294             }
295             else {
296                 return(RM_FALSE);
297             }                
298         }
299     }
300     else {
301         return(RM_FALSE);
302     }  
303     
304     return(RM_TRUE);
307 /* FUNCTION PURPOSE: Deletes an owner from an allocator resource
308  ***********************************************************************
309  * DESCRIPTION: Removes a RM owner entry from a resource node's
310  *              list of owners.  If the refCnt for the specified
311  *              owner is greater than 1 only the refCnt is
312  *              decremented
313  */
314 static void allocatorResNodeOwnerDelete(Rm_Handle rmHandle, Rm_ResourceNode *node, void *serviceInstNode)
316     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;    
317     Rm_Owner *owner = node->ownerList;
318     Rm_Owner *prevOwner = NULL;
320     if (allocatorResNodeIsOwnedBy(rmHandle, node, serviceInstNode) > 1) {
321         allocatorResNodeOwnerRefCntDec(rmHandle, node, serviceInstNode);
322     }
323     else {
324         while (owner) {
325             RM_SS_OBJ_INV(owner, Rm_Owner);
326             if (owner->instNameNode == serviceInstNode) {
327                 break;             
328             }
329             prevOwner = owner;
330             owner = owner->nextOwner;
331         }
333         if (owner) {
334             if (prevOwner == NULL) {
335                 node->ownerList = owner->nextOwner;
336             }
337             else {
338                 prevOwner->nextOwner = owner->nextOwner;
339                 RM_SS_OBJ_WB(prevOwner, Rm_Owner);
340             }
341             
342             node->allocationCount--;
343             owner->instNameNode->allocRefCount--;
344             RM_SS_OBJ_WB(owner->instNameNode, Rm_PolicyValidInstNode);
345             Rm_osalFree((void *)owner, sizeof(*owner));
346         }
347     }
350 /* FUNCTION PURPOSE: Copies the owners of a resource node
351  ***********************************************************************
352  * DESCRIPTION: Creates a list of resource owners for the destination
353  *              resource node that is equivalent to the source resource
354  *              node's owners
355  *
356  *              dstNode must be a newly created node without any owners.
357  */
358 static void allocatorResNodeOwnerCopy(Rm_Handle rmHandle, Rm_ResourceNode *dstNode, Rm_ResourceNode *srcNode)
360     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;
361     Rm_Owner *srcOwnerList = srcNode->ownerList;
362     Rm_Owner *dstNewOwner;
363     Rm_Owner *dstPrevOwner;
365     if (dstNode->ownerList != NULL) {
366         return;
367     }
368     dstNode->allocationCount = srcNode->allocationCount;
370     while (srcOwnerList) {
371         RM_SS_OBJ_INV(srcOwnerList, Rm_Owner);
372         dstNewOwner = Rm_osalMalloc(sizeof(*dstNewOwner));
373         dstNewOwner->instNameNode = srcOwnerList->instNameNode;
374         dstNewOwner->refCnt = srcOwnerList->refCnt;
375         dstNewOwner->nextOwner = NULL;
376         RM_SS_OBJ_WB(dstNewOwner, Rm_Owner);
378         if (dstNode->ownerList == NULL) {
379             dstNode->ownerList = dstNewOwner;
380         }
381         else {
382             dstPrevOwner->nextOwner = dstNewOwner;
383             RM_SS_OBJ_WB(dstPrevOwner, Rm_Owner);
384         }
385         dstPrevOwner = dstNewOwner;
386         srcOwnerList = srcOwnerList->nextOwner;
387     }
390 /* FUNCTION PURPOSE: Clears a resource node's owners
391  ***********************************************************************
392  * DESCRIPTION: Deletes all owners from the owners list of a 
393  *              resource node.
394  */
395 static void allocatorResNodeOwnerClear(Rm_Handle rmHandle, Rm_ResourceNode *node)
397     Rm_Inst  *rmInst = (Rm_Inst *)rmHandle;    
398     Rm_Owner *owner = node->ownerList;
399     Rm_Owner *nextOwner;
401     while (owner) {
402         RM_SS_OBJ_INV(owner, Rm_Owner);
403         nextOwner = owner->nextOwner;
404         node->allocationCount--;
405         owner->instNameNode->allocRefCount--;
406         RM_SS_OBJ_WB(owner->instNameNode, Rm_PolicyValidInstNode);
407         Rm_osalFree((void *)owner, sizeof(*owner));
408         owner = nextOwner;
409     }
412 /* FUNCTION PURPOSE: Get the status for an allocator resource
413  ***********************************************************************
414  * DESCRIPTION: Called when a resource status request is made.  The
415  *              resource's allocator is searched for the resource base
416  *              and length specified in the transaction.  The 
417  *              resource's owner reference count is returned if the 
418  *              resource range is found.
419  */
420 static int32_t allocatorStatus(Rm_Handle rmHandle, Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)
422     Rm_ResourceNode  findNode;
423     Rm_ResourceNode *matchingNode = NULL; 
424     uint32_t         matchingEnd;
425     uint32_t         findEnd;    
426     int32_t          retVal;
428     memset((void *)&findNode, 0, sizeof(findNode));
429     findNode.base = opInfo->resourceInfo->base;
430     findNode.length = opInfo->resourceInfo->length;
431     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
433     if (matchingNode) {
434         matchingEnd = matchingNode->base + matchingNode->length - 1;
435         findEnd = findNode.base + findNode.length - 1;
436         if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {        
437             opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
438             opInfo->resourceInfo->instAllocCount = allocatorResNodeOwnerGetRefCnt(rmHandle, matchingNode,
439                                                                                   opInfo->serviceSrcInstNode);            
440             retVal = RM_SERVICE_APPROVED;
441         }
442         else {
443             retVal = RM_SERVICE_DENIED_PARTIAL_STATUS;
444         }
445     }
446     else {
447         retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;
448     }
450     return(retVal);  
453 /* FUNCTION PURPOSE: Preallocates an allocator resource
454  ***********************************************************************
455  * DESCRIPTION: Called when an allocate request is made but the base 
456  *              is unspecified.  The preallocation algorithm looks at 
457  *              available resources as well as policy permissions to 
458  *              determine a resource range that satisfies the request.
459  *              If a valid range is found it will be returned for the 
460  *              treeAllocate algorithm to handle.
461  */
462 static int32_t allocatorPreAllocate(Rm_Handle rmHandle, Rm_Allocator *allocator, int32_t resourcePolicy, 
463                                     Rm_AllocatorOpInfo *opInfo)
464 {   
465     Rm_Inst           *rmInst = (Rm_Inst *)rmHandle;
466     Rm_ResourceNode    findNode;
467     Rm_ResourceNode   *matchingNode = NULL;
468     Rm_ResourceNode   *nextNode;
469     uint32_t           matchingEnd;
470     uint32_t           findEnd;
471     uint32_t           rangeIndex;
472     int                resourceFound = RM_FALSE;
473     Rm_PolicyCheckType policyCheckType;
474     Rm_PolicyCheckCfg  policyCheckCfg;
475     int                nodePassesPolicy;
476     int32_t            retVal = RM_OK;
478     if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE_INIT) {
479         policyCheckType = Rm_policyCheck_INIT;
480     }
481     else if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE_USE) {
482         policyCheckType = Rm_policyCheck_USE;
483     }
484     else {
485         retVal = RM_ERROR_INVALID_SERVICE_TYPE;
486         return (retVal);
487     }
489     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
490         /* Set base to first node's base since CD will not have all resources like Server */
491         matchingNode = RB_MIN(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry);
492         opInfo->resourceInfo->base = matchingNode->base;
493     }
494     else {
495         opInfo->resourceInfo->base = rmPolicyGetResourceBase(opInfo->policy, opInfo->serviceSrcInstNode, 
496                                                              resourcePolicy, policyCheckType, 
497                                                              &retVal);
498     }
499     
500     if (retVal != RM_OK) {
501         return (retVal);
502     }
504     if (opInfo->resourceInfo->alignment == RM_RESOURCE_ALIGNMENT_UNSPECIFIED) {  
505         /* Get alignment from policy */
506         opInfo->resourceInfo->alignment = rmPolicyGetResourceAlignment(opInfo->policy, resourcePolicy);
507     }
508     
509     if (opInfo->resourceInfo->alignment == 0) {
510         opInfo->resourceInfo->alignment = 1;
511     }    
513     memset((void *)&findNode, 0, sizeof(findNode));
514     findNode.base = opInfo->resourceInfo->base;
515     findNode.length = opInfo->resourceInfo->length;
517     /* Configure policy checking structure */
518     memset((void *)&policyCheckCfg, 0, sizeof(policyCheckCfg));
519     policyCheckCfg.policyDtb = opInfo->policy;
520     policyCheckCfg.resourceOffset = resourcePolicy;
521     
522     do {
523         matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
524         
525         if (matchingNode) {
526             matchingEnd = matchingNode->base + matchingNode->length - 1;
527             findEnd = findNode.base + findNode.length - 1;
528             nodePassesPolicy = RM_BOOL_UNDEF;
529             if ((matchingNode->allocationCount == 0) &&
530                 (findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {
531                 /* Attempt to preallocate from node only if not owned by anyone and sits
532                  * within a matching node. */
533                 policyCheckCfg.type = policyCheckType;
534                 policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
535                 policyCheckCfg.resourceBase = findNode.base;
536                 policyCheckCfg.resourceLength = findNode.length;
537                 nodePassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);    
538                 
539                 if (nodePassesPolicy && (matchingNode->allocationCount > 0)) {
540                     policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
541                     
542                     if (allocatorResNodeIsOwnedBy(rmHandle, matchingNode, rmPolicyGetLinuxInstNode(rmHandle))) {
543                         /* Check if instance requesting resource has privileges to share
544                          * a resource already reserved by Linux */
545                         policyCheckCfg.type = Rm_policyCheck_SHARED_LINUX;
546                         nodePassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
547                     }
549                     if (nodePassesPolicy) {
550                         /* Check exclusive privileges of instance requesting resource.  Requesting
551                          * instance with exclusive privileges can't reserve resource if already owned*/
552                         policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
553                         nodePassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
554                     }
555                 }
556                 
557                 if (nodePassesPolicy && (matchingNode->allocationCount == 1)) {
558                     /* Check exclusive privileges of instance that currently owns resource */
559                     policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
560                     policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;
561                     nodePassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
562                 }
564                 if (retVal != RM_OK) {
565                     break;
566                 }
568                 if (nodePassesPolicy) {
569                     /* Initialize indexer to be first resource value that alignment satisfies */
570                     rangeIndex = findNode.base;
571                     if (rangeIndex % opInfo->resourceInfo->alignment) {
572                         rangeIndex += (opInfo->resourceInfo->alignment -
573                                       (rangeIndex % opInfo->resourceInfo->alignment));
574                     }
575                     
576                     if ((rangeIndex + opInfo->resourceInfo->length - 1) <= matchingEnd) {
577                         /* Block of unallocated resources within matchingNode that satisfies
578                          * allocate requirements */
579                         opInfo->resourceInfo->base = rangeIndex;
580                         resourceFound = RM_TRUE;
581                         retVal = RM_SERVICE_PROCESSING;
582                     }     
583                 }
584             }
585             
586             if (!resourceFound) {
587                 /* Check next resource node for available resources */
588                 if (findNode.base < matchingNode->base) {
589                     findNode.base = matchingNode->base;
590                 }
591                 else {
592                     if (!nodePassesPolicy) {
593                         findNode.base += findNode.length;
594                     }
595                     else {
596                         /* Matching node allocated, move to next node */
597                         if (nextNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode)) {
598                             findNode.base = nextNode->base;
599                         }
600                         else {
601                             retVal = RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET;
602                         }
603                     }
604                 }
605             }
606         }
607         else {
608             retVal = RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET;
609         }
610     } while ((!resourceFound) && 
611              (retVal != RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET));
613     return(retVal); 
616 /* FUNCTION PURPOSE: Allocates an allocator resource
617  ***********************************************************************
618  * DESCRIPTION: Will attempt to allocate the resource with specified
619  *              base and length from the resource's allocator.  The
620  *              allocation algorithm will verify the allocation against
621  *              the policy permissions for the instance requesting the
622  *              allocation.  If the policy allows the allocation the 
623  *              algorithm will allocate the resource then combine any
624  *              resource nodes that may have become equivalent (in terms
625  *              of ownership) after the allocation.
626  */
627 static int32_t allocatorAllocate(Rm_Handle rmHandle, Rm_Allocator *allocator, int32_t resourcePolicy, 
628                                  Rm_AllocatorOpInfo *opInfo)
630     Rm_ResourceNode     findNode;
631     Rm_ResourceNode    *matchingNode = NULL;
632     Rm_ResourceNode    *leftNode = NULL;
633     Rm_ResourceNode    *rightNode = NULL;
634     Rm_PolicyCheckType  policyCheckType;    
635     Rm_PolicyCheckCfg   policyCheckCfg;
636     int                 allocPassesPolicy;
637     int                 combineLeft = RM_FALSE;
638     int                 combineRight = RM_FALSE;    
639     uint32_t            findEnd;
640     uint32_t            matchingEnd;  
641     int32_t             retVal;
643     if (opInfo->operation == Rm_allocatorOp_ALLOCATE_INIT) {
644         policyCheckType = Rm_policyCheck_INIT;
645     }
646     else if (opInfo->operation == Rm_allocatorOp_ALLOCATE_USE) {
647         policyCheckType = Rm_policyCheck_USE;
648     }
649     else {
650         retVal = RM_ERROR_INVALID_SERVICE_TYPE;
651         return (retVal);
652     }   
654     memset((void *)&findNode, 0, sizeof(findNode));
655     findNode.base = opInfo->resourceInfo->base;
656     findNode.length = opInfo->resourceInfo->length;
657     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
659     /* Prepare privilege checks */
660     memset((void *)&policyCheckCfg, 0, sizeof(policyCheckCfg)); 
662     if (matchingNode) {
663         findEnd = findNode.base + findNode.length - 1;
664         matchingEnd = matchingNode->base + matchingNode->length - 1;
665         
666         if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {
667             if (opInfo->serviceSrcInstNode == rmPolicyGetLinuxInstNode(rmHandle)) {
668                 /* Bypass policy checks since Linux Kernel has full privileges */
669                 allocPassesPolicy = RM_TRUE;
670             }
671             else {
672                 policyCheckCfg.policyDtb = opInfo->policy;
673                 policyCheckCfg.resourceOffset = resourcePolicy;    
674                 policyCheckCfg.type = policyCheckType;
675                 policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
676                 policyCheckCfg.resourceBase = findNode.base;
677                 policyCheckCfg.resourceLength = findNode.length;
678                 allocPassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
679                 if (!allocPassesPolicy) {
680                     if (policyCheckType == Rm_policyCheck_INIT) {
681                         retVal = RM_SERVICE_DENIED_INIT_PERM_NOT_GIVEN;
682                     }
683                     else {
684                         retVal = RM_SERVICE_DENIED_USE_PERM_NOT_GIVEN;
685                     }
686                 }
688                 if (!allocatorResNodeIsOwnedBy(rmHandle, matchingNode, opInfo->serviceSrcInstNode)) {
689                     if (allocPassesPolicy && (matchingNode->allocationCount > 0)) {
690                         if (allocatorResNodeIsOwnedBy(rmHandle, matchingNode, rmPolicyGetLinuxInstNode(rmHandle))) {
691                             /* Check if instance requesting resource has privileges to share
692                              * a resource already reserved by Linux */
693                             policyCheckCfg.type = Rm_policyCheck_SHARED_LINUX;
694                             policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
695                             allocPassesPolicy = rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
696                             if (!allocPassesPolicy) {
697                                 retVal = RM_SERVICE_DENIED_RES_NOT_SHARED_LINUX;
698                             }
699                         }
700                         if (allocPassesPolicy) {
701                             /* Check exclusive privileges of instance requesting resource.  Requesting
702                              * instance with exclusive privileges can't reserve resource if already owned*/
703                             policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
704                             policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
705                             allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
706                             if (!allocPassesPolicy) {
707                                 retVal = RM_SERVICE_DENIED_EXCLUSIVE_RES_ALLOCD;
708                             }
709                         }
710                     }
711                     if (allocPassesPolicy && (matchingNode->allocationCount == 1)) {
712                         /* Check exclusive privileges of instance that currently owns resource */
713                         policyCheckCfg.type = Rm_policyCheck_EXCLUSIVE;
714                         policyCheckCfg.validInstNode = matchingNode->ownerList->instNameNode;
715                         allocPassesPolicy = !rmPolicyCheckPrivilege(&policyCheckCfg, &retVal);
716                         if (!allocPassesPolicy) {
717                             retVal = RM_SERVICE_DENIED_ALLOCD_TO_EXCLUSIVE_INST;
718                         }                
719                     }  
720                 }
721             }
722             
723             if (allocPassesPolicy) {
724                 /* Handle any possible node combinations if requesting instance is
725                  * not already in resource's owner list.  Automatic approval if requesting
726                  * instance is already in owner list. */
727                 if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd)) {
728                     /* findNode range matches matchingNode range
729                      *
730                      *   |<--left node-->||<--matched  node-->||<--right node-->| => existing node
731                      *                    |<--alloc request-->|  => requested resources
732                      */                     
733                     leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
734                     rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
735                     RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
736                     allocatorResNodeOwnerAdd(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
738                     if (leftNode && allocatorResNodeOwnerCompare(rmHandle, leftNode, matchingNode) &&
739                         allocatorResNodeBoundaryCompare(leftNode, matchingNode)) {
740                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
741                         combineLeft = RM_TRUE;
742                     }
743                     if (rightNode && allocatorResNodeOwnerCompare(rmHandle, rightNode, matchingNode) &&
744                         allocatorResNodeBoundaryCompare(rightNode, matchingNode)) {
745                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
746                         combineRight = RM_TRUE;
747                     }
749                     if (combineLeft && combineRight) {
750                         /* Combine all three nodes into matchingNode */
751                         matchingNode->base = leftNode->base;
752                         matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;
754                         allocatorResNodeOwnerClear(rmHandle, leftNode);
755                         rmResourceNodeFree(leftNode);
756                         allocatorResNodeOwnerClear(rmHandle, rightNode);
757                         rmResourceNodeFree(rightNode);                        
758                     }
759                     else if (combineLeft) {
760                         /* Combine left and matching nodes.  Reinsert right. */
761                         matchingNode->base = leftNode->base;
762                         matchingNode->length += leftNode->length;
764                         allocatorResNodeOwnerClear(rmHandle, leftNode);
765                         rmResourceNodeFree(leftNode);
766                         if (rightNode) {
767                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);  
768                         }
769                     }
770                     else if (combineRight) {
771                         /* Combine right and matching nodes.  Reinsert left. */
772                         matchingNode->length += rightNode->length;
774                         allocatorResNodeOwnerClear(rmHandle, rightNode);
775                         rmResourceNodeFree(rightNode);
776                         if (leftNode) {
777                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
778                         }
779                     }
780                     else {
781                         /* No combine. */
782                         if (leftNode) {
783                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
784                         }
785                         if (rightNode) {
786                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
787                         }
788                     }
790                     /* Always reinsert matchingNode */                
791                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
792                     
793                     /* Matching node contains new reference count after alloc.  Return new owner count
794                      * and originating instance allocation reference count. */
795                     opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
796                     opInfo->resourceInfo->instAllocCount = allocatorResNodeOwnerGetRefCnt(rmHandle, matchingNode,
797                                                                                           opInfo->serviceSrcInstNode);
798                 }   
799                 else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {
800                     /* findNode range is subset of matchingNode range and neither boundary is
801                      * equivalent.
802                      *
803                      * |<----------matched node---------->|
804                      *        |<---alloc request--->|
805                      */ 
806                     RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
807                     leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);
808                     allocatorResNodeOwnerCopy(rmHandle, leftNode, matchingNode);
809                     rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);
810                     allocatorResNodeOwnerCopy(rmHandle, rightNode, matchingNode);
812                     matchingNode->base = findNode.base;                                    
813                     matchingNode->length = findNode.length;
814                     allocatorResNodeOwnerAdd(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
816                     /* Insert all the nodes */
817                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
818                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
819                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
820                     
821                     /* Matching node contains new reference count after alloc.  Return new owner count
822                      * and originating instance allocation reference count. */
823                     opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
824                     opInfo->resourceInfo->instAllocCount = allocatorResNodeOwnerGetRefCnt(rmHandle, matchingNode, 
825                                                                                           opInfo->serviceSrcInstNode);
826                 }  
827                 else {    
828                     if (findNode.base == matchingNode->base) {
829                         /* findNode base and matchingNode base are equivalent.  May be combine
830                          * possibilities to the left
831                          *
832                          * |<---left node (alloc'd)--->||<----------matched node---------->|
833                          *                              |<---findNode (alloc req)--->|
834                          */                         
835                         leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
836                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
837                         /* Add allocating instance to owner list for compare with leftNode */
838                         allocatorResNodeOwnerAdd(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
839                         
840                         if (leftNode && allocatorResNodeOwnerCompare(rmHandle, leftNode, matchingNode) &&
841                             allocatorResNodeBoundaryCompare(leftNode, matchingNode)) {
842                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
843                             /* Combine leftNode and findNode */
844                             leftNode->length += findNode.length;
845                         }
846                         else {
847                             leftNode = rmResourceNodeNew(findNode.base, findNode.length);
848                             allocatorResNodeOwnerCopy(rmHandle, leftNode, matchingNode);
849                         }
851                         /* Account for leftNode in matchingNode */
852                         matchingNode->base = findNode.base + findNode.length;
853                         matchingNode->length = matchingEnd - findEnd;  
855                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
856                         /* Left node contains new reference count after alloc.  Return new owner count
857                          * and originating instance allocation reference count. */
858                         opInfo->resourceInfo->ownerCount = leftNode->allocationCount;
859                         opInfo->resourceInfo->instAllocCount = allocatorResNodeOwnerGetRefCnt(rmHandle, leftNode, 
860                                                                                               opInfo->serviceSrcInstNode);
861                     }
862                     else if (findEnd == matchingEnd) {
863                         /* findNode end and matchingNode end are equivalent.  May be combine
864                          * possibilities to the right
865                          *
866                          * |<----------matched node---------->||<---right node (alloc'd)--->|
867                          *       |<---findNode (alloc req)--->| 
868                          */                        
869                         rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
870                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
871                         /* Add allocating instance to owner list for compare with rightNode */
872                         allocatorResNodeOwnerAdd(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
873                         
874                         if (rightNode && allocatorResNodeOwnerCompare(rmHandle, rightNode, matchingNode) &&
875                             allocatorResNodeBoundaryCompare(rightNode, matchingNode)) {
876                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
877                             /* Combine rightNode and findNode */
878                             rightNode->base = findNode.base;
879                             rightNode->length += findNode.length;
880                         }
881                         else {
882                             rightNode = rmResourceNodeNew(findNode.base, findNode.length);
883                             allocatorResNodeOwnerCopy(rmHandle, rightNode, matchingNode);
884                         }
886                         /* Account for rightNode in matchingNode */
887                         matchingNode->length -= findNode.length;  
889                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
890                         /* Right node contains new reference count after alloc.  Return new owner count
891                          * and originating instance allocation reference count. */
892                         opInfo->resourceInfo->ownerCount = rightNode->allocationCount;
893                         opInfo->resourceInfo->instAllocCount = allocatorResNodeOwnerGetRefCnt(rmHandle, rightNode, 
894                                                                                               opInfo->serviceSrcInstNode);
895                     }
896                     /* Remove allocating instance from leftover matchingNode */
897                     allocatorResNodeOwnerDelete(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
898                     RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
899                 }
900                 retVal = RM_SERVICE_APPROVED;
901             }
902         }
903         else {
904             retVal = RM_SERVICE_DENIED_PARTIAL_ALLOCATION;
905         }
906     }
907     else {
908         retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;
909     }
911     return(retVal);        
914 /* FUNCTION PURPOSE: Frees an allocator resource
915  ***********************************************************************
916  * DESCRIPTION: Will attempt to free the resource with specified
917  *              base and length from the resource's allocator.  The
918  *              free algorithm will verify the free request parameters
919  *              match an allocated range for the resource and that the
920  *              range is owned by the instance requesting the free. If
921  *              the free is validated the algorithm will free the 
922  *              resource then combine any resource nodes that may have
923  *              become equivalent (in terms of ownership) after the
924  *              allocation.
925  */
926 static int32_t allocatorFree(Rm_Handle rmHandle, Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)
928     Rm_ResourceNode  findNode;
929     Rm_ResourceNode *matchingNode = NULL;
930     Rm_ResourceNode *leftNode = NULL;
931     Rm_ResourceNode *rightNode = NULL;
932     int              combineLeft = RM_FALSE;
933     int              combineRight = RM_FALSE;
934     uint32_t         findEnd;
935     uint32_t         matchingEnd;
936     int32_t          retVal;
938     memset((void *)&findNode, 0, sizeof(findNode));
939     findNode.base = opInfo->resourceInfo->base;
940     findNode.length = opInfo->resourceInfo->length;
941     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
943     if (matchingNode) {
944         findEnd = findNode.base + findNode.length - 1;
945         matchingEnd = matchingNode->base + matchingNode->length - 1;
946         
947         if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd)) {  
948             if (matchingNode->allocationCount) {
949                 if (allocatorResNodeIsOwnedBy(rmHandle, matchingNode, opInfo->serviceSrcInstNode)) {
950                     if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))
951                     {
952                         /* Case 1: Free range equals allocated matched node exactly. Attempt to combine 
953                          *         freed node with nodes to left and right.
954                          *
955                          * |<--left node-->||<---matched node--->||<--right node-->|
956                          *                  |<---free request--->|
957                          */ 
958                         leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
959                         rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
960                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
961                         allocatorResNodeOwnerDelete(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
963                         if (leftNode && allocatorResNodeOwnerCompare(rmHandle, leftNode, matchingNode) &&
964                             allocatorResNodeBoundaryCompare(leftNode, matchingNode)) {
965                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
966                             combineLeft = RM_TRUE;
967                         }
968                         if (rightNode && allocatorResNodeOwnerCompare(rmHandle, rightNode, matchingNode) &&
969                             allocatorResNodeBoundaryCompare(rightNode, matchingNode)) {
970                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
971                             combineRight = RM_TRUE;
972                         }
974                         if (combineLeft && combineRight) {
975                             /* Combine all three nodes into matchingNode */
976                             matchingNode->base = leftNode->base;
977                             matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;
979                             allocatorResNodeOwnerClear(rmHandle, leftNode);
980                             rmResourceNodeFree(leftNode);
981                             allocatorResNodeOwnerClear(rmHandle, rightNode);
982                             rmResourceNodeFree(rightNode);                        
983                         }
984                         else if (combineLeft) {
985                             /* Combine left and matching nodes.  Reinsert right. */
986                             matchingNode->base = leftNode->base;
987                             matchingNode->length += leftNode->length;
989                             allocatorResNodeOwnerClear(rmHandle, leftNode);
990                             rmResourceNodeFree(leftNode);
991                             if (rightNode) {
992                                 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode); 
993                             }
994                         }
995                         else if (combineRight) {
996                             /* Combine right and matching nodes.  Reinsert left. */
997                             matchingNode->length += rightNode->length;
999                             allocatorResNodeOwnerClear(rmHandle, rightNode);
1000                             rmResourceNodeFree(rightNode);
1001                             if (leftNode) {
1002                                 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
1003                             }
1004                         }
1005                         else {
1006                             /* No combine. */
1007                             if (leftNode) {
1008                                 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
1009                             }
1010                             if (rightNode) {
1011                                 RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
1012                             }
1013                         }
1015                         /* Always reinsert matchingNode */
1016                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1017                         
1018                         /* Matching node is what remains after free.  Return remaining owner count
1019                          * and originating instance allocation reference count. */
1020                         opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
1021                         opInfo->resourceInfo->instAllocCount = allocatorResNodeOwnerGetRefCnt(rmHandle, matchingNode,
1022                                                                                               opInfo->serviceSrcInstNode);
1023                     }
1024                     else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd)) {
1025                         /* Case 2: Free range is less than range in matched node. Split
1026                          *         matched node into three nodes.
1027                          *
1028                          * |<----------matched node---------->|
1029                          *        |<---free request--->|
1030                          *
1031                          * Remove instance from owner list then add it back in for side nodes for
1032                          * proper accounting of allocations in validInstance list
1033                          */ 
1034                         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1035                         allocatorResNodeOwnerDelete(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
1036                         
1037                         leftNode = rmResourceNodeNew(matchingNode->base, findNode.base - matchingNode->base);
1038                         allocatorResNodeOwnerCopy(rmHandle, leftNode, matchingNode);
1039                         allocatorResNodeOwnerAdd(rmHandle, leftNode, opInfo->serviceSrcInstNode);
1040                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
1041                         
1042                         rightNode = rmResourceNodeNew(findNode.base + findNode.length, matchingEnd - findEnd);
1043                         allocatorResNodeOwnerCopy(rmHandle, rightNode, matchingNode);
1044                         allocatorResNodeOwnerAdd(rmHandle, rightNode, opInfo->serviceSrcInstNode);
1045                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
1047                         matchingNode->base = findNode.base;                                    
1048                         matchingNode->length = findNode.length;
1049                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1050                         
1051                         /* Matching node is what remains after free.  Return remaining owner count
1052                          * and originating instance allocation reference count. */
1053                         opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
1054                         opInfo->resourceInfo->instAllocCount = allocatorResNodeOwnerGetRefCnt(rmHandle, matchingNode,
1055                                                                                               opInfo->serviceSrcInstNode);
1056                     }
1057                     else {                        
1058                         if (findNode.base == matchingNode->base) {
1059                             /* Case 3: Free range is on left boundary of matched node. Try to 
1060                              *         combine free range with left node.
1061                              *
1062                              * |<---left node (free)--->||<----------matched node---------->|
1063                              *                           |<---findNode (free req)--->|
1064                              */ 
1066                             leftNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1067                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1068                             /* Remove freeing instance from owner list for compare with leftNode */
1069                             allocatorResNodeOwnerDelete(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
1070                             
1071                             if (leftNode && allocatorResNodeOwnerCompare(rmHandle, leftNode, matchingNode) &&
1072                                 allocatorResNodeBoundaryCompare(leftNode, matchingNode)) {
1073                                 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
1074                                 /* Combine leftNode and findNode */
1075                                 leftNode->length += findNode.length;
1076                             }
1077                             else {
1078                                 leftNode = rmResourceNodeNew(findNode.base, findNode.length);
1079                                 allocatorResNodeOwnerCopy(rmHandle, leftNode, matchingNode);
1080                             }
1082                             /* Remove leftNode range from matchingNode */
1083                             matchingNode->base = findNode.base + findNode.length;
1084                             matchingNode->length = matchingEnd - findEnd;  
1085                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, leftNode);
1086                             
1087                             /* Left node is what remains after free.  Return remaining owner count
1088                              * and originating instance allocation reference count. */
1089                             opInfo->resourceInfo->ownerCount = leftNode->allocationCount;
1090                             opInfo->resourceInfo->instAllocCount = allocatorResNodeOwnerGetRefCnt(rmHandle, leftNode,
1091                                                                                                   opInfo->serviceSrcInstNode);
1092                         }
1093                         else if (findEnd == matchingEnd) {
1094                             /* Case 4: Free range is on right boundary of matched node. Try to 
1095                              *         combine free range with right node.
1096                              *
1097                              * |<----------matched node---------->||<---right node (free)--->|
1098                              *        |<---findNode (free req)--->|
1099                              */ 
1100                             
1101                             rightNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1102                             RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode); 
1103                             /* Remove freeing instance from owner list for compare with rightNode */
1104                             allocatorResNodeOwnerDelete(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
1105                             
1106                             if (rightNode && allocatorResNodeOwnerCompare(rmHandle, rightNode, matchingNode) &&
1107                                 allocatorResNodeBoundaryCompare(rightNode, matchingNode)) {
1108                                 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
1109                                 /* Combine rightNode and findNode */
1110                                 rightNode->base = findNode.base;
1111                                 rightNode->length += findNode.length;
1112                             }
1113                             else {
1114                                 rightNode = rmResourceNodeNew(findNode.base, findNode.length);
1115                                 allocatorResNodeOwnerCopy(rmHandle, rightNode, matchingNode);
1116                             }
1118                             /* Remove rightNode range from matchingNode */
1119                             matchingNode->length -= findNode.length;  
1120                             RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, rightNode);
1121                             
1122                             /* Right node is what remains after free.  Return remaining owner count
1123                              * and originating instance allocation reference count. */
1124                             opInfo->resourceInfo->ownerCount = rightNode->allocationCount;
1125                             opInfo->resourceInfo->instAllocCount = allocatorResNodeOwnerGetRefCnt(rmHandle, rightNode,
1126                                                                                                   opInfo->serviceSrcInstNode);
1127                         }
1129                         /* Add freeing instance back into matchingNode allocations */
1130                         allocatorResNodeOwnerAdd(rmHandle, matchingNode, opInfo->serviceSrcInstNode);
1131                         RB_INSERT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1132                     }
1133                     retVal = RM_SERVICE_APPROVED;
1134                 }
1135                 else {
1136                     /* Return owner count and instance alloc count.  In case it's a reference count
1137                      * check in application */
1138                     opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
1139                     opInfo->resourceInfo->instAllocCount = allocatorResNodeOwnerGetRefCnt(rmHandle, matchingNode,
1140                                                                                           opInfo->serviceSrcInstNode);
1141                     retVal = RM_SERVICE_DENIED_RES_NOT_ALLOCD_TO_INST;
1142                 }
1143             }
1144             else {
1145                 /* Return owner count and instance alloc count.  In case it's a reference count
1146                  * check in application */
1147                 opInfo->resourceInfo->ownerCount = matchingNode->allocationCount;
1148                 opInfo->resourceInfo->instAllocCount = allocatorResNodeOwnerGetRefCnt(rmHandle, matchingNode,
1149                                                                                       opInfo->serviceSrcInstNode);
1150                 retVal = RM_SERVICE_DENIED_RES_ALREADY_FREE;
1151             }
1152         }
1153         else {
1154             retVal = RM_SERVICE_DENIED_PARTIAL_FREE;
1155         }
1156     }
1157     else {
1158         retVal = RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST;
1159     }
1160     return(retVal);  
1163 /* FUNCTION PURPOSE: Reserves a Linux resource
1164  ***********************************************************************
1165  * DESCRIPTION: Reserves resources for Linux using the base and length
1166  *              values retrieved from the Linux DTB via the
1167  *              "linux-dtb-alias" properties within the GRL.
1168  */
1169 static int32_t allocatorReserveLinuxResource(Rm_Handle rmHandle, Rm_LinuxAlias *linuxAlias, 
1170                                              Rm_LinuxValueRange *linuxValues, Rm_AllocatorOpInfo *opInfo)
1172     int32_t   retVal = RM_OK;
1173     int       baseFound = RM_FALSE;
1174     int       lengthFound = RM_FALSE;
1175     uint32_t  valueIndex = 0;
1177     while ((linuxValues) && (!baseFound || !lengthFound)) {
1178         if (linuxAlias->baseOffset == valueIndex) {
1179             opInfo->resourceInfo->base = linuxValues->value;
1180             baseFound = RM_TRUE;
1182             if (linuxAlias->lengthOffset == RM_DTB_UTIL_LINUX_ALIAS_OFFSET_NOT_SET) {
1183                 opInfo->resourceInfo->length = 1;
1184                 lengthFound = RM_TRUE;
1185             }
1186         }
1187         else if (linuxAlias->lengthOffset == valueIndex) {
1188             opInfo->resourceInfo->length = linuxValues->value;
1189             lengthFound = RM_TRUE;
1190         }
1192         linuxValues = (Rm_LinuxValueRange *)linuxValues->nextValue;
1193         valueIndex++;
1194     }
1196     if (!baseFound || !lengthFound) {
1197         retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;
1198     }
1199     else {
1200         /* Allocate resource to Linux */
1201         retVal = rmAllocatorOperation(rmHandle, opInfo);
1202         if (retVal == RM_SERVICE_APPROVED) {
1203             retVal = RM_OK;
1204         }
1205     }
1206     return (retVal);
1209 /* FUNCTION PURPOSE: Finds and reserves Linux resources
1210  ***********************************************************************
1211  * DESCRIPTION: Parses the Linux DTB for resources consumed by the
1212  *              Linux kernel.  If the resource is found via the
1213  *              "linux-dtb-alias" property defined in the GRL it is 
1214  *              reserved.
1215  */
1216 static int32_t allocatorFindLinuxResource(Rm_Handle rmHandle, const char *resourceName, void *linuxDtb, 
1217                                           Rm_LinuxAlias *linuxAlias)
1219     Rm_Inst            *rmInst = (Rm_Inst *)rmHandle;
1220     Rm_AllocatorOpInfo  opInfo;
1221     Rm_ResourceInfo     resourceInfo;
1222     uint32_t            pathOffset;
1223     uint32_t            pathSize;
1224     char               *spacePtr;
1225     int32_t             propOffset;
1226     int32_t             nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
1227     int32_t             prevDepth = RM_DTB_UTIL_STARTING_DEPTH;
1228     int32_t             depth = RM_DTB_UTIL_STARTING_DEPTH;
1229     int32_t             propertyLen;
1230     const char         *propertyName;
1231     const void         *propertyData; 
1232     Rm_LinuxValueRange *linuxValueRange;
1233     int32_t             retVal = RM_OK; 
1235     memset((void *)&opInfo, 0, sizeof(opInfo));
1236     memset((void *)&resourceInfo, 0, sizeof(resourceInfo));
1238     strncpy(resourceInfo.name, resourceName, RM_NAME_MAX_CHARS);
1239     opInfo.policy = rmInst->u.server.globalPolicy;
1240     opInfo.serviceSrcInstNode = rmPolicyGetLinuxInstNode(rmHandle);
1241     opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
1242     opInfo.resourceInfo = &resourceInfo;    
1244     while(linuxAlias) {
1245         /* Reset parsing variables */
1246         pathOffset = 0;
1247         pathSize = strlen(linuxAlias->path) + 1;
1248         nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
1249         prevDepth = RM_DTB_UTIL_STARTING_DEPTH;   
1250         resourceInfo.base = 0;
1251         resourceInfo.length = 0;
1253         spacePtr = strpbrk(linuxAlias->path, " ");
1254         if (spacePtr) {
1255             *spacePtr = '\0';
1256         }       
1257         
1258         while(pathOffset < pathSize) {
1259             /* Move through DTB nodes until next alias path node found */
1260             if (strcmp(linuxAlias->path + pathOffset, fdt_get_name(linuxDtb, nodeOffset, NULL))) {
1261                 nodeOffset = fdt_next_node(linuxDtb, nodeOffset, &depth);
1263                 if ((depth < prevDepth) || (nodeOffset == -FDT_ERR_NOTFOUND)) {
1264                     /* Returning from subnode that matched part of alias path without finding
1265                      * resource values */
1266                     retVal = RM_ERROR_DATA_NOT_FOUND_AT_LINUX_ALIAS;
1267                     break;
1268                 }
1269             }
1270             else {
1271                 /* Found next alias path node.  Move to next node name in path string. */
1272                 pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);
1273                 spacePtr = strpbrk(linuxAlias->path + pathOffset, " ");
1274                 if (spacePtr) {
1275                     *spacePtr = '\0';
1276                 }       
1277                 
1278                 prevDepth = fdt_node_depth(linuxDtb, nodeOffset);
1279                 propOffset = fdt_first_property_offset(linuxDtb, nodeOffset);
1280                 while ((propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) &&
1281                        (pathOffset < pathSize)) {
1282                     propertyData = fdt_getprop_by_offset(linuxDtb, propOffset, 
1283                                                          &propertyName, &propertyLen);
1285                     if (strcmp(linuxAlias->path + pathOffset, propertyName) == 0) {
1286                         /* Found resource at end of alias path */
1287                         pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);
1288                         linuxValueRange = rmDtbUtilLinuxExtractValues(propertyData, propertyLen);
1289                         retVal = allocatorReserveLinuxResource(rmHandle, linuxAlias, 
1290                                                                linuxValueRange, &opInfo);
1291                         rmDtbUtilLinuxFreeValues(linuxValueRange);
1292                     }
1293                     propOffset = fdt_next_property_offset(linuxDtb, propOffset);
1294                 } 
1296                 if (propOffset < -FDT_ERR_NOTFOUND) {
1297                     retVal = propOffset;
1298                     break;
1299                 }
1300             }
1301         }
1303         if (retVal < RM_OK) {
1304             break;
1305         }
1306         linuxAlias = linuxAlias->nextLinuxAlias;
1307     }
1308     return (retVal);
1311 /* FUNCTION PURPOSE: Creates and initializes a resource allocator
1312  ***********************************************************************
1313  * DESCRIPTION: Creates a resource allocator for the provided
1314  *              resource name and resource properties retrieved
1315  *              from the GRL.  Resources will be reserved for 
1316  *              the Linux kernel if the Linux DTB is provided
1317  *              and there are "linux-dtb-alias" properties
1318  *              specified in the GRL.
1319  */
1320 static int32_t allocatorExtractGrlResProps(Rm_Handle rmHandle, const char *resourceName, 
1321                                            Rm_ResourceProperties *resourceProperties, void *linuxDtb)
1323     Rm_Inst             *rmInst = (Rm_Inst *)rmHandle;
1324     Rm_ResourceRange    *range = NULL;
1325     Rm_ResourceRange    *rangeBasePtr = NULL;
1326     Rm_NsAssignment     *nsAssignments = NULL;
1327     Rm_NsAssignment     *nsAssignmentBasePtr = NULL;
1328     Rm_LinuxAlias       *linuxAlias = NULL;
1329     Rm_NameServerObjCfg  nameServerObjCfg;      
1330     int32_t              retVal = RM_OK;
1332     if (resourceProperties->rangeData && (resourceProperties->rangeLen > 0)) {
1333         range = rangeBasePtr = rmDtbUtilResExtractRange(resourceProperties->rangeData, 
1334                                                         resourceProperties->rangeLen);
1335         
1336         if ((retVal = rmAllocatorCreate(rmHandle, resourceName, range)) >= RM_OK) {
1337             if (resourceProperties->linuxAliasData && resourceProperties->linuxAliasLen) {
1338                 if (linuxDtb) {
1339                     linuxAlias = rmDtbUtilResExtractLinuxAlias(resourceProperties->linuxAliasData,
1340                                                                resourceProperties->linuxAliasLen, &retVal);
1341                     if (linuxAlias) {
1342                         retVal = allocatorFindLinuxResource(rmHandle, resourceName, linuxDtb, linuxAlias);            
1343                     }
1344                 }
1345             }
1346         }
1347     }
1348     
1349     if (retVal >= RM_OK) {
1350         if (resourceProperties->nsAssignData && resourceProperties->nsAssignLen) {
1351             nsAssignments = rmDtbUtilResExtractNsAssignment(resourceProperties->nsAssignData, 
1352                                                             resourceProperties->nsAssignLen, &retVal);
1353             if (nsAssignments) {
1354                 nsAssignmentBasePtr = nsAssignments;
1355                 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1356                     rmNameServerTreeInv(rmInst->u.server.nameServer);
1357                 }                  
1358                 while (nsAssignments) {
1359                     memset((void *)&nameServerObjCfg, 0, sizeof(nameServerObjCfg));
1360                     nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
1361                     nameServerObjCfg.nodeCfg.objName = nsAssignments->nsName;
1362                     nameServerObjCfg.nodeCfg.resourceName = (char *)resourceName;
1363                     nameServerObjCfg.nodeCfg.resourceBase= nsAssignments->resourceBase;
1364                     nameServerObjCfg.nodeCfg.resourceLength = nsAssignments->resourceLength;                
1365                     rmNameServerAddObject(&nameServerObjCfg);
1366                     nsAssignments = nsAssignments->nextNsAssignment;
1367                 }
1368                 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1369                     rmNameServerTreeWb(rmInst->u.server.nameServer);
1370                 }                
1371                 rmDtbUtilResFreeNsAssignmentList(nsAssignmentBasePtr);
1372             }
1373         }
1374     }
1375     else {
1376         rmAllocatorDelete(rmHandle, resourceName);
1377     }
1379     rmDtbUtilResFreeRange(rangeBasePtr);
1380     if (linuxAlias) {
1381         rmDtbUtilResFreeLinuxAlias(linuxAlias);
1382     }
1383     return(retVal);
1386 /**********************************************************************
1387  ********************** Internal Functions ****************************
1388  **********************************************************************/
1390 /* FUNCTION PURPOSE: Creates a new resource tree
1391  ***********************************************************************
1392  * DESCRIPTION: Creates and populates a new resource tree allocator
1393  *              using the provided resource name and value range.  The
1394  *              name and value originate from the GRL.
1395  */
1396 int32_t rmAllocatorCreate(Rm_Handle rmHandle, const char *resourceName, Rm_ResourceRange *range)
1398     Rm_Inst         *rmInst = (Rm_Inst *)rmHandle;
1399     Rm_Allocator    *allocator = NULL;
1400     Rm_ResourceTree *treeRoot = NULL;
1401     Rm_ResourceNode *treeNode = NULL;
1403     allocator = allocatorAdd(rmHandle, resourceName);
1404     treeRoot = Rm_osalMalloc(sizeof(*treeRoot));
1405     RB_INIT(treeRoot);
1407     while (range != NULL) {
1408         treeNode = rmResourceNodeNew(range->base, range->length);
1409         RB_INSERT(_Rm_AllocatorResourceTree, treeRoot, treeNode);
1410         range = range->nextRange;
1411     }
1412     if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1413         rmResourceTreeWb(treeRoot);
1414     }
1415     
1416     allocator->allocatorRootEntry = treeRoot;
1417     RM_SS_OBJ_WB(allocator, Rm_Allocator);
1418     return(RM_OK);
1421 /* FUNCTION PURPOSE: Returns a pointer to the allocator list
1422  ***********************************************************************
1423  * DESCRIPTION: Returns a pointer to the instance's allocator list
1424  *              based on the instance type
1425  */
1426 Rm_Allocator *rmAllocatorGetAllocatorList(Rm_Handle rmHandle)
1428     Rm_Inst      *rmInst = (Rm_Inst *)rmHandle;
1429     Rm_Allocator *list = NULL;
1431     if ((rmInst->instType == Rm_instType_SERVER) ||
1432         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1433         list = rmInst->u.server.allocators;
1434     }
1435     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1436         list = rmInst->u.cd.allocators;
1437     }
1438     return(list);
1441 /* FUNCTION PURPOSE: Finds an allocator
1442  ***********************************************************************
1443  * DESCRIPTION: Returns a pointer to an allocator that matches the 
1444  *              provided resource name.
1445  */
1446 Rm_Allocator *rmAllocatorFind(Rm_Handle rmHandle, const char *resourceName)
1448     Rm_Inst      *rmInst = (Rm_Inst *)rmHandle;
1449     Rm_Allocator *allocatorList = rmAllocatorGetAllocatorList(rmHandle);
1450     
1451     while (allocatorList) {
1452         RM_SS_OBJ_INV(allocatorList, Rm_Allocator);
1453         if (strncmp(allocatorList->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {
1454             break;             
1455         }
1456         allocatorList = allocatorList->nextAllocator;
1457     }
1459     return (allocatorList);
1462 /* FUNCTION PURPOSE: Checks if a resource node is localized
1463  ***********************************************************************
1464  * DESCRIPTION: Checks if a resource node is localized.  A localized
1465  *              node is one that is free and has no neighboring nodes
1466  *              or neighboring nodes that do not have resource values
1467  *              contiguous with the node being checked.  The function
1468  *              will return RM_TRUE is the node is localized.  
1469  *              Otherwise, the function returns RM_FALSE
1470  */
1471 int rmAllocatorGetNodeLocalization(Rm_Handle rmHandle, char *resourceName, 
1472                                    int32_t *resBase, uint32_t *resLen)
1474     Rm_Inst         *rmInst = (Rm_Inst *)rmHandle;
1475     void *           policy = rmPolicyGetPolicy((Rm_Handle)rmInst);
1476     int32_t          resOffsetInPolicy = rmPolicyGetResourceOffset(policy, resourceName);
1477     uint32_t         allocSize = rmPolicyGetResourceCdAllocSize(policy, resOffsetInPolicy);    
1478     Rm_Allocator    *allocator = rmAllocatorFind(rmHandle, resourceName);
1479     Rm_ResourceNode  findNode;
1480     Rm_ResourceNode *matchingNode = NULL;
1481     Rm_ResourceNode *neighborNode = NULL;   
1482     int              nodeIsLocalized;
1484     memset((void *)&findNode, 0, sizeof(findNode));
1485     findNode.base = *resBase;
1486     findNode.length = *resLen;
1487     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
1489     if (matchingNode) {
1490         /* Node can be freed back to Server from CD if:
1491          * - allocationCount == 0
1492          * - node's resource range is multiple of policy allocation size
1493          * - node's resource range boundaries are not contiguous with surrounding nodes */
1494         if (matchingNode->allocationCount) {
1495             nodeIsLocalized = RM_FALSE;
1496             goto exitLocalization;
1497         }
1498             
1499         if (matchingNode->length % allocSize) {
1500             nodeIsLocalized = RM_FALSE;
1501             goto exitLocalization;        
1502         }
1504         /* Check left neighbor */
1505         neighborNode = RB_PREV(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1506         if (neighborNode && allocatorResNodeBoundaryCompare(neighborNode, matchingNode)) {
1507             nodeIsLocalized = RM_FALSE;
1508             goto exitLocalization; 
1509         }
1511         /* Check right neighbor */
1512         neighborNode = RB_NEXT(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1513         if (neighborNode && allocatorResNodeBoundaryCompare(neighborNode, matchingNode)) {
1514             nodeIsLocalized = RM_FALSE;
1515             goto exitLocalization; 
1516         }
1518         /* All localization checks passed.  Return the base and length of localized node. */
1519         nodeIsLocalized = RM_TRUE;
1520         *resBase = matchingNode->base;
1521         *resLen = matchingNode->length;
1522     }
1523     else {
1524         nodeIsLocalized = RM_FALSE;
1525     }
1527 exitLocalization:
1528     return (nodeIsLocalized);
1531 /* FUNCTION PURPOSE: Issues an allocator operation
1532  ***********************************************************************
1533  * DESCRIPTION: Issues an allocator preallocate, allocate, or free
1534  *              for an RM resource.
1535  */
1536 int32_t rmAllocatorOperation(Rm_Handle rmHandle, Rm_AllocatorOpInfo *opInfo)
1538     Rm_Inst      *rmInst = (Rm_Inst *)rmHandle;
1539     Rm_Allocator *allocator = NULL;
1540     int32_t       resourceOffsetInPolicy;
1541     int32_t       retVal;
1542     
1543     resourceOffsetInPolicy = rmPolicyGetResourceOffset(opInfo->policy, opInfo->resourceInfo->name);
1544     allocator = rmAllocatorFind(rmHandle, opInfo->resourceInfo->name);
1545     
1546     if ((resourceOffsetInPolicy > 0) && allocator) {
1547         if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1548             rmResourceTreeInv(allocator->allocatorRootEntry);
1549         }
1551         if (opInfo->operation == Rm_allocatorOp_GET_STATUS) {
1552             retVal = allocatorStatus(rmHandle, allocator, opInfo);
1553         }
1554         else if ((opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE_INIT) ||
1555                  (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE_USE)) {
1556             retVal = allocatorPreAllocate(rmHandle, allocator, resourceOffsetInPolicy, opInfo);
1557         }               
1558         else if ((opInfo->operation == Rm_allocatorOp_ALLOCATE_INIT) ||
1559                  (opInfo->operation == Rm_allocatorOp_ALLOCATE_USE)) {
1560             retVal = allocatorAllocate(rmHandle, allocator, resourceOffsetInPolicy, opInfo);
1561         }
1562         else if (opInfo->operation == Rm_allocatorOp_FREE) {
1563             retVal = allocatorFree(rmHandle, allocator, opInfo);
1564         } 
1566         if ((rmInst->instType == Rm_instType_SHARED_SERVER) &&
1567             (opInfo->operation != Rm_allocatorOp_GET_STATUS) &&
1568             (retVal == RM_SERVICE_APPROVED)) {
1569             rmResourceTreeWb(allocator->allocatorRootEntry);
1570         }        
1571     }
1572     else {
1573         /* Resource could not be found in policy and/or allocator */
1574         retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
1575     }
1576     return(retVal);
1579 /* FUNCTION PURPOSE: Initializes server allocators
1580  ***********************************************************************
1581  * DESCRIPTION: Creates and initializes a server instance's
1582  *              resource allocators using the GRL and, if
1583  *              provided, Linux DTB.
1584  */
1585 int32_t rmAllocatorInitializeResources(Rm_Handle rmHandle, void *globalResourceDtb, void *linuxDtb)
1587     int32_t                nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;
1588     int32_t                nodeDepth = RM_DTB_UTIL_STARTING_DEPTH;
1589     Rm_ResourceProperties  resProperties;    
1590     int32_t                propOffset;
1591     int32_t                propertyLen;
1592     const char            *propertyName;
1593     const void            *propertyData;
1594     Rm_ResourcePropType    propertyType;  
1595     int32_t                retVal = RM_OK;
1597     /* Parse the Global Resource List, creating an allocator for each specified resource node */
1598     while ((nodeOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && (nodeDepth >= RM_DTB_UTIL_STARTING_DEPTH)) {
1599         memset((void *)&resProperties, 0, sizeof(resProperties));
1600         /* Get properties of resource node */
1601         propOffset = fdt_first_property_offset(globalResourceDtb, nodeOffset);
1602         while (propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) {
1603             propertyData = fdt_getprop_by_offset(globalResourceDtb, propOffset, &propertyName, &propertyLen);
1604             propertyType = rmDtbUtilResGetPropertyType(propertyName);
1605             if (propertyType == Rm_resourcePropType_RESOURCE_RANGE) {
1606                 resProperties.rangeData = propertyData;
1607                 resProperties.rangeLen = propertyLen;
1608             }
1609             else if (propertyType == Rm_resourcePropType_NSASSIGNMENT) {
1610                 resProperties.nsAssignData = propertyData;
1611                 resProperties.nsAssignLen = propertyLen;
1612             }
1613             else if (propertyType == Rm_resourcePropType_RESOURCE_LINUX_ALIAS) {
1614                 resProperties.linuxAliasData = propertyData;
1615                 resProperties.linuxAliasLen = propertyLen;
1616             }        
1617             else {
1618                 retVal = RM_ERROR_GRL_UNKNOWN_RESOURCE_PROPERTY;
1619                 goto exitAllocInit;
1620             }
1622             propOffset = fdt_next_property_offset(globalResourceDtb, propOffset);
1623             if (propOffset == -FDT_ERR_NOTFOUND) {
1624                 /* No more resource properties but at least one found.  Extract the property values */
1625                 retVal = allocatorExtractGrlResProps(rmHandle, fdt_get_name(globalResourceDtb, nodeOffset, NULL), 
1626                                                      &resProperties, linuxDtb);
1627                 if (retVal < RM_OK) {
1628                     goto exitAllocInit;
1629                 }
1630             }
1631             else if (propOffset < -FDT_ERR_NOTFOUND) {
1632                 /* Error returned by LIBFDT */
1633                 retVal = propOffset;
1634                 goto exitAllocInit;
1635             }
1636         }
1637         if (propOffset < -FDT_ERR_NOTFOUND) {
1638             /* Error returned by LIBFDT */
1639             retVal = propOffset;
1640             goto exitAllocInit;
1641         }
1643         nodeOffset = fdt_next_node(globalResourceDtb, nodeOffset, &nodeDepth);
1644         if (nodeOffset < -FDT_ERR_NOTFOUND) {
1645             /* Error returned by LIBFDT */
1646             retVal = nodeOffset;
1647             goto exitAllocInit;
1648         }
1649     }
1650 exitAllocInit:    
1651     return(retVal);
1654 /* FUNCTION PURPOSE: Deletes a resource allocator resource node
1655  ***********************************************************************
1656  * DESCRIPTION: Deletes a resource allocator's node based on the given
1657  *              resource name, base and length.
1658  */
1659 void rmAllocatorDeleteNode(Rm_Handle rmHandle, const char *resName, int32_t resBase, uint32_t resLen)
1661     Rm_Allocator    *allocator = rmAllocatorFind(rmHandle, resName);
1662     Rm_ResourceNode  findNode;
1663     Rm_ResourceNode *matchingNode;
1665     memset((void *)&findNode, 0, sizeof(findNode));
1666     findNode.base = resBase;
1667     findNode.length = resLen;
1668     matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
1669     
1670     if (matchingNode) {
1671         RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1672         rmResourceNodeFree(matchingNode);
1673     }
1676 /* FUNCTION PURPOSE: Deletes a resource allocator
1677  ***********************************************************************
1678  * DESCRIPTION: Deletes a resource allocator based on the given
1679  *              resource name.  The resource allocator will be
1680  *              removed from the RM instance allocator list.
1681  */
1682 int32_t rmAllocatorDelete(Rm_Handle rmHandle, const char *resourceName)
1684     Rm_Inst         *rmInst = (Rm_Inst *)rmHandle;    
1685     Rm_Allocator    *allocator = rmAllocatorGetAllocatorList(rmHandle);
1686     Rm_Allocator    *prevAllocator = NULL;
1687     Rm_ResourceTree *treeRoot;
1688     Rm_ResourceNode *node = NULL;
1689     Rm_ResourceNode *nextNode = NULL;
1690     int32_t          retVal = RM_OK;
1692     while (allocator) {
1693         if (strncmp(allocator->resourceName, resourceName, RM_NAME_MAX_CHARS) == 0) {
1694             break;             
1695         }
1696         prevAllocator = allocator;
1697         allocator = allocator->nextAllocator;
1698     }
1700     if (allocator) {
1701         if (prevAllocator == NULL) {
1702             if ((rmInst->instType == Rm_instType_SERVER) ||
1703                 (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1704                 rmInst->u.server.allocators = allocator->nextAllocator;
1705             }
1706             else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1707                 rmInst->u.cd.allocators = allocator->nextAllocator;
1708             }              
1709         }
1710         else {
1711             prevAllocator->nextAllocator = allocator->nextAllocator;
1712             RM_SS_OBJ_WB(prevAllocator, Rm_Allocator);
1713         }
1714             
1715         /* Destroy tree and return error */
1716         treeRoot = allocator->allocatorRootEntry;
1717         for (node = RB_MIN(_Rm_AllocatorResourceTree, treeRoot); node != NULL; node = nextNode) {
1718                 nextNode = RB_NEXT(_Rm_AllocatorResourceTree, treeRoot, node);
1719                 RB_REMOVE(_Rm_AllocatorResourceTree, treeRoot, nextNode);
1720             rmResourceNodeFree(node);
1721         }
1722         Rm_osalFree((void *)treeRoot, sizeof(*treeRoot));        
1723         Rm_osalFree((void *)allocator, sizeof(*allocator));
1724     }
1725     else {
1726         retVal = RM_ERROR_RES_ALLOCATOR_DOES_NOT_EXIST;
1727     }
1728     return (retVal);
1731 /* FUNCTION PURPOSE: Deletes server allocators
1732  ***********************************************************************
1733  * DESCRIPTION: Removes all resource nodes for each
1734  *              resource allocator and then deletes the allocator
1735  *              itself.  Used to free all memory consumed
1736  *              by the allocators.
1737  */
1738 void rmAllocatorDeleteResources(Rm_Handle rmHandle)
1740     Rm_Inst         *rmInst = (Rm_Inst *)rmHandle;
1741     Rm_Allocator    *allocatorList = rmAllocatorGetAllocatorList(rmHandle);
1742     Rm_Allocator    *nextAllocator;
1743     Rm_ResourceTree *resTree;
1744     Rm_ResourceNode *resNode;
1745     Rm_ResourceNode *nextResNode;
1747     while (allocatorList) {
1748         RM_SS_OBJ_INV(allocatorList, Rm_Allocator);
1749         nextAllocator = allocatorList->nextAllocator;
1750         resTree = allocatorList->allocatorRootEntry;
1752         if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1753             rmResourceTreeInv(resTree);
1754         }
1755         /* Delete each resource node in the allocator */
1756         for (resNode = RB_MIN(_Rm_AllocatorResourceTree, resTree); resNode != NULL; resNode = nextResNode) {
1757             nextResNode = RB_NEXT(_Rm_AllocatorResourceTree, resTree, resNode);
1758             RB_REMOVE(_Rm_AllocatorResourceTree, resTree, resNode);
1759             if (resNode->allocationCount) {
1760                 /* Delete all the owners in the resource's owner list */
1761                 allocatorResNodeOwnerClear(rmHandle, resNode);
1762             }
1763             rmResourceNodeFree(resNode);
1764         }        
1766         Rm_osalFree((void *)resTree, sizeof(*resTree));
1767         Rm_osalFree((void *)allocatorList, sizeof(*allocatorList));
1768         allocatorList = nextAllocator;
1769     }