933f4ffb023685d40af6887dfef0c9de53de065d
[keystone-rtos/rm-lld.git] / src / rm_transport.c
1 /**\r
2  *   @file  rm_transport.c\r
3  *\r
4  *   @brief   \r
5  *      This is the Resource Manager transport source.\r
6  *\r
7  *  \par\r
8  *  ============================================================================\r
9  *  @n   (C) Copyright 2012-2014, 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 \r
45 /* RM external includes */\r
46 #include <ti/drv/rm/rm.h>\r
47 #include <ti/drv/rm/rm_transport.h>\r
48 \r
49 /* RM internal includes */\r
50 #include <ti/drv/rm/include/rm_loc.h>\r
51 #include <ti/drv/rm/include/rm_transportloc.h>\r
52 \r
53 /* RM OSAL layer */\r
54 #include <rm_osal.h>\r
55 \r
56 /**********************************************************************\r
57  ************************ Local Functions *****************************\r
58  **********************************************************************/\r
59 \r
60 /* FUNCTION PURPOSE: Adds a transport\r
61  ***********************************************************************\r
62  * DESCRIPTION: Returns a pointer to a transport structure that\r
63  *              was created, initialized, and added to the \r
64  *              instance transport list.\r
65  */\r
66 static Rm_Transport *transportAdd(const Rm_TransportCfg *transportCfg)\r
67 {\r
68     Rm_Inst      *rmInst = (Rm_Inst *) transportCfg->rmHandle;\r
69     Rm_Transport *transports = rmInst->transports;\r
70     Rm_Transport *newTransport = NULL;\r
71 \r
72     newTransport = Rm_osalMalloc (sizeof(Rm_Transport));\r
73     memset((void *)newTransport, 0, sizeof(Rm_Transport));\r
74 \r
75     if (newTransport) {\r
76         newTransport->rmHandle = transportCfg->rmHandle;\r
77         newTransport->appTransportHandle = transportCfg->appTransportHandle;\r
78         newTransport->remoteInstType = transportCfg->remoteInstType;\r
79         newTransport->callouts.rmAllocPkt = transportCfg->transportCallouts.rmAllocPkt;\r
80         newTransport->callouts.rmSendPkt = transportCfg->transportCallouts.rmSendPkt;\r
81         newTransport->nextTransport = NULL;\r
82 \r
83         if (transports) {\r
84             while (transports->nextTransport) {\r
85                 transports = transports->nextTransport;\r
86             }\r
87             transports->nextTransport = newTransport;\r
88         }\r
89         else {\r
90             rmInst->transports = newTransport;\r
91         }\r
92     }\r
93     return (newTransport);\r
94 }\r
95 \r
96 /* FUNCTION PURPOSE: Tests if a transport is registered to an instance\r
97  ***********************************************************************\r
98  * DESCRIPTION: Returns TRUE if the supplied transport is found in\r
99  *              the instance transport list.  Otherwise, returns FALSE\r
100  */\r
101 static int transportIsRegistered(Rm_Handle rmHandle, Rm_Transport *transport)\r
102 {\r
103     Rm_Inst      *rmInst = (Rm_Inst *)rmHandle;\r
104     Rm_Transport *transportList = (Rm_Transport *)rmInst->transports;\r
105     \r
106     while (transportList) {\r
107         if (transportList == transport) {\r
108             return(RM_TRUE);             \r
109         }\r
110         transportList = transportList->nextTransport;\r
111     }\r
112     return (RM_FALSE);\r
113 }\r
114 \r
115 /* FUNCTION PURPOSE: Deletes a transport\r
116  ***********************************************************************\r
117  * DESCRIPTION: Removes a transport from an instance transport list\r
118  *              and then frees the memory associated with the transport\r
119  *              data structure\r
120  */\r
121 static void transportDelete(Rm_Transport *transport)\r
122 {\r
123     Rm_Inst      *rmInst = (Rm_Inst *)transport->rmHandle;\r
124     Rm_Transport *transportList = (Rm_Transport *)rmInst->transports;\r
125     Rm_Transport *prevTransport = NULL;\r
126 \r
127     /* Get previous transport in list */\r
128     while (transportList) {\r
129         if (transportList == transport) {\r
130             break;             \r
131         }\r
132         prevTransport = transportList;\r
133         transportList = transportList->nextTransport;\r
134     }\r
135 \r
136     if (prevTransport == NULL) {\r
137          rmInst->transports = transport->nextTransport;\r
138     }\r
139     else {\r
140          prevTransport->nextTransport = transport->nextTransport;\r
141     }\r
142     Rm_osalFree((void *)transport, sizeof(Rm_Transport));\r
143 }\r
144 \r
145 /**********************************************************************\r
146  ********************** Internal Functions ****************************\r
147  **********************************************************************/\r
148 \r
149 /* FUNCTION PURPOSE: Finds a transport based on remote inst type\r
150  ***********************************************************************\r
151  * DESCRIPTION: Returns a pointer to the transport within an instance's\r
152  *              transport list that matches the provided remote\r
153  *              instance type.  NULL is returned if no transports in \r
154  *              the list match the remote instance type.\r
155  */\r
156 Rm_Transport *rmTransportFindRemoteInstType(Rm_Transport *transports, Rm_InstType remoteInstType)\r
157 {\r
158     while (transports) {\r
159         if (transports->remoteInstType == remoteInstType) {\r
160             break;             \r
161         }\r
162         transports = transports->nextTransport;\r
163     }\r
164     return (transports);\r
165 }\r
166 \r
167 /* FUNCTION PURPOSE: Returns RM packet source instance\r
168  ***********************************************************************\r
169  * DESCRIPTION: Can return the RM instance name for one of two things:\r
170  *                  - RM instance from which provided RM packet originated\r
171  *                  - RM instance from which the service request contained\r
172  *                    in the provided RM packet originated\r
173  */\r
174 int32_t getPktSrcNames(const Rm_Packet *pkt, char *pktSrc, char *serviceSrc, int32_t bufLen)\r
175 {\r
176     int32_t retVal = RM_OK;\r
177 \r
178     if (bufLen != RM_NAME_MAX_CHARS) {\r
179         retVal = RM_ERROR_SRC_NAME_BUF_INVALID_SIZE;\r
180     }\r
181     else {\r
182         switch (pkt->pktType) {\r
183             case Rm_pktType_RESOURCE_REQUEST:\r
184             {\r
185                 Rm_ResourceRequestPkt *resourceReqPkt = (Rm_ResourceRequestPkt *)pkt->data;\r
186 \r
187                 if (pktSrc){\r
188                     strncpy(pktSrc, resourceReqPkt->pktSrcInstName, RM_NAME_MAX_CHARS);\r
189                 }\r
190 \r
191                 if (serviceSrc) {\r
192                     strncpy(serviceSrc, resourceReqPkt->serviceSrcInstName, RM_NAME_MAX_CHARS);\r
193                 }\r
194 \r
195                 break;\r
196             }\r
197             case Rm_pktType_NAMESERVER_REQUEST:\r
198             {\r
199                 Rm_NsRequestPkt *nsRequestPkt = (Rm_NsRequestPkt *)pkt->data;\r
200 \r
201                 if (pktSrc){\r
202                     strncpy(pktSrc, nsRequestPkt->pktSrcInstName, RM_NAME_MAX_CHARS);\r
203                 }\r
204 \r
205                 if (serviceSrc) {\r
206                     strncpy(serviceSrc, nsRequestPkt->serviceSrcInstName, RM_NAME_MAX_CHARS);\r
207                 }\r
208 \r
209                 break;\r
210             }\r
211             case Rm_pktType_RESOURCE_RESPONSE:\r
212             case Rm_pktType_NAMESERVER_RESPONSE:\r
213             default:\r
214             {\r
215                 retVal = RM_ERROR_PKT_AND_SERVICE_SRC_NOT_AVAIL;\r
216                 break;\r
217             }\r
218         }\r
219     }\r
220 \r
221     return (retVal);\r
222 }\r
223 \r
224 /**********************************************************************\r
225  ********************* Application visible APIs ***********************\r
226  **********************************************************************/\r
227 \r
228 /* FUNCTION PURPOSE: Registers an app transport with a RM instance\r
229  ***********************************************************************\r
230  * DESCRIPTION: Returns a transport handle to the application that\r
231  *              has been registered with an RM instance.  The handle\r
232  *              is used by the application to route packets to the\r
233  *              proper RM instance's based on the application\r
234  *              transport receive code.  The handle is also used\r
235  *              internally by RM to route request and response \r
236  *              packets to the correct application transports. NULL\r
237  *              is returned for the transport handle if any errors\r
238  *              are encountered.\r
239  */\r
240 Rm_TransportHandle Rm_transportRegister (const Rm_TransportCfg *transportCfg, int32_t *result)\r
241 {\r
242     Rm_Inst      *rmInst = (Rm_Inst *) transportCfg->rmHandle;\r
243     Rm_Transport *transport = NULL;\r
244     void         *key;\r
245 \r
246     *result = RM_OK;\r
247 \r
248     RM_SS_INST_INV_ENTER_CS(key);\r
249 \r
250     /* Shared servers and clients cannot connect to anyone */\r
251     if ((rmInst->instType == Rm_instType_SHARED_SERVER) ||\r
252         (rmInst->instType == Rm_instType_SHARED_CLIENT)){\r
253         *result = RM_ERROR_SHARED_INSTANCE_CANNOT_REG_TRANS;\r
254         goto errorExit;\r
255     }\r
256 \r
257     /* No one can connect to a shared server\r
258      * RM Servers cannot connect to other Servers.  \r
259      * RM Client Delegates cannot connect to other Client Delegates.\r
260      * RM Clients cannot connect to other Clients */\r
261     if ((transportCfg->remoteInstType == Rm_instType_SHARED_SERVER) ||\r
262         ((rmInst->instType == Rm_instType_SERVER) &&\r
263          (transportCfg->remoteInstType == Rm_instType_SERVER)) ||\r
264         ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
265          (transportCfg->remoteInstType == Rm_instType_CLIENT_DELEGATE)) ||\r
266         ((rmInst->instType == Rm_instType_CLIENT) &&\r
267          (transportCfg->remoteInstType == Rm_instType_CLIENT))) {\r
268         *result = RM_ERROR_INVALID_REMOTE_INST_TYPE;\r
269         goto errorExit;\r
270     }\r
271 \r
272     /* Verify Clients are not registering with more than one Client Delegate or Server. And\r
273      * that Client Delegate is not registering with more than one Server. */\r
274     if (rmInst->registeredWithDelegateOrServer &&\r
275         (((rmInst->instType == Rm_instType_CLIENT) &&\r
276           (transportCfg->remoteInstType == Rm_instType_CLIENT_DELEGATE)) || \r
277          ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
278           (transportCfg->remoteInstType == Rm_instType_SERVER)))) {\r
279         *result = RM_ERROR_ALREADY_REGD_SERVER_OR_CD;\r
280         goto errorExit;\r
281     }         \r
282     \r
283     if (!transportCfg->transportCallouts.rmAllocPkt) {\r
284         *result = RM_ERROR_TRANSPORT_ALLOC_PKT_NOT_REGD;\r
285         goto errorExit;\r
286     }\r
287     else if (!transportCfg->transportCallouts.rmSendPkt) {\r
288         *result = RM_ERROR_TRANSPORT_SEND_NOT_REGD;\r
289         goto errorExit;\r
290     }\r
291 \r
292     transport = transportAdd(transportCfg);\r
293     if ((transport->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
294         (transport->remoteInstType == Rm_instType_SERVER)) {\r
295         rmInst->registeredWithDelegateOrServer = RM_TRUE;\r
296     }\r
297 errorExit:\r
298     RM_SS_INST_WB_EXIT_CS(key);    \r
299     return ((Rm_TransportHandle) transport);\r
300 }\r
301 \r
302 /* FUNCTION PURPOSE: Reconfigures an instance's transport handle\r
303  ***********************************************************************\r
304  * DESCRIPTION: Reconfigures a transport handle based on the provided\r
305  *              configuration parameters if it exists within the \r
306  *              instance.\r
307  */\r
308 int32_t Rm_transportReconfig (Rm_TransportHandle transportHandle, const Rm_TransportReCfg *reCfg)\r
309 {\r
310     Rm_Transport *transport = (Rm_Transport *)transportHandle;\r
311     Rm_Inst      *rmInst = (Rm_Inst *)transport->rmHandle;\r
312     void         *key;\r
313     int32_t       retVal = RM_OK;\r
314 \r
315     RM_SS_INST_INV_ENTER_CS(key);\r
316 \r
317     if (transportIsRegistered(transport->rmHandle, transport)) {\r
318         /* Reconfigure existing transport's appTransportHandle.  Used in cases where instances\r
319          * running on same core connected by function call. */\r
320         transport->appTransportHandle = reCfg->appTransportHandle;\r
321 \r
322         if (reCfg->transportCallouts.rmAllocPkt) {\r
323             transport->callouts.rmAllocPkt = reCfg->transportCallouts.rmAllocPkt;\r
324         }\r
325         if (reCfg->transportCallouts.rmSendPkt) {\r
326             transport->callouts.rmSendPkt = reCfg->transportCallouts.rmSendPkt;\r
327         }\r
328     }\r
329     else {\r
330         retVal = RM_ERROR_TRANSPORT_HANDLE_DOES_NOT_EXIST;\r
331     }        \r
332 \r
333     RM_SS_INST_WB_EXIT_CS(key);    \r
334     return (retVal);\r
335 }\r
336 \r
337 /* FUNCTION PURPOSE: Unregisters an app transport from a RM instance\r
338  ***********************************************************************\r
339  * DESCRIPTION: Deletes a registered transport from the transport\r
340  *              list and cleans up the memory associated with the\r
341  *              transport data structure.\r
342  */\r
343 int32_t Rm_transportUnregister(Rm_TransportHandle transportHandle)\r
344 {\r
345     Rm_Transport *transport = (Rm_Transport *)transportHandle;\r
346     Rm_Inst      *rmInst = (Rm_Inst *)transport->rmHandle;\r
347     int32_t       retVal = RM_OK;\r
348 \r
349     if (transportIsRegistered(transport->rmHandle, transport)) {\r
350         if ((transport->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
351             (transport->remoteInstType == Rm_instType_SERVER)) {\r
352             rmInst->registeredWithDelegateOrServer = RM_FALSE;\r
353         }\r
354         transportDelete(transport);\r
355     }\r
356     else {\r
357         retVal = RM_ERROR_TRANSPORT_HANDLE_DOES_NOT_EXIST;\r
358     }\r
359     return (retVal);\r
360 }\r
361 \r
362 /* FUNCTION PURPOSE: Returns a RM packet's service source instance name\r
363  ***********************************************************************\r
364  * DESCRIPTION: Returns the RM instance name from which the service\r
365  *              encapsulated in the RM packet originated.\r
366  */\r
367 int32_t Rm_receiveGetPktServiceSrcName(const Rm_Packet *pkt, char *serviceInstName, \r
368                                          int32_t charBufLen)\r
369 {\r
370     return(getPktSrcNames(pkt, NULL, serviceInstName, charBufLen));\r
371 }\r
372 \r
373 /* FUNCTION PURPOSE: Returns a RM packet's source instance name\r
374  ***********************************************************************\r
375  * DESCRIPTION: Returns the RM instance name from which the RM packet\r
376  *              originated.\r
377  */\r
378 int32_t Rm_receiveGetPktSrcName(const Rm_Packet *pkt, char *pktInstName, \r
379                                   int32_t charBufLen)\r
380 {\r
381     return(getPktSrcNames(pkt, pktInstName, NULL, charBufLen));\r
382 }\r
383 \r
384 /* FUNCTION PURPOSE: Receives RM packets\r
385  ***********************************************************************\r
386  * DESCRIPTION: The application provides RM packets received on the\r
387  *              application transports to RM via this API.  Function\r
388  *              can be called from polling or ISR contexts.  Assume \r
389  *              invoking application will free packet after this\r
390  *              function returns.\r
391  */\r
392 int32_t Rm_receivePacket(Rm_TransportHandle transportHandle, const Rm_Packet *pkt)\r
393 {\r\r\r
394     Rm_Transport   *transport = (Rm_Transport *)transportHandle;\r
395     Rm_Inst        *rmInst = (Rm_Inst *)transport->rmHandle;\r
396     Rm_Transaction *transaction;\r
397     int32_t         retVal = RM_OK;\r
398 \r
399     if (!transportIsRegistered(transport->rmHandle, transport)) {\r
400         retVal = RM_ERROR_TRANSPORT_HANDLE_DOES_NOT_EXIST;\r
401         goto errorExit;\r
402     }\r
403 \r
404     switch (pkt->pktType) {\r
405         case Rm_pktType_RESOURCE_REQUEST:\r
406         {\r
407             Rm_ResourceRequestPkt *resourceReqPkt = (Rm_ResourceRequestPkt *)pkt->data;\r
408 \r
409             transaction = rmTransactionQueueAdd(rmInst);\r
410             transaction->remoteOriginatingId = resourceReqPkt->requestId;\r
411             transaction->u.respTrans = transport;\r
412             if (resourceReqPkt->resourceReqType == Rm_resReqPktType_ALLOCATE_INIT) {\r
413                 transaction->type = Rm_service_RESOURCE_ALLOCATE_INIT;\r
414             }\r
415             else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_ALLOCATE_USE) {\r
416                 transaction->type = Rm_service_RESOURCE_ALLOCATE_USE;\r
417             }\r
418             else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_GET_STATUS) {\r
419                 transaction->type = Rm_service_RESOURCE_STATUS;\r
420             }\r
421             else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_FREE) {\r
422                 transaction->type = Rm_service_RESOURCE_FREE;\r
423             }\r
424             else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_GET_NAMED) {\r
425                 transaction->type = Rm_service_RESOURCE_GET_BY_NAME;\r
426             }            \r
427             strncpy(transaction->serviceSrcInstName, resourceReqPkt->serviceSrcInstName, RM_NAME_MAX_CHARS);\r
428             transaction->state = RM_SERVICE_PROCESSING;\r
429             memcpy ((void *)&(transaction->resourceInfo), (void *)&(resourceReqPkt->resourceInfo),\r
430                     sizeof(Rm_ResourceInfo));\r
431             break;\r
432         }\r
433         case Rm_pktType_RESOURCE_RESPONSE:\r
434         {\r
435             Rm_ResourceResponsePkt *resourceRespPkt = (Rm_ResourceResponsePkt *)pkt->data;\r
436 \r
437             if (transaction = rmTransactionQueueFind(rmInst,resourceRespPkt->responseId)) {\r
438                 if ((transaction->state == RM_SERVICE_APPROVED_STATIC) &&\r
439                     (resourceRespPkt->requestState != RM_SERVICE_APPROVED)) {\r
440                     /* Lock the RM instance since service validated against static policy failed against \r
441                      * Server's global policy */\r
442                     rmInst->isLocked = RM_TRUE;\r
443                 }\r
444                 transaction->state = resourceRespPkt->requestState;\r
445 \r
446                 if ((transaction->state == RM_SERVICE_APPROVED) &&\r
447                     ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||\r
448                      (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||\r
449                      (transaction->type == Rm_service_RESOURCE_STATUS) ||\r
450                      (transaction->type == Rm_service_RESOURCE_GET_BY_NAME))) {\r
451                     memcpy ((void *)&(transaction->resourceInfo), (void *)&(resourceRespPkt->resourceInfo),\r
452                             sizeof(Rm_ResourceInfo));\r
453                 }\r
454                 else {\r
455                     /* Always copy owner count and instance allocation count */\r
456                     transaction->resourceInfo.ownerCount = resourceRespPkt->resourceInfo.ownerCount;\r
457                     transaction->resourceInfo.instAllocCount = resourceRespPkt->resourceInfo.instAllocCount;\r
458                 }\r
459             }\r
460             else {\r
461                 retVal = RM_ERROR_PKT_RESP_DOES_NOT_MATCH_ANY_REQ;\r
462                 goto errorExit;\r
463             }\r
464             break;\r
465         }\r
466         case Rm_pktType_NAMESERVER_REQUEST:\r
467         {\r
468             Rm_NsRequestPkt *nsRequestPkt = (Rm_NsRequestPkt *)pkt->data;\r
469 \r
470             transaction = rmTransactionQueueAdd(rmInst);\r
471             transaction->remoteOriginatingId = nsRequestPkt->requestId;\r
472             transaction->u.respTrans = transport;\r
473 \r
474             if (nsRequestPkt->nsRequestType == Rm_nsReqPktType_MAP_RESOURCE) {\r
475                 transaction->type = Rm_service_RESOURCE_MAP_TO_NAME;\r
476             }\r
477             else if (nsRequestPkt->nsRequestType == Rm_nsReqPktType_UNMAP_RESOURCE) {\r
478                 transaction->type = Rm_service_RESOURCE_UNMAP_NAME;\r
479             }\r
480 \r
481             strncpy(transaction->serviceSrcInstName, nsRequestPkt->serviceSrcInstName, RM_NAME_MAX_CHARS);\r
482             transaction->state = RM_SERVICE_PROCESSING;\r
483             memcpy ((void *)&(transaction->resourceInfo), (void *)&(nsRequestPkt->resourceInfo),\r
484                     sizeof(Rm_ResourceInfo));           \r
485             break;\r
486         }\r
487         case Rm_pktType_NAMESERVER_RESPONSE:\r
488         {\r
489             Rm_NsResponsePkt *nsResponsePkt = (Rm_NsResponsePkt *)pkt->data;\r
490 \r
491             if (transaction = rmTransactionQueueFind(rmInst, nsResponsePkt->responseId)) {\r
492                 if ((transaction->state == RM_SERVICE_APPROVED_STATIC) &&\r
493                     (nsResponsePkt->requestState != RM_SERVICE_APPROVED)) {\r
494                     /* Lock the RM instance since service validated against static policy failed against \r
495                      * Server's global policy */                    \r
496                     rmInst->isLocked = RM_TRUE;\r
497                 }                \r
498                 transaction->state = nsResponsePkt->requestState;            \r
499             }\r
500             else {\r
501                 retVal = RM_ERROR_PKT_RESP_DOES_NOT_MATCH_ANY_REQ;\r
502                 goto errorExit;\r
503             }\r
504             break;\r
505         }\r
506         default:\r
507             retVal = RM_ERROR_RECEIVED_INVALID_PACKET_TYPE;\r
508             goto errorExit;\r
509     }\r
510 \r
511     /* Process received transaction */\r
512     rmProcessRouter(rmInst, transaction);   \r
513 errorExit:\r
514     return(retVal);\r
515 }\r
516 \r