1 /**
2 * @file rm.c
3 *
4 * @brief
5 * This is the Resource Manager 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 /* Standard includes */
43 #include <stdint.h>
44 #include <string.h>
45 #include <stdbool.h>
47 /* RM external includes */
48 #include <ti/drv/rm/rm.h>
49 #include <ti/drv/rm/rmver.h>
50 #include <ti/drv/rm/rm_services.h>
51 #include <ti/drv/rm/rm_transport.h>
53 /* RM internal includes */
54 #include <ti/drv/rm/include/rm_loc.h>
55 #include <ti/drv/rm/include/rm_allocatorloc.h>
56 #include <ti/drv/rm/include/rm_transportloc.h>
57 #include <ti/drv/rm/include/rm_nameserverloc.h>
59 /* RM LIBFDT includes */
60 #include <ti/drv/rm/util/libfdt/libfdt.h>
62 /* RM OSAL layer */
63 #include <rm_osal.h>
65 /**********************************************************************
66 ************************** Globals ***********************************
67 **********************************************************************/
69 /** @brief Global Variable which describes the RM Version Information */
70 const char rmVersionStr[] = RM_VERSION_STR ":" __DATE__ ":" __TIME__;
72 /**********************************************************************
73 ************************ Local Functions *****************************
74 **********************************************************************/
76 /* FUNCTION PURPOSE: Initializes a RM inst's transaction sequence number
77 ***********************************************************************
78 * DESCRIPTION: The RM instance transaction sequence number can never
79 * have a value of 0 to avoid conflicts with transactions
80 * that have a remoteOriginatingId of 0 (transaction ID
81 * will be used as the remoteOriginatingId for
82 * transactions that are responses to requests).
83 */
84 static uint32_t transactionInitSequenceNum(void)
85 {
86 return (1);
87 }
89 /* FUNCTION PURPOSE: Provides a sequence number for new transactions
90 ***********************************************************************
91 * DESCRIPTION: Returns a sequence number for a new transaction
92 * specific to a RM instance. Handles rollover of
93 * sequence number.
94 */
95 static uint32_t transactionGetSequenceNum(Rm_Inst *rmInst)
96 {
97 rmInst->transactionSeqNum++;
98 if (!rmInst->transactionSeqNum) {
99 rmInst->transactionSeqNum++;
100 }
101 return (rmInst->transactionSeqNum);
102 }
104 /* FUNCTION PURPOSE: Creates a resource request packet
105 ***********************************************************************
106 * DESCRIPTION: Returns a RM packet handle that points to a RM
107 * resource request packet that has been prepared
108 * for sending to another RM instance. The packet
109 * is allocated via the rmAllocPkt API using the
110 * appTransport handle provided by the application
111 */
112 void createResourceReqPkt(Rm_Packet *rmPkt, char *localInstName, Rm_Transaction *transaction)
113 {
114 Rm_ResourceRequestPkt *resourceReqPkt = NULL;
116 rmPkt->pktType = Rm_pktType_RESOURCE_REQUEST;
117 resourceReqPkt = (Rm_ResourceRequestPkt *) rmPkt->data;
118 resourceReqPkt->requestId = transaction->localId;
119 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
120 resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_INIT;
121 }
122 else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
123 resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_USE;
124 }
125 else if (transaction->type == Rm_service_RESOURCE_FREE) {
126 resourceReqPkt->resourceReqType = Rm_resReqPktType_FREE;
127 }
128 else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
129 resourceReqPkt->resourceReqType = Rm_resReqPktType_GET_NAMED;
130 }
131 strncpy(resourceReqPkt->pktSrcInstName, localInstName, RM_NAME_MAX_CHARS);
132 strncpy(resourceReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);
133 memcpy ((void *)&(resourceReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),
134 sizeof(Rm_ResourceInfo));
135 }
137 /* FUNCTION PURPOSE: Creates a resource response packet
138 ***********************************************************************
139 * DESCRIPTION: Returns a RM packet handle that points to a RM
140 * resource response packet that has been prepared
141 * for sending to another RM instance. The packet
142 * is allocated via the rmAllocPkt API using the
143 * appTransport handle provided by the application
144 */
145 void createResourceResponsePkt(Rm_Packet *rmPkt, Rm_Transaction *transaction)
146 {
147 Rm_ResourceResponsePkt *resourceRespPkt = NULL;
149 rmPkt->pktType = Rm_pktType_RESOURCE_RESPONSE;
150 resourceRespPkt = (Rm_ResourceResponsePkt *)rmPkt->data;
151 resourceRespPkt->responseId = transaction->remoteOriginatingId;
152 resourceRespPkt->requestState = transaction->state;
153 memcpy ((void *)&(resourceRespPkt->resourceInfo), (void *)&(transaction->resourceInfo),
154 sizeof(Rm_ResourceInfo));
155 }
157 /* FUNCTION PURPOSE: Creates a NameServer request packet
158 ***********************************************************************
159 * DESCRIPTION: Returns a RM packet handle that points to a RM
160 * NameServer request packet that has been prepared
161 * for sending to another RM instance. The packet
162 * is allocated via the rmAllocPkt API using the
163 * appTransport handle provided by the application
164 */
165 void createNsRequestPkt(Rm_Packet *rmPkt, char *localInstName, Rm_Transaction *transaction)
166 {
167 Rm_NsRequestPkt *nsReqPkt = NULL;
169 rmPkt->pktType = Rm_pktType_NAMESERVER_REQUEST;
170 nsReqPkt = (Rm_NsRequestPkt *)rmPkt->data;
171 nsReqPkt->requestId = transaction->localId;
172 if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {
173 nsReqPkt->nsRequestType = Rm_nsReqPktType_MAP_RESOURCE;
174 }
175 else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {
176 nsReqPkt->nsRequestType = Rm_nsReqPktType_UNMAP_RESOURCE;
177 }
178 strncpy(nsReqPkt->pktSrcInstName, localInstName, RM_NAME_MAX_CHARS);
179 strncpy(nsReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);
180 memcpy ((void *)&(nsReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),
181 sizeof(Rm_ResourceInfo));
182 }
184 /* FUNCTION PURPOSE: Creates a NameServer response packet
185 ***********************************************************************
186 * DESCRIPTION: Returns a RM packet handle that points to a RM
187 * NameServer response packet that has been prepared
188 * for sending to another RM instance. The packet
189 * is allocated via the rmAllocPkt API using the
190 * appTransport handle provided by the application
191 */
192 void createNsResponsePkt(Rm_Packet *rmPkt, Rm_Transaction *transaction)
193 {
194 Rm_NsResponsePkt *nsRespPkt = NULL;
196 rmPkt->pktType = Rm_pktType_NAMESERVER_RESPONSE;
197 nsRespPkt = (Rm_NsResponsePkt *)rmPkt->data;
198 nsRespPkt->responseId = transaction->remoteOriginatingId;
199 nsRespPkt->requestState = transaction->state;
200 }
202 /* FUNCTION PURPOSE: Issues a service response to application
203 ***********************************************************************
204 * DESCRIPTION: Provides a service response back to the application
205 * using the service callback function provided to
206 * the RM instance at the time of the service request.
207 */
208 static void serviceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
209 {
210 Rm_ServiceRespInfo serviceResponse;
212 /* The responseTransaction will contain the resultant state details of
213 * the requestTransaction's service request */
214 serviceResponse.serviceState = transaction->state;
215 /* Pass back the ID that was provided to the component when it requested
216 * the service */
217 serviceResponse.serviceId = transaction->localId;
219 /* Service was approved and service was an allocate request. The resource
220 * data is passed back to the component */
221 if ((serviceResponse.serviceState == RM_SERVICE_APPROVED) &&
222 ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
223 (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
224 (transaction->type == Rm_service_RESOURCE_GET_BY_NAME)))
225 {
226 strncpy(serviceResponse.resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
227 serviceResponse.resourceBase = transaction->resourceInfo.base;
228 serviceResponse.resourceLength = transaction->resourceInfo.length;
229 }
231 /* Issue the callback to the requesting component with the response information */
232 transaction->callback.serviceCallback(&serviceResponse);
234 /* Delete the transaction from the transaction queue */
235 rmTransactionQueueDelete(rmInst, transaction->localId);
236 return;
237 }
239 /* FUNCTION PURPOSE: Sends RM response packets
240 ***********************************************************************
241 * DESCRIPTION: Sends RM response packets to RM instance's that sent
242 * RM request packets to the RM instance. The response
243 * is sent via the RM transport API which is plugged
244 * with an application created transport path.
245 */
246 static void transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
247 {
248 Rm_Transport *dstTransport = NULL;
249 Rm_Packet *rmPkt = NULL;
250 Rm_PacketHandle pktHandle = NULL;
252 if (dstTransport = rmTransportFindRemoteName(rmInst->transports, transaction->pktSrcInstName)) {
253 rmPkt = dstTransport->callouts.rmAllocPkt(dstTransport->appTransportHandle,
254 sizeof(Rm_Packet), &pktHandle);
255 if (!rmPkt || !pktHandle) {
256 transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;
257 goto errorExit;
258 }
260 switch (transaction->type) {
261 case Rm_service_RESOURCE_ALLOCATE_INIT:
262 case Rm_service_RESOURCE_ALLOCATE_USE:
263 case Rm_service_RESOURCE_FREE:
264 case Rm_service_RESOURCE_GET_BY_NAME:
265 createResourceResponsePkt(rmPkt, transaction);
266 break;
267 case Rm_service_RESOURCE_MAP_TO_NAME:
268 case Rm_service_RESOURCE_UNMAP_NAME:
269 createNsResponsePkt(rmPkt, transaction);
270 break;
271 }
272 if (dstTransport->callouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {
273 transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
274 goto errorExit;
275 }
277 /* Response packet sent: Delete transaction from queue */
278 rmTransactionQueueDelete(rmInst, transaction->localId);
279 }
280 else {
281 transaction->state = RM_ERROR_TRANSPORT_REMOTE_HNDL_NOT_REGD;
282 }
283 errorExit:
284 /* Do not delete transaction on error. Error transactions should be visible from
285 * from Rm_printInstanceStatus() */
286 return;
287 }
289 /* FUNCTION PURPOSE: Sends RM request packets
290 ***********************************************************************
291 * DESCRIPTION: Sends RM request packets to RM instance's that are
292 * capable of forwarding or validating service requests.
293 * The request is sent via the RM transport API which is
294 * plugged with an application created transport path.
295 */
296 static void transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)
297 {
298 Rm_Transport *dstTransport = NULL;
299 Rm_Packet *rmPkt = NULL;
300 Rm_PacketHandle pktHandle = NULL;
302 if (rmInst->instType == Rm_instType_CLIENT) {
303 dstTransport = rmTransportFindRemoteInstType(rmInst->transports, Rm_instType_CLIENT_DELEGATE);
305 if (!dstTransport) {
306 dstTransport = rmTransportFindRemoteInstType(rmInst->transports, Rm_instType_SERVER);
307 }
308 }
309 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
310 dstTransport = rmTransportFindRemoteInstType(rmInst->transports, Rm_instType_SERVER);
311 }
313 /* Just queue transaction if transport hasn't been registered. Do not return error */
314 if (dstTransport) {
315 rmPkt = dstTransport->callouts.rmAllocPkt(dstTransport->appTransportHandle,
316 sizeof(Rm_Packet), &pktHandle);
317 if (!rmPkt || !pktHandle) {
318 transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;
319 goto errorExit;
320 }
322 switch (transaction->type) {
323 case Rm_service_RESOURCE_ALLOCATE_INIT:
324 case Rm_service_RESOURCE_ALLOCATE_USE:
325 case Rm_service_RESOURCE_FREE:
326 case Rm_service_RESOURCE_GET_BY_NAME:
327 createResourceReqPkt(rmPkt, rmInst->instName, transaction);
328 break;
329 case Rm_service_RESOURCE_MAP_TO_NAME:
330 case Rm_service_RESOURCE_UNMAP_NAME:
331 createNsRequestPkt(rmPkt, rmInst->instName, transaction);
332 break;
333 }
335 if (dstTransport->callouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {
336 transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
337 goto errorExit;
338 }
339 transaction->hasBeenForwarded = true;
340 /* Transaction not deleted. Waiting for response from RM CD or Server */
341 }
342 errorExit:
343 return;
344 }
346 /* FUNCTION PURPOSE: Arbitrates allocation service requests
347 ***********************************************************************
348 * DESCRIPTION: Issues a set of allocator operations in order to
349 * handle a received allocation request. Allocation
350 * requests are always forwarded to the Server on Client
351 * CD instances. If a request is made with a NameServer
352 * name the resource base and length parameters are
353 * retrieved from the NameServer prior to the allocation
354 * attempt.
355 */
356 static void allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, void *validInstNode,
357 uint32_t allocType)
358 {
359 Rm_AllocatorOpInfo opInfo;
360 Rm_NameServerObjCfg nameServerObjCfg;
361 int32_t retVal = transaction->state;
363 memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
365 if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
366 /* Forward all allocation requests to Server if transport is up. Otherwise, just queue. */
367 if (rmInst->registeredWithDelegateOrServer) {
368 transactionForwarder(rmInst, transaction);
369 }
370 }
371 else if (rmInst->instType == Rm_instType_SERVER) {
372 opInfo.policy = rmInst->policy;
373 opInfo.resourceInfo = &transaction->resourceInfo;
374 opInfo.serviceSrcInstNode = validInstNode;
375 if (validInstNode == rmPolicyGetLinuxInstNode(rmInst->validInstances)) {
376 opInfo.LinuxKernelBypass = true;
377 }
378 else {
379 opInfo.LinuxKernelBypass = false;
380 }
381 opInfo.allocType = allocType;
383 /* Populated NameServer name has precedence over base */
384 if (strlen(transaction->resourceInfo.nameServerName) > 0) {
385 if ((transaction->resourceInfo.base == 0) &&
386 (transaction->resourceInfo.length == 0) &&
387 (transaction->resourceInfo.alignment == 0)) {
388 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
389 nameServerObjCfg.nameServerTree = rmInst->nameServer;
390 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
391 if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {
392 strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
393 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
394 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
395 }
396 }
397 else {
398 retVal = RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT;
399 }
400 }
402 if (retVal == RM_SERVICE_PROCESSING) {
403 if (transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) {
404 opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE;
405 retVal = rmAllocatorOperation(rmInst->allocators, &opInfo);
406 }
408 if (retVal == RM_SERVICE_PROCESSING) {
409 opInfo.operation = Rm_allocatorOp_ALLOCATE;
410 retVal = rmAllocatorOperation(rmInst->allocators, &opInfo);
411 }
412 }
414 transaction->state = retVal;
416 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
417 /* Source of allocation was not the server instance, provide the transaction
418 * to the transaction responder */
419 transactionResponder(rmInst, transaction);
420 }
421 /* Otherwise let the return stack return the transaction to the serviceHandler */
422 }
423 }
425 /* FUNCTION PURPOSE: Arbitrates free service requests
426 ***********************************************************************
427 * DESCRIPTION: Issues a set of allocator operations in order to
428 * handle a received free request. Free
429 * requests are always forwarded to the Server on Client
430 * CD instances. If a request is made with a NameServer
431 * name the resource base and length parameters are
432 * retrieved from the NameServer prior to the free
433 * attempt.
434 */
435 static void freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction, void *validInstNode)
436 {
437 Rm_AllocatorOpInfo opInfo;
438 Rm_NameServerObjCfg nameServerObjCfg;
439 int32_t retVal = transaction->state;
441 memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
443 if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
444 /* Forward all free requests to Server if transport is up. Otherwise, just queue. */
445 if (rmInst->registeredWithDelegateOrServer) {
446 transactionForwarder(rmInst, transaction);
447 }
448 }
449 else if (rmInst->instType == Rm_instType_SERVER) {
450 opInfo.policy = rmInst->policy;
451 opInfo.resourceInfo = &transaction->resourceInfo;
452 opInfo.serviceSrcInstNode = validInstNode;
454 /* Populated NameServer name has precedence over base */
455 if (strlen(transaction->resourceInfo.nameServerName) > 0) {
456 if ((transaction->resourceInfo.base == 0) &&
457 (transaction->resourceInfo.length == 0) &&
458 (transaction->resourceInfo.alignment == 0)) {
459 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
460 nameServerObjCfg.nameServerTree = rmInst->nameServer;
461 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
462 if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {
463 strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
464 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
465 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
466 }
467 }
468 else {
469 retVal = RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT;
470 }
471 }
473 if(retVal == RM_SERVICE_PROCESSING) {
474 opInfo.operation = Rm_allocatorOp_FREE;
475 retVal = rmAllocatorOperation(rmInst->allocators, &opInfo);
476 }
478 transaction->state = retVal;
480 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
481 /* Source of allocation was not the server instance, provide the transaction
482 * to the transaction responder */
483 transactionResponder(rmInst, transaction);
484 }
485 /* Otherwise let the return stack return the transaction to the serviceHandler */
486 }
487 }
489 /**********************************************************************
490 ********************** Internal Functions ****************************
491 **********************************************************************/
493 /* FUNCTION PURPOSE: Adds a transaction
494 ***********************************************************************
495 * DESCRIPTION: Returns a pointer to a newly created transaction.
496 * The transaction is created based on a new service
497 * request received via the service API or the
498 * transport API (service forwarded from another instance)
499 */
500 Rm_Transaction *rmTransactionQueueAdd(Rm_Inst *rmInst)
501 {
502 Rm_Transaction *transactionQueue = rmInst->transactionQueue;
503 Rm_Transaction *newTransaction = NULL;
505 newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));
506 if (newTransaction) {
507 memset((void *)newTransaction, 0, sizeof(Rm_Transaction));
509 newTransaction->localId = transactionGetSequenceNum(rmInst);
510 newTransaction->nextTransaction = NULL;
511 if (transactionQueue) {
512 while (transactionQueue->nextTransaction) {
513 transactionQueue = transactionQueue->nextTransaction;
514 }
515 transactionQueue->nextTransaction = newTransaction;
516 }
517 else {
518 rmInst->transactionQueue = newTransaction;
519 }
520 }
521 return (newTransaction);
522 }
524 /* FUNCTION PURPOSE: Finds a transaction
525 ***********************************************************************
526 * DESCRIPTION: Returns a pointer to a transaction resident
527 * in the transaction queue that matches the provided
528 * transaction ID.
529 */
530 Rm_Transaction *rmTransactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)
531 {
532 Rm_Transaction *transaction = rmInst->transactionQueue;
534 while (transaction) {
535 if (transaction->localId == transactionId) {
536 break;
537 }
538 transaction = transaction->nextTransaction;
539 }
541 return (transaction);
542 }
544 /* FUNCTION PURPOSE: Deletes a transaction
545 ***********************************************************************
546 * DESCRIPTION: Deletes the transaction with the provided transaction
547 * ID from the instance's transaction queue.
548 */
549 int32_t rmTransactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)
550 {
551 Rm_Transaction *transaction = rmInst->transactionQueue;
552 Rm_Transaction *prevTransaction = NULL;
553 int32_t retVal = RM_OK;
555 while (transaction) {
556 if (transaction->localId == transactionId) {
557 break;
558 }
560 prevTransaction = transaction;
561 transaction = transaction->nextTransaction;
562 }
564 if (transaction) {
565 if (prevTransaction == NULL) {
566 /* Transaction at start of queue. Map second transaction to start of queue
567 * as long as more than one transactions. */
568 rmInst->transactionQueue = transaction->nextTransaction;
569 }
570 else {
571 /* Transaction in middle or end of queue. */
572 prevTransaction->nextTransaction = transaction->nextTransaction;
573 }
574 Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));
575 }
576 else {
577 retVal = RM_ERROR_SERVICE_TRANS_DOES_NOT_EXIST;
578 }
579 return (retVal);
580 }
582 /* FUNCTION PURPOSE: Processes a transaction
583 ***********************************************************************
584 * DESCRIPTION: Processes transactions created from services
585 * received via the service handle or the transport.
586 * Transactions will be routed within the RM system
587 * based on the RM instance type and the type of
588 * the transaction.
589 */
590 void rmTransactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction)
591 {
592 void *validInstNode;
593 Rm_PolicyCheckCfg privCheckCfg;
594 Rm_NameServerObjCfg nameServerObjCfg;
595 uint32_t allocType = 0;
597 /* Handle static transactions originating on this instance. Any other static transactions will be
598 * stored in transaction queue until all transports are up. */
599 if (((rmInst->instType == Rm_instType_CLIENT) || (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) &&
600 (!rmInst->registeredWithDelegateOrServer) &&
601 (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS) == 0)) {
602 if (rmInst->staticInfo.staticPolicy) {
603 if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
604 (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE)) {
605 /* Check request against startup policy */
606 memset((void *)&privCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));
608 if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
609 privCheckCfg.type = Rm_policyCheck_INIT;
610 }
611 else {
612 privCheckCfg.type = Rm_policyCheck_USE;
613 }
614 privCheckCfg.policyDtb = rmInst->staticInfo.staticPolicy;
615 privCheckCfg.validInstNode = rmPolicyGetValidInstNode(rmInst->staticInfo.staticValidInstTree,
616 rmInst->instName);
617 privCheckCfg.resourceOffset = rmPolicyGetResourceOffset(rmInst->staticInfo.staticPolicy,
618 transaction->resourceInfo.name);
619 privCheckCfg.resourceBase = transaction->resourceInfo.base;
620 privCheckCfg.resourceLength = transaction->resourceInfo.length;
622 if (rmPolicyCheckPrivilege(&privCheckCfg, &transaction->state)) {
623 transaction->state = RM_SERVICE_APPROVED_STATIC;
624 }
625 else if (transaction->state == RM_SERVICE_PROCESSING) {
626 /* Privilege check returned false without error */
627 transaction->state = RM_SERVICE_DENIED_BY_STATIC_POLICY;
628 }
629 }
630 else {
631 transaction->state = RM_SERVICE_DENIED_INVALID_STATIC_REQUEST;
632 }
633 }
634 else {
635 transaction->state = RM_ERROR_REQ_FAILED_NO_STATIC_POLICY;
636 }
637 }
638 else {
639 /* Handle auto-forwarded transactions. These transactions include:
640 * - All request transactions received on Clients are forwarded to the Client Delegate
641 * - NameServer requests received on the Client Delegate are forwarded to the Server */
642 if ((rmInst->instType == Rm_instType_CLIENT) ||
643 ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&
644 ((transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||
645 (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) ||
646 (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)))) {
648 if ((transaction->state != RM_SERVICE_PROCESSING) &&
649 (transaction->state != RM_SERVICE_APPROVED_STATIC)) {
650 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
651 /* Transaction did not originate on this instance */
652 transactionResponder(rmInst, transaction);
653 }
654 else {
655 /* Transaction originated on this instance */
656 serviceResponder(rmInst, transaction);
657 }
658 }
659 else {
660 /* Forward request if transport is up. Otherwise, just queue. */
661 if (rmInst->registeredWithDelegateOrServer) {
662 transactionForwarder(rmInst, transaction);
663 }
664 }
665 }
666 else {
667 /* Validate service's originating instance name */
668 if (rmInst->instType == Rm_instType_SERVER) {
669 validInstNode = rmPolicyGetValidInstNode(rmInst->validInstances, transaction->serviceSrcInstName);
670 if (validInstNode == NULL) {
671 transaction->state = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
673 /* Send result via responder if transaction did not originate from this instance */
674 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
675 transactionResponder(rmInst, transaction);
676 }
677 }
678 }
680 switch (transaction->type) {
681 case Rm_service_RESOURCE_ALLOCATE_INIT:
682 case Rm_service_RESOURCE_ALLOCATE_USE:
683 case Rm_service_RESOURCE_FREE:
684 if ((transaction->state != RM_SERVICE_PROCESSING) &&
685 (transaction->state != RM_SERVICE_APPROVED_STATIC)) {
686 /* Transaction complete */
687 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
688 /* Transaction result not destined for this instance */
689 transactionResponder(rmInst, transaction);
690 }
691 else {
692 /* Transaction result destined for this instance */
693 serviceResponder(rmInst, transaction);
694 }
695 }
696 else {
697 /* Complete allocation/free request */
698 if (transaction->type == Rm_service_RESOURCE_FREE) {
699 freeHandler(rmInst, transaction, validInstNode);
700 }
701 else {
702 switch (transaction->type) {
703 case Rm_service_RESOURCE_ALLOCATE_INIT:
704 RM_policy_SET_PERM(allocType, RM_POLICY_PERM_INIT_SHIFT, 1);
705 break;
706 case Rm_service_RESOURCE_ALLOCATE_USE:
707 RM_policy_SET_PERM(allocType, RM_POLICY_PERM_USE_SHIFT, 1);
708 break;
709 }
710 allocationHandler(rmInst, transaction, validInstNode, allocType);
711 }
712 }
713 break;
714 case Rm_service_RESOURCE_MAP_TO_NAME:
715 case Rm_service_RESOURCE_GET_BY_NAME:
716 case Rm_service_RESOURCE_UNMAP_NAME:
717 /* NameServer resides on server */
718 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
719 if (rmInst->nameServer) {
720 nameServerObjCfg.nameServerTree = rmInst->nameServer;
721 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
722 if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {
723 nameServerObjCfg.nodeCfg.resourceName = transaction->resourceInfo.name;
724 nameServerObjCfg.nodeCfg.resourceBase= transaction->resourceInfo.base;
725 nameServerObjCfg.nodeCfg.resourceLength = transaction->resourceInfo.length;
726 transaction->state = rmNameServerAddObject(&nameServerObjCfg);
727 }
728 else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
729 if ((transaction->state = rmNameServerFindObject(&nameServerObjCfg)) ==
730 RM_SERVICE_PROCESSING) {
731 strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
732 transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
733 transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
734 transaction->state = RM_SERVICE_APPROVED;
735 }
736 }
737 else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {
738 transaction->state = rmNameServerDeleteObject(&nameServerObjCfg);
739 }
740 }
741 else {
742 transaction->state = RM_ERROR_NAMESERVER_DOES_NOT_EXIST;
743 }
745 /* Send result via responder if transaction did not originate from this instance */
746 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
747 transactionResponder(rmInst, transaction);
748 }
749 break;
750 }
751 }
752 }
754 /* Forward any queued requests that weren't forwarded yet */
755 if (rmInst->registeredWithDelegateOrServer) {
756 transaction = rmInst->transactionQueue;
757 while(transaction) {
758 if (((transaction->state == RM_SERVICE_PROCESSING) ||
759 (transaction->state == RM_SERVICE_APPROVED_STATIC)) &&
760 !transaction->hasBeenForwarded) {
761 transactionForwarder(rmInst, transaction);
762 }
763 transaction = transaction->nextTransaction;
764 }
765 }
766 }
768 /**********************************************************************
769 ********************** Application visible APIs **********************
770 **********************************************************************/
772 /* FUNCTION PURPOSE: Display status of managed resources
773 ***********************************************************************
774 * DESCRIPTION: Prints the status (allocate/free status, as well as
775 * owners) for all resources managed by the RM
776 * instance network. Also, prints the NameServer name
777 * entries. This function is only available on server
778 * instances.
779 */
780 void Rm_printResourceStatus(Rm_Handle rmServerHandle)
781 {
782 Rm_Inst *rmInst = (Rm_Inst *)rmServerHandle;
783 Rm_Allocator *allocator = rmInst->allocators;
784 Rm_Owner *owners;
785 Rm_ResourceTree *treeRoot;
786 Rm_ResourceNode *treeNode;
788 if (rmInst->instType == Rm_instType_SERVER) {
789 while (allocator != NULL) {
790 Rm_osalLog("Resource: %s\n", allocator->resourceName);
792 treeRoot = allocator->allocatorRootEntry;
794 RB_FOREACH(treeNode, _Rm_AllocatorResourceTree, treeRoot) {
795 Rm_osalLog(" %10d - %10d ", treeNode->base,
796 treeNode->base + treeNode->length -1);
798 if (treeNode->allocationCount == 0) {
799 Rm_osalLog("NOT ALLOCATED\n");
800 }
801 else {
802 owners = treeNode->ownerList;
803 Rm_osalLog("allocated to");
804 while (owners) {
805 Rm_osalLog(" %s", owners->instNameNode->name);
806 owners = owners->nextOwner;
807 }
808 Rm_osalLog("\n");
809 }
810 }
811 allocator = allocator->nextAllocator;
812 }
813 rmNameServerPrintObjects(rmInst->nameServer);
814 }
815 }
817 /* FUNCTION PURPOSE: Display status of a RM instance
818 ***********************************************************************
819 * DESCRIPTION: Prints the current status of various RM instance
820 * properties such as the state of all transactions
821 * in the transaction queue and registered transports
822 */
823 void Rm_printInstanceStatus(Rm_Handle rmHandle)
824 {
825 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
826 Rm_Transport *transportList = rmInst->transports;
827 Rm_Transaction *transactionQ = rmInst->transactionQueue;
829 Rm_osalLog("Instance name: %s\n", rmInst->instName);
830 if (rmInst->instType == Rm_instType_SERVER) {
831 Rm_osalLog("Type: Server\n");
832 }
833 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
834 Rm_osalLog("Type: Client Delegate\n");
835 }
836 else {
837 Rm_osalLog("Type: Client\n");
838 }
840 if (transportList) {
841 Rm_osalLog("\nRegistered Transports:\n");
842 while (transportList) {
843 Rm_osalLog(" Remote instName: %s\n", transportList->remoteInstName);
844 if (transportList->remoteInstType == Rm_instType_SERVER) {
845 Rm_osalLog(" Remote instType: Server\n");
846 }
847 else if (transportList->remoteInstType == Rm_instType_CLIENT_DELEGATE) {
848 Rm_osalLog(" Remote instType: Client Delegate\n");
849 }
850 else {
851 Rm_osalLog(" Remote instType: Client\n");
852 }
853 Rm_osalLog(" appTransportHandle: 0x%08x\n", transportList->appTransportHandle);
854 Rm_osalLog("\n");
855 transportList = transportList->nextTransport;
856 }
857 }
859 if (transactionQ) {
860 Rm_osalLog("\nQueued Service Transactions:\n");
861 while (transactionQ) {
862 Rm_osalLog(" Service type: %d\n", transactionQ->type);
863 Rm_osalLog(" Service ID: %d\n", transactionQ->localId);
864 Rm_osalLog(" Service srcInstName %s\n", transactionQ->serviceSrcInstName);
865 Rm_osalLog(" Service state: %d\n", transactionQ->state);
866 Rm_osalLog(" Resource name: %s\n", transactionQ->resourceInfo.name);
867 Rm_osalLog(" Resource base: %d\n", transactionQ->resourceInfo.base);
868 Rm_osalLog(" Resource length: %d\n", transactionQ->resourceInfo.length);
869 Rm_osalLog(" Resource alignment: %d\n", transactionQ->resourceInfo.alignment);
870 Rm_osalLog(" Resource NS name: %s\n", transactionQ->resourceInfo.nameServerName);
871 Rm_osalLog("\n");
872 transactionQ = transactionQ->nextTransaction;
873 }
874 }
875 }
877 /* FUNCTION PURPOSE: RM instance creation and initialization
878 ***********************************************************************
879 * DESCRIPTION: Returns a new RM instance created and initialized
880 * using the parameters provided via the initCfg
881 * structure.
882 */
883 Rm_Handle Rm_init(const Rm_InitCfg *initCfg, int32_t *result)
884 {
885 Rm_Inst *rmInst;
886 void *globalResourceDtb = NULL;
887 void *linuxResourceDtb = NULL;
888 bool addLinux = false;
890 *result = RM_OK;
892 if ((initCfg->instName == NULL) ||
893 ((strlen(initCfg->instName) + 1) > RM_NAME_MAX_CHARS)) {
894 *result = RM_ERROR_INVALID_INST_NAME;
895 return (NULL);
896 }
898 if (initCfg->instType >= Rm_instType_LAST) {
899 *result = RM_ERROR_INVALID_INST_TYPE;
900 }
902 /* Create and initialize instance */
903 rmInst = Rm_osalMalloc (sizeof(Rm_Inst));
904 memset ((void *) rmInst, 0, sizeof(Rm_Inst));
905 rmInst->isLocked = false;
906 rmInst->registeredWithDelegateOrServer = false;
907 rmInst->transactionSeqNum = transactionInitSequenceNum();
909 rmInst->instType = initCfg->instType;
910 strncpy (rmInst->instName, initCfg->instName, RM_NAME_MAX_CHARS);
912 if (rmInst->instType == Rm_instType_SERVER) {
913 if (!initCfg->instCfg.serverCfg.globalResourceList ||
914 !initCfg->instCfg.serverCfg.globalPolicy) {
915 *result = RM_ERROR_INVALID_SERVER_CONFIGURATION;
916 Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
917 return(NULL);
918 }
920 rmInst->policy = initCfg->instCfg.serverCfg.globalPolicy;
921 fdt_open_into(rmInst->policy, rmInst->policy, fdt_totalsize(rmInst->policy));
923 if (initCfg->instCfg.serverCfg.linuxDtb) {
924 linuxResourceDtb = initCfg->instCfg.serverCfg.linuxDtb;
925 fdt_open_into(linuxResourceDtb, linuxResourceDtb, fdt_totalsize(linuxResourceDtb));
926 addLinux = true;
927 }
929 /* Create valid instance list from policy. Must be done prior to parsing
930 * GRL so that Linux resources can be reserved correctly */
931 rmInst->validInstances = rmPolicyCreateValidInstTree(rmInst->policy, addLinux, result);
932 /* Validate policy assignment strings */
933 *result = rmPolicyValidatePolicy(rmInst->policy, rmInst->validInstances);
935 rmInst->nameServer = rmNameServerInit();
937 globalResourceDtb = initCfg->instCfg.serverCfg.globalResourceList;
938 fdt_open_into(globalResourceDtb, globalResourceDtb, fdt_totalsize(globalResourceDtb));
940 if ((*result = rmAllocatorInitializeResources((Rm_Handle) rmInst, globalResourceDtb, linuxResourceDtb)) == RM_OK) {
941 *result = rmPolicyValidatePolicyResourceNames(rmInst->policy, (void *)rmInst->allocators);
942 }
943 if (*result < RM_OK) {
944 Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
945 return(NULL);
946 }
947 }
949 if ((rmInst->instType == Rm_instType_CLIENT) &&
950 (initCfg->instCfg.clientCfg.staticPolicy)) {
951 rmInst->staticInfo.staticPolicy = initCfg->instCfg.clientCfg.staticPolicy;
952 }
953 else if ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&
954 (initCfg->instCfg.cdCfg.staticPolicy)) {
955 rmInst->staticInfo.staticPolicy = initCfg->instCfg.cdCfg.staticPolicy;
956 }
957 if (rmInst->staticInfo.staticPolicy) {
958 fdt_open_into(rmInst->staticInfo.staticPolicy, rmInst->staticInfo.staticPolicy,
959 fdt_totalsize(rmInst->staticInfo.staticPolicy));
960 rmInst->staticInfo.staticValidInstTree = rmPolicyCreateValidInstTree(rmInst->staticInfo.staticPolicy,
961 addLinux, result);
962 if (*result == RM_OK) {
963 /* Validate policy assignment strings */
964 *result = rmPolicyValidatePolicy(rmInst->staticInfo.staticPolicy, rmInst->staticInfo.staticValidInstTree);
965 }
966 if (*result != RM_OK) {
967 if (rmInst->staticInfo.staticValidInstTree) {
968 rmPolicyFreeValidInstTree(rmInst->staticInfo.staticValidInstTree);
969 }
970 Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
971 rmInst = NULL;
972 }
973 }
974 return ((Rm_Handle) rmInst);
975 }
977 /* FUNCTION PURPOSE: Returns RM version information
978 ***********************************************************************
979 */
980 uint32_t Rm_getVersion (void)
981 {
982 return RM_VERSION_ID;
983 }
985 /* FUNCTION PURPOSE: Returns RM version string
986 ***********************************************************************
987 */
988 const char* Rm_getVersionStr (void)
989 {
990 return rmVersionStr;
991 }