]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - linux/src/daemon/GateHWSpinlock.c
SDOCM00115428 Incorrect return status from NameServer_delete
[ipc/ipcdev.git] / linux / src / daemon / 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 /* Module level headers */
56 #include <_lad.h>
58 /* Linux headers */
59 #include <assert.h>
60 #include <fcntl.h>
61 #include <string.h>
62 #include <stdlib.h>
63 #include <sys/mman.h>
64 #include <sys/stat.h>
66 /* =============================================================================
67  * Structures & Enums
68  * =============================================================================
69  */
70 /* GateHWSpinlock Module Local State */
71 typedef struct {
72     UInt32 *                        baseAddr;   /* base addr lock registers */
73     GateMutex_Handle                gmHandle;   /* handle to gate mutex */
74 } GateHWSpinlock_Module_State;
76 /* GateHWSpinlock instance object */
77 struct GateHWSpinlock_Object {
78     IGateProvider_SuperObject; /* For inheritance from IGateProvider */
79     UInt                        lockNum;
80     UInt                        nested;
81     IGateProvider_Handle        localGate;
82     int                         token;  /* HWSpinlock token */
83 };
86 /* =============================================================================
87  * Globals
88  * =============================================================================
89  */
90 GateHWSpinlock_Config _GateHWSpinlock_cfgParams;
92 static GateHWSpinlock_Module_State GateHWSpinlock_state =
93 {
94     .baseAddr = NULL,
95     .gmHandle = NULL
96 };
98 static GateHWSpinlock_Module_State *Mod = &GateHWSpinlock_state;
100 static GateHWSpinlock_Params GateHWSpinlock_defInstParams =
102     .resourceId = 0,
103     .openFlag   = FALSE,
104     .regionId   = 0,
105     .sharedAddr = NULL
106 };
108 /* =============================================================================
109  * APIS
110  * =============================================================================
111  */
112 /*
113  *  Function to start the GateHWSpinlock module.
114  */
115 Int32 GateHWSpinlock_start(Void)
117     Int32               status = GateHWSpinlock_S_SUCCESS;
118     UInt32              dst;
119     Int32               fdMem;
121     fdMem = open ("/dev/mem", O_RDWR | O_SYNC);
123     if (fdMem < 0){
124         LOG0("GateHWSpinlock_start: failed to open the /dev/mem");
125         status = GateHWSpinlock_E_OSFAILURE;
126     }
128     /* map the hardware lock registers into the local address space */
129     if (status == GateHWSpinlock_S_SUCCESS) {
130         dst = (UInt32)mmap(NULL, _GateHWSpinlock_cfgParams.size,
131                             (PROT_READ | PROT_WRITE),
132                             (MAP_SHARED), fdMem,
133                             (off_t)_GateHWSpinlock_cfgParams.baseAddr);
135         if (dst == (UInt32)MAP_FAILED) {
136             LOG0("GateHWSpinlock_start: Memory map failed")
137             status = GateHWSpinlock_E_OSFAILURE;
138         }
139         else {
140             Mod->baseAddr = (UInt32 *)(dst + _GateHWSpinlock_cfgParams.offset);
141             status = GateHWSpinlock_S_SUCCESS;
142         }
143     }
145     /* create GateMutex for local protection*/
146     if (status == GateHWSpinlock_S_SUCCESS) {
147         Mod->gmHandle = GateMutex_create(NULL, NULL);
149         if (Mod->gmHandle == NULL) {
150             LOG0("GateHWSpinlock_start: GateMutex create failed")
151             status = GateHWSpinlock_E_FAIL;
152             GateHWSpinlock_stop();
153         }
154     }
156     return (status);
159 /*
160  *  Function to stop the GateHWSpinlock module.
161  */
162 Int GateHWSpinlock_stop(Void)
164     Int32               status = GateHWSpinlock_S_SUCCESS;
166     /* delete GateMutex */
167     if (Mod->gmHandle != NULL) {
168         status = GateMutex_delete(&Mod->gmHandle);
169     }
171     /* release lock register mapping */
172     if (Mod->baseAddr != NULL) {
173         munmap((void *)_GateHWSpinlock_cfgParams.baseAddr,
174            _GateHWSpinlock_cfgParams.size);
175     }
177     return(status);
180 /*
181  *  Initialize parameter structure
182  */
183 Void GateHWSpinlock_Params_init(GateHWSpinlock_Params *params)
185     assert(params != NULL);
187     memcpy(params, &GateHWSpinlock_defInstParams,
188         sizeof(GateHWSpinlock_Params));
191 /*
192  * Create a GateHWSpinlock instance
193  */
194 /* TODO: change the function to accept a local gate. Do this on all platforms */
195 GateHWSpinlock_Handle GateHWSpinlock_create(GateHWSpinlock_LocalProtect
196     localProtect, const GateHWSpinlock_Params * params)
198     GateHWSpinlock_Object * obj = (GateHWSpinlock_Object *)calloc(1,
199         sizeof (GateHWSpinlock_Object));
201     if (!obj) {
202         LOG0("GateHWSpinlock_create: memory allocation failure")
203         return NULL;
204     }
206     IGateProvider_ObjectInitializer(obj, GateHWSpinlock);
207     /* TODO: handle more local protection types */
208     obj->localGate = (IGateProvider_Handle)Mod->gmHandle;
209     obj->lockNum = params->resourceId;
210     obj->nested = 0;
212     return (GateHWSpinlock_Handle)obj;
215 /*
216  * Delete a GateHWSpinlock instance
217  */
218 Int GateHWSpinlock_delete (GateHWSpinlock_Handle * handle)
220     GateHWSpinlock_Object * obj;
221     Int  status = GateHWSpinlock_S_SUCCESS;
223     if (handle == NULL) {
224         return GateHWSpinlock_E_INVALIDARG;
225     }
226     if (*handle == NULL) {
227         return GateHWSpinlock_E_INVALIDARG;
228     }
230     obj = (GateHWSpinlock_Object *)(*handle);
232     free(obj);
233     *handle = NULL;
235     return (status);
238 /*
239  *  Enter a GateHWSpinlock instance
240  */
241 IArg GateHWSpinlock_enter(GateHWSpinlock_Object *obj)
243     volatile UInt32 *baseAddr = Mod->baseAddr;
244     IArg key;
246     key = IGateProvider_enter(obj->localGate);
248     /* if gate already entered, just return with current key */
249     obj->nested++;
250     if (obj->nested > 1) {
251         return(key);
252     }
254     /* enter the spinlock */
255     while (1) {
256         /* read the spinlock, returns non-zero when we get it */
257         if (baseAddr[obj->lockNum] == 0) {
258             break;
259         }
260         obj->nested--;
261         IGateProvider_leave(obj->localGate, key);
262         key = IGateProvider_enter(obj->localGate);
263         obj->nested++; /* re-nest the gate */
264     }
266     return (key);
269 /*
270  *  Leave a GateHWSpinlock instance
271  */
272 Int GateHWSpinlock_leave(GateHWSpinlock_Object *obj, IArg key)
274     volatile UInt32 *baseAddr = Mod->baseAddr;
276     obj->nested--;
278     /* release the spinlock if not nested */
279     if (obj->nested == 0) {
280         baseAddr[obj->lockNum] = 0;
281     }
283     IGateProvider_leave(obj->localGate, key);
285     return GateHWSpinlock_S_SUCCESS;