a68288ea962a1c5807ece042a7abae4300c2ee94
[keystone-rtos/rm-lld.git] / src / rm_transport.c
1 /**\r
2  *   @file  rm.c\r
3  *\r
4  *   @brief   \r
5  *      This is the Resource Manager source.\r
6  *\r
7  *  \par\r
8  *  ============================================================================\r
9  *  @n   (C) Copyright 2012-2013, Texas Instruments, Inc.\r
10  * \r
11  *  Redistribution and use in source and binary forms, with or without \r
12  *  modification, are permitted provided that the following conditions \r
13  *  are met:\r
14  *\r
15  *    Redistributions of source code must retain the above copyright \r
16  *    notice, this list of conditions and the following disclaimer.\r
17  *\r
18  *    Redistributions in binary form must reproduce the above copyright\r
19  *    notice, this list of conditions and the following disclaimer in the \r
20  *    documentation and/or other materials provided with the   \r
21  *    distribution.\r
22  *\r
23  *    Neither the name of Texas Instruments Incorporated nor the names of\r
24  *    its contributors may be used to endorse or promote products derived\r
25  *    from this software without specific prior written permission.\r
26  *\r
27  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
28  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
29  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
30  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
31  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
32  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
33  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
34  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
35  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
36  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
37  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
38  *\r
39  *  \par\r
40 */\r
41 \r
42 /* Standard includes */\r
43 #include <string.h>\r
44 #include <stdbool.h>\r
45 \r
46 /* RM external includes */\r
47 #include <ti/drv/rm/rm.h>\r
48 #include <ti/drv/rm/rm_transport.h>\r
49 \r
50 /* RM internal includes */\r
51 #include <ti/drv/rm/include/rm_loc.h>\r
52 #include <ti/drv/rm/include/rm_transportloc.h>\r
53 \r
54 /* RM OSAL layer */\r
55 #include <rm_osal.h>\r
56 \r
57 /**********************************************************************\r
58  ********************** Internal Functions ****************************\r
59  **********************************************************************/\r
60 \r
61 static Rm_Transport *transportAdd(Rm_TransportCfg *transportCfg)\r
62 {\r
63     Rm_Inst      *rmInst = (Rm_Inst *) transportCfg->rmHandle;\r
64     Rm_Transport *transports = rmInst->transports;\r
65     Rm_Transport *newTransport = NULL;\r
66 \r
67     newTransport = Rm_osalMalloc (sizeof(Rm_Transport));\r
68     memset((void *)newTransport, 0, sizeof(Rm_Transport));\r
69 \r
70     if (newTransport) {\r
71         newTransport->rmHandle = transportCfg->rmHandle;\r
72         newTransport->appTransportHandle = transportCfg->appTransportHandle;\r
73         newTransport->remoteInstType = transportCfg->remoteInstType;\r
74         strncpy(newTransport->remoteInstName, transportCfg->remoteInstName, RM_NAME_MAX_CHARS);\r
75         newTransport->nextTransport = NULL;\r
76 \r
77         if (transports) {\r
78             while (transports->nextTransport) {\r
79                 transports = transports->nextTransport;\r
80             }\r
81             transports->nextTransport = newTransport;\r
82         }\r
83         else {\r
84             rmInst->transports = (void *)newTransport;\r
85         }\r
86     }\r
87     return (newTransport);\r
88 }\r
89 \r
90 static bool transportIsTransportRegistered(Rm_Handle rmHandle, Rm_Transport *transport)\r
91 {\r
92     Rm_Inst      *rmInst = (Rm_Inst *)rmHandle;\r
93     Rm_Transport *transportList = (Rm_Transport *)rmInst->transports;\r
94     \r
95     while (transportList) {\r
96         if (transportList == transport) {\r
97             return(true);             \r
98         }\r
99         transportList = transportList->nextTransport;\r
100     }\r
101     return (false);\r
102 }\r
103 \r
104 static void transportDelete(Rm_Transport *transport)\r
105 {\r
106     Rm_Inst      *rmInst = (Rm_Inst *)transport->rmHandle;\r
107     Rm_Transport *transportList = (Rm_Transport *)rmInst->transports;\r
108     Rm_Transport *prevTransport = NULL;\r
109 \r
110     /* Get previous transport in list */\r
111     while (transportList) {\r
112         if (transportList == transport) {\r
113             break;             \r
114         }\r
115         prevTransport = transportList;\r
116         transportList = transportList->nextTransport;\r
117     }\r
118 \r
119     if (prevTransport == NULL) {\r
120          rmInst->transports = (void *)transport->nextTransport;\r
121     }\r
122     else {\r
123          prevTransport->nextTransport = transport->nextTransport;\r
124     }\r
125     Rm_osalFree((void *)transport, sizeof(Rm_Transport));\r
126 }\r
127 \r
128 Rm_Transport *rmTransportFindRemoteName(Rm_Transport *transports, char *remoteName)\r
129 {\r
130     while (transports) {\r
131         if (strncmp(transports->remoteInstName, remoteName, RM_NAME_MAX_CHARS) == 0) {\r
132             break;             \r
133         }\r
134         transports = transports->nextTransport;\r
135     }\r
136     return (transports);\r
137 }\r
138 \r
139 Rm_Transport *rmTransportFindRemoteInstType(Rm_Transport *transports, Rm_InstType remoteInstType)\r
140 {\r
141     while (transports) {\r
142         if (transports->remoteInstType == remoteInstType) {\r
143             break;             \r
144         }\r
145         transports = transports->nextTransport;\r
146     }\r
147     return (transports);\r
148 }\r
149 \r
150 Rm_PacketHandle rmTransportCreateResourceReqPkt(Rm_Inst *rmInst, Rm_AppTransportHandle appTransport,\r
151                                                 Rm_Transaction *transaction)\r
152 {\r
153     Rm_Packet             *rmPkt = NULL;\r
154     Rm_PacketHandle        pktHandle = NULL;\r
155     Rm_ResourceRequestPkt *resourceReqPkt = NULL;\r
156 \r
157     if ((rmPkt = rmInst->transportCallouts.rmAllocPkt(appTransport, \r
158                                                       sizeof(Rm_Packet),\r
159                                                       &pktHandle)) == NULL) {\r
160         transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
161         return (NULL);\r
162     }\r
163    \r
164     rmPkt->pktType = Rm_pktType_RESOURCE_REQUEST;\r
165     resourceReqPkt = (Rm_ResourceRequestPkt *) rmPkt->data;\r
166     resourceReqPkt->requestId = transaction->localId;\r
167     if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {\r
168         resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_INIT;\r
169     }\r
170     else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {\r
171         resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_USE;\r
172     }    \r
173     else if (transaction->type == Rm_service_RESOURCE_FREE) {\r
174         resourceReqPkt->resourceReqType = Rm_resReqPktType_FREE;\r
175     }\r
176     else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {\r
177         resourceReqPkt->resourceReqType = Rm_resReqPktType_GET_NAMED;\r
178     }\r
179     strncpy(resourceReqPkt->pktSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS);\r
180     strncpy(resourceReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);\r
181     memcpy ((void *)&(resourceReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),\r
182             sizeof(Rm_ResourceInfo));\r
183     \r
184     return (pktHandle);\r
185 }\r
186 \r
187 Rm_PacketHandle rmTransportCreateResourceResponsePkt(Rm_Inst *rmInst, Rm_AppTransportHandle appTransport,\r
188                                                      Rm_Transaction *transaction)\r
189 {\r
190     Rm_Packet              *rmPkt = NULL;\r
191     Rm_PacketHandle         pktHandle = NULL;\r
192     Rm_ResourceResponsePkt *resourceRespPkt = NULL;\r
193 \r
194     if ((rmPkt = rmInst->transportCallouts.rmAllocPkt(appTransport, \r
195                                                       sizeof(Rm_Packet),\r
196                                                       &pktHandle)) == NULL) {\r
197         transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
198         return (NULL);\r
199     }\r
200  \r
201     rmPkt->pktType = Rm_pktType_RESOURCE_RESPONSE;                 \r
202     resourceRespPkt = (Rm_ResourceResponsePkt *)rmPkt->data;\r
203     resourceRespPkt->responseId = transaction->remoteOriginatingId;\r
204     resourceRespPkt->requestState = transaction->state;\r
205     memcpy ((void *)&(resourceRespPkt->resourceInfo), (void *)&(transaction->resourceInfo),\r
206             sizeof(Rm_ResourceInfo));\r
207 \r
208     return (pktHandle);\r
209 }\r
210 \r
211 Rm_PacketHandle rmTransportCreateNsRequestPkt(Rm_Inst *rmInst, Rm_AppTransportHandle appTransport,\r
212                                               Rm_Transaction *transaction)\r
213 {\r
214     Rm_Packet       *rmPkt = NULL;\r
215     Rm_PacketHandle  pktHandle = NULL;    \r
216     Rm_NsRequestPkt *nsReqPkt = NULL;\r
217 \r
218     if ((rmPkt = rmInst->transportCallouts.rmAllocPkt(appTransport, \r
219                                                       sizeof(Rm_Packet),\r
220                                                       &pktHandle)) == NULL) {\r
221         transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
222         return (NULL);\r
223     }\r
224 \r
225     rmPkt->pktType = Rm_pktType_NAMESERVER_REQUEST;                   \r
226     nsReqPkt = (Rm_NsRequestPkt *)rmPkt->data;\r
227     nsReqPkt->requestId = transaction->localId;\r
228     if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {\r
229         nsReqPkt->nsRequestType = Rm_nsReqPktType_MAP_RESOURCE;\r
230     }\r
231     else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {\r
232         nsReqPkt->nsRequestType = Rm_nsReqPktType_UNMAP_RESOURCE;\r
233     }\r
234     strncpy(nsReqPkt->pktSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS);\r
235     strncpy(nsReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);\r
236     memcpy ((void *)&(nsReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),\r
237             sizeof(Rm_ResourceInfo));\r
238     \r
239     return (pktHandle);\r
240 }\r
241 \r
242 Rm_PacketHandle rmTransportCreateNsResponsePkt(Rm_Inst *rmInst, Rm_AppTransportHandle appTransport,\r
243                                                Rm_Transaction *transaction)\r
244 {\r
245     Rm_Packet        *rmPkt = NULL;\r
246     Rm_PacketHandle   pktHandle = NULL;\r
247     Rm_NsResponsePkt *nsRespPkt = NULL;\r
248 \r
249     if ((rmPkt = rmInst->transportCallouts.rmAllocPkt(appTransport, \r
250                                                       sizeof(Rm_Packet),\r
251                                                       &pktHandle)) == NULL) {\r
252         transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
253         return (NULL);\r
254     }\r
255  \r
256     rmPkt->pktType = Rm_pktType_NAMESERVER_RESPONSE;                \r
257     nsRespPkt = (Rm_NsResponsePkt *)rmPkt->data;\r
258     nsRespPkt->responseId = transaction->remoteOriginatingId;\r
259     nsRespPkt->requestState = transaction->state;\r
260 \r
261     return (pktHandle);\r
262 }\r
263 \r
264 /**********************************************************************\r
265  ********************* Application visible APIs ***********************\r
266  **********************************************************************/\r
267 \r
268 Rm_TransportHandle Rm_transportRegister (Rm_TransportCfg *transportCfg, int32_t *result)\r
269 {\r
270     Rm_Inst      *rmInst = (Rm_Inst *) transportCfg->rmHandle;\r
271     Rm_Transport *transport = NULL;\r
272 \r
273     /* RM Servers cannot connect to other Servers.  \r
274      * RM Client Delegates cannot connect to other Client Delegates.\r
275      * RM Clients cannot connect to other Clients */\r
276     if (((rmInst->instType == Rm_instType_SERVER) &&\r
277          (transportCfg->remoteInstType == Rm_instType_SERVER)) ||\r
278         ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
279          (transportCfg->remoteInstType == Rm_instType_CLIENT_DELEGATE)) ||\r
280         ((rmInst->instType == Rm_instType_CLIENT) &&\r
281          (transportCfg->remoteInstType == Rm_instType_CLIENT))) {\r
282         *result = RM_ERROR_INVALID_REMOTE_INST_TYPE;\r
283         return(NULL);\r
284     }\r
285 \r
286     /* Verify Clients are not registering with more than one Client Delegate or Server. And\r
287      * that Client Delegate is not registering with more than one Server. */\r
288     if (rmInst->registeredWithDelegateOrServer &&\r
289         (((rmInst->instType == Rm_instType_CLIENT) &&\r
290           (transportCfg->remoteInstType == Rm_instType_CLIENT_DELEGATE)) || \r
291          ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
292           (transportCfg->remoteInstType == Rm_instType_SERVER)))) {\r
293         *result = RM_ERROR_ALREADY_REGD_SERVER_OR_CD;\r
294         return(NULL);\r
295     }         \r
296     \r
297     if (transportCfg->transportCalloutsValid &&\r
298         ((transportCfg->transportCallouts.rmAllocPkt == NULL) ||\r
299          (transportCfg->transportCallouts.rmSendPkt == NULL))) {\r
300         *result = RM_ERROR_NULL_CALLOUTS_WHEN_VALID;\r
301         return(NULL);\r
302     }\r
303     else {\r
304         rmInst->transportCallouts.rmAllocPkt = transportCfg->transportCallouts.rmAllocPkt;\r
305         rmInst->transportCallouts.rmSendPkt = transportCfg->transportCallouts.rmSendPkt;\r
306     }\r
307 \r
308     transport = transportAdd(transportCfg);\r
309 \r
310     if ((transport->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
311         (transport->remoteInstType == Rm_instType_SERVER)) {\r
312         rmInst->registeredWithDelegateOrServer = true;\r
313     }\r
314 \r
315     *result = RM_OK;\r
316     return ((Rm_TransportHandle) transport);\r
317 }\r
318 \r
319 int32_t Rm_transportUnregister(Rm_TransportHandle transportHandle)\r
320 {\r
321     Rm_Transport *transport = (Rm_Transport *)transportHandle;\r
322     Rm_Inst      *rmInst = (Rm_Inst *)transport->rmHandle;\r
323     int32_t       retVal = RM_OK;  \r
324 \r
325     if (transportIsTransportRegistered(transport->rmHandle, transport)) {\r
326         if ((transport->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
327             (transport->remoteInstType == Rm_instType_SERVER)) {\r
328             rmInst->registeredWithDelegateOrServer = false;\r
329         }\r
330         transportDelete(transport);\r
331     }\r
332     else {\r
333         retVal = RM_ERROR_TRANSPORT_HANDLE_DOES_NOT_EXIST;\r
334     }\r
335     return (retVal);\r
336 }\r
337 \r
338 /* Used by the application to pass RM packets received from a transport to RM.\r
339  * Function can be called from polling or ISR context. */\r
340 int32_t Rm_receivePacket(Rm_TransportHandle transportHandle, Rm_Packet *pkt)\r
341 {\r\r\r
342     Rm_Transport   *transport = (Rm_Transport *)transportHandle;\r
343     Rm_Inst        *rmInst = (Rm_Inst *)transport->rmHandle;\r
344     Rm_Transaction *transaction;\r
345 \r
346     if (!transportIsTransportRegistered(transport->rmHandle, transport)) {\r
347         return (RM_ERROR_TRANSPORT_HANDLE_DOES_NOT_EXIST);\r
348     }\r
349 \r
350     switch (pkt->pktType) {\r
351         case Rm_pktType_RESOURCE_REQUEST:\r
352         {\r
353             Rm_ResourceRequestPkt *resourceReqPkt = (Rm_ResourceRequestPkt *)pkt->data;\r
354 \r
355             transaction = rmTransactionQueueAdd(rmInst);\r
356             transaction->remoteOriginatingId = resourceReqPkt->requestId;\r
357             if (resourceReqPkt->resourceReqType == Rm_resReqPktType_ALLOCATE_INIT) {\r
358                 transaction->type = Rm_service_RESOURCE_ALLOCATE_INIT;\r
359             }\r
360             else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_ALLOCATE_USE) {\r
361                 transaction->type = Rm_service_RESOURCE_ALLOCATE_USE;\r
362             }            \r
363             else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_FREE) {\r
364                 transaction->type = Rm_service_RESOURCE_FREE;\r
365             }\r
366             else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_GET_NAMED) {\r
367                 transaction->type = Rm_service_RESOURCE_GET_BY_NAME;\r
368             }            \r
369             strncpy(transaction->pktSrcInstName, resourceReqPkt->pktSrcInstName, RM_NAME_MAX_CHARS);\r
370             strncpy(transaction->serviceSrcInstName, resourceReqPkt->serviceSrcInstName, RM_NAME_MAX_CHARS);\r
371             transaction->state = RM_SERVICE_PROCESSING;\r
372             memcpy ((void *)&(transaction->resourceInfo), (void *)&(resourceReqPkt->resourceInfo),\r
373                     sizeof(Rm_ResourceInfo));\r
374             rmTransactionProcessor(rmInst, transaction);\r
375             break;\r
376         }\r
377         case Rm_pktType_RESOURCE_RESPONSE:\r
378         {\r
379             Rm_ResourceResponsePkt *resourceRespPkt = (Rm_ResourceResponsePkt *)pkt->data;\r
380 \r
381             if (transaction = rmTransactionQueueFind(rmInst,resourceRespPkt->responseId)) {\r
382                 if ((transaction->state == RM_SERVICE_APPROVED_STATIC) &&\r
383                     (resourceRespPkt->requestState != RM_SERVICE_APPROVED)) {\r
384                     /* Lock the RM instance since service validated against static policy failed against \r
385                      * Server's global policy */\r
386                     rmInst->isLocked = true;\r
387                 }\r
388                 transaction->state = resourceRespPkt->requestState;\r
389 \r
390                 if ((transaction->state == RM_SERVICE_APPROVED) &&\r
391                     ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||\r
392                      (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||\r
393                      (transaction->type == Rm_service_RESOURCE_GET_BY_NAME))) {\r
394                     memcpy ((void *)&(transaction->resourceInfo), (void *)&(resourceRespPkt->resourceInfo),\r
395                             sizeof(Rm_ResourceInfo));\r
396                 }\r
397                 rmTransactionProcessor(rmInst, transaction);\r
398             }\r
399             else {\r
400                 return (RM_ERROR_PKT_RESP_DOES_NOT_MATCH_ANY_REQ);\r
401             }\r
402             break;\r
403         }\r
404         case Rm_pktType_NAMESERVER_REQUEST:\r
405         {\r
406             Rm_NsRequestPkt *nsRequestPkt = (Rm_NsRequestPkt *)pkt->data;\r
407 \r
408             transaction = rmTransactionQueueAdd(rmInst);\r
409             transaction->remoteOriginatingId = nsRequestPkt->requestId;\r
410 \r
411             if (nsRequestPkt->nsRequestType == Rm_nsReqPktType_MAP_RESOURCE) {\r
412                 transaction->type = Rm_service_RESOURCE_MAP_TO_NAME;\r
413             }\r
414             else if (nsRequestPkt->nsRequestType == Rm_nsReqPktType_UNMAP_RESOURCE) {\r
415                 transaction->type = Rm_service_RESOURCE_UNMAP_NAME;\r
416             }\r
417 \r
418             strncpy(transaction->pktSrcInstName, nsRequestPkt->pktSrcInstName, RM_NAME_MAX_CHARS);\r
419             strncpy(transaction->serviceSrcInstName, nsRequestPkt->serviceSrcInstName, RM_NAME_MAX_CHARS);\r
420             transaction->state = RM_SERVICE_PROCESSING;\r
421             memcpy ((void *)&(transaction->resourceInfo), (void *)&(nsRequestPkt->resourceInfo),\r
422                     sizeof(Rm_ResourceInfo));\r
423             rmTransactionProcessor(rmInst, transaction);            \r
424             break;\r
425         }\r
426         case Rm_pktType_NAMESERVER_RESPONSE:\r
427         {\r
428             Rm_NsResponsePkt *nsResponsePkt = (Rm_NsResponsePkt *)pkt->data;\r
429 \r
430             if (transaction = rmTransactionQueueFind(rmInst, nsResponsePkt->responseId)) {\r
431                 if ((transaction->state == RM_SERVICE_APPROVED_STATIC) &&\r
432                     (nsResponsePkt->requestState != RM_SERVICE_APPROVED)) {\r
433                     /* Lock the RM instance since service validated against static policy failed against \r
434                      * Server's global policy */                    \r
435                     rmInst->isLocked = true;\r
436                 }                \r
437                 transaction->state = nsResponsePkt->requestState;            \r
438                 rmTransactionProcessor(rmInst, transaction);\r
439             }\r
440             else {\r
441                 return (RM_ERROR_PKT_RESP_DOES_NOT_MATCH_ANY_REQ);\r
442             }\r
443             break;\r
444         }\r
445         default:\r
446             return (RM_ERROR_RECEIVED_INVALID_PACKET_TYPE);\r
447       }\r
448 \r
449     return (RM_OK);\r
450 }\r
451 \r