]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/rm-lld.git/blob - src/rm_services.c
Fixed SDOCM00115772 plus some formatting changes
[keystone-rtos/rm-lld.git] / src / rm_services.c
1 /**
2  *   @file  rm_services.c
3  *
4  *   @brief   
5  *      This is the Resource Manager services source.
6  *
7  *  \par
8  *  ============================================================================
9  *  @n   (C) Copyright 2012-2015, 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 API includes */
43 #include <ti/drv/rm/rm.h>
44 #include <ti/drv/rm/rm_services.h>
46 /* RM internal API includes */
47 #include <ti/drv/rm/include/rm_loc.h>
48 #include <ti/drv/rm/include/rm_internal.h>
50 /* RM OSAL layer */
51 #include <rm_osal.h>
53 /**********************************************************************
54  ********************** Internal Functions ****************************
55  **********************************************************************/
57 /* FUNCTION PURPOSE: Internal Callback to unblock RM instance
58  ***********************************************************************
59  * DESCRIPTION: Internal callback function executed when the result
60  *              of a service request has been received from a remote
61  *              instance.  The original service request did not specify
62  *              a callback function so the Rm_serviceHandler is blocked
63  *              waiting for the response.  This function unblocks the
64  *              Rm_serviceHandler to return the response to the 
65  *              application.
66  */
67 void rmServiceInternalCallback(Rm_Handle rmHandle)
68 {
69     Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
71     /* Unblock so Rm_serviceHandler can provide response to application */
72     Rm_osalTaskUnblock(rmInst->blockHandle);
73 }
75 /**********************************************************************
76  ********************** Application visible APIs **********************
77  **********************************************************************/
79 /* FUNCTION PURPOSE: Handles application component service requests
80  ***********************************************************************
81  * DESCRIPTION: Receives service requests from application components
82  *              and routes them to the transaction processor.  If
83  *              the service can be handled immediately the response
84  *              will be provided in the service response.  If the
85  *              service requires a blocking operation the handler
86  *              will provide a service ID back to the application.
87  *              The response will be sent at a later time via the
88  *              application supplied callback function.
89  */
90 void Rm_serviceHandler (void *rmHandle, const Rm_ServiceReqInfo *serviceRequest,
91                         Rm_ServiceRespInfo *serviceResponse)
92 {
93     Rm_Inst        *rmInst = (Rm_Inst *)rmHandle;
94     char           *instanceName;
95     Rm_Transaction *transaction;
96     void           *key;
97     void           *mtKey;
99     RM_SS_INST_INV_ENTER_CS(rmInst, key);
100     RM_SC_INST_INV_ENTER_CS(rmInst, key);
101     if (rmInst->mtSemObj) {
102         mtKey = Rm_osalMtCsEnter(rmInst->mtSemObj);
103     }
105     if (rmInst->isLocked) {
106         serviceResponse->serviceState = RM_SERVICE_DENIED_RM_INSTANCE_LOCKED;
107         goto errorExit;
108     }
110     if (serviceRequest->type >= Rm_service_LAST) {
111         serviceResponse->serviceState = RM_ERROR_INVALID_SERVICE_TYPE;
112         goto errorExit;
113     }
115     if (serviceRequest->resourceName) {
116         if ((strlen(serviceRequest->resourceName) + 1) > RM_NAME_MAX_CHARS) {
117             serviceResponse->serviceState = RM_ERROR_RESOURCE_NAME_TOO_LONG;
118             goto errorExit;
119         }
120     }
122     if (serviceRequest->resourceNsName) {
123         if ((strlen(serviceRequest->resourceNsName) + 1) > RM_NAME_MAX_CHARS) {
124             serviceResponse->serviceState = RM_ERROR_NAMESERVER_NAME_TOO_LONG;
125             goto errorExit;
126         }
127     }
129     /* Copy location of instance name to local variable in case Shared Client
130      * needs to transfer control to a shared server */
131     instanceName = rmInst->instName;
132     if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
133         /* Transfer control to shared server instance */
134         rmInst = rmInst->u.sharedClient.sharedServerHandle;
135     }
137     if (transaction = rmTransactionQueueAdd(rmInst)) {
138         transaction->type = serviceRequest->type;
139         rm_strncpy(transaction->serviceSrcInstName, instanceName,
140                    RM_NAME_MAX_CHARS);
141         transaction->u.callback.serviceCallback = serviceRequest->callback.serviceCallback;
142         transaction->state = RM_SERVICE_PROCESSING;
143         if (serviceRequest->resourceName) {
144             rm_strncpy(transaction->resourceInfo.name,
145                        serviceRequest->resourceName, RM_NAME_MAX_CHARS);
146         }
147         transaction->resourceInfo.base = serviceRequest->resourceBase;
148         transaction->resourceInfo.length = serviceRequest->resourceLength;
149         transaction->resourceInfo.alignment = serviceRequest->resourceAlignment;
150         transaction->resourceInfo.ownerCount = RM_RESOURCE_NUM_OWNERS_INVALID;
151         transaction->resourceInfo.instAllocCount = RM_INST_ALLOC_COUNT_INVALID;
152         if (serviceRequest->resourceNsName) {
153             rm_strncpy(transaction->resourceInfo.nameServerName,
154                        serviceRequest->resourceNsName, RM_NAME_MAX_CHARS);
155         }
157         /* Process received transaction */
158         rmProcessRouter(rmInst, transaction);
160         memset((void *)serviceResponse, 0, sizeof(*serviceResponse));
162         if ((rmInst->instType == Rm_instType_SHARED_SERVER) && 
163             (transaction->state == RM_SERVICE_PROCESSING)) {
164             /* Shared Server should always return a fully processed transaction */
165             serviceResponse->serviceState = RM_ERROR_SHARED_INSTANCE_UNFINISHED_REQ;
166             rmTransactionQueueDelete(rmInst, transaction->localId);
167         } else {
168             if ((transaction->state == RM_SERVICE_PROCESSING) && 
169                 (transaction->u.callback.serviceCallback == NULL)) {
170                 /* Block until response is received.  Response will be
171                  * received in transaction. */
172                 Rm_osalTaskBlock(rmInst->blockHandle);
173             }
175             serviceResponse->rmHandle = rmHandle;
176             serviceResponse->serviceState = transaction->state;
177             /* Owner and instance allocation count will only be set within RM
178              * under certain circumstances. */
179             serviceResponse->resourceNumOwners = transaction->resourceInfo.ownerCount;
180             serviceResponse->instAllocCount = transaction->resourceInfo.instAllocCount;
181             if ((serviceResponse->serviceState == RM_SERVICE_PROCESSING) ||
182                 (serviceResponse->serviceState == RM_SERVICE_APPROVED_STATIC) ||
183                 (serviceResponse->serviceState ==
184                  RM_SERVICE_PENDING_SERVER_RESPONSE)) {
185                 /* Service still being processed.  Static requests will have
186                  * their validation responses sent once all transports have
187                  * been established.  Provide transaction ID back to component
188                  * so it can sort service responses received via callback
189                  * function */
190                 serviceResponse->serviceId = transaction->localId;
191             }
193             if ((serviceResponse->serviceState == RM_SERVICE_APPROVED) ||
194                 (serviceResponse->serviceState == RM_SERVICE_APPROVED_STATIC)) {
195                 rm_strncpy(serviceResponse->resourceName,
196                            transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
197                 serviceResponse->resourceBase = transaction->resourceInfo.base;
198                 serviceResponse->resourceLength = transaction->resourceInfo.length;
199             }
201             /* Transactions still processing not deleted from queue including
202              * static transactions which will be verified once all transports
203              * are up */
204             if ((serviceResponse->serviceState != RM_SERVICE_PROCESSING) &&
205                 (serviceResponse->serviceState != RM_SERVICE_APPROVED_STATIC) &&
206                 (serviceResponse->serviceState !=
207                  RM_SERVICE_PENDING_SERVER_RESPONSE)) {
208                 rmTransactionQueueDelete(rmInst, transaction->localId);
209             }
210         }
211     } else {
212         serviceResponse->serviceState = RM_ERROR_SERVICE_TRANS_NOT_CREATED;
213     }
215 errorExit:
216     /* Free sem object using originating instance in case the Shared Client to
217      * Shared Server instance switch took place */
218     if (((Rm_Inst *)rmHandle)->mtSemObj) {
219         Rm_osalMtCsExit(((Rm_Inst *)rmHandle)->mtSemObj, mtKey);
220     }
221     /* Shared Client switches to Shared Server instance so only need
222      * SS_EXIT_CS macro */
223     RM_SS_INST_WB_EXIT_CS(rmInst, key);
224     return;
227 /* FUNCTION PURPOSE: Opens the RM instance service handle
228  ***********************************************************************
229  * DESCRIPTION: Returns the service handle for an RM instance.  Only
230  *              one service handle is opened per instance.
231  */
232 Rm_ServiceHandle *Rm_serviceOpenHandle(Rm_Handle rmHandle, int32_t *result)
234     Rm_Inst          *rmInst = (Rm_Inst *)rmHandle;
235     Rm_ServiceHandle *serviceHandle = NULL;
236     void             *key;
237     void             *mtKey;
238     
239     RM_SS_INST_INV_ENTER_CS(rmInst, key);
240     if (rmInst->mtSemObj) {
241         mtKey = Rm_osalMtCsEnter(rmInst->mtSemObj);
242     }
244     *result = RM_OK;
246     serviceHandle = rmInst->serviceHandle;
247     if (serviceHandle == NULL) {
248         serviceHandle = Rm_osalMalloc(sizeof(*serviceHandle));
249         if (serviceHandle) {
250             serviceHandle->rmHandle = rmHandle;
251             serviceHandle->Rm_serviceHandler = Rm_serviceHandler;
252             RM_SS_OBJ_WB(rmInst, serviceHandle, Rm_ServiceHandle);
253             rmInst->serviceHandle = serviceHandle;
254         }
255         else {
256             *result = RM_ERROR_SERVICE_HANDLE_MEM_ALLOC_FAILED;
257         }
258     }
259     
260     if (rmInst->mtSemObj) {
261         Rm_osalMtCsExit(rmInst->mtSemObj, mtKey);
262     }    
263     RM_SS_INST_WB_EXIT_CS(rmInst, key);
264     return (serviceHandle);
267 /* FUNCTION PURPOSE: Closes the RM instance service handle
268  ***********************************************************************
269  * DESCRIPTION: Closes the service handle for an RM instance.
270  */
271 int32_t Rm_serviceCloseHandle(Rm_ServiceHandle *rmServiceHandle)
273     Rm_Inst *rmInst = (Rm_Inst *)rmServiceHandle->rmHandle;
274     int32_t  retVal = RM_OK;
275     void    *key;
276     void    *mtKey;
278     RM_SS_INST_INV_ENTER_CS(rmInst, key);
279     if (rmInst->mtSemObj) {
280         mtKey = Rm_osalMtCsEnter(rmInst->mtSemObj);
281     }
283     if (rmInst->serviceHandle) {
284         Rm_osalFree((void *)rmServiceHandle, sizeof(*rmServiceHandle));
285         rmInst->serviceHandle = NULL;
286     }
287     else {
288         retVal = RM_ERROR_SERVICE_HANDLE_ALREADY_CLOSED;
289     }
290     
291     if (rmInst->mtSemObj) {
292         Rm_osalMtCsExit(rmInst->mtSemObj, mtKey);
293     }    
294     RM_SS_INST_WB_EXIT_CS(rmInst, key);
295     return(retVal);