SDOCM00115428 Incorrect return status from NameServer_delete
[ipc/ipcdev.git] / linux / src / daemon / GateMP_daemon.c
1 /*
2  * Copyright (c) 2013-2015, 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  *  ======== GateMP_daemon.c ========
35  */
38 /* Standard headers */
39 #include <ti/ipc/Std.h>
41 /* Linux specific header files */
42 #include <pthread.h>
44 /* System headers */
45 #include <sys/mman.h>
46 #include <sys/stat.h>
47 #include <fcntl.h>
48 #include <stdlib.h>
49 #include <assert.h>
51 /* Module level headers */
52 #include <ti/ipc/GateMP.h>
53 #include <ti/ipc/NameServer.h>
54 #include <ti/ipc/MultiProc.h>
55 #include <_MultiProc.h>
56 #include <GateMP_config.h>
57 #include <_GateMP.h>
59 #include <IGateProvider.h>
60 #include <_GateMP_daemon.h>
61 #include <_lad.h>
63 #if defined (__cplusplus)
64 extern "C" {
65 #endif
67 #define NUM_INFO_FIELDS       6    /* Number of fields in info entry */
69 /* Values used to populate the resource 'inUse' arrays */
70 #define UNUSED          ((UInt8)0)
71 #define USED            ((UInt8)1)
72 #define RESERVED        ((UInt8)-1)
74 /* Name of GateMP's nameserver */
75 #define GateMP_NAMESERVER  "GateMP"
77 #define PAGE_ALIGN(size, psz)  (((size) + psz - 1) & ~(psz -1))
79 /* =============================================================================
80  * Structures & Enums
81  * =============================================================================
82  */
84 /* structure for GateMP module state */
85 typedef struct {
86     Int               numRemoteSystem;
87     Int               numRemoteCustom1;
88     Int               numRemoteCustom2;
89     UInt8 *           remoteSystemInUse;
90     UInt8 *           remoteCustom1InUse;
91     UInt8 *           remoteCustom2InUse;
92     GateMP_Handle     defaultGate;
93     NameServer_Handle nameServer;
94     Bool              isSetup;
95 } GateMP_ModuleObject;
97 /* Internal functions */
98 static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr);
99 static Int GateMP_closeDefaultGate(GateMP_Handle *handlePtr);
101 /* =============================================================================
102  *  Globals
103  * =============================================================================
104  */
105 /*
106  * GateMP_state
107  */
108 static GateMP_ModuleObject GateMP_state = {
109     .numRemoteSystem                 = 0,
110     .numRemoteCustom1                = 0,
111     .numRemoteCustom2                = 0,
112     .remoteSystemInUse               = NULL,
113     .remoteCustom1InUse              = NULL,
114     .remoteCustom2InUse              = NULL,
115     .defaultGate                     = NULL,
116     .nameServer                      = NULL,
117     .isSetup                         = FALSE
118 };
120 static GateMP_ModuleObject * GateMP_module = &GateMP_state;
122 /* =============================================================================
123  * APIS
124  * =============================================================================
125  */
127 /* Function to setup the gatemp module. */
128 Int GateMP_setup(Void)
130     Int               status = GateMP_S_SUCCESS;
131     NameServer_Params params;
132     UInt32            nsValue[NUM_INFO_FIELDS];
133     UInt32            len;
134     UInt32            size;
135     UInt32            alignDiff;
136     UInt32            offset;
137     Int32             fdMem;
139     NameServer_Params_init(&params);
140     params.maxRuntimeEntries = MAX_RUNTIME_ENTRIES;
141     params.maxNameLen = MAX_NAME_LEN;
143     /* Assume info entry has more fields than other entries */
144     params.maxValueLen = NUM_INFO_FIELDS * sizeof(UInt32);
146     GateMP_module->nameServer =
147                 NameServer_create(GateMP_NAMESERVER, &params);
149     if (GateMP_module->nameServer == NULL) {
150         status = GateMP_E_FAIL;
151         LOG0("GateMP_setup: NameServer_create failed\n");
152     }
154     if (status == GateMP_S_SUCCESS) {
155         do {
156             sleep(1);   /* Give the slaves some time to get NameServer ready */
157             status = GateMP_openDefaultGate(&GateMP_module->defaultGate);
158         } while (status == GateMP_E_NOTFOUND);
161         if (status < 0) {
162             LOG0("GateMP_setup: failed to open default gate\n");
163             status = GateMP_E_FAIL;
164         }
165     }
167     if (status == GateMP_S_SUCCESS) {
168         /* Process global info NameServer entry */
169         len = sizeof(nsValue);
171         status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_info",
172             &nsValue, &len, NULL);
174         if (status < 0) {
175             LOG0("GateMP_setup: failed to find info entry\n");
176             status = GateMP_E_NOTFOUND;
177         }
178         else {
179             fdMem = open ("/dev/mem", O_RDWR | O_SYNC);
181             if (fdMem < 0){
182                 LOG0("GateMP_setup: failed to open the /dev/mem!\n");
183                 status = GateMP_E_FAIL;
184                 goto cleanup;
185             }
187             GateMP_module->numRemoteSystem = nsValue[3];
188             GateMP_module->numRemoteCustom1 = nsValue[4];
189             GateMP_module->numRemoteCustom2 = nsValue[5];
191             /* Map InUse arrays to daemon's address space */
192             size = GateMP_module->numRemoteSystem * sizeof (UInt8) +
193                 (nsValue[0] & (sysconf(_SC_PAGE_SIZE) - 1));
194             size = PAGE_ALIGN(size, sysconf(_SC_PAGE_SIZE));
195             offset = nsValue[0] & ~(sysconf(_SC_PAGE_SIZE) - 1);
196 #if defined(IPC_BUILDOS_ANDROID)
197             GateMP_module->remoteSystemInUse = mmap64(NULL, size,
198                 (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
199                 (off64_t)offset);
200 #else
201             GateMP_module->remoteSystemInUse = mmap(NULL, size,
202                 (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
203                 (off_t)offset);
204 #endif
205             if (GateMP_module->remoteSystemInUse == MAP_FAILED) {
206                  LOG1("Failed to map remoteSystemInUse=0x%p to host address" \
207                       "  space!", GateMP_module->remoteSystemInUse);
208                  GateMP_module->remoteSystemInUse = NULL;
209                  status = GateMP_E_MEMORY;
210             }
211             else {
212                 alignDiff = nsValue[0] - offset;
213                 GateMP_module->remoteSystemInUse =
214                     GateMP_module->remoteSystemInUse + alignDiff;
215             }
217             size = GateMP_module->numRemoteCustom1 * sizeof (UInt8) +
218                 (nsValue[1] & (sysconf(_SC_PAGE_SIZE) - 1));
219             size = PAGE_ALIGN(size, sysconf(_SC_PAGE_SIZE));
220             offset = nsValue[1] & ~(sysconf(_SC_PAGE_SIZE) - 1);
221             if (status == GateMP_S_SUCCESS) {
222 #if defined(IPC_BUILDOS_ANDROID)
223                 GateMP_module->remoteCustom1InUse = mmap64(NULL, size,
224                     (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
225                     (off64_t)offset);
226 #else
227                 GateMP_module->remoteCustom1InUse = mmap(NULL, size,
228                     (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
229                     (off_t)offset);
230 #endif
231                 if (GateMP_module->remoteCustom1InUse == MAP_FAILED) {
232                     LOG1("Failed to map remoteCustom1InUse=%p to host address" \
233                         " space!", GateMP_module->remoteCustom1InUse);
234                     GateMP_module->remoteCustom1InUse = NULL;
235                     status = GateMP_E_MEMORY;
236                 }
237                 else {
238                     alignDiff = nsValue[1] - offset;
239                     GateMP_module->remoteCustom1InUse =
240                         GateMP_module->remoteCustom1InUse + alignDiff;
241                 }
242             }
244             size = GateMP_module->numRemoteCustom2 * sizeof (UInt8) +
245                 (nsValue[2] & (sysconf(_SC_PAGE_SIZE) - 1));
246             size = PAGE_ALIGN(size, sysconf(_SC_PAGE_SIZE));
247             offset = nsValue[2] & ~(sysconf(_SC_PAGE_SIZE) - 1);
248             if (status == GateMP_S_SUCCESS) {
249 #if defined(IPC_BUILDOS_ANDROID)
250                 GateMP_module->remoteCustom2InUse = mmap64(NULL, size,
251                     (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
252                     (off64_t)offset);
253 #else
254                 GateMP_module->remoteCustom2InUse = mmap(NULL, size,
255                     (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
256                     (off_t)offset);
257 #endif
258                 if (GateMP_module->remoteCustom2InUse == MAP_FAILED) {
259                     LOG1("Failed to map remoteCustom2InUse=%p to host address" \
260                         " space!", GateMP_module->remoteCustom2InUse);
261                     GateMP_module->remoteCustom2InUse = NULL;
262                     status = GateMP_E_MEMORY;
263                 }
264                 else {
265                     alignDiff = nsValue[2] - offset;
266                     GateMP_module->remoteCustom2InUse =
267                         GateMP_module->remoteCustom2InUse + alignDiff;
268                 }
269             }
270         }
271     }
273     /* TODO: setup the proxy map */
275 cleanup:
276     /* clean up if error */
277     if (status < 0) {
278         GateMP_destroy();
279     }
281     GateMP_module->isSetup = TRUE;
283     return (status);
286 Void GateMP_destroy(Void)
288     if (GateMP_module->remoteSystemInUse) {
289         munmap((unsigned int *)GateMP_module->remoteSystemInUse,
290             GateMP_module->numRemoteSystem * sizeof (UInt8));
291         GateMP_module->remoteSystemInUse = NULL;
292     }
294     if (GateMP_module->remoteCustom1InUse) {
295         munmap((unsigned int *)GateMP_module->remoteCustom1InUse,
296             GateMP_module->numRemoteCustom1 * sizeof (UInt8));
297         GateMP_module->remoteCustom1InUse = NULL;
298     }
300     if (GateMP_module->remoteCustom2InUse) {
301         munmap((unsigned int *)GateMP_module->remoteCustom2InUse,
302             GateMP_module->numRemoteCustom2 * sizeof (UInt8));
303         GateMP_module->remoteCustom2InUse = NULL;
304     }
306     if (GateMP_module->defaultGate) {
307         GateMP_closeDefaultGate(&GateMP_module->defaultGate);
308     }
310     if (GateMP_module->nameServer) {
311         NameServer_delete(&GateMP_module->nameServer);
312         GateMP_module->nameServer = NULL;
313     }
315     GateMP_module->isSetup = FALSE;
317     return;
320 /* Open default gate during GateMP_setup. Should only be called once */
321 static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr)
323     Int             status = GateMP_S_SUCCESS;
324     UInt32          len;
325     UInt32          nsValue[4];
326     GateMP_Object * obj = NULL;
327     UInt32          arg;
328     UInt32          mask;
329     UInt32          creatorProcId;
331     GateMP_RemoteSystemProxy_Params     systemParams;
333     /* assert that a valid pointer has been supplied */
334     if (handlePtr == NULL) {
335         LOG0("GateMP_open: argument cannot be null\n");
336         status = GateMP_E_INVALIDARG;
337     }
339     if (status == GateMP_S_SUCCESS) {
340         len = sizeof(nsValue);
342         status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_dGate",
343             &nsValue, &len, NULL);
345         if (status < 0) {
346             *handlePtr = NULL;
347             status = GateMP_E_NOTFOUND;
348         }
349         else {
350             arg = nsValue[2];
351             mask = nsValue[3];
352             creatorProcId = nsValue[1] >> 16;
353         }
354     }
356     if (status == GateMP_S_SUCCESS) {
357         /* allocate the instance object */
358         obj = (GateMP_Object *)calloc(1, sizeof (GateMP_Object));
359         if (obj != NULL) {
360             obj->localGate  = NULL;  /* TODO: create the local gate instance */
361             obj->localProtect  = GETLOCAL(mask);
362             obj->remoteProtect = GETREMOTE(mask);
363             obj->nsKey         = 0;
364             obj->numOpens      = 1;
365             obj->objType       = Ipc_ObjType_OPENDYNAMIC;
366             obj->resourceId    = arg;
368             assert(obj->remoteProtect == GateMP_RemoteProtect_SYSTEM);
370             /* create the proxy object */
371             GateMP_RemoteSystemProxy_Params_init(&systemParams);
372             systemParams.resourceId = obj->resourceId;
373             systemParams.openFlag = TRUE;
375             /*
376              * TODO: Currently passing in localProtect instead of localGate,
377              * since GateHWSpinlock owns the local gate
378              */
379             obj->gateHandle = (IGateProvider_Handle)
380                 GateMP_RemoteSystemProxy_create(obj->localProtect,
381                     &systemParams);
383             if (obj->gateHandle == NULL) {
384                 LOG0("GateMP_openDefaultGate: failed to create proxy\n");
385                 free(obj);
386                 obj = NULL;
387             }
388         }
389         else {
390             LOG0("GateMP_openDefaultGate: Memory allocation failed")
391         }
393         if (obj == NULL) {
394             status = GateMP_E_FAIL;
395         }
396     }
398     /* Return the "opened" GateMP instance  */
399     *handlePtr = (GateMP_Handle)obj;
401     return status;
404 static Int GateMP_closeDefaultGate(GateMP_Handle *handlePtr)
406     Int status = GateMP_S_SUCCESS;
407     GateMP_Object * obj = *(GateMP_Object **)handlePtr;
409     if (obj->gateHandle != NULL) {
410         /* Default gate is always of type System when more than 1 processor */
411         GateMP_RemoteSystemProxy_delete(
412             (GateMP_RemoteSystemProxy_Handle *)&obj->gateHandle);
413     }
415     free(*handlePtr);
416     *handlePtr = NULL;
418     return(status);
421 Int GateMP_getFreeResource(GateMP_RemoteProtect type)
423     IArg   key;
424     Bool   flag = FALSE;
425     Int    resourceId = -1;
426     UInt8* inUse = NULL;
427     Int    num = 0;
429     /* Remote case */
430     switch (type) {
431         /* TODO: currently only support System proxy */
432         case GateMP_RemoteProtect_SYSTEM:
433         case GateMP_RemoteProtect_CUSTOM1:
434         case GateMP_RemoteProtect_CUSTOM2:
435             inUse = GateMP_module->remoteSystemInUse;
436             num = GateMP_module->numRemoteSystem;
437             break;
439         default:
440             LOG0("GateMP_getFreeResource: Invalid remote protection type\n");
441             break;
442     }
444     if (inUse != NULL) {
445         assert(GateMP_module->defaultGate != NULL);
446         key = GateMP_enter(GateMP_module->defaultGate);
448         /*
449          *  Find a free resource id. Note: zero is reserved on the
450          *  system proxy for the default gate.
451          */
452         for (resourceId = 0; resourceId < num; resourceId++) {
453             /*
454              *  If not in-use, set the inUse to TRUE to prevent other
455              *  creates from getting this one.
456              */
457             if (inUse[resourceId] == UNUSED) {
458                 flag = TRUE;
460                 /* Denote in shared memory that the resource is used */
461                 inUse[resourceId] = USED;
462                 break;
463             }
464         }
466         GateMP_leave(GateMP_module->defaultGate, key);
467     }
469     if (flag == FALSE) {
470         resourceId = -1;
471     }
473     return (resourceId);
476 Int GateMP_releaseResource(UInt id, GateMP_RemoteProtect type)
478     Int    status = GateMP_S_SUCCESS;
479     IArg   key;
480     UInt8* inUse = NULL;
481     Int    num = 0;
483     /* Remote case */
484     switch (type) {
485         /* TODO: currently only support System proxy */
486         case GateMP_RemoteProtect_SYSTEM:
487         case GateMP_RemoteProtect_CUSTOM1:
488         case GateMP_RemoteProtect_CUSTOM2:
489             inUse = GateMP_module->remoteSystemInUse;
490             num = GateMP_module->numRemoteSystem;
491             break;
493         default:
494             LOG0("GateMP_releaseResource: Invalid remote protection type\n");
495             status = GateMP_E_FAIL;
496             break;
497     }
499     if ((inUse != NULL) && (id < num)) {
500         assert(GateMP_module->defaultGate != NULL);
501         key = GateMP_enter(GateMP_module->defaultGate);
502         inUse[id] = UNUSED;
503         GateMP_leave(GateMP_module->defaultGate, key);
504     }
505     else {
506         /* Should not happen if module is properly setup */
507         status = GateMP_E_FAIL;
508     }
510     return (status);
513 Int GateMP_getNumResources(GateMP_RemoteProtect type)
515     Int   num = -1;
517     /* Remote case */
518     switch (type) {
519         /* TODO: currently only support System proxy */
520         case GateMP_RemoteProtect_SYSTEM:
521         case GateMP_RemoteProtect_CUSTOM1:
522         case GateMP_RemoteProtect_CUSTOM2:
523             num = GateMP_module->numRemoteSystem;
524             break;
526         default:
527             LOG0("GateMP_getNumResources: Invalid remote protection type\n");
528             break;
529     }
531     return (num);
534 NameServer_Handle GateMP_getNameServer(Void)
536     return (GateMP_module->nameServer);
539 Bool GateMP_isSetup(Void)
541     return (GateMP_module->isSetup);
544 IArg GateMP_enter(GateMP_Handle handle)
546     GateMP_Object * obj;
547     IArg            key;
549     obj = (GateMP_Object *)handle;
550     key = IGateProvider_enter(obj->gateHandle);
552     return(key);
555 Void GateMP_leave(GateMP_Handle handle, IArg key)
557     GateMP_Object *obj;
559     obj = (GateMP_Object *)handle;
560     IGateProvider_leave(obj->gateHandle, key);