]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - qnx/src/ipc3x_dev/ti/syslink/ipc/hlos/knl/GateMP_daemon.c
QNX: GateMP: Check Number of Resources for Gates Before Mapping
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / ipc / hlos / knl / 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 /* Qnx specific header files */
42 #include <pthread.h>
44 /* System headers */
45 #include <sys/mman.h>
46 #include <stdlib.h>
47 #include <assert.h>
49 /* Module level headers */
50 #include <ti/ipc/GateMP.h>
51 #include <ti/ipc/NameServer.h>
52 #include <ti/ipc/MultiProc.h>
53 #include <_MultiProc.h>
54 #include <GateMP_config.h>
55 #include <_GateMP.h>
57 #include <ti/syslink/utils/IGateProvider.h>
58 #include <ti/syslink/inc/_GateMP_daemon.h>
59 #include <_IpcLog.h>
61 #if defined (__cplusplus)
62 extern "C" {
63 #endif
65 /* How often to poll for default gate during setup (in microseconds) */
66 #define POLL_INTERVAL         10000
68 /*
69  * Number of times to repeatedly poll for default gate in GateMP_setup before
70  * timing out.
71  * The default adds up to a total of roughly 2 seconds, which means the slave
72  * core that owns SR0 must have setup GateMP within that time. Otherwise the
73  * driver will simply move on without setting up GateMP.
74  */
75 #define SETUP_TIMEOUT         200
77 #define NUM_INFO_FIELDS       6    /* Number of fields in info entry */
79 /* Values used to populate the resource 'inUse' arrays */
80 #define UNUSED          ((UInt8)0)
81 #define USED            ((UInt8)1)
82 #define RESERVED        ((UInt8)-1)
84 /* Name of GateMP's nameserver */
85 #define GateMP_NAMESERVER  "GateMP"
87 /* =============================================================================
88  * Structures & Enums
89  * =============================================================================
90  */
92 /* structure for GateMP module state */
93 typedef struct {
94     Int                numRemoteSystem;
95     Int                numRemoteCustom1;
96     Int                numRemoteCustom2;
97     UInt8 *            remoteSystemInUse;
98     UInt8 *            remoteCustom1InUse;
99     UInt8 *            remoteCustom2InUse;
100     GateMP_Handle      defaultGate;
101     NameServer_Handle  nameServer;
102     Bool               isSetup;
103     UInt32             startCount;   /* number of times GateMP is started */
104     pthread_mutex_t    lock;
105 } GateMP_ModuleObject;
107 /* Internal functions */
108 static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr,
109     UInt16 * creatorProcId);
110 static Int GateMP_closeDefaultGate(GateMP_Handle *handlePtr);
112 /* =============================================================================
113  *  Globals
114  * =============================================================================
115  */
116 /*
117  * GateMP_state
118  */
119 static GateMP_ModuleObject GateMP_state = {
120     .numRemoteSystem                 = 0,
121     .numRemoteCustom1                = 0,
122     .numRemoteCustom2                = 0,
123     .remoteSystemInUse               = NULL,
124     .remoteCustom1InUse              = NULL,
125     .remoteCustom2InUse              = NULL,
126     .defaultGate                     = NULL,
127     .nameServer                      = NULL,
128     .isSetup                         = FALSE,
129     .startCount                      = 0,
130     .lock                            = PTHREAD_RMUTEX_INITIALIZER
131 };
133 static GateMP_ModuleObject * GateMP_module = &GateMP_state;
135 /* =============================================================================
136  * APIS
137  * =============================================================================
138  */
140 /* Function to setup the gatemp module. */
141 Int GateMP_setup(Int32 * sr0ProcId)
143     Int               status = GateMP_S_SUCCESS;
144     NameServer_Params params;
145     UInt32            nsValue[NUM_INFO_FIELDS];
146     UInt32            len;
147     UInt              timeout = SETUP_TIMEOUT;
148     UInt16            procId;
150     NameServer_Params_init(&params);
151     params.maxRuntimeEntries = MAX_RUNTIME_ENTRIES;
152     params.maxNameLen = MAX_NAME_LEN;
154     /* Assume info entry has more fields than other entries */
155     params.maxValueLen = NUM_INFO_FIELDS * sizeof(UInt32);
157     pthread_mutex_lock(&GateMP_module->lock);
159     if (GateMP_module->isSetup) {
160         pthread_mutex_unlock(&GateMP_module->lock);
161         return (GateMP_S_ALREADYSETUP);
162     }
164     GateMP_module->nameServer =
165                 NameServer_create(GateMP_NAMESERVER, &params);
167     if (GateMP_module->nameServer == NULL) {
168         status = GateMP_E_FAIL;
169         LOG0("GateMP_setup: NameServer_create failed\n");
170     }
172     if (status == GateMP_S_SUCCESS) {
173         /* The default gate creator is the owner of SR0 */
174         while (((status = GateMP_openDefaultGate(&GateMP_module->defaultGate,
175             &procId)) == GateMP_E_NOTFOUND) && (timeout > 0)) {
176             usleep(POLL_INTERVAL);
177             timeout--;
178         }
180         if ((status < 0) && (status != GateMP_E_NOTFOUND)) {
181             LOG0("GateMP_setup: failed to open default gate\n");
182             status = GateMP_E_FAIL;
183         }
184         else if (status == GateMP_S_SUCCESS) {
185             *sr0ProcId = procId;
186         }
187         else {
188             /* If default gate is not found, return GateMP_E_NOTFOUND */
189         }
190     }
192     if (status == GateMP_S_SUCCESS) {
193         /* Process global info NameServer entry */
194         len = sizeof(nsValue);
196         status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_info",
197             &nsValue, &len, NULL);
199         if (status < 0) {
200             LOG0("GateMP_setup: failed to find info entry\n");
201             status = GateMP_E_NOTFOUND;
202         }
203         else {
204             GateMP_module->numRemoteSystem = nsValue[3];
205             GateMP_module->numRemoteCustom1 = nsValue[4];
206             GateMP_module->numRemoteCustom2 = nsValue[5];
208             /* Map InUse arrays to daemon's address space */
209             if (GateMP_module->numRemoteSystem != 0) {
210                 GateMP_module->remoteSystemInUse = mmap(NULL,
211                     GateMP_module->numRemoteSystem * sizeof (UInt8),
212                     (PROT_READ|PROT_WRITE|PROT_NOCACHE),
213                     (MAP_PHYS|MAP_SHARED), NOFD, (off_t)nsValue[0]);
214                 if (GateMP_module->remoteSystemInUse == MAP_FAILED) {
215                     GateMP_module->remoteSystemInUse = NULL;
216                     status = GateMP_E_MEMORY;
217                     LOG0("Failed to map remoteSystemInUse to host address" \
218                          " space!");
219                 }
220             }
222             if ((status == GateMP_S_SUCCESS) &&
223                 (GateMP_module->numRemoteCustom1 != 0)) {
224                 GateMP_module->remoteCustom1InUse = mmap(NULL,
225                     GateMP_module->numRemoteCustom1 * sizeof (UInt8),
226                     (PROT_READ|PROT_WRITE|PROT_NOCACHE),
227                     (MAP_PHYS|MAP_SHARED), NOFD, (off_t)nsValue[1]);
228                 if (GateMP_module->remoteCustom1InUse == MAP_FAILED) {
229                     GateMP_module->remoteCustom1InUse = NULL;
230                     status = GateMP_E_MEMORY;
231                     LOG0("Failed to map remoteCustom1InUse to host address" \
232                         " space!");
233                 }
234             }
236             if ((status == GateMP_S_SUCCESS) &&
237                 (GateMP_module->numRemoteCustom2 != 0)) {
238                 GateMP_module->remoteCustom2InUse = mmap(NULL,
239                     GateMP_module->numRemoteCustom2 * sizeof (UInt8),
240                     (PROT_READ|PROT_WRITE|PROT_NOCACHE),
241                     (MAP_PHYS|MAP_SHARED), NOFD, (off_t)nsValue[2]);
242                 if (GateMP_module->remoteCustom2InUse == MAP_FAILED) {
243                     GateMP_module->remoteCustom2InUse = NULL;
244                     status = GateMP_E_MEMORY;
245                     LOG0("Failed to map remoteCustom2InUse to host address" \
246                         " space!");
247                 }
248             }
249         }
250     }
252     /* TODO: setup the proxy map */
254     /* clean up if error */
255     if (status < 0) {
256         GateMP_destroy(TRUE);
257     }
258     else {
259         GateMP_module->isSetup = TRUE;
260     }
262     pthread_mutex_unlock(&GateMP_module->lock);
264     return (status);
267 Int GateMP_destroy(Bool forced)
269     pthread_mutex_lock(&GateMP_module->lock);
271     if ((!forced) && (GateMP_module->startCount != 0)) {
272         /* Some process on the host is still using GateMP */
273         pthread_mutex_unlock(&GateMP_module->lock);
274         return (GateMP_E_FAIL);
275     }
277     if (GateMP_module->remoteSystemInUse) {
278         munmap((unsigned int *)GateMP_module->remoteSystemInUse,
279             GateMP_module->numRemoteSystem * sizeof (UInt8));
280         GateMP_module->remoteSystemInUse = NULL;
281     }
283     if (GateMP_module->remoteCustom1InUse) {
284         munmap((unsigned int *)GateMP_module->remoteCustom1InUse,
285             GateMP_module->numRemoteCustom1 * sizeof (UInt8));
286         GateMP_module->remoteCustom1InUse = NULL;
287     }
289     if (GateMP_module->remoteCustom2InUse) {
290         munmap((unsigned int *)GateMP_module->remoteCustom2InUse,
291             GateMP_module->numRemoteCustom2 * sizeof (UInt8));
292         GateMP_module->remoteCustom2InUse = NULL;
293     }
295     if (GateMP_module->defaultGate) {
296         GateMP_closeDefaultGate(&GateMP_module->defaultGate);
297     }
299     if (GateMP_module->nameServer) {
300         NameServer_delete(&GateMP_module->nameServer);
301         GateMP_module->nameServer = NULL;
302     }
304     GateMP_module->isSetup = FALSE;
306     pthread_mutex_unlock(&GateMP_module->lock);
308     return (GateMP_S_SUCCESS);
311 /* Open default gate during GateMP_setup. Should only be called once */
312 static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr,
313     UInt16 * creatorProcId)
315     Int             status = GateMP_S_SUCCESS;
316     UInt32          len;
317     UInt32          nsValue[4];
318     GateMP_Object * obj = NULL;
319     UInt32          arg;
320     UInt32          mask;
322     GateMP_RemoteSystemProxy_Params     systemParams;
324     /* assert that a valid pointer has been supplied */
325     if (handlePtr == NULL) {
326         LOG0("GateMP_open: argument cannot be null\n");
327         status = GateMP_E_INVALIDARG;
328     }
330     if (status == GateMP_S_SUCCESS) {
331         len = sizeof(nsValue);
333         status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_dGate",
334             &nsValue, &len, NULL);
336         if (status < 0) {
337             *handlePtr = NULL;
338             status = GateMP_E_NOTFOUND;
339         }
340         else {
341             arg = nsValue[2];
342             mask = nsValue[3];
343             *creatorProcId = nsValue[1] >> 16;
344         }
345     }
347     if (status == GateMP_S_SUCCESS) {
348         /* allocate the instance object */
349         obj = (GateMP_Object *)calloc(1, sizeof (GateMP_Object));
350         if (obj != NULL) {
351             obj->localGate  = NULL;  /* TODO: create the local gate instance */
352             obj->localProtect  = GETLOCAL(mask);
353             obj->remoteProtect = GETREMOTE(mask);
354             obj->nsKey         = 0;
355             obj->numOpens      = 1;
356             obj->objType       = Ipc_ObjType_OPENDYNAMIC;
357             obj->resourceId    = arg;
359             assert(obj->remoteProtect == GateMP_RemoteProtect_SYSTEM);
361             /* create the proxy object */
362             GateMP_RemoteSystemProxy_Params_init(&systemParams);
363             systemParams.resourceId = obj->resourceId;
364             systemParams.openFlag = TRUE;
366             /*
367              * TODO: Currently passing in localProtect instead of localGate,
368              * since GateHWSpinlock owns the local gate
369              */
370             obj->gateHandle = (IGateProvider_Handle)
371                 GateMP_RemoteSystemProxy_create(obj->localProtect,
372                     &systemParams);
374             if (obj->gateHandle == NULL) {
375                 LOG0("GateMP_openDefaultGate: failed to create proxy\n");
376                 free(obj);
377                 obj = NULL;
378             }
379         }
380         else {
381             LOG0("GateMP_openDefaultGate: Memory allocation failed")
382         }
384         if (obj == NULL) {
385             status = GateMP_E_FAIL;
386         }
387     }
389     /* Return the "opened" GateMP instance  */
390     *handlePtr = (GateMP_Handle)obj;
392     return status;
395 static Int GateMP_closeDefaultGate(GateMP_Handle *handlePtr)
397     Int status = GateMP_S_SUCCESS;
398     GateMP_Object * obj = *(GateMP_Object **)handlePtr;
400     if (obj->gateHandle != NULL) {
401         /* Default gate is always of type System when more than 1 processor */
402         GateMP_RemoteSystemProxy_delete(
403             (GateMP_RemoteSystemProxy_Handle *)&obj->gateHandle);
404     }
406     free(*handlePtr);
407     *handlePtr = NULL;
409     return(status);
412 Int GateMP_getFreeResource(GateMP_RemoteProtect type)
414     IArg   key;
415     Bool   flag = FALSE;
416     Int    resourceId = -1;
417     UInt8* inUse = NULL;
418     Int    num = 0;
420     /* Remote case */
421     switch (type) {
422         /* TODO: currently only support System proxy */
423         case GateMP_RemoteProtect_SYSTEM:
424         case GateMP_RemoteProtect_CUSTOM1:
425         case GateMP_RemoteProtect_CUSTOM2:
426             inUse = GateMP_module->remoteSystemInUse;
427             num = GateMP_module->numRemoteSystem;
428             break;
430         default:
431             LOG0("GateMP_getFreeResource: Invalid remote protection type\n");
432             break;
433     }
435     if (inUse != NULL) {
436         assert(GateMP_module->defaultGate != NULL);
437         key = GateMP_enter(GateMP_module->defaultGate);
439         /*
440          *  Find a free resource id. Note: zero is reserved on the
441          *  system proxy for the default gate.
442          */
443         for (resourceId = 0; resourceId < num; resourceId++) {
444             /*
445              *  If not in-use, set the inUse to TRUE to prevent other
446              *  creates from getting this one.
447              */
448             if (inUse[resourceId] == UNUSED) {
449                 flag = TRUE;
451                 /* Denote in shared memory that the resource is used */
452                 inUse[resourceId] = USED;
453                 break;
454             }
455         }
457         GateMP_leave(GateMP_module->defaultGate, key);
458     }
460     if (flag == FALSE) {
461         resourceId = -1;
462     }
464     return (resourceId);
467 Int GateMP_releaseResource(UInt id, GateMP_RemoteProtect type)
469     Int    status = GateMP_S_SUCCESS;
470     IArg   key;
471     UInt8* inUse = NULL;
472     Int    num = 0;
474     /* Remote case */
475     switch (type) {
476         /* TODO: currently only support System proxy */
477         case GateMP_RemoteProtect_SYSTEM:
478         case GateMP_RemoteProtect_CUSTOM1:
479         case GateMP_RemoteProtect_CUSTOM2:
480             inUse = GateMP_module->remoteSystemInUse;
481             num = GateMP_module->numRemoteSystem;
482             break;
484         default:
485             LOG0("GateMP_releaseResource: Invalid remote protection type\n");
486             status = GateMP_E_FAIL;
487             break;
488     }
490     if ((inUse != NULL) && (id < num)) {
491         assert(GateMP_module->defaultGate != NULL);
492         key = GateMP_enter(GateMP_module->defaultGate);
493         inUse[id] = UNUSED;
494         GateMP_leave(GateMP_module->defaultGate, key);
495     }
496     else {
497         /* Should not happen if module is properly setup */
498         status = GateMP_E_FAIL;
499     }
501     return (status);
504 Int GateMP_getNumResources(GateMP_RemoteProtect type)
506     Int   num = -1;
508     /* Remote case */
509     switch (type) {
510         /* TODO: currently only support System proxy */
511         case GateMP_RemoteProtect_SYSTEM:
512         case GateMP_RemoteProtect_CUSTOM1:
513         case GateMP_RemoteProtect_CUSTOM2:
514             num = GateMP_module->numRemoteSystem;
515             break;
517         default:
518             LOG0("GateMP_getNumResources: Invalid remote protection type\n");
519             break;
520     }
522     return (num);
525 NameServer_Handle GateMP_getNameServer(Void)
527     return (GateMP_module->nameServer);
530 Int GateMP_start(Void)
532     Int status = GateMP_S_SUCCESS;
534     pthread_mutex_lock(&GateMP_module->lock);
536     if (GateMP_isSetup()) {
537         GateMP_module->startCount++;
538     }
539     else {
540         /* Cannot start GateMP if it is not setup */
541         status = GateMP_E_FAIL;
542     }
544     pthread_mutex_unlock(&GateMP_module->lock);
546     return (status);
549 Int GateMP_stop(Void)
551     Int status = GateMP_S_SUCCESS;
553     pthread_mutex_lock(&GateMP_module->lock);
555     if (GateMP_isSetup()) {
556         GateMP_module->startCount--;
557     }
558     else {
559         /* Cannot stop GateMP if it is not setup */
560         status = GateMP_E_FAIL;
561     }
563     pthread_mutex_unlock(&GateMP_module->lock);
565     return (status);
568 Bool GateMP_isSetup(Void)
570     return (GateMP_module->isSetup);
573 IArg GateMP_enter(GateMP_Handle handle)
575     GateMP_Object * obj;
576     IArg            key;
578     obj = (GateMP_Object *)handle;
579     key = IGateProvider_enter(obj->gateHandle);
581     return(key);
584 Void GateMP_leave(GateMP_Handle handle, IArg key)
586     GateMP_Object *obj;
588     obj = (GateMP_Object *)handle;
589     IGateProvider_leave(obj->gateHandle, key);