]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - linux/src/api/gates/GateHWSpinlock.c
Tests: ping_rpmsg: Update Test with Proper Socket Usage
[ipc/ipcdev.git] / linux / src / api / gates / GateHWSpinlock.c
1 /*
2  * Copyright (c) 2013-2014, Texas Instruments Incorporated
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  */
33 /*
34  *  ======== GateHWSpinlock.c ========
35  */
37 /* Standard headers */
38 #include <ti/ipc/Std.h>
40 /* Utilities & OSAL headers */
41 #include <ti/ipc/MultiProc.h>
42 #include <ti/ipc/GateMP.h>
44 #include <GateHWSpinlock.h>
46 #include <IGateProvider.h>
48 /*
49  * TODO: does this belong in ti/ipc/Std.h? We should consider getting rid of
50  *       error blocks from the GateMutex.h interface.
51  */
52 typedef UInt32            Error_Block;
53 #include <GateMutex.h>
55 /* Socket Utils */
56 #include <_lad.h>
57 #include <ladclient.h>
59 /* Linux headers */
60 #include <assert.h>
61 #include <fcntl.h>
62 #include <string.h>
63 #include <stdlib.h>
64 #include <sys/mman.h>
65 #include <sys/stat.h>
67 /* =============================================================================
68  * Structures & Enums
69  * =============================================================================
70  */
71 /* GateHWSpinlock Module Local State */
72 typedef struct {
73     UInt32 *                        baseAddr;   /* base addr lock registers */
74     GateMutex_Handle                gmHandle;   /* handle to gate mutex */
75 } GateHWSpinlock_Module_State;
77 /* GateHWSpinlock instance object */
78 struct GateHWSpinlock_Object {
79     IGateProvider_SuperObject; /* For inheritance from IGateProvider */
80     UInt                        lockNum;
81     UInt                        nested;
82     IGateProvider_Handle        localGate;
83     int                         token;  /* HWSpinlock token */
84 };
87 /* =============================================================================
88  * Globals
89  * =============================================================================
90  */
91 GateHWSpinlock_Config _GateHWSpinlock_cfgParams;
93 static GateHWSpinlock_Module_State GateHWSpinlock_state =
94 {
95     .baseAddr = NULL,
96     .gmHandle = NULL
97 };
99 static GateHWSpinlock_Module_State *Mod = &GateHWSpinlock_state;
101 static GateHWSpinlock_Params GateHWSpinlock_defInstParams =
103     .resourceId = 0,
104     .openFlag   = FALSE,
105     .regionId   = 0,
106     .sharedAddr = NULL
107 };
109 /* traces in this file are controlled via _GateHWSpinlock_verbose */
110 Bool _GateHWSpinlock_verbose = FALSE;
111 #define verbose _GateHWSpinlock_verbose
113 /* =============================================================================
114  * APIS
115  * =============================================================================
116  */
117 /* Function to get configuration address & sizes for the GateHWSpinlock module.
118  *
119  */
120 Void GateHWSpinlock_getConfig (GateHWSpinlock_Config * cfgParams)
122     Int status;
123     LAD_ClientHandle handle;
124     struct LAD_CommandObj cmd;
125     union LAD_ResponseObj rsp;
127     assert (cfgParams != NULL);
129     handle = LAD_findHandle();
130     if (handle == LAD_MAXNUMCLIENTS) {
131         PRINTVERBOSE0(
132           "GateHWSpinlock_getConfig: can't find connection to daemon for pid")
133         PRINTVERBOSE1("%d\n", getpid())
135         return;
136     }
138     cmd.cmd = LAD_GATEHWSPINLOCK_GETCONFIG;
139     cmd.clientId = handle;
141     if ((status = LAD_putCommand(&cmd)) != LAD_SUCCESS) {
142         PRINTVERBOSE1(
143           "GateHWSpinlock_getConfig: sending LAD command failed, status=%d\n",
144           status)
145         return;
146     }
148     if ((status = LAD_getResponse(handle, &rsp)) != LAD_SUCCESS) {
149         PRINTVERBOSE1("GateHWSpinlock_getConfig: no LAD response, status=%d\n",
150         status)
151         return;
152     }
153     status = rsp.gateHWSpinlockGetConfig.status;
155     PRINTVERBOSE2(
156       "GateHWSpinlock_getConfig: got LAD response for client %d, status=%d\n",
157       handle, status)
159     memcpy(cfgParams, &rsp.gateHWSpinlockGetConfig.cfgParams,
160         sizeof(*cfgParams));
162     return;
166 /*
167  *  Function to start the GateHWSpinlock module.
168  */
169 Int32 GateHWSpinlock_start(Void)
171     Int32               status = GateHWSpinlock_S_SUCCESS;
172     UInt32              dst;
173     Int32               fdMem;
174     int                 flags;
176     fdMem = open ("/dev/mem", O_RDWR | O_SYNC);
178     if (fdMem < 0){
179         PRINTVERBOSE0("GateHWSpinlock_start: failed to open the /dev/mem");
180         status = GateHWSpinlock_E_OSFAILURE;
181     }
183     /* make sure /dev/mem fd doesn't exist for 'fork() -> exec*()'ed child */
184     flags = fcntl(fdMem, F_GETFD);
185     if (flags != -1) {
186         fcntl(fdMem, F_SETFD, flags | FD_CLOEXEC);
187     }
189     /* map the hardware lock registers into the local address space */
190     if (status == GateHWSpinlock_S_SUCCESS) {
191         dst = (UInt32)mmap(NULL, _GateHWSpinlock_cfgParams.size,
192                             (PROT_READ | PROT_WRITE),
193                             (MAP_SHARED), fdMem,
194                             (off_t)_GateHWSpinlock_cfgParams.baseAddr);
196         if (dst == (UInt32)MAP_FAILED) {
197             PRINTVERBOSE0("GateHWSpinlock_start: Memory map failed")
198             status = GateHWSpinlock_E_OSFAILURE;
199         }
200         else {
201             Mod->baseAddr = (UInt32 *)(dst + _GateHWSpinlock_cfgParams.offset);
202             status = GateHWSpinlock_S_SUCCESS;
203         }
204     }
206     /* create GateMutex for local protection*/
207     if (status == GateHWSpinlock_S_SUCCESS) {
208         Mod->gmHandle = GateMutex_create(NULL, NULL);
210         if (Mod->gmHandle == NULL) {
211             PRINTVERBOSE0("GateHWSpinlock_start: GateMutex create failed")
212             status = GateHWSpinlock_E_FAIL;
213             GateHWSpinlock_stop();
214         }
215     }
217     return (status);
220 /*
221  *  Function to stop the GateHWSpinlock module.
222  */
223 Int GateHWSpinlock_stop(Void)
225     Int32               status = GateHWSpinlock_S_SUCCESS;
227     /* delete GateMutex */
228     if (Mod->gmHandle != NULL) {
229         status = GateMutex_delete(&Mod->gmHandle);
230     }
232     /* release lock register mapping */
233     if (Mod->baseAddr != NULL) {
234         munmap((void *)_GateHWSpinlock_cfgParams.baseAddr,
235            _GateHWSpinlock_cfgParams.size);
236     }
238     return(status);
241 /*
242  *  Initialize parameter structure
243  */
244 Void GateHWSpinlock_Params_init(GateHWSpinlock_Params *params)
246     assert(params != NULL);
248     memcpy(params, &GateHWSpinlock_defInstParams,
249         sizeof(GateHWSpinlock_Params));
252 /*
253  * Create a GateHWSpinlock instance
254  */
255 /* TODO: change the function to accept a local gate. Do this on all platforms */
256 GateHWSpinlock_Handle GateHWSpinlock_create(GateHWSpinlock_LocalProtect
257     localProtect, const GateHWSpinlock_Params * params)
259     GateHWSpinlock_Object * obj = (GateHWSpinlock_Object *)calloc(1,
260         sizeof (GateHWSpinlock_Object));
262     if (!obj) {
263         PRINTVERBOSE0("GateHWSpinlock_create: memory allocation failure")
264         return NULL;
265     }
267     IGateProvider_ObjectInitializer(obj, GateHWSpinlock);
268     /* TODO: handle more local protection types */
269     obj->localGate = (IGateProvider_Handle)Mod->gmHandle;
270     obj->lockNum = params->resourceId;
271     obj->nested = 0;
273     return (GateHWSpinlock_Handle)obj;
276 /*
277  * Delete a GateHWSpinlock instance
278  */
279 Int GateHWSpinlock_delete (GateHWSpinlock_Handle * handle)
281     GateHWSpinlock_Object * obj;
282     Int  status = GateHWSpinlock_S_SUCCESS;
284     if (handle == NULL) {
285         return GateHWSpinlock_E_INVALIDARG;
286     }
287     if (*handle == NULL) {
288         return GateHWSpinlock_E_INVALIDARG;
289     }
291     obj = (GateHWSpinlock_Object *)(*handle);
293     free(obj);
294     *handle = NULL;
296     return (status);
299 /*
300  *  Enter a GateHWSpinlock instance
301  */
302 IArg GateHWSpinlock_enter(GateHWSpinlock_Object *obj)
304     volatile UInt32 *baseAddr = Mod->baseAddr;
305     IArg key;
307     key = IGateProvider_enter(obj->localGate);
309     /* if gate already entered, just return with current key */
310     obj->nested++;
311     if (obj->nested > 1) {
312         return(key);
313     }
315     /* enter the spinlock */
316     while (1) {
317         /* read the spinlock, returns non-zero when we get it */
318         if (baseAddr[obj->lockNum] == 0) {
319             break;
320         }
321         obj->nested--;
322         IGateProvider_leave(obj->localGate, key);
323         key = IGateProvider_enter(obj->localGate);
324         obj->nested++; /* re-nest the gate */
325     }
327     return (key);
330 /*
331  *  Leave a GateHWSpinlock instance
332  */
333 Int GateHWSpinlock_leave(GateHWSpinlock_Object *obj, IArg key)
335     volatile UInt32 *baseAddr = Mod->baseAddr;
337     obj->nested--;
339     /* release the spinlock if not nested */
340     if (obj->nested == 0) {
341         baseAddr[obj->lockNum] = 0;
342     }
344     IGateProvider_leave(obj->localGate, key);
346     return GateHWSpinlock_S_SUCCESS;