QNX: Change LOGn to GT traces for consistency
[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         GT_setFailureReason(curTrace,
170                             GT_4CLASS,
171                             "GateMP_setup",
172                             status,
173                             "NameServer_create failed");
174     }
176     if (status == GateMP_S_SUCCESS) {
177         /* The default gate creator is the owner of SR0 */
178         while (((status = GateMP_openDefaultGate(&GateMP_module->defaultGate,
179             &procId)) == GateMP_E_NOTFOUND) && (timeout > 0)) {
180             usleep(POLL_INTERVAL);
181             timeout--;
182         }
184         if ((status < 0) && (status != GateMP_E_NOTFOUND)) {
185             status = GateMP_E_FAIL;
186             GT_setFailureReason(curTrace,
187                                 GT_4CLASS,
188                                 "GateMP_setup",
189                                 status,
190                                 "failed to open default gate");
191         }
192         else if (status == GateMP_S_SUCCESS) {
193             *sr0ProcId = procId;
194         }
195         else {
196             /* If default gate is not found, return GateMP_E_NOTFOUND */
197         }
198     }
200     if (status == GateMP_S_SUCCESS) {
201         /* Process global info NameServer entry */
202         len = sizeof(nsValue);
204         status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_info",
205             &nsValue, &len, NULL);
207         if (status < 0) {
208             status = GateMP_E_NOTFOUND;
209             GT_setFailureReason(curTrace,
210                                 GT_4CLASS,
211                                 "GateMP_setup",
212                                 status,
213                                 "failed to find info entry");
214         }
215         else {
216             GateMP_module->numRemoteSystem = nsValue[3];
217             GateMP_module->numRemoteCustom1 = nsValue[4];
218             GateMP_module->numRemoteCustom2 = nsValue[5];
220             /* Map InUse arrays to daemon's address space */
221             if (GateMP_module->numRemoteSystem != 0) {
222                 GateMP_module->remoteSystemInUse = mmap(NULL,
223                     GateMP_module->numRemoteSystem * sizeof (UInt8),
224                     (PROT_READ|PROT_WRITE|PROT_NOCACHE),
225                     (MAP_PHYS|MAP_SHARED), NOFD, (off_t)nsValue[0]);
226                 if (GateMP_module->remoteSystemInUse == MAP_FAILED) {
227                     GateMP_module->remoteSystemInUse = NULL;
228                     status = GateMP_E_MEMORY;
229                     GT_setFailureReason(curTrace,
230                                         GT_4CLASS,
231                                         "GateMP_setup",
232                                         status,
233                                         "Failed to map remoteSystemInUse to " \
234                                         "host address space!");
235                 }
236             }
238             if ((status == GateMP_S_SUCCESS) &&
239                 (GateMP_module->numRemoteCustom1 != 0)) {
240                 GateMP_module->remoteCustom1InUse = mmap(NULL,
241                     GateMP_module->numRemoteCustom1 * sizeof (UInt8),
242                     (PROT_READ|PROT_WRITE|PROT_NOCACHE),
243                     (MAP_PHYS|MAP_SHARED), NOFD, (off_t)nsValue[1]);
244                 if (GateMP_module->remoteCustom1InUse == MAP_FAILED) {
245                     GateMP_module->remoteCustom1InUse = NULL;
246                     status = GateMP_E_MEMORY;
247                     GT_setFailureReason(curTrace,
248                                         GT_4CLASS,
249                                         "GateMP_setup",
250                                         status,
251                                         "Failed to map remoteCustom1InUse to " \
252                                         "host address space!");
253                 }
254             }
256             if ((status == GateMP_S_SUCCESS) &&
257                 (GateMP_module->numRemoteCustom2 != 0)) {
258                 GateMP_module->remoteCustom2InUse = mmap(NULL,
259                     GateMP_module->numRemoteCustom2 * sizeof (UInt8),
260                     (PROT_READ|PROT_WRITE|PROT_NOCACHE),
261                     (MAP_PHYS|MAP_SHARED), NOFD, (off_t)nsValue[2]);
262                 if (GateMP_module->remoteCustom2InUse == MAP_FAILED) {
263                     GateMP_module->remoteCustom2InUse = NULL;
264                     status = GateMP_E_MEMORY;
265                     GT_setFailureReason(curTrace,
266                                         GT_4CLASS,
267                                         "GateMP_setup",
268                                         status,
269                                         "Failed to map remoteCustom2InUse to " \
270                                         "host address space!");
271                 }
272             }
273         }
274     }
276     /* TODO: setup the proxy map */
278     /* clean up if error */
279     if (status < 0) {
280         GateMP_destroy(TRUE);
281     }
282     else {
283         GateMP_module->isSetup = TRUE;
284     }
286     pthread_mutex_unlock(&GateMP_module->lock);
288     return (status);
291 Int GateMP_destroy(Bool forced)
293     pthread_mutex_lock(&GateMP_module->lock);
295     if ((!forced) && (GateMP_module->startCount != 0)) {
296         /* Some process on the host is still using GateMP */
297         pthread_mutex_unlock(&GateMP_module->lock);
298         return (GateMP_E_FAIL);
299     }
301     if (GateMP_module->remoteSystemInUse) {
302         munmap((unsigned int *)GateMP_module->remoteSystemInUse,
303             GateMP_module->numRemoteSystem * sizeof (UInt8));
304         GateMP_module->remoteSystemInUse = NULL;
305     }
307     if (GateMP_module->remoteCustom1InUse) {
308         munmap((unsigned int *)GateMP_module->remoteCustom1InUse,
309             GateMP_module->numRemoteCustom1 * sizeof (UInt8));
310         GateMP_module->remoteCustom1InUse = NULL;
311     }
313     if (GateMP_module->remoteCustom2InUse) {
314         munmap((unsigned int *)GateMP_module->remoteCustom2InUse,
315             GateMP_module->numRemoteCustom2 * sizeof (UInt8));
316         GateMP_module->remoteCustom2InUse = NULL;
317     }
319     if (GateMP_module->defaultGate) {
320         GateMP_closeDefaultGate(&GateMP_module->defaultGate);
321     }
323     if (GateMP_module->nameServer) {
324         NameServer_delete(&GateMP_module->nameServer);
325         GateMP_module->nameServer = NULL;
326     }
328     GateMP_module->isSetup = FALSE;
330     pthread_mutex_unlock(&GateMP_module->lock);
332     return (GateMP_S_SUCCESS);
335 /* Open default gate during GateMP_setup. Should only be called once */
336 static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr,
337     UInt16 * creatorProcId)
339     Int             status = GateMP_S_SUCCESS;
340     UInt32          len;
341     UInt32          nsValue[4];
342     GateMP_Object * obj = NULL;
343     UInt32          arg;
344     UInt32          mask;
346     GateMP_RemoteSystemProxy_Params     systemParams;
348     /* assert that a valid pointer has been supplied */
349     if (handlePtr == NULL) {
350         status = GateMP_E_INVALIDARG;
351         GT_setFailureReason(curTrace,
352                             GT_4CLASS,
353                             "GateMP_openDefaultGate",
354                             status,
355                             "argument cannot be null");
356     }
358     if (status == GateMP_S_SUCCESS) {
359         len = sizeof(nsValue);
361         status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_dGate",
362             &nsValue, &len, NULL);
364         if (status < 0) {
365             *handlePtr = NULL;
366             status = GateMP_E_NOTFOUND;
367         }
368         else {
369             arg = nsValue[2];
370             mask = nsValue[3];
371             *creatorProcId = nsValue[1] >> 16;
372         }
373     }
375     if (status == GateMP_S_SUCCESS) {
376         /* allocate the instance object */
377         obj = (GateMP_Object *)calloc(1, sizeof (GateMP_Object));
378         if (obj != NULL) {
379             obj->localGate  = NULL;  /* TODO: create the local gate instance */
380             obj->localProtect  = GETLOCAL(mask);
381             obj->remoteProtect = GETREMOTE(mask);
382             obj->nsKey         = 0;
383             obj->numOpens      = 1;
384             obj->objType       = Ipc_ObjType_OPENDYNAMIC;
385             obj->resourceId    = arg;
387             assert(obj->remoteProtect == GateMP_RemoteProtect_SYSTEM);
389             /* create the proxy object */
390             GateMP_RemoteSystemProxy_Params_init(&systemParams);
391             systemParams.resourceId = obj->resourceId;
392             systemParams.openFlag = TRUE;
394             /*
395              * TODO: Currently passing in localProtect instead of localGate,
396              * since GateHWSpinlock owns the local gate
397              */
398             obj->gateHandle = (IGateProvider_Handle)
399                 GateMP_RemoteSystemProxy_create(obj->localProtect,
400                     &systemParams);
402             if (obj->gateHandle == NULL) {
403                 GT_setFailureReason(curTrace,
404                                     GT_4CLASS,
405                                     "GateMP_openDefaultGate",
406                                     GateMP_E_FAIL,
407                                     "failed to create proxy");
408                 free(obj);
409                 obj = NULL;
410             }
411         }
412         else {
413             GT_setFailureReason(curTrace,
414                                 GT_4CLASS,
415                                 "GateMP_openDefaultGate",
416                                 GateMP_E_FAIL,
417                                 "Memory allocation failed");
418         }
420         if (obj == NULL) {
421             status = GateMP_E_FAIL;
422         }
423     }
425     /* Return the "opened" GateMP instance  */
426     *handlePtr = (GateMP_Handle)obj;
428     return status;
431 static Int GateMP_closeDefaultGate(GateMP_Handle *handlePtr)
433     Int status = GateMP_S_SUCCESS;
434     GateMP_Object * obj = *(GateMP_Object **)handlePtr;
436     if (obj->gateHandle != NULL) {
437         /* Default gate is always of type System when more than 1 processor */
438         GateMP_RemoteSystemProxy_delete(
439             (GateMP_RemoteSystemProxy_Handle *)&obj->gateHandle);
440     }
442     free(*handlePtr);
443     *handlePtr = NULL;
445     return(status);
448 Int GateMP_getFreeResource(GateMP_RemoteProtect type)
450     IArg   key;
451     Bool   flag = FALSE;
452     Int    resourceId = -1;
453     UInt8* inUse = NULL;
454     Int    num = 0;
456     /* Remote case */
457     switch (type) {
458         /* TODO: currently only support System proxy */
459         case GateMP_RemoteProtect_SYSTEM:
460         case GateMP_RemoteProtect_CUSTOM1:
461         case GateMP_RemoteProtect_CUSTOM2:
462             inUse = GateMP_module->remoteSystemInUse;
463             num = GateMP_module->numRemoteSystem;
464             break;
466         default:
467             GT_setFailureReason(curTrace,
468                                 GT_4CLASS,
469                                 "GateMP_getFreeResource",
470                                 GateMP_E_FAIL,
471                                 "Invalid remote protection type");
472             break;
473     }
475     if (inUse != NULL) {
476         assert(GateMP_module->defaultGate != NULL);
477         key = GateMP_enter(GateMP_module->defaultGate);
479         /*
480          *  Find a free resource id. Note: zero is reserved on the
481          *  system proxy for the default gate.
482          */
483         for (resourceId = 0; resourceId < num; resourceId++) {
484             /*
485              *  If not in-use, set the inUse to TRUE to prevent other
486              *  creates from getting this one.
487              */
488             if (inUse[resourceId] == UNUSED) {
489                 flag = TRUE;
491                 /* Denote in shared memory that the resource is used */
492                 inUse[resourceId] = USED;
493                 break;
494             }
495         }
497         GateMP_leave(GateMP_module->defaultGate, key);
498     }
500     if (flag == FALSE) {
501         resourceId = -1;
502     }
504     return (resourceId);
507 Int GateMP_releaseResource(UInt id, GateMP_RemoteProtect type)
509     Int    status = GateMP_S_SUCCESS;
510     IArg   key;
511     UInt8* inUse = NULL;
512     Int    num = 0;
514     /* Remote case */
515     switch (type) {
516         /* TODO: currently only support System proxy */
517         case GateMP_RemoteProtect_SYSTEM:
518         case GateMP_RemoteProtect_CUSTOM1:
519         case GateMP_RemoteProtect_CUSTOM2:
520             inUse = GateMP_module->remoteSystemInUse;
521             num = GateMP_module->numRemoteSystem;
522             break;
524         default:
525             status = GateMP_E_FAIL;
526             GT_setFailureReason(curTrace,
527                                 GT_4CLASS,
528                                 "GateMP_releaseResource",
529                                 status,
530                                 "Invalid remote protection type");
531             break;
532     }
534     if ((inUse != NULL) && (id < num)) {
535         assert(GateMP_module->defaultGate != NULL);
536         key = GateMP_enter(GateMP_module->defaultGate);
537         inUse[id] = UNUSED;
538         GateMP_leave(GateMP_module->defaultGate, key);
539     }
540     else {
541         /* Should not happen if module is properly setup */
542         status = GateMP_E_FAIL;
543     }
545     return (status);
548 Int GateMP_getNumResources(GateMP_RemoteProtect type)
550     Int   num = -1;
552     /* Remote case */
553     switch (type) {
554         /* TODO: currently only support System proxy */
555         case GateMP_RemoteProtect_SYSTEM:
556         case GateMP_RemoteProtect_CUSTOM1:
557         case GateMP_RemoteProtect_CUSTOM2:
558             num = GateMP_module->numRemoteSystem;
559             break;
561         default:
562             GT_setFailureReason(curTrace,
563                                 GT_4CLASS,
564                                 "GateMP_getNumResources",
565                                 GateMP_E_FAIL,
566                                 "Invalid remote protection type");
567             break;
568     }
570     return (num);
573 NameServer_Handle GateMP_getNameServer(Void)
575     return (GateMP_module->nameServer);
578 Int GateMP_start(Void)
580     Int status = GateMP_S_SUCCESS;
582     pthread_mutex_lock(&GateMP_module->lock);
584     if (GateMP_isSetup()) {
585         GateMP_module->startCount++;
586     }
587     else {
588         /* Cannot start GateMP if it is not setup */
589         status = GateMP_E_FAIL;
590     }
592     pthread_mutex_unlock(&GateMP_module->lock);
594     return (status);
597 Int GateMP_stop(Void)
599     Int status = GateMP_S_SUCCESS;
601     pthread_mutex_lock(&GateMP_module->lock);
603     if (GateMP_isSetup()) {
604         GateMP_module->startCount--;
605     }
606     else {
607         /* Cannot stop GateMP if it is not setup */
608         status = GateMP_E_FAIL;
609     }
611     pthread_mutex_unlock(&GateMP_module->lock);
613     return (status);
616 Bool GateMP_isSetup(Void)
618     return (GateMP_module->isSetup);
621 IArg GateMP_enter(GateMP_Handle handle)
623     GateMP_Object * obj;
624     IArg            key;
626     obj = (GateMP_Object *)handle;
627     key = IGateProvider_enter(obj->gateHandle);
629     return(key);
632 Void GateMP_leave(GateMP_Handle handle, IArg key)
634     GateMP_Object *obj;
636     obj = (GateMP_Object *)handle;
637     IGateProvider_leave(obj->gateHandle, key);