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);
104 }
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)
113 {
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);
125 }
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)
132 {
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 }
145 }
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)
152 {
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 }
165 }
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)
172 {
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);
185 }
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)
194 {
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 }
231 }
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)
239 {
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);
256 }
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)
264 {
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 }
304 return(RM_TRUE);
305 }
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)
315 {
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 }
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 }
348 }
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)
359 {
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 }
388 }
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)
396 {
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 }
410 }
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)
421 {
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);
451 }
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 }
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 }
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;
522 do {
523 matchingNode = RB_FIND(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, &findNode);
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);
539 if (nodePassesPolicy && (matchingNode->allocationCount > 0)) {
540 policyCheckCfg.validInstNode = opInfo->serviceSrcInstNode;
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 }
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 }
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 }
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);
614 }
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)
629 {
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;
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 }
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);
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);
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);
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);
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);
912 }
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)
927 {
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;
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);
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);
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);
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);
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);
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);
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 */
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);
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);
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);
1161 }
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)
1171 {
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);
1207 }
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)
1218 {
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 }
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 }
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);
1309 }
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)
1322 {
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);
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 }
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);
1384 }
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)
1397 {
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 }
1416 allocator->allocatorRootEntry = treeRoot;
1417 RM_SS_OBJ_WB(allocator, Rm_Allocator);
1418 return(RM_OK);
1419 }
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)
1427 {
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);
1439 }
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)
1447 {
1448 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
1449 Rm_Allocator *allocatorList = rmAllocatorGetAllocatorList(rmHandle);
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);
1460 }
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)
1473 {
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 }
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);
1529 }
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)
1537 {
1538 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
1539 Rm_Allocator *allocator = NULL;
1540 int32_t resourceOffsetInPolicy;
1541 int32_t retVal;
1543 resourceOffsetInPolicy = rmPolicyGetResourceOffset(opInfo->policy, opInfo->resourceInfo->name);
1544 allocator = rmAllocatorFind(rmHandle, opInfo->resourceInfo->name);
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);
1577 }
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)
1586 {
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);
1652 }
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)
1660 {
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);
1670 if (matchingNode) {
1671 RB_REMOVE(_Rm_AllocatorResourceTree, allocator->allocatorRootEntry, matchingNode);
1672 rmResourceNodeFree(matchingNode);
1673 }
1674 }
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)
1683 {
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 }
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);
1729 }
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)
1739 {
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 }
1770 }