266b0f53f015dcf6c267fe2d5861561927bf7308
1 /*
2 * @file syslink_main.c
3 *
4 * @brief syslink main
5 *
6 *
7 * @ver 02.00.00.46_alpha1
8 *
9 * ============================================================================
10 *
11 * Copyright (c) 2011-2014, Texas Instruments Incorporated
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * * Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 *
20 * * Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 *
24 * * Neither the name of Texas Instruments Incorporated nor the names of
25 * its contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
30 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
32 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
35 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
36 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
37 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
38 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 * Contact information for paper mail:
40 * Texas Instruments
41 * Post Office Box 655303
42 * Dallas, Texas 75265
43 * Contact information:
44 * http://www-k.ext.ti.com/sc/technical-support/product-information-centers.htm?
45 * DCMP=TIHomeTracking&HQS=Other+OT+home_d_contact
46 * ============================================================================
47 *
48 */
50 #include "proto.h"
52 #include <pthread.h>
53 #include <fcntl.h>
54 #include <stdint.h>
55 #include <sys/procmgr.h>
56 #include <sys/neutrino.h>
57 #include <sys/siginfo.h>
58 #include <signal.h>
59 #include <stdbool.h>
61 #include <IpcKnl.h>
63 /* OSAL & Utils headers */
64 #include <ti/syslink/utils/List.h>
65 #include <ti/syslink/utils/MemoryOS.h>
66 #include <ti/ipc/MultiProc.h>
67 #include <ti/ipc/NameServer.h>
68 #include <_MultiProc.h>
69 #include <_NameServer.h>
70 #include <_GateMP_daemon.h>
71 #include <OsalSemaphore.h>
72 #include <ti/syslink/utils/OsalPrint.h>
73 #if defined(SYSLINK_PLATFORM_OMAP5430)
74 #include <_ipu_pm.h>
75 #endif
76 #include <ti/syslink/utils/Trace.h>
77 #include <ti/syslink/ProcMgr.h>
78 #include <Bitops.h>
79 #include <RscTable.h>
81 #include <ti-ipc.h>
83 #define DENY_ALL \
84 PROCMGR_ADN_ROOT \
85 | PROCMGR_ADN_NONROOT \
86 | PROCMGR_AOP_DENY \
87 | PROCMGR_AOP_LOCK
90 static int verbosity = 2;
92 /* Disable recovery mechanism if true */
93 static int disableRecovery = false;
95 #if defined(SYSLINK_PLATFORM_VAYU)
96 static bool gatempEnabled = false;
97 #endif
99 // Syslink hibernation global variables
100 Bool syslink_hib_enable = TRUE;
101 #if !defined(SYSLINK_PLATFORM_OMAP5430)
102 #define PM_HIB_DEFAULT_TIME 5000
103 #endif
104 uint32_t syslink_hib_timeout = PM_HIB_DEFAULT_TIME;
105 Bool syslink_hib_hibernating = FALSE;
106 pthread_mutex_t syslink_hib_mutex = PTHREAD_MUTEX_INITIALIZER;
107 pthread_cond_t syslink_hib_cond = PTHREAD_COND_INITIALIZER;
109 extern Int rpmsg_rpc_setup (Void);
110 extern Void rpmsg_rpc_destroy (Void);
111 extern Void GateHWSpinlock_LeaveLockForPID(int pid);
113 typedef struct syslink_firmware_info_t {
114 uint16_t proc_id;
115 char * proc;
116 char * firmware;
117 } syslink_firmware_info;
118 static syslink_firmware_info syslink_firmware[MultiProc_MAXPROCESSORS];
119 static unsigned int syslink_num_cores = 0;
121 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover);
122 int deinit_ipc(syslink_dev_t * dev, bool recover);
124 static RscTable_Handle rscHandle[MultiProc_MAXPROCESSORS];
126 static ProcMgr_Handle procH[MultiProc_MAXPROCESSORS];
127 static unsigned int procH_fileId[MultiProc_MAXPROCESSORS];
128 static ProcMgr_State errStates[] = {ProcMgr_State_Mmu_Fault,
129 ProcMgr_State_Error,
130 ProcMgr_State_Watchdog,
131 ProcMgr_State_EndValue};
133 typedef struct syslink_trace_info_t {
134 uintptr_t va;
135 uint32_t len;
136 uint32_t * widx;
137 uint32_t * ridx;
138 Bool firstRead;
139 } syslink_trace_info;
141 static syslink_trace_info proc_traces[MultiProc_MAXPROCESSORS];
143 int syslink_read(resmgr_context_t *ctp, io_read_t *msg, syslink_ocb_t *ocb)
144 {
145 int nbytes;
146 int nparts;
147 int status;
148 int nleft;
149 uint32_t len;
150 uint16_t procid = ocb->ocb.attr->procid;
152 if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK)
153 return (status);
155 if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE)
156 return (ENOSYS);
158 /* check to see where the trace buffer is */
159 if (proc_traces[procid].va == NULL) {
160 return (ENOSYS);
161 }
162 if (ocb->ocb.offset == 0) {
163 ocb->widx = *(proc_traces[procid].widx);
164 ocb->ridx = *(proc_traces[procid].ridx);
165 *(proc_traces[procid].ridx) = ocb->widx;
166 }
168 /* Check for wrap-around */
169 if (ocb->widx < ocb->ridx)
170 len = proc_traces[procid].len - ocb->ridx + ocb->widx;
171 else
172 len = ocb->widx - ocb->ridx;
174 /* Determine the amount left to print */
175 if (ocb->widx >= ocb->ridx)
176 nleft = len - ocb->ocb.offset;
177 else if (ocb->ocb.offset < proc_traces[procid].len - ocb->ridx)
178 nleft = proc_traces[procid].len - ocb->ridx - ocb->ocb.offset;
179 else
180 nleft = proc_traces[procid].len - ocb->ridx + ocb->widx - ocb->ocb.offset;
182 nbytes = min (msg->i.nbytes, nleft);
184 /* Make sure the user has supplied a big enough buffer */
185 if (nbytes > 0) {
186 /* set up the return data IOV */
187 if (ocb->widx < ocb->ridx && ocb->ocb.offset >= proc_traces[procid].len - ocb->ridx)
188 SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ocb.offset - (proc_traces[procid].len - ocb->ridx), nbytes);
189 else
190 SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ridx + ocb->ocb.offset, nbytes);
192 /* set up the number of bytes (returned by client's read()) */
193 _IO_SET_READ_NBYTES (ctp, nbytes);
195 ocb->ocb.offset += nbytes;
197 nparts = 1;
198 }
199 else {
200 _IO_SET_READ_NBYTES (ctp, 0);
202 /* reset offset */
203 ocb->ocb.offset = 0;
205 nparts = 0;
206 }
208 /* mark the access time as invalid (we just accessed it) */
210 if (msg->i.nbytes > 0)
211 ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
213 return (_RESMGR_NPARTS (nparts));
214 }
216 extern OsalSemaphore_Handle mqcopy_test_sem;
218 int syslink_unblock(resmgr_context_t *ctp, io_pulse_t *msg, syslink_ocb_t *ocb)
219 {
220 int status = _RESMGR_NOREPLY;
221 struct _msg_info info;
223 /*
224 * Try to run the default unblock for this message.
225 */
226 if ((status = iofunc_unblock_default(ctp,msg,&(ocb->ocb))) != _RESMGR_DEFAULT) {
227 return status;
228 }
230 /*
231 * Check if rcvid is still valid and still has an unblock
232 * request pending.
233 */
234 if (MsgInfo(ctp->rcvid, &info) == -1 ||
235 !(info.flags & _NTO_MI_UNBLOCK_REQ)) {
236 return _RESMGR_NOREPLY;
237 }
239 if (mqcopy_test_sem)
240 OsalSemaphore_post(mqcopy_test_sem);
242 return _RESMGR_NOREPLY;
243 }
245 IOFUNC_OCB_T *
246 syslink_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
247 {
248 syslink_ocb_t *ocb = NULL;
250 /* Allocate the OCB */
251 ocb = (syslink_ocb_t *) calloc (1, sizeof (syslink_ocb_t));
252 if (ocb == NULL){
253 errno = ENOMEM;
254 return (NULL);
255 }
257 ocb->pid = ctp->info.pid;
259 return (IOFUNC_OCB_T *)(ocb);
260 }
262 void
263 syslink_ocb_free (IOFUNC_OCB_T * i_ocb)
264 {
265 syslink_ocb_t * ocb = (syslink_ocb_t *)i_ocb;
267 if (ocb) {
268 #ifndef SYSLINK_PLATFORM_VAYU
269 GateHWSpinlock_LeaveLockForPID(ocb->pid);
270 #endif
271 free (ocb);
272 }
273 }
275 int init_syslink_trace_device(syslink_dev_t *dev)
276 {
277 resmgr_attr_t resmgr_attr;
278 int i;
279 syslink_attr_t * trace_attr;
280 char trace_name[_POSIX_PATH_MAX];
281 int status = 0;
282 unsigned int da = 0, pa = 0;
283 unsigned int len;
285 memset(&resmgr_attr, 0, sizeof resmgr_attr);
286 resmgr_attr.nparts_max = 10;
287 resmgr_attr.msg_max_size = 2048;
289 for (i = 0; i < syslink_num_cores; i++) {
290 iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs_trace[i],
291 _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_trace[i]);
292 trace_attr = &dev->syslink.cattr_trace[i];
293 iofunc_attr_init(&trace_attr->attr,
294 S_IFCHR | 0777, NULL, NULL);
295 trace_attr->attr.mount = &dev->syslink.mattr;
296 trace_attr->procid = i;
297 iofunc_time_update(&trace_attr->attr);
298 snprintf (dev->syslink.device_name, _POSIX_PATH_MAX,
299 "/dev/ipc-trace%d", syslink_firmware[i].proc_id);
300 dev->syslink.iofuncs_trace[i].read = syslink_read;
301 snprintf (trace_name, _POSIX_PATH_MAX, "%d", 0);
302 pa = 0;
303 status = RscTable_getInfo(syslink_firmware[i].proc_id, TYPE_TRACE, 0, &da, &pa, &len);
304 if (status == 0) {
305 /* last 8 bytes are for writeIdx/readIdx */
306 proc_traces[i].len = len - (sizeof(uint32_t) * 2);
307 if (da && !pa) {
308 /* need to translate da->pa */
309 status = ProcMgr_translateAddr (procH[syslink_firmware[i].proc_id],
310 (Ptr *) &pa,
311 ProcMgr_AddrType_MasterPhys,
312 (Ptr) da,
313 ProcMgr_AddrType_SlaveVirt);
314 }
315 else {
316 GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
317 status, "not performing ProcMgr_translate");
318 }
319 /* map length aligned to page size */
320 proc_traces[i].va =
321 mmap_device_io (((len + 0x1000 - 1) / 0x1000) * 0x1000, pa);
322 proc_traces[i].widx = (uint32_t *)(proc_traces[i].va + \
323 proc_traces[i].len);
324 proc_traces[i].ridx = (uint32_t *)((uint32_t)proc_traces[i].widx + \
325 sizeof(uint32_t));
326 if (proc_traces[i].va == MAP_DEVICE_FAILED) {
327 GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
328 status, "mmap_device_io failed");
329 GT_1trace(curTrace, GT_4CLASS, "errno %d", errno);
330 proc_traces[i].va = NULL;
331 }
332 proc_traces[i].firstRead = TRUE;
333 }
334 else {
335 GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
336 status, "RscTable_getInfo failed");
337 proc_traces[i].va = NULL;
338 }
339 if (-1 == (dev->syslink.resmgr_id_trace[i] =
340 resmgr_attach(dev->dpp, &resmgr_attr,
341 dev->syslink.device_name, _FTYPE_ANY, 0,
342 &dev->syslink.cfuncs_trace[i],
343 &dev->syslink.iofuncs_trace[i],
344 &trace_attr->attr))) {
345 GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
346 status, "resmgr_attach failed");
347 return(-1);
348 }
349 }
351 return (status);
352 }
354 int deinit_syslink_trace_device(syslink_dev_t *dev)
355 {
356 int status = EOK;
357 int i = 0;
359 for (i = 0; i < syslink_num_cores; i++) {
360 status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_trace[i], 0);
361 if (status < 0) {
362 Osal_printf("syslink: resmgr_detach failed %d", errno);
363 status = errno;
364 }
365 if (proc_traces[i].va && proc_traces[i].va != MAP_DEVICE_FAILED) {
366 munmap((void *)proc_traces[i].va,
367 ((proc_traces[i].len + 8 + 0x1000 - 1) / 0x1000) * 0x1000);
368 }
369 proc_traces[i].va = NULL;
370 }
372 return (status);
373 }
375 /* Initialize the syslink device */
376 int init_syslink_device(syslink_dev_t *dev)
377 {
378 iofunc_attr_t * attr;
379 resmgr_attr_t resmgr_attr;
380 int status = 0;
382 pthread_mutex_init(&dev->lock, NULL);
384 memset(&resmgr_attr, 0, sizeof resmgr_attr);
385 resmgr_attr.nparts_max = 10;
386 resmgr_attr.msg_max_size = 2048;
388 memset(&dev->syslink.mattr, 0, sizeof(iofunc_mount_t));
389 dev->syslink.mattr.flags = ST_NOSUID | ST_NOEXEC;
390 dev->syslink.mattr.conf = IOFUNC_PC_CHOWN_RESTRICTED |
391 IOFUNC_PC_NO_TRUNC |
392 IOFUNC_PC_SYNC_IO;
393 dev->syslink.mattr.funcs = &dev->syslink.mfuncs;
395 memset(&dev->syslink.mfuncs, 0, sizeof(iofunc_funcs_t));
396 dev->syslink.mfuncs.nfuncs = _IOFUNC_NFUNCS;
398 iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs,
399 _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs);
401 iofunc_attr_init(attr = &dev->syslink.cattr, S_IFCHR | 0777, NULL, NULL);
403 dev->syslink.mfuncs.ocb_calloc = syslink_ocb_calloc;
404 dev->syslink.mfuncs.ocb_free = syslink_ocb_free;
405 dev->syslink.iofuncs.devctl = syslink_devctl;
406 dev->syslink.iofuncs.unblock = syslink_unblock;
408 attr->mount = &dev->syslink.mattr;
409 iofunc_time_update(attr);
411 if (-1 == (dev->syslink.resmgr_id =
412 resmgr_attach(dev->dpp, &resmgr_attr,
413 IPC_DEVICE_PATH, _FTYPE_ANY, 0,
414 &dev->syslink.cfuncs,
415 &dev->syslink.iofuncs, attr))) {
416 return(-1);
417 }
419 status = init_syslink_trace_device(dev);
420 if (status < 0) {
421 return status;
422 }
424 return(0);
425 }
427 /* De-initialize the syslink device */
428 int deinit_syslink_device(syslink_dev_t *dev)
429 {
430 int status = EOK;
432 status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id, 0);
433 if (status < 0) {
434 Osal_printf("syslink: resmgr_detach failed %d", errno);
435 status = errno;
436 }
438 status = deinit_syslink_trace_device(dev);
440 return(status);
441 }
444 /* Initialize the devices */
445 int init_devices(syslink_dev_t *dev)
446 {
447 if (init_syslink_device(dev) < 0) {
448 Osal_printf("syslink: syslink device init failed");
449 return(-1);
450 }
452 return(0);
453 }
456 /* De-initialize the devices */
457 int deinit_devices(syslink_dev_t *dev)
458 {
459 int status = EOK;
461 if ((status = deinit_syslink_device(dev)) < 0) {
462 fprintf( stderr, "syslink: syslink device de-init failed %d\n", status);
463 status = errno;
464 }
466 return(status);
467 }
469 static void ipc_recover(Ptr args)
470 {
471 syslink_dev_t * dev = (syslink_dev_t *)args;
473 if (!disableRecovery) {
474 deinit_ipc(dev, TRUE);
475 init_ipc(dev, syslink_firmware, TRUE);
476 deinit_syslink_trace_device(dev);
477 init_syslink_trace_device(dev);
478 }
479 }
481 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
482 ProcMgr_State fromState, ProcMgr_State toState,
483 ProcMgr_EventStatus status, Ptr args)
484 {
485 Int ret = 0;
486 String errString = NULL;
487 syslink_dev_t * dev = (syslink_dev_t *)args;
489 if (status == ProcMgr_EventStatus_Event) {
490 switch (toState) {
491 case ProcMgr_State_Mmu_Fault:
492 errString = "MMU Fault";
493 break;
494 case ProcMgr_State_Error:
495 errString = "Exception";
496 break;
497 case ProcMgr_State_Watchdog:
498 errString = "Watchdog";
499 break;
500 default:
501 errString = "Unexpected State";
502 ret = -1;
503 break;
504 }
505 GT_2trace (curTrace, GT_4CLASS,
506 "syslink_error_cb: Received Error Callback for %s : %s\n",
507 MultiProc_getName(procId), errString);
508 /* Don't allow re-schedule of recovery until complete */
509 pthread_mutex_lock(&dev->lock);
510 if (ret != -1 && dev->recover == FALSE) {
511 /* Schedule recovery. */
512 dev->recover = TRUE;
513 /* Activate a thread to handle the recovery. */
514 GT_0trace (curTrace, GT_4CLASS,
515 "syslink_error_cb: Scheduling recovery...");
516 OsalThread_activate(dev->ipc_recovery_work);
517 }
518 else {
519 GT_0trace (curTrace, GT_4CLASS,
520 "syslink_error_cb: Recovery already scheduled.");
521 }
522 pthread_mutex_unlock(&dev->lock);
523 }
524 else if (status == ProcMgr_EventStatus_Canceled) {
525 GT_1trace (curTrace, GT_3CLASS,
526 "SysLink Error Callback Cancelled for %s",
527 MultiProc_getName(procId));
528 }
529 else {
530 GT_1trace (curTrace, GT_4CLASS,
531 "SysLink Error Callback Unexpected Event for %s",
532 MultiProc_getName(procId));
533 }
535 return ret;
536 }
538 /*
539 * Initialize the syslink ipc
540 *
541 * This function sets up the "kernel"-side IPC modules, and does any special
542 * initialization required for QNX and the platform being used. This function
543 * also registers for error notifications and initializes the recovery thread.
544 */
545 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover)
546 {
547 int status = 0;
548 Ipc_Config iCfg;
549 OsalThread_Params threadParams;
550 ProcMgr_AttachParams attachParams;
551 UInt16 procId;
552 int i;
554 if (status >= 0) {
555 if (!recover) {
556 /* Set up the MemoryOS module */
557 status = MemoryOS_setup();
558 if (status < 0)
559 goto memoryos_fail;
560 }
562 /* Setup IPC and platform-specific items */
563 status = Ipc_setup (&iCfg);
564 if (status < 0)
565 goto ipcsetup_fail;
567 /* NOTE: this is for handling the procmgr event notifications to userspace list */
568 if (!recover) {
569 /* Setup Fault recovery items. */
570 /* Create the thread object used for the interrupt handler. */
571 threadParams.priority = OsalThread_Priority_Medium;
572 threadParams.priorityType = OsalThread_PriorityType_Generic;
573 threadParams.once = FALSE;
574 dev->ipc_recovery_work = OsalThread_create ((OsalThread_CallbackFxn)
575 ipc_recover,
576 dev,
577 &threadParams);
578 if (dev->ipc_recovery_work == NULL)
579 goto osalthreadcreate_fail;
580 }
581 else {
582 pthread_mutex_lock(&dev->lock);
583 dev->recover = FALSE;
584 pthread_mutex_unlock(&dev->lock);
585 }
587 for (i = 0; i < syslink_num_cores; i++) {
588 procId = firmware[i].proc_id = MultiProc_getId(firmware[i].proc);
589 if (procId >= MultiProc_MAXPROCESSORS) {
590 status = -1;
591 fprintf(stderr, "Invalid processor name specified\n");
592 break;
593 }
595 if (procH[procId]) {
596 GT_setFailureReason (curTrace,
597 GT_4CLASS,
598 "init_ipc",
599 status,
600 "invalid proc!");
601 break;
602 }
604 if (syslink_firmware[i].firmware) {
605 rscHandle[procId] = RscTable_alloc(firmware[i].firmware, procId);
606 if (rscHandle[procId] == NULL) {
607 status = -1;
608 break;
609 }
610 }
612 status = ProcMgr_open(&procH[procId], procId);
613 if (status < 0 || procH[procId] == NULL)
614 goto procmgropen_fail;
616 /* Load and start the remote processor. */
617 ProcMgr_getAttachParams (procH[procId], &attachParams);
618 status = ProcMgr_attach (procH[procId], &attachParams);
619 if (status < 0) {
620 GT_setFailureReason (curTrace,
621 GT_4CLASS,
622 "init_ipc",
623 status,
624 "ProcMgr_attach failed!");
625 goto procmgrattach_fail;
626 }
628 if (syslink_firmware[i].firmware) {
629 status = ProcMgr_load (procH[procId],
630 (String)firmware[i].firmware, 0, NULL,
631 NULL, &procH_fileId[procId]);
632 if (status < 0) {
633 GT_setFailureReason (curTrace,
634 GT_4CLASS,
635 "init_ipc",
636 status,
637 "ProcMgr_load failed!");
638 goto procmgrload_fail;
639 }
640 }
642 status = Ipc_attach (procId);
643 if (status < 0) {
644 GT_setFailureReason (curTrace,
645 GT_4CLASS,
646 "init_ipc",
647 status,
648 "Ipc_attach failed!");
649 goto ipcattach_fail;
650 }
652 status = ProcMgr_registerNotify(procH[procId], syslink_error_cb, (Ptr)dev,
653 -1, errStates);
654 if (status < 0) {
655 goto procmgrreg_fail;
656 }
658 status = ProcMgr_start(procH[procId], NULL);
659 if (status < 0) {
660 GT_setFailureReason (curTrace,
661 GT_4CLASS,
662 "init_ipc",
663 status,
664 "ProcMgr_start failed!");
665 goto procmgrstart_fail;
666 }
668 continue;
670 procmgrstart_fail:
671 ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
672 (Ptr)dev, errStates);
673 procmgrreg_fail:
674 Ipc_detach(procId);
675 ipcattach_fail:
676 if (syslink_firmware[i].firmware)
677 ProcMgr_unload(procH[procId], procH_fileId[procId]);
678 procmgrload_fail:
679 ProcMgr_detach(procH[procId]);
680 procmgrattach_fail:
681 ProcMgr_close(&procH[procId]);
682 procH[procId] = NULL;
683 procmgropen_fail:
684 RscTable_free(&rscHandle[procId]);
685 break;
686 }
688 if (status < 0)
689 goto tiipcsetup_fail;
691 /* Set up rpmsg_mq */
692 status = ti_ipc_setup();
693 if (status < 0)
694 goto tiipcsetup_fail;
696 /* Set up rpmsg_rpc */
697 status = rpmsg_rpc_setup();
698 if (status < 0)
699 goto rpcsetup_fail;
701 #if defined(SYSLINK_PLATFORM_VAYU)
702 if (gatempEnabled) {
703 /* Set up NameServer for resource manager process */
704 status = NameServer_setup();
705 if (status < 0) {
706 goto nameserversetup_fail;
707 }
709 /* Set up GateMP */
710 status = GateMP_setup();
711 if (status < 0) {
712 goto gatempsetup_fail;
713 }
714 }
715 #endif
717 goto exit;
718 }
720 #if defined(SYSLINK_PLATFORM_VAYU)
721 gatempsetup_fail:
722 NameServer_destroy();
723 nameserversetup_fail:
724 rpmsg_rpc_destroy();
725 #endif
726 rpcsetup_fail:
727 ti_ipc_destroy(recover);
728 tiipcsetup_fail:
729 for (i-=1; i >= 0; i--) {
730 procId = firmware[i].proc_id;
731 if (procId >= MultiProc_MAXPROCESSORS) {
732 continue;
733 }
734 ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
735 (Ptr)dev, errStates);
736 ProcMgr_stop(procH[procId]);
737 if (procH_fileId[procId]) {
738 ProcMgr_unload(procH[procId], procH_fileId[procId]);
739 procH_fileId[procId] = 0;
740 }
741 ProcMgr_detach(procH[procId]);
742 ProcMgr_close(&procH[procId]);
743 procH[procId] = NULL;
744 RscTable_free(&rscHandle[procId]);
745 rscHandle[procId] = NULL;
746 }
747 OsalThread_delete(&dev->ipc_recovery_work);
748 osalthreadcreate_fail:
749 Ipc_destroy();
750 ipcsetup_fail:
751 MemoryOS_destroy();
752 memoryos_fail:
753 exit:
754 return status;
755 }
757 int deinit_ipc(syslink_dev_t * dev, bool recover)
758 {
759 int status = EOK;
760 uint32_t i = 0, id = 0;
762 // Stop the remote cores right away
763 for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
764 if (procH[i]) {
765 GT_1trace(curTrace, GT_4CLASS, "stopping %s", MultiProc_getName(i));
766 ProcMgr_stop(procH[i]);
767 }
768 }
770 #if defined(SYSLINK_PLATFORM_VAYU)
771 if (gatempEnabled) {
772 GateMP_destroy();
774 NameServer_destroy();
775 }
776 #endif
778 rpmsg_rpc_destroy();
780 ti_ipc_destroy(recover);
782 for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
783 if (procH[i]) {
784 ProcMgr_unregisterNotify (procH[i], syslink_error_cb, (Ptr)dev,
785 errStates);
786 Ipc_detach(i);
787 if (procH_fileId[i]) {
788 ProcMgr_unload(procH[i], procH_fileId[i]);
789 procH_fileId[i] = 0;
790 }
791 ProcMgr_detach(procH[i]);
792 ProcMgr_close(&procH[i]);
793 procH[i] = NULL;
794 RscTable_free(&rscHandle[i]);
795 rscHandle[i] = NULL;
796 }
797 }
799 if (!recover && dev->ipc_recovery_work != NULL) {
800 OsalThread_delete (&dev->ipc_recovery_work);
801 dev->ipc_recovery_work = NULL;
802 }
804 if (recover) {
805 static FILE *log;
806 /* Dump the trace information */
807 Osal_printf("syslink: printing remote core trace dump to"
808 " /var/log/ducati-m3-traces.log");
809 log = fopen ("/var/log/ducati-m3-traces.log", "a+");
810 if (log) {
811 for (id = 0; id < syslink_num_cores; id++) {
812 if (proc_traces[id].va) {
813 /* print traces */
814 /* wait a little bit for traces to finish dumping */
815 sleep(1);
816 fprintf(log, "****************************************\n");
817 fprintf(log, "*** CORE%d TRACE DUMP ***\n",
818 id);
819 fprintf(log, "****************************************\n");
820 for (i = (*proc_traces[id].widx + 1);
821 i < (proc_traces[id].len - 8);
822 i++) {
823 fprintf(log, "%c",
824 *(char *)((uint32_t)proc_traces[id].va + i));
825 }
826 for (i = 0; i < *proc_traces[id].widx; i++) {
827 fprintf(log, "%c",
828 *(char *)((uint32_t)proc_traces[id].va + i));
829 }
830 }
831 }
832 fclose(log);
833 }
834 else {
835 GT_setFailureReason(curTrace, GT_4CLASS, "deinit_ipc", errno,
836 "error opening /var/log/ducati-m3-traces.log");
837 }
838 }
840 status = Ipc_destroy();
841 if (status < 0) {
842 printf("Ipc_destroy() failed 0x%x", status);
843 }
844 if (!recover) {
845 status = MemoryOS_destroy();
846 if (status < 0) {
847 printf("MemoryOS_destroy() failed 0x%x", status);
848 }
849 }
851 return status;
852 }
855 /** print usage */
856 static Void printUsage (Char * app)
857 {
858 printf("\n\nUsage:\n");
859 #if defined(SYSLINK_PLATFORM_OMAP5430)
860 printf("\n%s: [-HT] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
861 app);
862 printf(" <core_id#> should be set to a core name (e.g. IPU, DSP)\n");
863 printf(" followed by the path to the executable to load on that core.\n");
864 printf("Options:\n");
865 printf(" -H enable/disable hibernation, 1: ON, 0: OFF, Default: 1)\n");
866 printf(" -T specify the hibernation timeout in ms, Default: 5000 ms)\n");
867 #else
868 printf("\n%s: [-g] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
869 app);
870 printf(" <core_id#> should be set to a core name (e.g. DSP1, IPU2)\n");
871 printf(" followed by the path to the executable to load on that core.\n");
872 printf("Options:\n");
873 printf(" -g enable GateMP support on host\n");
874 #endif
875 printf(" -d disable recovery\n");
876 exit (EXIT_SUCCESS);
877 }
879 dispatch_t * syslink_dpp = NULL;
881 int main(int argc, char *argv[])
882 {
883 syslink_dev_t * dev = NULL;
884 thread_pool_attr_t tattr;
885 int status;
886 int error = 0;
887 sigset_t set;
888 int channelid = 0;
889 int c;
890 int hib_enable = 1;
891 uint32_t hib_timeout = PM_HIB_DEFAULT_TIME;
892 char *user_parm = NULL;
893 struct stat sbuf;
894 int i = 0;
895 char * abs_path = NULL;
897 if (-1 != stat(IPC_DEVICE_PATH, &sbuf)) {
898 printf ("Syslink Already Running...\n");
899 return EXIT_FAILURE;
900 }
901 printf ("Starting syslink resource manager...\n");
903 /* Parse the input args */
904 while (1)
905 {
906 c = getopt (argc, argv, "H:T:U:gdv:");
907 if (c == -1)
908 break;
910 switch (c)
911 {
912 #if defined(SYSLINK_PLATFORM_OMAP5430)
913 case 'H':
914 hib_enable = atoi(optarg);
915 if (hib_enable != 0 && hib_enable != 1) {
916 hib_enable = -1;
917 }
918 break;
919 case 'T':
920 hib_timeout = atoi(optarg);
921 break;
922 #endif
923 case 'U':
924 user_parm = optarg;
925 break;
926 case 'd':
927 disableRecovery = true;
928 break;
929 case 'v':
930 verbosity++;
931 break;
932 #if defined(SYSLINK_PLATFORM_VAYU)
933 case 'g':
934 printf("GateMP support enabled on host\n");
935 gatempEnabled = true;
936 break;
937 #endif
938 default:
939 fprintf (stderr, "Unrecognized argument\n");
940 }
941 }
943 /* Now parse the operands, which should be in the format:
944 * "<multiproc_name> <firmware_file> ..*/
945 for (; optind + 1 < argc; optind+=2) {
946 if (syslink_num_cores == MultiProc_MAXPROCESSORS) {
947 printUsage(argv[0]);
948 return (error);
949 }
950 syslink_firmware[syslink_num_cores].proc = argv [optind];
951 syslink_firmware[syslink_num_cores++].firmware = argv [optind+1];
952 }
955 /* Get the name of the binary from the input args */
956 if (!syslink_num_cores) {
957 fprintf(stderr, "At least one core_id and executable must be "\
958 "specified");
959 printUsage(argv[0]);
960 return (error);
961 }
963 /* Validate hib_enable args */
964 if (hib_enable == -1) {
965 fprintf (stderr, "invalid hibernation enable value\n");
966 printUsage(argv[0]);
967 return (error);
968 }
970 syslink_hib_enable = (Bool)hib_enable;
971 syslink_hib_timeout = hib_timeout;
973 /* Init logging for syslink */
974 if (Osal_initlogging(verbosity) != 0) {
975 return -1;
976 }
978 /* Obtain I/O privity */
979 error = ThreadCtl_r (_NTO_TCTL_IO, 0);
980 if (error == -1) {
981 Osal_printf("Unable to obtain I/O privity");
982 return (error);
983 }
985 /* Get the abs path for all firmware files */
986 for (i = 0; i < syslink_num_cores; i++) {
987 abs_path = calloc(1, PATH_MAX + 1);
988 if (abs_path == NULL) {
989 return -1;
990 }
991 if (NULL == realpath(syslink_firmware[i].firmware, abs_path)) {
992 fprintf (stderr, "invalid path to executable\n");
993 return -1;
994 }
995 syslink_firmware[i].firmware = abs_path;
996 }
998 /* allocate the device structure */
999 if (NULL == (dev = calloc(1, sizeof(syslink_dev_t)))) {
1000 Osal_printf("syslink: calloc() failed");
1001 return (-1);
1002 }
1004 /* create the channel */
1005 if ((channelid = ChannelCreate_r (_NTO_CHF_UNBLOCK |
1006 _NTO_CHF_DISCONNECT |
1007 _NTO_CHF_COID_DISCONNECT |
1008 _NTO_CHF_REPLY_LEN |
1009 _NTO_CHF_SENDER_LEN)) < 0) {
1010 Osal_printf("Unable to create channel %d", channelid);
1011 return (channelid);
1012 }
1014 /* create the dispatch structure */
1015 if (NULL == (dev->dpp = syslink_dpp = dispatch_create_channel (channelid, 0))) {
1016 Osal_printf("syslink: dispatch_create() failed");
1017 return(-1);
1018 }
1020 /*
1021 * Mask out all signals before creating a thread pool.
1022 * This prevents other threads in the thread pool
1023 * from intercepting signals such as SIGTERM.
1024 */
1025 sigfillset(&set);
1026 pthread_sigmask(SIG_BLOCK, &set, NULL);
1028 /* Initialize the thread pool */
1029 memset (&tattr, 0x00, sizeof (thread_pool_attr_t));
1030 tattr.handle = dev->dpp;
1031 tattr.context_alloc = dispatch_context_alloc;
1032 tattr.context_free = dispatch_context_free;
1033 tattr.block_func = dispatch_block;
1034 tattr.unblock_func = dispatch_unblock;
1035 tattr.handler_func = dispatch_handler;
1036 tattr.lo_water = 2;
1037 tattr.hi_water = 4;
1038 tattr.increment = 1;
1039 tattr.maximum = 10;
1041 /* Create the thread pool */
1042 if ((dev->tpool = thread_pool_create(&tattr, 0)) == NULL) {
1043 Osal_printf("syslink: thread pool create failed");
1044 return(-1);
1045 }
1047 /* init syslink */
1048 status = init_ipc(dev, syslink_firmware, FALSE);
1049 if (status < 0) {
1050 Osal_printf("syslink: IPC init failed");
1051 return(-1);
1052 }
1054 /* init the syslink device */
1055 status = init_devices(dev);
1056 if (status < 0) {
1057 Osal_printf("syslink: device init failed");
1058 return(-1);
1059 }
1061 #if (_NTO_VERSION >= 800)
1062 /* Relinquish privileges */
1063 status = procmgr_ability( 0,
1064 DENY_ALL | PROCMGR_AID_SPAWN,
1065 DENY_ALL | PROCMGR_AID_FORK,
1066 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PEER,
1067 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PHYS,
1068 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_INTERRUPT,
1069 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_PATHSPACE,
1070 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_RSRCDBMGR,
1071 PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETUID,
1072 (uint64_t)1, (uint64_t)~0,
1073 PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETGID,
1074 (uint64_t)1, (uint64_t)~0,
1075 PROCMGR_ADN_ROOT | PROCMGR_AOP_DENY | PROCMGR_AOP_LOCK | PROCMGR_AID_EOL);
1077 if (status != EOK) {
1078 Osal_printf("procmgr_ability failed! errno=%d", status);
1079 return EXIT_FAILURE;
1080 }
1082 /* Reduce priority to either what defined from command line or at least nobody */
1083 if (user_parm != NULL) {
1084 if (set_ids_from_arg(user_parm) < 0) {
1085 Osal_printf("unable to set uid/gid - %s", strerror(errno));
1086 return EXIT_FAILURE;
1087 }
1088 } else {
1089 if (setuid(99) != 0) {
1090 Osal_printf("unable to set uid - %s", strerror(errno));
1091 return EXIT_FAILURE;
1092 }
1093 }
1094 #endif
1096 /* make this a daemon process */
1097 if (-1 == procmgr_daemon(EXIT_SUCCESS,
1098 PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL)) {
1099 Osal_printf("syslink: procmgr_daemon() failed");
1100 return(-1);
1101 }
1103 /* start the thread pool */
1104 thread_pool_start(dev->tpool);
1106 /* Unmask signals to be caught */
1107 sigdelset (&set, SIGINT);
1108 sigdelset (&set, SIGTERM);
1109 pthread_sigmask (SIG_BLOCK, &set, NULL);
1111 /* Wait for one of these signals */
1112 sigemptyset (&set);
1113 sigaddset (&set, SIGINT);
1114 sigaddset (&set, SIGQUIT);
1115 sigaddset (&set, SIGTERM);
1117 Osal_printf("Syslink resource manager started");
1119 /* Wait for a signal */
1120 while (1)
1121 {
1122 switch (SignalWaitinfo (&set, NULL))
1123 {
1124 case SIGTERM:
1125 case SIGQUIT:
1126 case SIGINT:
1127 error = EOK;
1128 goto done;
1130 default:
1131 break;
1132 }
1133 }
1135 error = EOK;
1137 done:
1138 GT_0trace(curTrace, GT_4CLASS, "Syslink resource manager exiting \n");
1140 error = thread_pool_destroy(dev->tpool);
1141 if (error < 0)
1142 Osal_printf("syslink: thread_pool_destroy returned an error");
1143 deinit_ipc(dev, FALSE);
1144 deinit_devices(dev);
1145 free(dev);
1146 return (EOK);
1147 }