TransportShm: Fix handling of address > 32 bits
[ipc/ipcdev.git] / packages / ti / sdo / ipc / transports / TransportShm.c
1 /*
2  * Copyright (c) 2012-2019 Texas Instruments Incorporated - http://www.ti.com
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 /*
33  *  ======== TransportShm.c ========
34  */
36 #include <xdc/std.h>
37 #include <xdc/runtime/Assert.h>
38 #include <xdc/runtime/Error.h>
39 #include <xdc/runtime/Gate.h>
40 #include <xdc/runtime/Memory.h>
42 #include <ti/sysbios/hal/Cache.h>
43 #include <ti/sysbios/knl/Swi.h>
45 #include "package/internal/TransportShm.xdc.h"
47 #include <ti/sdo/ipc/_Ipc.h>
48 #include <ti/sdo/utils/_MultiProc.h>
49 #include <ti/sdo/ipc/_SharedRegion.h>
50 #include <ti/sdo/ipc/_Notify.h>
51 #include <ti/sdo/ipc/_GateMP.h>
52 #include <ti/sdo/ipc/_ListMP.h>
53 #include <ti/sdo/ipc/_MessageQ.h>
55 /* Need to use reserved notify events */
56 #undef TransportShm_notifyEventId
57 #define TransportShm_notifyEventId \
58         ti_sdo_ipc_transports_TransportShm_notifyEventId + \
59                     (UInt32)((UInt32)Notify_SYSTEMKEY << 16)
61 /*
62  *************************************************************************
63  *                       Module functions
64  *************************************************************************
65  */
68 /*
69  *  ======== TransportShm_notifyFxn ========
70  */
71 Void TransportShm_notifyFxn(UInt16 procId,
72                             UInt16 lineId,
73                             UInt32 eventId,
74                             UArg arg,
75                             UInt32 payload)
76 {
77     Swi_Handle swiHandle;
79     /* Swi_Handle was passed as arg in register */
80     swiHandle = (Swi_Handle)arg;
82     /* post the Swi */
83     Swi_post(swiHandle);
84 }
86 /*
87  *  ======== TransportShm_swiFxn ========
88  */
89 Void TransportShm_swiFxn(UArg arg)
90 {
91     UInt32 queueId;
92     TransportShm_Object *obj = (TransportShm_Object *)arg;
93     MessageQ_Msg msg = NULL;
95     /*
96      *  While there are messages, get them out and send them to
97      *  their final destination.
98      */
99     msg = (MessageQ_Msg)ListMP_getHead((ListMP_Handle)obj->localList);
100     while (msg != NULL) {
101         /* Get the destination message queue Id */
102         queueId = MessageQ_getDstQueue(msg);
104         /* put the message to the destination queue */
105         MessageQ_put(queueId, msg);
107         /* check to see if there are more messages */
108         msg = (MessageQ_Msg)ListMP_getHead((ListMP_Handle)obj->localList);
109     }
112 /*
113  *************************************************************************
114  *                       Instance functions
115  *************************************************************************
116  */
118 /*
119  *  ======== TransportShm_Instance_init ========
120  */
121 Int TransportShm_Instance_init(TransportShm_Object *obj,
122         UInt16 procId, const TransportShm_Params *params,
123         Error_Block *eb)
125     Int            localIndex;
126     Int            remoteIndex;
127     Int            status;
128     Bool           flag;
129     UInt32         minAlign;
130     ListMP_Params  listMPParams[2];
131     Swi_Handle     swiHandle;
132     Swi_Params     swiParams;
133     Ptr            localAddr;
135     swiHandle = TransportShm_Instance_State_swiObj(obj);
137     /*
138      *  Determine who gets the '0' slot in shared memory and who gets
139      *  the '1' slot. The '0' slot is given to the lower MultiProc id.
140      */
141     if (MultiProc_self() < procId) {
142         localIndex  = 0;
143         remoteIndex = 1;
144     }
145     else {
146         localIndex  = 1;
147         remoteIndex = 0;
148     }
150     if (params->openFlag) {
151         /* Open by sharedAddr */
152         obj->objType = ti_sdo_ipc_Ipc_ObjType_OPENDYNAMIC;
153         obj->self = (TransportShm_Attrs *)params->sharedAddr;
154         obj->regionId = SharedRegion_getId(params->sharedAddr);
155         obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
157         localAddr = SharedRegion_getPtr(obj->self->gateMPAddr);
158         if (localAddr == NULL) {
159             Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0);
160             return(1);
161         }
163         status = GateMP_openByAddr(localAddr, (GateMP_Handle *)&obj->gate);
164         if (status < 0) {
165             Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0);
166             return(1);
167         }
168     }
169     else {
170         /* init the gate for ListMP create below */
171         if (params->gate != NULL) {
172             obj->gate = params->gate;
173         }
174         else {
175             obj->gate = (ti_sdo_ipc_GateMP_Handle)GateMP_getDefaultRemote();
176         }
178         /* Creating using sharedAddr */
179         obj->regionId = SharedRegion_getId(params->sharedAddr);
181         /* Assert that the buffer is in a valid shared region */
182         Assert_isTrue(obj->regionId != SharedRegion_INVALIDREGIONID,
183                 ti_sdo_ipc_Ipc_A_addrNotInSharedRegion);
185         /* Assert that sharedAddr is cache aligned */
186         Assert_isTrue(SharedRegion_getCacheLineSize(obj->regionId) == 0 ||
187                 ((UArg)params->sharedAddr %
188                 SharedRegion_getCacheLineSize(obj->regionId) == 0),
189                 ti_sdo_ipc_Ipc_A_addrNotCacheAligned);
191         /* set object's cacheEnabled, type, self */
192         obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
193         obj->objType = ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC;
194         obj->self = (TransportShm_Attrs *)params->sharedAddr;
195     }
197     /* determine the minimum alignment to align to */
198     minAlign = Memory_getMaxDefaultTypeAlign();
199     if (SharedRegion_getCacheLineSize(obj->regionId) > minAlign) {
200         minAlign = SharedRegion_getCacheLineSize(obj->regionId);
201     }
203     /*
204      *  Carve up the shared memory.
205      *  If cache is enabled, these need to be on separate cache lines.
206      *  This is done with minAlign and _Ipc_roundup function.
207      */
208     obj->other = (TransportShm_Attrs *)((UArg)(obj->self) +
209         (_Ipc_roundup(sizeof(TransportShm_Attrs), minAlign)));
211     ListMP_Params_init(&(listMPParams[0]));
212     listMPParams[0].gate = (GateMP_Handle)obj->gate;
213     listMPParams[0].sharedAddr = (UInt32 *)((UArg)(obj->other) +
214         (_Ipc_roundup(sizeof(TransportShm_Attrs), minAlign)));
216     ListMP_Params_init(&listMPParams[1]);
217     listMPParams[1].gate = (GateMP_Handle)obj->gate;
218     listMPParams[1].sharedAddr = (UInt32 *)((UArg)(listMPParams[0].sharedAddr)
219         + ListMP_sharedMemReq(&listMPParams[0]));
221     obj->priority      = params->priority;
222     obj->remoteProcId  = procId;
224     Swi_Params_init(&swiParams);
225     swiParams.arg0 = (UArg)obj;
226     Swi_construct(Swi_struct(swiHandle),
227                  (Swi_FuncPtr)TransportShm_swiFxn,
228                  &swiParams, eb);
230     if (params->openFlag == FALSE) {
231         obj->localList = (ti_sdo_ipc_ListMP_Handle)
232                 ListMP_create(&(listMPParams[localIndex]));
233         if (obj->localList == NULL) {
234             Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0);
235             return (2);
236         }
238         obj->remoteList = (ti_sdo_ipc_ListMP_Handle)
239                 ListMP_create(&(listMPParams[remoteIndex]));
240         if (obj->localList == NULL) {
241             Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0);
242             return (2);
243         }
244     }
245     else {
246         /* Open the local ListMP instance */
247         status = ListMP_openByAddr(listMPParams[localIndex].sharedAddr,
248                                    (ListMP_Handle *)&(obj->localList));
250         if (status < 0) {
251             Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0);
252             return (2);
253         }
255         /* Open the remote ListMP instance */
256         status = ListMP_openByAddr(listMPParams[remoteIndex].sharedAddr,
257                                    (ListMP_Handle *)&(obj->remoteList));
259         if (status < 0) {
260             Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0);
261             return (2);
262         }
263     }
265     /* register the event with Notify */
266     status = Notify_registerEventSingle(
267                  procId,    /* remoteProcId */
268                  0,         /* lineId */
269                  TransportShm_notifyEventId,
270                  (Notify_FnNotifyCbck)TransportShm_notifyFxn,
271                  (UArg)swiHandle);
272     if (status < 0) {
273         Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0);
274         return (3);
275     }
277     /* Register the transport with MessageQ */
278     flag = ti_sdo_ipc_MessageQ_registerTransport(
279             TransportShm_Handle_upCast(obj), procId, params->priority);
280     if (flag == FALSE) {
281         Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0);
282         return (4);
283     }
285     if (params->openFlag == FALSE) {
286         obj->self->creatorProcId = MultiProc_self();
287         obj->self->notifyEventId = TransportShm_notifyEventId;
288         obj->self->priority = obj->priority;
290         /* Store the GateMP sharedAddr in the Attrs */
291         obj->self->gateMPAddr = ti_sdo_ipc_GateMP_getSharedAddr(obj->gate);
292         obj->self->flag = TransportShm_UP;
294         if (obj->cacheEnabled) {
295             Cache_wbInv(obj->self, sizeof(TransportShm_Attrs),
296                      Cache_Type_ALL, TRUE);
297         }
298     }
299     else {
300         obj->other->flag = TransportShm_UP;
301         if (obj->cacheEnabled) {
302             Cache_wbInv(&(obj->other->flag), minAlign, Cache_Type_ALL, TRUE);
303         }
304     }
306     obj->status = TransportShm_UP;
308     return (0);
311 /*
312  *  ======== TransportShm_Instance_finalize ========
313  */
314 Void TransportShm_Instance_finalize(TransportShm_Object* obj, Int status)
316     Swi_Handle     swiHandle;
318     if (obj->objType == ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC) {
319         /* clear the self flag */
320         obj->self->flag = 0;
322         if (obj->cacheEnabled) {
323             Cache_wbInv(&(obj->self->flag),
324                 SharedRegion_getCacheLineSize(obj->regionId), Cache_Type_ALL,
325                     TRUE);
326         }
328         if (obj->localList != NULL) {
329             ListMP_delete((ListMP_Handle *)&(obj->localList));
330         }
332         if (obj->remoteList != NULL) {
333             ListMP_delete((ListMP_Handle *)&(obj->remoteList));
334         }
335     }
336     else {
337         /* other flag was set by remote proc */
338         obj->other->flag = 0;
340         if (obj->cacheEnabled) {
341             Cache_wbInv(&(obj->other->flag),
342                 SharedRegion_getCacheLineSize(obj->regionId), Cache_Type_ALL,
343                     TRUE);
344         }
346         if (obj->gate != NULL) {
347             GateMP_close((GateMP_Handle *)&(obj->gate));
348         }
350         if (obj->localList != NULL) {
351             ListMP_close((ListMP_Handle *)&(obj->localList));
352         }
354         if (obj->remoteList != NULL) {
355             ListMP_close((ListMP_Handle *)&(obj->remoteList));
356         }
357     }
359     switch(status) {
360         case 0:
361             /* MessageQ_registerTransport succeeded */
362             ti_sdo_ipc_MessageQ_unregisterTransport(obj->remoteProcId, obj->priority);
363             /* OK to fall through */
364         case 1: /* GateMP open failed */
365         case 2: /* ListMP create/open failed */
366         case 3: /* Notify_registerEventSingle failed */
367         case 4: /* MessageQ_registerTransport failed */
368             Notify_unregisterEventSingle(
369                 obj->remoteProcId,
370                 0,
371                 TransportShm_notifyEventId);
372             break;
373     }
375     /* Destruct the swi */
376     swiHandle = TransportShm_Instance_State_swiObj(obj);
377     if (swiHandle != NULL) {
378         Swi_destruct(Swi_struct(swiHandle));
379     }
382 /*
383  *  ======== TransportShm_put ========
384  *  Assuming MessageQ_put is making sure that the arguments are ok
385  */
386 Bool TransportShm_put(TransportShm_Object *obj, Ptr msg)
388     Int32 status;
389     Bool retval = TRUE;
390     IArg key;
391     UInt16 id = SharedRegion_getId(msg);
393     /* This transport only deals with messages allocated from SR's */
394     Assert_isTrue(id != SharedRegion_INVALIDREGIONID,
395             ti_sdo_ipc_SharedRegion_A_regionInvalid);
397     /* writeback invalidate the message */
398     if (SharedRegion_isCacheEnabled(id)) {
399         Cache_wbInv(msg, ((MessageQ_Msg)(msg))->msgSize, Cache_Type_ALL,
400             TRUE);
401     }
403     /* make sure ListMP_put and sendEvent are done before remote executes */
404     key = GateMP_enter((GateMP_Handle)obj->gate);
406     /* Put the message on the remoteList */
407     ListMP_putTail((ListMP_Handle)obj->remoteList, (ListMP_Elem *)msg);
409     /* Notify the remote processor */
410     status = Notify_sendEvent(obj->remoteProcId, 0, TransportShm_notifyEventId,
411         0, FALSE);
413     /* check the status of the sendEvent */
414     if (status < 0) {
415         /* remove the message from the List and return 'FALSE' */
416         ListMP_remove((ListMP_Handle)obj->remoteList, (ListMP_Elem *)msg);
417         retval = FALSE;
418     }
420     /* leave the gate */
421     GateMP_leave((GateMP_Handle)obj->gate, key);
423     return (retval);
426 /*
427  *  ======== TransportShm_control ========
428  */
429 Bool TransportShm_control(TransportShm_Object *obj, UInt cmd, UArg cmdArg)
431     return (FALSE);
434 /*
435  *  ======== TransportShm_getStatus ========
436  */
437 Int TransportShm_getStatus(TransportShm_Object *obj)
439     return (obj->status);
442 /*
443  *************************************************************************
444  *                      Module functions
445  *************************************************************************
446  */
448 /*
449  *  ======== TransportShm_close ========
450  */
451 Void TransportShm_close(TransportShm_Handle *handle)
453     TransportShm_delete(handle);
456 /*
457  *  ======== TransportShm_openByAddr ========
458  */
459 Int TransportShm_openByAddr(Ptr sharedAddr,
460                       TransportShm_Handle *handlePtr,
461                       Error_Block *eb)
463     TransportShm_Params params;
464     TransportShm_Attrs *attrs;
465     Int status;
466     UInt16 id;
468     if (sharedAddr == NULL) {
469         return (MessageQ_E_FAIL);
470     }
472     TransportShm_Params_init(&params);
474     /* Tell Instance_init() that we're opening */
475     params.openFlag = TRUE;
477     attrs = (TransportShm_Attrs *)sharedAddr;
478     id = SharedRegion_getId(sharedAddr);
480     /* Assert that the region is valid */
481     Assert_isTrue(id != SharedRegion_INVALIDREGIONID,
482             ti_sdo_ipc_Ipc_A_addrNotInSharedRegion);
484     /* invalidate the attrs before using it */
485     if (SharedRegion_isCacheEnabled(id)) {
486         Cache_inv(attrs, sizeof(TransportShm_Attrs), Cache_Type_ALL, TRUE);
487     }
489     /* set params field */
490     params.sharedAddr    = sharedAddr;
491     params.priority      = attrs->priority;
493     if (attrs->flag != TransportShm_UP) {
494         /* make sure transport is up */
495         *handlePtr = NULL;
496         status = MessageQ_E_NOTFOUND;
497     }
498     else {
499         /* Create the object */
500         *handlePtr = TransportShm_create(attrs->creatorProcId, &params, eb);
501         if (*handlePtr == NULL) {
502             status = MessageQ_E_FAIL;
503         }
504         else {
505             status = MessageQ_S_SUCCESS;
506         }
507     }
509     return (status);
512 /*
513  *  ======== TransportShm_sharedMemReq ========
514  */
515 SizeT TransportShm_sharedMemReq(const TransportShm_Params *params)
517     SizeT memReq, minAlign;
518     UInt16 regionId;
519     ListMP_Params listMPParams;
521     regionId = SharedRegion_getId(params->sharedAddr);
523     minAlign = Memory_getMaxDefaultTypeAlign();
524     if (SharedRegion_getCacheLineSize(regionId) > minAlign) {
525         minAlign = SharedRegion_getCacheLineSize(regionId);
526     }
528     /* for the Attrs structure */
529     memReq = _Ipc_roundup(sizeof(TransportShm_Attrs), minAlign);
531     /* for the second Attrs structure */
532     memReq += _Ipc_roundup(sizeof(TransportShm_Attrs), minAlign);
534     ListMP_Params_init(&listMPParams);
535     listMPParams.regionId = regionId;
537     /* for localListMP */
538     memReq += ListMP_sharedMemReq(&listMPParams);
540     /* for remoteListMP */
541     memReq += ListMP_sharedMemReq(&listMPParams);
543     return(memReq);
546 /*
547  *  ======== TransportShm_setErrFxn ========
548  */
549 Void TransportShm_setErrFxn(TransportShm_ErrFxn errFxn)
551     /* Ignore errFxn */