306a7553408cdcce229e9a5eabb1af614658ecab
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 * ======== 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)
129 {
130 Int status = GateMP_S_SUCCESS;
131 NameServer_Params params;
132 UInt32 nsValue[NUM_INFO_FIELDS];
133 UInt32 len;
134 UInt32 size;
135 Int32 fdMem;
137 NameServer_Params_init(¶ms);
138 params.maxRuntimeEntries = MAX_RUNTIME_ENTRIES;
139 params.maxNameLen = MAX_NAME_LEN;
141 /* Assume info entry has more fields than other entries */
142 params.maxValueLen = NUM_INFO_FIELDS * sizeof(UInt32);
144 GateMP_module->nameServer =
145 NameServer_create(GateMP_NAMESERVER, ¶ms);
147 if (GateMP_module->nameServer == NULL) {
148 status = GateMP_E_FAIL;
149 LOG0("GateMP_setup: NameServer_create failed\n");
150 }
152 if (status == GateMP_S_SUCCESS) {
153 do {
154 sleep(1); /* Give the slaves some time to get NameServer ready */
155 status = GateMP_openDefaultGate(&GateMP_module->defaultGate);
156 } while (status == GateMP_E_NOTFOUND);
159 if (status < 0) {
160 LOG0("GateMP_setup: failed to open default gate\n");
161 status = GateMP_E_FAIL;
162 }
163 }
165 if (status == GateMP_S_SUCCESS) {
166 /* Process global info NameServer entry */
167 len = sizeof(nsValue);
169 status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_info",
170 &nsValue, &len, NULL);
172 if (status < 0) {
173 LOG0("GateMP_setup: failed to find info entry\n");
174 status = GateMP_E_NOTFOUND;
175 }
176 else {
177 fdMem = open ("/dev/mem", O_RDWR | O_SYNC);
179 if (fdMem < 0){
180 LOG0("GateMP_setup: failed to open the /dev/mem!\n");
181 status = GateMP_E_FAIL;
182 goto cleanup;
183 }
185 GateMP_module->numRemoteSystem = nsValue[3];
186 GateMP_module->numRemoteCustom1 = nsValue[4];
187 GateMP_module->numRemoteCustom2 = nsValue[5];
189 /* Map InUse arrays to daemon's address space */
190 size = GateMP_module->numRemoteSystem * sizeof (UInt8) +
191 (nsValue[0] & (sysconf(_SC_PAGE_SIZE) - 1));
192 size = PAGE_ALIGN(size, sysconf(_SC_PAGE_SIZE));
193 GateMP_module->remoteSystemInUse = mmap(NULL, size,
194 (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
195 (off_t)nsValue[0] & ~(sysconf(_SC_PAGE_SIZE) - 1));
196 if (GateMP_module->remoteSystemInUse == MAP_FAILED) {
197 GateMP_module->remoteSystemInUse = NULL;
198 status = GateMP_E_MEMORY;
199 LOG1("Failed to map remoteSystemInUse=0x%p to host address" \
200 " space!", GateMP_module->remoteSystemInUse);
201 }
203 size = GateMP_module->numRemoteCustom1 * sizeof (UInt8) +
204 (nsValue[0] & (sysconf(_SC_PAGE_SIZE) - 1));
205 size = PAGE_ALIGN(size, sysconf(_SC_PAGE_SIZE));
206 if (status == GateMP_S_SUCCESS) {
207 GateMP_module->remoteCustom1InUse = mmap(NULL, size,
208 (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
209 (off_t)nsValue[1] & ~(sysconf(_SC_PAGE_SIZE) - 1));
210 if (GateMP_module->remoteCustom1InUse == MAP_FAILED) {
211 GateMP_module->remoteCustom1InUse = NULL;
212 status = GateMP_E_MEMORY;
213 LOG1("Failed to map remoteCustom1InUse=%p to host address" \
214 " space!", GateMP_module->remoteCustom1InUse);
215 }
216 }
218 size = GateMP_module->numRemoteCustom2 * sizeof (UInt8) +
219 (nsValue[0] & (sysconf(_SC_PAGE_SIZE) - 1));
220 size = PAGE_ALIGN(size, sysconf(_SC_PAGE_SIZE));
221 if (status == GateMP_S_SUCCESS) {
222 GateMP_module->remoteCustom2InUse = mmap(NULL, size,
223 (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
224 (off_t)nsValue[2] & ~(sysconf(_SC_PAGE_SIZE) - 1));
225 if (GateMP_module->remoteCustom2InUse == MAP_FAILED) {
226 GateMP_module->remoteCustom2InUse = NULL;
227 status = GateMP_E_MEMORY;
228 LOG1("Failed to map remoteCustom2InUse=%p to host address" \
229 " space!", GateMP_module->remoteCustom2InUse);
230 }
231 }
232 }
233 }
235 /* TODO: setup the proxy map */
237 cleanup:
238 /* clean up if error */
239 if (status < 0) {
240 GateMP_destroy();
241 }
243 GateMP_module->isSetup = TRUE;
245 return (status);
246 }
248 Void GateMP_destroy(Void)
249 {
250 if (GateMP_module->remoteSystemInUse) {
251 munmap((unsigned int *)GateMP_module->remoteSystemInUse,
252 GateMP_module->numRemoteSystem * sizeof (UInt8));
253 GateMP_module->remoteSystemInUse = NULL;
254 }
256 if (GateMP_module->remoteCustom1InUse) {
257 munmap((unsigned int *)GateMP_module->remoteCustom1InUse,
258 GateMP_module->numRemoteCustom1 * sizeof (UInt8));
259 GateMP_module->remoteCustom1InUse = NULL;
260 }
262 if (GateMP_module->remoteCustom2InUse) {
263 munmap((unsigned int *)GateMP_module->remoteCustom2InUse,
264 GateMP_module->numRemoteCustom2 * sizeof (UInt8));
265 GateMP_module->remoteCustom2InUse = NULL;
266 }
268 if (GateMP_module->defaultGate) {
269 GateMP_closeDefaultGate(&GateMP_module->defaultGate);
270 }
272 if (GateMP_module->nameServer) {
273 NameServer_delete(&GateMP_module->nameServer);
274 GateMP_module->nameServer = NULL;
275 }
277 GateMP_module->isSetup = FALSE;
279 return;
280 }
282 /* Open default gate during GateMP_setup. Should only be called once */
283 static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr)
284 {
285 Int status = GateMP_S_SUCCESS;
286 UInt32 len;
287 UInt32 nsValue[4];
288 GateMP_Object * obj = NULL;
289 UInt32 arg;
290 UInt32 mask;
291 UInt32 creatorProcId;
293 GateMP_RemoteSystemProxy_Params systemParams;
295 /* assert that a valid pointer has been supplied */
296 if (handlePtr == NULL) {
297 LOG0("GateMP_open: argument cannot be null\n");
298 status = GateMP_E_INVALIDARG;
299 }
301 if (status == GateMP_S_SUCCESS) {
302 len = sizeof(nsValue);
304 status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_dGate",
305 &nsValue, &len, NULL);
307 if (status < 0) {
308 *handlePtr = NULL;
309 status = GateMP_E_NOTFOUND;
310 }
311 else {
312 arg = nsValue[2];
313 mask = nsValue[3];
314 creatorProcId = nsValue[1] >> 16;
315 }
316 }
318 if (status == GateMP_S_SUCCESS) {
319 /* allocate the instance object */
320 obj = (GateMP_Object *)calloc(1, sizeof (GateMP_Object));
321 if (obj != NULL) {
322 obj->localGate = NULL; /* TODO: create the local gate instance */
323 obj->localProtect = GETLOCAL(mask);
324 obj->remoteProtect = GETREMOTE(mask);
325 obj->nsKey = 0;
326 obj->numOpens = 1;
327 obj->objType = Ipc_ObjType_OPENDYNAMIC;
328 obj->resourceId = arg;
330 assert(obj->remoteProtect == GateMP_RemoteProtect_SYSTEM);
332 /* create the proxy object */
333 GateMP_RemoteSystemProxy_Params_init(&systemParams);
334 systemParams.resourceId = obj->resourceId;
335 systemParams.openFlag = TRUE;
337 /*
338 * TODO: Currently passing in localProtect instead of localGate,
339 * since GateHWSpinlock owns the local gate
340 */
341 obj->gateHandle = (IGateProvider_Handle)
342 GateMP_RemoteSystemProxy_create(obj->localProtect,
343 &systemParams);
345 if (obj->gateHandle == NULL) {
346 LOG0("GateMP_openDefaultGate: failed to create proxy\n");
347 free(obj);
348 obj = NULL;
349 }
350 }
351 else {
352 LOG0("GateMP_openDefaultGate: Memory allocation failed")
353 }
355 if (obj == NULL) {
356 status = GateMP_E_FAIL;
357 }
358 }
360 /* Return the "opened" GateMP instance */
361 *handlePtr = (GateMP_Handle)obj;
363 return status;
364 }
366 static Int GateMP_closeDefaultGate(GateMP_Handle *handlePtr)
367 {
368 Int status = GateMP_S_SUCCESS;
369 GateMP_Object * obj = *(GateMP_Object **)handlePtr;
371 if (obj->gateHandle != NULL) {
372 /* Default gate is always of type System when more than 1 processor */
373 GateMP_RemoteSystemProxy_delete(
374 (GateMP_RemoteSystemProxy_Handle *)&obj->gateHandle);
375 }
377 free(*handlePtr);
378 *handlePtr = NULL;
380 return(status);
381 }
383 Int GateMP_getFreeResource(GateMP_RemoteProtect type)
384 {
385 IArg key;
386 Bool flag = FALSE;
387 Int resourceId = -1;
388 UInt8* inUse = NULL;
389 Int num = 0;
391 /* Remote case */
392 switch (type) {
393 /* TODO: currently only support System proxy */
394 case GateMP_RemoteProtect_SYSTEM:
395 case GateMP_RemoteProtect_CUSTOM1:
396 case GateMP_RemoteProtect_CUSTOM2:
397 inUse = GateMP_module->remoteSystemInUse;
398 num = GateMP_module->numRemoteSystem;
399 break;
401 default:
402 LOG0("GateMP_getFreeResource: Invalid remote protection type\n");
403 break;
404 }
406 if (inUse != NULL) {
407 assert(GateMP_module->defaultGate != NULL);
408 key = GateMP_enter(GateMP_module->defaultGate);
410 /*
411 * Find a free resource id. Note: zero is reserved on the
412 * system proxy for the default gate.
413 */
414 for (resourceId = 0; resourceId < num; resourceId++) {
415 /*
416 * If not in-use, set the inUse to TRUE to prevent other
417 * creates from getting this one.
418 */
419 if (inUse[resourceId] == UNUSED) {
420 flag = TRUE;
422 /* Denote in shared memory that the resource is used */
423 inUse[resourceId] = USED;
424 break;
425 }
426 }
428 GateMP_leave(GateMP_module->defaultGate, key);
429 }
431 if (flag == FALSE) {
432 resourceId = -1;
433 }
435 return (resourceId);
436 }
438 Int GateMP_releaseResource(UInt id, GateMP_RemoteProtect type)
439 {
440 Int status = GateMP_S_SUCCESS;
441 IArg key;
442 UInt8* inUse = NULL;
443 Int num = 0;
445 /* Remote case */
446 switch (type) {
447 /* TODO: currently only support System proxy */
448 case GateMP_RemoteProtect_SYSTEM:
449 case GateMP_RemoteProtect_CUSTOM1:
450 case GateMP_RemoteProtect_CUSTOM2:
451 inUse = GateMP_module->remoteSystemInUse;
452 num = GateMP_module->numRemoteSystem;
453 break;
455 default:
456 LOG0("GateMP_releaseResource: Invalid remote protection type\n");
457 status = GateMP_E_FAIL;
458 break;
459 }
461 if ((inUse != NULL) && (id < num)) {
462 assert(GateMP_module->defaultGate != NULL);
463 key = GateMP_enter(GateMP_module->defaultGate);
464 inUse[id] = UNUSED;
465 GateMP_leave(GateMP_module->defaultGate, key);
466 }
467 else {
468 /* Should not happen if module is properly setup */
469 status = GateMP_E_FAIL;
470 }
472 return (status);
473 }
475 Int GateMP_getNumResources(GateMP_RemoteProtect type)
476 {
477 Int num = -1;
479 /* Remote case */
480 switch (type) {
481 /* TODO: currently only support System proxy */
482 case GateMP_RemoteProtect_SYSTEM:
483 case GateMP_RemoteProtect_CUSTOM1:
484 case GateMP_RemoteProtect_CUSTOM2:
485 num = GateMP_module->numRemoteSystem;
486 break;
488 default:
489 LOG0("GateMP_getNumResources: Invalid remote protection type\n");
490 break;
491 }
493 return (num);
494 }
496 NameServer_Handle GateMP_getNameServer(Void)
497 {
498 return (GateMP_module->nameServer);
499 }
501 Bool GateMP_isSetup(Void)
502 {
503 return (GateMP_module->isSetup);
504 }
506 IArg GateMP_enter(GateMP_Handle handle)
507 {
508 GateMP_Object * obj;
509 IArg key;
511 obj = (GateMP_Object *)handle;
512 key = IGateProvider_enter(obj->gateHandle);
514 return(key);
515 }
517 Void GateMP_leave(GateMP_Handle handle, IArg key)
518 {
519 GateMP_Object *obj;
521 obj = (GateMP_Object *)handle;
522 IGateProvider_leave(obj->gateHandle, key);
523 }