diff --git a/src/rm_services.c b/src/rm_services.c
index 441f94720c6d04e6d180ff333702e2750c34b7b8..46ac94bf84714f065a412b5b2b07e0c0d42b105f 100644 (file)
--- a/src/rm_services.c
+++ b/src/rm_services.c
/**
- * @file rmservices.c
+ * @file rm_services.c
*
* @brief
* This is the Resource Manager services source.
*
* \par
* ============================================================================
- * @n (C) Copyright 2012-2013, Texas Instruments, Inc.
+ * @n (C) Copyright 2012-2016, Texas Instruments, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* \par
*/
-/* Standard includes */
-#include <string.h>
-
/* RM external API includes */
+#include <ti/drv/rm/rm.h>
#include <ti/drv/rm/rm_services.h>
/* RM internal API includes */
-#include <ti/drv/rm/include/rm_servicesloc.h>
#include <ti/drv/rm/include/rm_loc.h>
-#include <ti/drv/rm/include/rm_policyloc.h>
+#include <ti/drv/rm/include/rm_internal.h>
/* RM OSAL layer */
#include <rm_osal.h>
+/**********************************************************************
+ ********************** Internal Functions ****************************
+ **********************************************************************/
+
+/* FUNCTION PURPOSE: Internal Callback to unblock RM instance
+ ***********************************************************************
+ * DESCRIPTION: Internal callback function executed when the result
+ * of a service request has been received from a remote
+ * instance. The original service request did not specify
+ * a callback function so the Rm_serviceHandler is blocked
+ * waiting for the response. This function unblocks the
+ * Rm_serviceHandler to return the response to the
+ * application.
+ */
+void rmServiceInternalCallback(Rm_Handle rmHandle)
+{
+ Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
+
+ /* Unblock so Rm_serviceHandler can provide response to application */
+ Rm_osalTaskUnblock(rmInst->blockHandle);
+}
+
/**********************************************************************
********************** Application visible APIs **********************
**********************************************************************/
-void Rm_serviceHandler (void *rmHandle, Rm_ServiceReqInfo *serviceRequest,
+/* FUNCTION PURPOSE: Handles application component service requests
+ ***********************************************************************
+ * DESCRIPTION: Receives service requests from application components
+ * and routes them to the transaction processor. If
+ * the service can be handled immediately the response
+ * will be provided in the service response. If the
+ * service requires a blocking operation the handler
+ * will provide a service ID back to the application.
+ * The response will be sent at a later time via the
+ * application supplied callback function.
+ */
+void Rm_serviceHandler (void *rmHandle, const Rm_ServiceReqInfo *serviceRequest,
Rm_ServiceRespInfo *serviceResponse)
{
Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
+ char *instanceName;
Rm_Transaction *transaction;
+ void *key;
+ void *mtKey;
- if (serviceRequest->callback.serviceCallback == NULL) {
- serviceResponse->serviceState = RM_SERVICE_ERROR_CALLBACK_NOT_PROVIDED;
+ if (serviceRequest->type >= Rm_service_LAST) {
+ serviceResponse->serviceState = RM_ERROR_INVALID_SERVICE_TYPE;
return;
}
- if (serviceRequest->type >= Rm_service_LAST) {
- serviceResponse->serviceState = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;
- return;
+ if (serviceRequest->resourceName) {
+ if ((strlen(serviceRequest->resourceName) + 1) > RM_NAME_MAX_CHARS) {
+ serviceResponse->serviceState = RM_ERROR_RESOURCE_NAME_TOO_LONG;
+ return;
+ }
+ }
+
+ if (serviceRequest->resourceNsName) {
+ if ((strlen(serviceRequest->resourceNsName) + 1) > RM_NAME_MAX_CHARS) {
+ serviceResponse->serviceState = RM_ERROR_NAMESERVER_NAME_TOO_LONG;
+ return;
+ }
}
- transaction = rmTransactionQueueAdd(rmInst);
- if (transaction) {
+ if (rmInst->isLocked) {
+ serviceResponse->serviceState = RM_SERVICE_DENIED_RM_INSTANCE_LOCKED;
+ return;
+ }
+
+ RM_SS_INST_INV_ENTER_CS(rmInst, key);
+ RM_SC_INST_INV_ENTER_CS(rmInst, key);
+
+ if (rmInst->mtSemObj) {
+ mtKey = Rm_osalMtCsEnter(rmInst->mtSemObj);
+ }
+
+ /* Copy location of instance name to local variable in case Shared Client
+ * needs to transfer control to a shared server */
+ instanceName = rmInst->instName;
+ if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
+ /* Transfer control to shared server instance */
+ rmInst = rmInst->u.sharedClient.sharedServerHandle;
+ }
+
+ if ((transaction = rmTransactionQueueAdd(rmInst))) {
transaction->type = serviceRequest->type;
- strncpy(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS);
- transaction->callback.serviceCallback = serviceRequest->callback.serviceCallback;
+ rm_strncpy(transaction->serviceSrcInstName, instanceName,
+ RM_NAME_MAX_CHARS);
+ transaction->u.callback.serviceCallback = serviceRequest->callback.serviceCallback;
transaction->state = RM_SERVICE_PROCESSING;
if (serviceRequest->resourceName) {
- strncpy(transaction->resourceInfo.name, serviceRequest->resourceName, RM_NAME_MAX_CHARS);
+ rm_strncpy(transaction->resourceInfo.name,
+ serviceRequest->resourceName, RM_NAME_MAX_CHARS);
}
transaction->resourceInfo.base = serviceRequest->resourceBase;
transaction->resourceInfo.length = serviceRequest->resourceLength;
transaction->resourceInfo.alignment = serviceRequest->resourceAlignment;
+ transaction->resourceInfo.ownerCount = RM_RESOURCE_NUM_OWNERS_INVALID;
+ transaction->resourceInfo.instAllocCount = RM_INST_ALLOC_COUNT_INVALID;
if (serviceRequest->resourceNsName) {
- strncpy(transaction->resourceInfo.nameServerName, serviceRequest->resourceNsName, RM_NAME_MAX_CHARS);
+ rm_strncpy(transaction->resourceInfo.nameServerName,
+ serviceRequest->resourceNsName, RM_NAME_MAX_CHARS);
}
- rmTransactionProcessor (rmInst, transaction);
- serviceResponse->serviceState = transaction->state;
- if (serviceResponse->serviceState == RM_SERVICE_PROCESSING) {
- /* Service still being processed. Provide transaction ID
- * back to component so it can sort service responses received
- * via callback function */
- serviceResponse->serviceId = transaction->localId;
- }
- else if (serviceResponse->serviceState == RM_SERVICE_APPROVED_AND_COMPLETED) {
- if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
- (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
- (transaction->type == Rm_service_RESOURCE_GET_BY_NAME)) {
- strncpy(serviceResponse->resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
- serviceResponse->resourceBase = transaction->resourceInfo.base;
- serviceResponse->resourceLength = transaction->resourceInfo.length;
- }
- rmTransactionQueueDelete(rmInst, transaction->localId);
- }
- else {
- rmTransactionQueueDelete(rmInst, transaction->localId);
- }
- }
- else {
- serviceResponse->serviceState = RM_SERVICE_ERROR_TRANSACTION_FAILED_TO_ALLOCATE;
- }
- return;
-}
+ /* Process received transaction */
+ rmProcessRouter(rmInst, transaction);
-void Rm_servicePreMainRequest(Rm_PreMainReqCfg *reqCfg, Rm_ServiceRespInfo *preMainResp)
-{
- Rm_PreMainInst *preMainInst = (Rm_PreMainInst *)reqCfg->rmPreMainHandle;
- Rm_PolicyCheckCfg privCheckCfg;
- Rm_ServicePreMainReq *lastServiceReq;
+ memset((void *)serviceResponse, 0, sizeof(*serviceResponse));
- preMainResp->serviceState = RM_SERVICE_PROCESSING;
- preMainResp->serviceId = 0;
+ if ((rmInst->instType == Rm_instType_SHARED_SERVER) &&
+ (transaction->state == RM_SERVICE_PROCESSING)) {
+ /* Shared Server should always return a fully processed
+ * transaction */
+ serviceResponse->serviceState = RM_ERROR_SHARED_INSTANCE_UNFINISHED_REQ;
+ rmTransactionQueueDelete(rmInst, transaction->localId);
+ } else {
+ if ((transaction->state == RM_SERVICE_PROCESSING) &&
+ (transaction->u.callback.serviceCallback == NULL)) {
+ /* Block until response is received. Response will be
+ * received in transaction. */
+ Rm_osalTaskBlock(rmInst->blockHandle);
+ }
- if ((reqCfg->request->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
- (reqCfg->request->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
- (reqCfg->request->resourceBase == RM_RESOURCE_BASE_UNSPECIFIED)) {
- /* Check request against startup policy */
- memset((void *)&privCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));
+ serviceResponse->rmHandle = rmHandle;
+ serviceResponse->serviceState = transaction->state;
+ /* Owner and instance allocation count will only be set within RM
+ * under certain circumstances. */
+ serviceResponse->resourceNumOwners = transaction->resourceInfo.ownerCount;
+ serviceResponse->instAllocCount = transaction->resourceInfo.instAllocCount;
+ if ((serviceResponse->serviceState == RM_SERVICE_PROCESSING) ||
+ (serviceResponse->serviceState == RM_SERVICE_APPROVED_STATIC) ||
+ (serviceResponse->serviceState ==
+ RM_SERVICE_PENDING_SERVER_RESPONSE)) {
+ /* Service still being processed. Static requests will have
+ * their validation responses sent once all transports have
+ * been established. Provide transaction ID back to component
+ * so it can sort service responses received via callback
+ * function */
+ serviceResponse->serviceId = transaction->localId;
+ }
- if (reqCfg->request->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
- privCheckCfg.type = Rm_policyCheck_INIT;
- }
- else {
- privCheckCfg.type = Rm_policyCheck_USE;
- }
- privCheckCfg.policyDtb = preMainInst->startupDtb;
- privCheckCfg.validInstNode = rmPolicyGetValidInstNode(preMainInst->validInstTree,
- preMainInst->instName);
- privCheckCfg.resourceOffset = rmPolicyGetResourceOffset(preMainInst->startupDtb,
- reqCfg->request->resourceName);
- privCheckCfg.resourceBase = reqCfg->request->resourceBase;
- privCheckCfg.resourceLength = reqCfg->request->resourceLength;
-
- if (rmPolicyCheckPrivilege(&privCheckCfg, &preMainResp->serviceState)) {
- preMainResp->serviceState = RM_SERVICE_APPROVED_AND_COMPLETED;
- }
- else if (preMainResp->serviceState == RM_SERVICE_PROCESSING) {
- /* Privilege check returned FALSE without error */
- preMainResp->serviceState = RM_SERVICE_DENIED_POLICY_DENIED_PREMAIN_ALLOCATION;
+ if ((serviceResponse->serviceState == RM_SERVICE_APPROVED) ||
+ (serviceResponse->serviceState == RM_SERVICE_APPROVED_STATIC)) {
+ rm_strncpy(serviceResponse->resourceName,
+ transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
+ serviceResponse->resourceBase = transaction->resourceInfo.base;
+ serviceResponse->resourceLength = transaction->resourceInfo.length;
+ }
+
+ /* Transactions still processing not deleted from queue including
+ * static transactions which will be verified once all transports
+ * are up */
+ if ((serviceResponse->serviceState != RM_SERVICE_PROCESSING) &&
+ (serviceResponse->serviceState != RM_SERVICE_APPROVED_STATIC) &&
+ (serviceResponse->serviceState !=
+ RM_SERVICE_PENDING_SERVER_RESPONSE)) {
+ rmTransactionQueueDelete(rmInst, transaction->localId);
+ }
}
- }
- else {
- preMainResp->serviceState = RM_SERVICE_DENIED_INVALID_PREMAIN_REQUEST;
+ } else {
+ serviceResponse->serviceState = RM_ERROR_SERVICE_TRANS_NOT_CREATED;
}
- /* Store the request for validation after post-main instance
- * transports have been established */
- if (preMainResp->serviceState == RM_SERVICE_APPROVED_AND_COMPLETED) {
- /* Store the request for validation after all instances have been setup post-main */
- lastServiceReq = preMainInst->preMainReqList;
- while(lastServiceReq) {
- lastServiceReq = lastServiceReq->nextPreMainReq;
- }
- lastServiceReq = (Rm_ServicePreMainReq *) Rm_osalMalloc (sizeof(Rm_ServicePreMainReq));
- lastServiceReq->nextPreMainReq = NULL;
- lastServiceReq->preMainReq = (Rm_ServiceReqInfo *) Rm_osalMalloc(sizeof(Rm_ServiceReqInfo));
- memcpy((void *)lastServiceReq->preMainReq, (void *)reqCfg->request, sizeof(Rm_ServiceReqInfo));
-
- /* Fill out response */
- preMainResp->resourceBase = reqCfg->request->resourceBase;
- preMainResp->resourceLength = reqCfg->request->resourceLength;
- strncpy(preMainResp->resourceName, reqCfg->request->resourceName, RM_NAME_MAX_CHARS);
- preMainResp->serviceId = ++preMainInst->requestCount;
+ /* Free sem object using originating instance in case the Shared Client to
+ * Shared Server instance switch took place */
+ if (((Rm_Inst *)rmHandle)->mtSemObj) {
+ Rm_osalMtCsExit(((Rm_Inst *)rmHandle)->mtSemObj, mtKey);
}
+ /* Shared Client switches to Shared Server instance so only need
+ * SS_EXIT_CS macro */
+ RM_SS_INST_WB_EXIT_CS(rmInst, key);
+ return;
}
+/* FUNCTION PURPOSE: Opens the RM instance service handle
+ ***********************************************************************
+ * DESCRIPTION: Returns the service handle for an RM instance. Only
+ * one service handle is opened per instance.
+ */
Rm_ServiceHandle *Rm_serviceOpenHandle(Rm_Handle rmHandle, int32_t *result)
{
Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
- Rm_ServiceHandle *newServiceHandle = NULL;
+ Rm_ServiceHandle *serviceHandle = NULL;
+ void *key;
+ void *mtKey;
+
+ RM_SS_INST_INV_ENTER_CS(rmInst, key);
+ if (rmInst->mtSemObj) {
+ mtKey = Rm_osalMtCsEnter(rmInst->mtSemObj);
+ }
- *result = RM_INIT_OK;
+ *result = RM_OK;
- if (rmInst->serviceHandle == NULL) {
- newServiceHandle = Rm_osalMalloc (sizeof(Rm_ServiceHandle));
- if (newServiceHandle) {
- newServiceHandle->rmHandle = rmHandle;
- newServiceHandle->Rm_serviceHandler = Rm_serviceHandler;
- rmInst->serviceHandle = newServiceHandle;
- }
- else {
- *result = RM_INIT_ERROR_SERVICE_HANDLE_MEMORY_ALLOC_FAILED;
+ serviceHandle = rmInst->serviceHandle;
+ if (serviceHandle == NULL) {
+ serviceHandle = Rm_osalMalloc(sizeof(*serviceHandle));
+ if (serviceHandle) {
+ serviceHandle->rmHandle = rmHandle;
+ serviceHandle->Rm_serviceHandler = Rm_serviceHandler;
+ RM_SS_OBJ_WB(rmInst, serviceHandle, Rm_ServiceHandle);
+ rmInst->serviceHandle = serviceHandle;
+ } else {
+ *result = RM_ERROR_SERVICE_HANDLE_MEM_ALLOC_FAILED;
}
}
- else {
- *result = RM_INIT_ERROR_SERVICE_HANDLE_ALREADY_ALLOCATED;
+
+ if (rmInst->mtSemObj) {
+ Rm_osalMtCsExit(rmInst->mtSemObj, mtKey);
}
- return (newServiceHandle);
+ RM_SS_INST_WB_EXIT_CS(rmInst, key);
+ return (serviceHandle);
}
+/* FUNCTION PURPOSE: Closes the RM instance service handle
+ ***********************************************************************
+ * DESCRIPTION: Closes the service handle for an RM instance.
+ */
int32_t Rm_serviceCloseHandle(Rm_ServiceHandle *rmServiceHandle)
{
Rm_Inst *rmInst = (Rm_Inst *)rmServiceHandle->rmHandle;
- int32_t retVal = RM_INIT_OK;
+ int32_t retVal = RM_OK;
+ void *key;
+ void *mtKey;
+
+ RM_SS_INST_INV_ENTER_CS(rmInst, key);
+ if (rmInst->mtSemObj) {
+ mtKey = Rm_osalMtCsEnter(rmInst->mtSemObj);
+ }
if (rmInst->serviceHandle) {
- Rm_osalFree((void *)rmServiceHandle, sizeof(Rm_ServiceHandle));
+ Rm_osalFree((void *)rmServiceHandle, sizeof(*rmServiceHandle));
rmInst->serviceHandle = NULL;
+ } else {
+ retVal = RM_ERROR_SERVICE_HANDLE_ALREADY_CLOSED;
}
- else {
- retVal = RM_INIT_ERROR_SERVICE_HANDLE_ALREADY_CLOSED_FOR_INSTANCE;
+
+ if (rmInst->mtSemObj) {
+ Rm_osalMtCsExit(rmInst->mtSemObj, mtKey);
}
+ RM_SS_INST_WB_EXIT_CS(rmInst, key);
return(retVal);
}
-/**
-@}
-*/