Removes all references to OMAP4 and TI81xx devices in QNX codebase
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / build / Qnx / resmgr / syslink_main.c
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-2013, 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;
93 #if defined(SYSLINK_PLATFORM_VAYU)
94 static bool gatempEnabled = false;
95 #endif
97 // Syslink hibernation global variables
98 Bool syslink_hib_enable = TRUE;
99 #if !defined(SYSLINK_PLATFORM_OMAP5430)
100 #define PM_HIB_DEFAULT_TIME 5000
101 #endif
102 uint32_t syslink_hib_timeout = PM_HIB_DEFAULT_TIME;
103 Bool syslink_hib_hibernating = FALSE;
104 pthread_mutex_t syslink_hib_mutex = PTHREAD_MUTEX_INITIALIZER;
105 pthread_cond_t syslink_hib_cond = PTHREAD_COND_INITIALIZER;
107 extern Int rpmsg_rpc_setup (Void);
108 extern Void rpmsg_rpc_destroy (Void);
109 extern Void GateHWSpinlock_LeaveLockForPID(int pid);
111 typedef struct syslink_firmware_info_t {
112     uint16_t proc_id;
113     char * proc;
114     char * firmware;
115 } syslink_firmware_info;
116 static syslink_firmware_info syslink_firmware[MultiProc_MAXPROCESSORS];
117 static unsigned int syslink_num_cores = 0;
119 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover);
120 int deinit_ipc(syslink_dev_t * dev, bool recover);
122 static RscTable_Handle rscHandle[MultiProc_MAXPROCESSORS];
124 static ProcMgr_Handle procH[MultiProc_MAXPROCESSORS];
125 static unsigned int procH_fileId[MultiProc_MAXPROCESSORS];
126 static ProcMgr_State errStates[] = {ProcMgr_State_Mmu_Fault,
127                                     ProcMgr_State_Error,
128                                     ProcMgr_State_Watchdog,
129                                     ProcMgr_State_EndValue};
131 typedef struct syslink_trace_info_t {
132     uintptr_t   va;
133     uint32_t    len;
134     uint32_t *  widx;
135     uint32_t *  ridx;
136     Bool        firstRead;
137 } syslink_trace_info;
139 static syslink_trace_info proc_traces[MultiProc_MAXPROCESSORS];
141 int syslink_read(resmgr_context_t *ctp, io_read_t *msg, syslink_ocb_t *ocb)
143     int         nbytes;
144     int         nparts;
145     int         status;
146     int         nleft;
147     uint32_t    len;
148     uint16_t    procid = ocb->ocb.attr->procid;
150     if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK)
151         return (status);
153     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE)
154         return (ENOSYS);
156     /* check to see where the trace buffer is */
157     if (proc_traces[procid].va == NULL) {
158         return (ENOSYS);
159     }
160     if (ocb->ocb.offset == 0) {
161         ocb->widx = *(proc_traces[procid].widx);
162         ocb->ridx = *(proc_traces[procid].ridx);
163         *(proc_traces[procid].ridx) = ocb->widx;
164     }
166     /* Check for wrap-around */
167     if (ocb->widx < ocb->ridx)
168         len = proc_traces[procid].len - ocb->ridx + ocb->widx;
169     else
170         len = ocb->widx - ocb->ridx;
172     /* Determine the amount left to print */
173     if (ocb->widx >= ocb->ridx)
174         nleft = len - ocb->ocb.offset;
175     else if (ocb->ocb.offset < proc_traces[procid].len - ocb->ridx)
176         nleft = proc_traces[procid].len - ocb->ridx - ocb->ocb.offset;
177     else
178         nleft = proc_traces[procid].len - ocb->ridx + ocb->widx - ocb->ocb.offset;
180     nbytes = min (msg->i.nbytes, nleft);
182     /* Make sure the user has supplied a big enough buffer */
183     if (nbytes > 0) {
184         /* set up the return data IOV */
185         if (ocb->widx < ocb->ridx && ocb->ocb.offset >= proc_traces[procid].len - ocb->ridx)
186             SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ocb.offset - (proc_traces[procid].len - ocb->ridx), nbytes);
187         else
188             SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ridx + ocb->ocb.offset, nbytes);
190         /* set up the number of bytes (returned by client's read()) */
191         _IO_SET_READ_NBYTES (ctp, nbytes);
193         ocb->ocb.offset += nbytes;
195         nparts = 1;
196     }
197     else {
198         _IO_SET_READ_NBYTES (ctp, 0);
200         /* reset offset */
201         ocb->ocb.offset = 0;
203         nparts = 0;
204     }
206     /* mark the access time as invalid (we just accessed it) */
208     if (msg->i.nbytes > 0)
209         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
211     return (_RESMGR_NPARTS (nparts));
214 extern OsalSemaphore_Handle mqcopy_test_sem;
216 int syslink_unblock(resmgr_context_t *ctp, io_pulse_t *msg, syslink_ocb_t *ocb)
218     int status = _RESMGR_NOREPLY;
219     struct _msg_info info;
221     /*
222      * Try to run the default unblock for this message.
223      */
224     if ((status = iofunc_unblock_default(ctp,msg,&(ocb->ocb))) != _RESMGR_DEFAULT) {
225         return status;
226     }
228     /*
229      * Check if rcvid is still valid and still has an unblock
230      * request pending.
231      */
232     if (MsgInfo(ctp->rcvid, &info) == -1 ||
233         !(info.flags & _NTO_MI_UNBLOCK_REQ)) {
234         return _RESMGR_NOREPLY;
235     }
237     if (mqcopy_test_sem)
238         OsalSemaphore_post(mqcopy_test_sem);
240     return _RESMGR_NOREPLY;
243 IOFUNC_OCB_T *
244 syslink_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
246     syslink_ocb_t *ocb = NULL;
248     /* Allocate the OCB */
249     ocb = (syslink_ocb_t *) calloc (1, sizeof (syslink_ocb_t));
250     if (ocb == NULL){
251         errno = ENOMEM;
252         return (NULL);
253     }
255     ocb->pid = ctp->info.pid;
257     return (IOFUNC_OCB_T *)(ocb);
260 void
261 syslink_ocb_free (IOFUNC_OCB_T * i_ocb)
263     syslink_ocb_t * ocb = (syslink_ocb_t *)i_ocb;
265     if (ocb) {
266 #ifndef SYSLINK_PLATFORM_VAYU
267         GateHWSpinlock_LeaveLockForPID(ocb->pid);
268 #endif
269         free (ocb);
270     }
273 int init_syslink_trace_device(syslink_dev_t *dev)
275     resmgr_attr_t    resmgr_attr;
276     int              i;
277     syslink_attr_t * trace_attr;
278     char             trace_name[_POSIX_PATH_MAX];
279     int              status = 0;
280     unsigned int     da = 0, pa = 0;
281     unsigned int     len;
283     memset(&resmgr_attr, 0, sizeof resmgr_attr);
284     resmgr_attr.nparts_max = 10;
285     resmgr_attr.msg_max_size = 2048;
287     for (i = 0; i < syslink_num_cores; i++) {
288         iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs_trace[i],
289                          _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_trace[i]);
290         trace_attr = &dev->syslink.cattr_trace[i];
291         iofunc_attr_init(&trace_attr->attr,
292                          S_IFCHR | 0777, NULL, NULL);
293         trace_attr->attr.mount = &dev->syslink.mattr;
294         trace_attr->procid = i;
295         iofunc_time_update(&trace_attr->attr);
296         snprintf (dev->syslink.device_name, _POSIX_PATH_MAX,
297                   "/dev/ipc-trace%d", syslink_firmware[i].proc_id);
298         dev->syslink.iofuncs_trace[i].read = syslink_read;
299         snprintf (trace_name, _POSIX_PATH_MAX, "%d", 0);
300         pa = 0;
301         status = RscTable_getInfo(syslink_firmware[i].proc_id, TYPE_TRACE, 0, &da, &pa, &len);
302         if (status == 0) {
303             /* last 8 bytes are for writeIdx/readIdx */
304             proc_traces[i].len = len - (sizeof(uint32_t) * 2);
305             if (da && !pa) {
306                 /* need to translate da->pa */
307                 status = ProcMgr_translateAddr (procH[syslink_firmware[i].proc_id],
308                                                 (Ptr *) &pa,
309                                                 ProcMgr_AddrType_MasterPhys,
310                                                 (Ptr) da,
311                                                 ProcMgr_AddrType_SlaveVirt);
312             }
313             else {
314                 GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
315                                     status, "not performing ProcMgr_translate");
316             }
317             /* map length aligned to page size */
318             proc_traces[i].va =
319                     mmap_device_io (((len + 0x1000 - 1) / 0x1000) * 0x1000, pa);
320             proc_traces[i].widx = (uint32_t *)(proc_traces[i].va + \
321                                                proc_traces[i].len);
322             proc_traces[i].ridx = (uint32_t *)((uint32_t)proc_traces[i].widx + \
323                                                sizeof(uint32_t));
324             if (proc_traces[i].va == MAP_DEVICE_FAILED) {
325                 GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
326                                     status, "mmap_device_io failed");
327                 GT_1trace(curTrace, GT_4CLASS, "errno %d", errno);
328                 proc_traces[i].va = NULL;
329             }
330             proc_traces[i].firstRead = TRUE;
331         }
332         else {
333             GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
334                                 status, "RscTable_getInfo failed");
335             proc_traces[i].va = NULL;
336         }
337         if (-1 == (dev->syslink.resmgr_id_trace[i] =
338                        resmgr_attach(dev->dpp, &resmgr_attr,
339                                      dev->syslink.device_name, _FTYPE_ANY, 0,
340                                      &dev->syslink.cfuncs_trace[i],
341                                      &dev->syslink.iofuncs_trace[i],
342                                      &trace_attr->attr))) {
343             GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
344                                 status, "resmgr_attach failed");
345             return(-1);
346         }
347     }
349     return (status);
352 int deinit_syslink_trace_device(syslink_dev_t *dev)
354     int status = EOK;
355     int i = 0;
357     for (i = 0; i < syslink_num_cores; i++) {
358         status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_trace[i], 0);
359         if (status < 0) {
360             Osal_printf("syslink: resmgr_detach failed %d", errno);
361             status = errno;
362         }
363         if (proc_traces[i].va && proc_traces[i].va != MAP_DEVICE_FAILED) {
364             munmap((void *)proc_traces[i].va,
365                    ((proc_traces[i].len + 8 + 0x1000 - 1) / 0x1000) * 0x1000);
366         }
367         proc_traces[i].va = NULL;
368     }
370     return (status);
373 /* Initialize the syslink device */
374 int init_syslink_device(syslink_dev_t *dev)
376     iofunc_attr_t *  attr;
377     resmgr_attr_t    resmgr_attr;
378     int              status = 0;
380     pthread_mutex_init(&dev->lock, NULL);
382     memset(&resmgr_attr, 0, sizeof resmgr_attr);
383     resmgr_attr.nparts_max = 10;
384     resmgr_attr.msg_max_size = 2048;
386     memset(&dev->syslink.mattr, 0, sizeof(iofunc_mount_t));
387     dev->syslink.mattr.flags = ST_NOSUID | ST_NOEXEC;
388     dev->syslink.mattr.conf = IOFUNC_PC_CHOWN_RESTRICTED |
389                               IOFUNC_PC_NO_TRUNC |
390                               IOFUNC_PC_SYNC_IO;
391     dev->syslink.mattr.funcs = &dev->syslink.mfuncs;
393     memset(&dev->syslink.mfuncs, 0, sizeof(iofunc_funcs_t));
394     dev->syslink.mfuncs.nfuncs = _IOFUNC_NFUNCS;
396     iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs,
397                     _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs);
399     iofunc_attr_init(attr = &dev->syslink.cattr, S_IFCHR | 0777, NULL, NULL);
401     dev->syslink.mfuncs.ocb_calloc = syslink_ocb_calloc;
402     dev->syslink.mfuncs.ocb_free = syslink_ocb_free;
403     dev->syslink.iofuncs.devctl = syslink_devctl;
404     dev->syslink.iofuncs.unblock = syslink_unblock;
406     attr->mount = &dev->syslink.mattr;
407     iofunc_time_update(attr);
409     if (-1 == (dev->syslink.resmgr_id =
410         resmgr_attach(dev->dpp, &resmgr_attr,
411                       IPC_DEVICE_PATH, _FTYPE_ANY, 0,
412                       &dev->syslink.cfuncs,
413                       &dev->syslink.iofuncs, attr))) {
414         return(-1);
415     }
417     status = init_syslink_trace_device(dev);
418     if (status < 0) {
419         return status;
420     }
422     return(0);
425 /* De-initialize the syslink device */
426 int deinit_syslink_device(syslink_dev_t *dev)
428     int status = EOK;
430     status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id, 0);
431     if (status < 0) {
432         Osal_printf("syslink: resmgr_detach failed %d", errno);
433         status = errno;
434     }
436     status = deinit_syslink_trace_device(dev);
438     return(status);
442 /* Initialize the devices */
443 int init_devices(syslink_dev_t *dev)
445     if (init_syslink_device(dev) < 0) {
446         Osal_printf("syslink: syslink device init failed");
447         return(-1);
448     }
450     return(0);
454 /* De-initialize the devices */
455 int deinit_devices(syslink_dev_t *dev)
457     int status = EOK;
459     if ((status = deinit_syslink_device(dev)) < 0) {
460         fprintf( stderr, "syslink: syslink device de-init failed %d\n", status);
461         status = errno;
462     }
464     return(status);
467 static void ipc_recover(Ptr args)
469     syslink_dev_t * dev = (syslink_dev_t *)args;
471     deinit_ipc(dev, TRUE);
472     init_ipc(dev, syslink_firmware, TRUE);
473     deinit_syslink_trace_device(dev);
474     init_syslink_trace_device(dev);
477 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
478                       ProcMgr_State fromState, ProcMgr_State toState,
479                       ProcMgr_EventStatus status, Ptr args)
481     Int ret = 0;
482     String errString = NULL;
483     syslink_dev_t * dev = (syslink_dev_t *)args;
485     if (status == ProcMgr_EventStatus_Event) {
486         switch (toState) {
487             case ProcMgr_State_Mmu_Fault:
488                 errString = "MMU Fault";
489                 break;
490             case ProcMgr_State_Error:
491                 errString = "Exception";
492                 break;
493             case ProcMgr_State_Watchdog:
494                 errString = "Watchdog";
495                 break;
496             default:
497                 errString = "Unexpected State";
498                 ret = -1;
499                 break;
500         }
501         GT_2trace (curTrace, GT_4CLASS,
502                    "syslink_error_cb: Received Error Callback for %s : %s\n",
503                    MultiProc_getName(procId), errString);
504         /* Don't allow re-schedule of recovery until complete */
505         pthread_mutex_lock(&dev->lock);
506         if (ret != -1 && dev->recover == FALSE) {
507             /* Schedule recovery. */
508             dev->recover = TRUE;
509             /* Activate a thread to handle the recovery. */
510             GT_0trace (curTrace, GT_4CLASS,
511                        "syslink_error_cb: Scheduling recovery...");
512             OsalThread_activate(dev->ipc_recovery_work);
513         }
514         else {
515             GT_0trace (curTrace, GT_4CLASS,
516                        "syslink_error_cb: Recovery already scheduled.");
517         }
518         pthread_mutex_unlock(&dev->lock);
519     }
520     else if (status == ProcMgr_EventStatus_Canceled) {
521         GT_1trace (curTrace, GT_3CLASS,
522                    "SysLink Error Callback Cancelled for %s",
523                    MultiProc_getName(procId));
524     }
525     else {
526         GT_1trace (curTrace, GT_4CLASS,
527                    "SysLink Error Callback Unexpected Event for %s",
528                    MultiProc_getName(procId));
529     }
531     return ret;
534 /*
535  * Initialize the syslink ipc
536  *
537  * This function sets up the "kernel"-side IPC modules, and does any special
538  * initialization required for QNX and the platform being used.  This function
539  * also registers for error notifications and initializes the recovery thread.
540  */
541 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover)
543     int status = 0;
544     Ipc_Config iCfg;
545     OsalThread_Params threadParams;
546     ProcMgr_AttachParams attachParams;
547     UInt16 procId;
548     int i;
550     if (status >= 0) {
551         if (!recover) {
552             /* Set up the MemoryOS module */
553             status = MemoryOS_setup();
554             if (status < 0)
555                 goto memoryos_fail;
556         }
558         /* Setup IPC and platform-specific items */
559         status = Ipc_setup (&iCfg);
560         if (status < 0)
561             goto ipcsetup_fail;
563         /* NOTE: this is for handling the procmgr event notifications to userspace list */
564         if (!recover) {
565             /* Setup Fault recovery items. */
566             /* Create the thread object used for the interrupt handler. */
567             threadParams.priority     = OsalThread_Priority_Medium;
568             threadParams.priorityType = OsalThread_PriorityType_Generic;
569             threadParams.once         = FALSE;
570             dev->ipc_recovery_work = OsalThread_create ((OsalThread_CallbackFxn)
571                                                         ipc_recover,
572                                                         dev,
573                                                         &threadParams);
574             if (dev->ipc_recovery_work == NULL)
575                 goto osalthreadcreate_fail;
576         }
577         else {
578             pthread_mutex_lock(&dev->lock);
579             dev->recover = FALSE;
580             pthread_mutex_unlock(&dev->lock);
581         }
583         for (i = 0; i < syslink_num_cores; i++) {
584             procId = firmware[i].proc_id = MultiProc_getId(firmware[i].proc);
585             if (procId >= MultiProc_MAXPROCESSORS) {
586                 status = -1;
587                 fprintf(stderr, "Invalid processor name specified\n");
588                 break;
589             }
591             if (procH[procId]) {
592                 GT_setFailureReason (curTrace,
593                                      GT_4CLASS,
594                                      "init_ipc",
595                                      status,
596                                      "invalid proc!");
597                 break;
598             }
600             if (syslink_firmware[i].firmware) {
601                 rscHandle[procId] = RscTable_alloc(firmware[i].firmware, procId);
602                 if (rscHandle[procId] == NULL) {
603                     status = -1;
604                     break;
605                 }
606             }
608             status = ProcMgr_open(&procH[procId], procId);
609             if (status < 0 || procH[procId] == NULL)
610                 goto procmgropen_fail;
612             /* Load and start the remote processor. */
613             ProcMgr_getAttachParams (procH[procId], &attachParams);
614             status = ProcMgr_attach (procH[procId], &attachParams);
615             if (status < 0) {
616                 GT_setFailureReason (curTrace,
617                                      GT_4CLASS,
618                                      "init_ipc",
619                                      status,
620                                      "ProcMgr_attach failed!");
621                 goto procmgrattach_fail;
622             }
624             if (syslink_firmware[i].firmware) {
625                 status = ProcMgr_load (procH[procId],
626                                        (String)firmware[i].firmware, 0, NULL,
627                                         NULL, &procH_fileId[procId]);
628                 if (status < 0) {
629                     GT_setFailureReason (curTrace,
630                                          GT_4CLASS,
631                                          "init_ipc",
632                                          status,
633                                          "ProcMgr_load failed!");
634                     goto procmgrload_fail;
635                 }
636             }
638             status = Ipc_attach (procId);
639             if (status < 0) {
640                 GT_setFailureReason (curTrace,
641                                      GT_4CLASS,
642                                      "init_ipc",
643                                      status,
644                                      "Ipc_attach failed!");
645                 goto ipcattach_fail;
646             }
648             status = ProcMgr_start(procH[procId], NULL);
649             if (status < 0) {
650                 GT_setFailureReason (curTrace,
651                                      GT_4CLASS,
652                                      "init_ipc",
653                                      status,
654                                      "ProcMgr_start failed!");
655                 goto procmgrstart_fail;
656             }
658             status = ProcMgr_registerNotify(procH[procId], syslink_error_cb, (Ptr)dev,
659                                             -1, errStates);
660             if (status < 0)
661                 goto procmgrreg_fail;
663             continue;
665 procmgrreg_fail:
666             ProcMgr_stop(procH[procId]);
667 procmgrstart_fail:
668             Ipc_detach(procId);
669 ipcattach_fail:
670             if (syslink_firmware[i].firmware)
671                 ProcMgr_unload(procH[procId], procH_fileId[procId]);
672 procmgrload_fail:
673             ProcMgr_detach(procH[procId]);
674 procmgrattach_fail:
675             ProcMgr_close(&procH[procId]);
676             procH[procId] = NULL;
677 procmgropen_fail:
678             RscTable_free(&rscHandle[procId]);
679             break;
680         }
682         if (status < 0)
683             goto tiipcsetup_fail;
685         /* Set up rpmsg_mq */
686         status = ti_ipc_setup();
687         if (status < 0)
688             goto tiipcsetup_fail;
690         /* Set up rpmsg_rpc */
691         status = rpmsg_rpc_setup();
692         if (status < 0)
693             goto rpcsetup_fail;
695 #if defined(SYSLINK_PLATFORM_VAYU)
696         if (gatempEnabled) {
697             /* Set up NameServer for resource manager process */
698             status = NameServer_setup();
699             if (status < 0) {
700                 goto nameserversetup_fail;
701             }
703             /* Set up GateMP */
704             status = GateMP_setup();
705             if (status < 0) {
706                 goto gatempsetup_fail;
707             }
708         }
709 #endif
711         goto exit;
712     }
714 #if defined(SYSLINK_PLATFORM_VAYU)
715 gatempsetup_fail:
716     NameServer_destroy();
717 nameserversetup_fail:
718     rpmsg_rpc_destroy();
719 #endif
720 rpcsetup_fail:
721     ti_ipc_destroy(recover);
722 tiipcsetup_fail:
723     for (i-=1; i >= 0; i--) {
724         procId = firmware[i].proc_id;
725         if (procId >= MultiProc_MAXPROCESSORS) {
726             continue;
727         }
728         ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
729                                 (Ptr)dev, errStates);
730         ProcMgr_stop(procH[procId]);
731         if (procH_fileId[procId]) {
732             ProcMgr_unload(procH[procId], procH_fileId[procId]);
733             procH_fileId[procId] = 0;
734         }
735         ProcMgr_detach(procH[procId]);
736         ProcMgr_close(&procH[procId]);
737         procH[procId] = NULL;
738         RscTable_free(&rscHandle[procId]);
739         rscHandle[procId] = NULL;
740     }
741     OsalThread_delete(&dev->ipc_recovery_work);
742 osalthreadcreate_fail:
743     Ipc_destroy();
744 ipcsetup_fail:
745     MemoryOS_destroy();
746 memoryos_fail:
747 exit:
748     return status;
751 int deinit_ipc(syslink_dev_t * dev, bool recover)
753     int status = EOK;
754     uint32_t i = 0, id = 0;
756     // Stop the remote cores right away
757     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
758         if (procH[i]) {
759             GT_1trace(curTrace, GT_4CLASS, "stopping %s", MultiProc_getName(i));
760             ProcMgr_stop(procH[i]);
761         }
762     }
764 #if defined(SYSLINK_PLATFORM_VAYU)
765     if (gatempEnabled) {
766         GateMP_destroy();
768         NameServer_destroy();
769     }
770 #endif
772     rpmsg_rpc_destroy();
774     ti_ipc_destroy(recover);
776     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
777         if (procH[i]) {
778             ProcMgr_unregisterNotify (procH[i], syslink_error_cb, (Ptr)dev,
779                                       errStates);
780             Ipc_detach(i);
781             if (procH_fileId[i]) {
782                 ProcMgr_unload(procH[i], procH_fileId[i]);
783                 procH_fileId[i] = 0;
784             }
785             ProcMgr_detach(procH[i]);
786             ProcMgr_close(&procH[i]);
787             procH[i] = NULL;
788             RscTable_free(&rscHandle[i]);
789             rscHandle[i] = NULL;
790         }
791     }
793     if (!recover && dev->ipc_recovery_work != NULL) {
794         OsalThread_delete (&dev->ipc_recovery_work);
795         dev->ipc_recovery_work = NULL;
796     }
798     if (recover) {
799         static FILE *log;
800         /* Dump the trace information */
801         Osal_printf("syslink: printing remote core trace dump to"
802                     " /var/log/ducati-m3-traces.log");
803         log = fopen ("/var/log/ducati-m3-traces.log", "a+");
804         if (log) {
805             for (id = 0; id < syslink_num_cores; id++) {
806                 if (proc_traces[id].va) {
807                     /* print traces */
808                     /* wait a little bit for traces to finish dumping */
809                     sleep(1);
810                     fprintf(log, "****************************************\n");
811                     fprintf(log, "***         CORE%d TRACE DUMP         ***\n",
812                             id);
813                     fprintf(log, "****************************************\n");
814                     for (i = (*proc_traces[id].widx + 1);
815                          i < (proc_traces[id].len - 8);
816                          i++) {
817                         fprintf(log, "%c",
818                                 *(char *)((uint32_t)proc_traces[id].va + i));
819                     }
820                     for (i = 0; i < *proc_traces[id].widx; i++) {
821                         fprintf(log, "%c",
822                                 *(char *)((uint32_t)proc_traces[id].va + i));
823                     }
824                 }
825             }
826             fclose(log);
827         }
828         else {
829             GT_setFailureReason(curTrace, GT_4CLASS, "deinit_ipc", errno,
830                                 "error opening /var/log/ducati-m3-traces.log");
831         }
832     }
834     status = Ipc_destroy();
835     if (status < 0) {
836         printf("Ipc_destroy() failed 0x%x", status);
837     }
838     if (!recover) {
839         status = MemoryOS_destroy();
840         if (status < 0) {
841             printf("MemoryOS_destroy() failed 0x%x", status);
842         }
843     }
845     return status;
849 /** print usage */
850 static Void printUsage (Char * app)
852     printf("\n\nUsage:\n");
853 #if defined(SYSLINK_PLATFORM_OMAP5430)
854     printf("\n%s: [-HT] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
855         app);
856     printf("  <core_id#> should be set to a core name (e.g. IPU, DSP)\n");
857     printf("      followed by the path to the executable to load on that core.\n");
858     printf("Options:\n");
859     printf("  -H   enable/disable hibernation, 1: ON, 0: OFF, Default: 1)\n");
860     printf("  -T   specify the hibernation timeout in ms, Default: 5000 ms)\n");
861 #else
862     printf("\n%s: [-g] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
863         app);
864     printf("  <core_id#> should be set to a core name (e.g. DSP1, IPU2)\n");
865     printf("      followed by the path to the executable to load on that core.\n");
866     printf("Options:\n");
867     printf("  -g   enable GateMP support on host\n");
868 #endif
869     exit (EXIT_SUCCESS);
872 dispatch_t * syslink_dpp = NULL;
874 int main(int argc, char *argv[])
876     syslink_dev_t * dev = NULL;
877     thread_pool_attr_t tattr;
878     int status;
879     int error = 0;
880     sigset_t set;
881     int channelid = 0;
882     int c;
883     int hib_enable = 1;
884     uint32_t hib_timeout = PM_HIB_DEFAULT_TIME;
885     char *user_parm = NULL;
886     struct stat          sbuf;
887     int i = 0;
888     char * abs_path = NULL;
890     if (-1 != stat(IPC_DEVICE_PATH, &sbuf)) {
891         printf ("Syslink Already Running...\n");
892         return EXIT_FAILURE;
893     }
894     printf ("Starting syslink resource manager...\n");
896     /* Parse the input args */
897     while (1)
898     {
899         c = getopt (argc, argv, "H:T:U:gv:");
900         if (c == -1)
901             break;
903         switch (c)
904         {
905 #if defined(SYSLINK_PLATFORM_OMAP5430)
906         case 'H':
907             hib_enable = atoi(optarg);
908             if (hib_enable != 0 && hib_enable != 1) {
909                 hib_enable = -1;
910             }
911             break;
912         case 'T':
913             hib_timeout = atoi(optarg);
914             break;
915 #endif
916         case 'U':
917             user_parm = optarg;
918             break;
919         case 'v':
920             verbosity++;
921             break;
922 #if defined(SYSLINK_PLATFORM_VAYU)
923         case 'g':
924             printf("GateMP support enabled on host\n");
925             gatempEnabled = true;
926             break;
927 #endif
928         default:
929             fprintf (stderr, "Unrecognized argument\n");
930         }
931     }
933     /* Now parse the operands, which should be in the format:
934      * "<multiproc_name> <firmware_file> ..*/
935     for (; optind + 1 < argc; optind+=2) {
936         if (syslink_num_cores == MultiProc_MAXPROCESSORS) {
937             printUsage(argv[0]);
938             return (error);
939         }
940         syslink_firmware[syslink_num_cores].proc = argv [optind];
941         syslink_firmware[syslink_num_cores++].firmware = argv [optind+1];
942     }
945     /* Get the name of the binary from the input args */
946     if (!syslink_num_cores) {
947         fprintf(stderr, "At least one core_id and executable must be "\
948             "specified");
949         printUsage(argv[0]);
950         return (error);
951     }
953     /* Validate hib_enable args */
954     if (hib_enable == -1) {
955         fprintf (stderr, "invalid hibernation enable value\n");
956         printUsage(argv[0]);
957         return (error);
958     }
960     syslink_hib_enable = (Bool)hib_enable;
961     syslink_hib_timeout = hib_timeout;
963     /* Init logging for syslink */
964     if (Osal_initlogging(verbosity) != 0) {
965         return -1;
966     }
968     /* Obtain I/O privity */
969     error = ThreadCtl_r (_NTO_TCTL_IO, 0);
970     if (error == -1) {
971         Osal_printf("Unable to obtain I/O privity");
972         return (error);
973     }
975     /* Get the abs path for all firmware files */
976     for (i = 0; i < syslink_num_cores; i++) {
977         abs_path = calloc(1, PATH_MAX + 1);
978         if (abs_path == NULL) {
979             return -1;
980         }
981         if (NULL == realpath(syslink_firmware[i].firmware, abs_path)) {
982             fprintf (stderr, "invalid path to executable\n");
983             return -1;
984         }
985         syslink_firmware[i].firmware = abs_path;
986     }
988     /* allocate the device structure */
989     if (NULL == (dev = calloc(1, sizeof(syslink_dev_t)))) {
990         Osal_printf("syslink: calloc() failed");
991         return (-1);
992     }
994     /* create the channel */
995     if ((channelid = ChannelCreate_r (_NTO_CHF_UNBLOCK |
996                                     _NTO_CHF_DISCONNECT |
997                                     _NTO_CHF_COID_DISCONNECT |
998                                     _NTO_CHF_REPLY_LEN |
999                                     _NTO_CHF_SENDER_LEN)) < 0) {
1000         Osal_printf("Unable to create channel %d", channelid);
1001         return (channelid);
1002     }
1004     /* create the dispatch structure */
1005     if (NULL == (dev->dpp = syslink_dpp = dispatch_create_channel (channelid, 0))) {
1006         Osal_printf("syslink:  dispatch_create() failed");
1007         return(-1);
1008     }
1010     /*
1011      * Mask out all signals before creating a thread pool.
1012      * This prevents other threads in the thread pool
1013      * from intercepting signals such as SIGTERM.
1014      */
1015     sigfillset(&set);
1016     pthread_sigmask(SIG_BLOCK, &set, NULL);
1018     /* Initialize the thread pool */
1019     memset (&tattr, 0x00, sizeof (thread_pool_attr_t));
1020     tattr.handle = dev->dpp;
1021     tattr.context_alloc = dispatch_context_alloc;
1022     tattr.context_free = dispatch_context_free;
1023     tattr.block_func = dispatch_block;
1024     tattr.unblock_func = dispatch_unblock;
1025     tattr.handler_func = dispatch_handler;
1026     tattr.lo_water = 2;
1027     tattr.hi_water = 4;
1028     tattr.increment = 1;
1029     tattr.maximum = 10;
1031     /* Create the thread pool */
1032     if ((dev->tpool = thread_pool_create(&tattr, 0)) == NULL) {
1033         Osal_printf("syslink: thread pool create failed");
1034         return(-1);
1035     }
1037     /* init syslink */
1038     status = init_ipc(dev, syslink_firmware, FALSE);
1039     if (status < 0) {
1040         Osal_printf("syslink: IPC init failed");
1041         return(-1);
1042     }
1044     /* init the syslink device */
1045     status = init_devices(dev);
1046     if (status < 0) {
1047         Osal_printf("syslink: device init failed");
1048         return(-1);
1049     }
1051 #if (_NTO_VERSION >= 800)
1052     /* Relinquish privileges */
1053     status = procmgr_ability(  0,
1054                  DENY_ALL | PROCMGR_AID_SPAWN,
1055                  DENY_ALL | PROCMGR_AID_FORK,
1056                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PEER,
1057                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PHYS,
1058                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_INTERRUPT,
1059                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_PATHSPACE,
1060                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_RSRCDBMGR,
1061                  PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETUID,
1062                  (uint64_t)1, (uint64_t)~0,
1063                  PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETGID,
1064                  (uint64_t)1, (uint64_t)~0,
1065                  PROCMGR_ADN_ROOT | PROCMGR_AOP_DENY | PROCMGR_AOP_LOCK | PROCMGR_AID_EOL);
1067     if (status != EOK) {
1068         Osal_printf("procmgr_ability failed! errno=%d", status);
1069         return EXIT_FAILURE;
1070     }
1072     /* Reduce priority to either what defined from command line or at least nobody */
1073     if (user_parm != NULL) {
1074         if (set_ids_from_arg(user_parm) < 0) {
1075             Osal_printf("unable to set uid/gid - %s", strerror(errno));
1076             return EXIT_FAILURE;
1077         }
1078     } else {
1079         if (setuid(99) != 0) {
1080             Osal_printf("unable to set uid - %s", strerror(errno));
1081             return EXIT_FAILURE;
1082         }
1083     }
1084 #endif
1086     /* make this a daemon process */
1087     if (-1 == procmgr_daemon(EXIT_SUCCESS,
1088         PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL)) {
1089         Osal_printf("syslink:  procmgr_daemon() failed");
1090         return(-1);
1091     }
1093     /* start the thread pool */
1094     thread_pool_start(dev->tpool);
1096     /* Unmask signals to be caught */
1097     sigdelset (&set, SIGINT);
1098     sigdelset (&set, SIGTERM);
1099     pthread_sigmask (SIG_BLOCK, &set, NULL);
1101     /* Wait for one of these signals */
1102     sigemptyset (&set);
1103     sigaddset (&set, SIGINT);
1104     sigaddset (&set, SIGQUIT);
1105     sigaddset (&set, SIGTERM);
1107     Osal_printf("Syslink resource manager started");
1109     /* Wait for a signal */
1110     while (1)
1111     {
1112         switch (SignalWaitinfo (&set, NULL))
1113         {
1114             case SIGTERM:
1115             case SIGQUIT:
1116             case SIGINT:
1117                 error = EOK;
1118                 goto done;
1120             default:
1121                 break;
1122         }
1123     }
1125     error = EOK;
1127 done:
1128     GT_0trace(curTrace, GT_4CLASS, "Syslink resource manager exiting \n");
1130     error = thread_pool_destroy(dev->tpool);
1131     if (error < 0)
1132         Osal_printf("syslink: thread_pool_destroy returned an error");
1133     deinit_ipc(dev, FALSE);
1134     deinit_devices(dev);
1135     free(dev);
1136     return (EOK);