182d1873ec37000fe49ac07875a47329852b52bd
[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>
60 #if defined(SYSLINK_PLATFORM_OMAP4430)
61 #include <login.h>
62 #endif
64 #include <IpcKnl.h>
66 /* OSAL & Utils headers */
67 #include <ti/syslink/utils/List.h>
68 #include <ti/syslink/utils/MemoryOS.h>
69 #include <ti/ipc/MultiProc.h>
70 #include <ti/ipc/NameServer.h>
71 #include <_MultiProc.h>
72 #include <_NameServer.h>
73 #include <_GateMP_daemon.h>
74 #include <OsalSemaphore.h>
75 #include <ti/syslink/utils/OsalPrint.h>
76 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
77 #include <_ipu_pm.h>
78 #endif
79 #include <ti/syslink/utils/Trace.h>
80 #include <ti/syslink/ProcMgr.h>
81 #include <Bitops.h>
82 #include <RscTable.h>
84 #include <ti-ipc.h>
86 #define DENY_ALL                    \
87             PROCMGR_ADN_ROOT        \
88             | PROCMGR_ADN_NONROOT   \
89             | PROCMGR_AOP_DENY      \
90             | PROCMGR_AOP_LOCK
93 static int verbosity = 2;
96 #if defined(SYSLINK_PLATFORM_VAYU)
97 static bool gatempEnabled = false;
98 #endif
100 // Syslink hibernation global variables
101 Bool syslink_hib_enable = TRUE;
102 #if !defined(SYSLINK_PLATFORM_OMAP4430) && !defined(SYSLINK_PLATFORM_OMAP5430)
103 #define PM_HIB_DEFAULT_TIME 5000
104 #endif
105 uint32_t syslink_hib_timeout = PM_HIB_DEFAULT_TIME;
106 Bool syslink_hib_hibernating = FALSE;
107 pthread_mutex_t syslink_hib_mutex = PTHREAD_MUTEX_INITIALIZER;
108 pthread_cond_t syslink_hib_cond = PTHREAD_COND_INITIALIZER;
110 extern Int rpmsg_rpc_setup (Void);
111 extern Void rpmsg_rpc_destroy (Void);
112 extern Void GateHWSpinlock_LeaveLockForPID(int pid);
114 typedef struct syslink_firmware_info_t {
115     uint16_t proc_id;
116     char * proc;
117     char * firmware;
118 } syslink_firmware_info;
119 static syslink_firmware_info syslink_firmware[MultiProc_MAXPROCESSORS];
120 static unsigned int syslink_num_cores = 0;
122 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover);
123 int deinit_ipc(syslink_dev_t * dev, bool recover);
125 static RscTable_Handle rscHandle[MultiProc_MAXPROCESSORS];
127 static ProcMgr_Handle procH[MultiProc_MAXPROCESSORS];
128 static unsigned int procH_fileId[MultiProc_MAXPROCESSORS];
129 static ProcMgr_State errStates[] = {ProcMgr_State_Mmu_Fault,
130                                     ProcMgr_State_Error,
131                                     ProcMgr_State_Watchdog,
132                                     ProcMgr_State_EndValue};
134 typedef struct syslink_trace_info_t {
135     uintptr_t   va;
136     uint32_t    len;
137     uint32_t *  widx;
138     uint32_t *  ridx;
139     Bool        firstRead;
140 } syslink_trace_info;
142 static syslink_trace_info proc_traces[MultiProc_MAXPROCESSORS];
144 int syslink_read(resmgr_context_t *ctp, io_read_t *msg, syslink_ocb_t *ocb)
146     int         nbytes;
147     int         nparts;
148     int         status;
149     int         nleft;
150     uint32_t    len;
151     uint16_t    procid = ocb->ocb.attr->procid;
153     if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK)
154         return (status);
156     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE)
157         return (ENOSYS);
159     /* check to see where the trace buffer is */
160     if (proc_traces[procid].va == NULL) {
161         return (ENOSYS);
162     }
163     if (ocb->ocb.offset == 0) {
164         ocb->widx = *(proc_traces[procid].widx);
165         ocb->ridx = *(proc_traces[procid].ridx);
166         *(proc_traces[procid].ridx) = ocb->widx;
167     }
169     /* Check for wrap-around */
170     if (ocb->widx < ocb->ridx)
171         len = proc_traces[procid].len - ocb->ridx + ocb->widx;
172     else
173         len = ocb->widx - ocb->ridx;
175     /* Determine the amount left to print */
176     if (ocb->widx >= ocb->ridx)
177         nleft = len - ocb->ocb.offset;
178     else if (ocb->ocb.offset < proc_traces[procid].len - ocb->ridx)
179         nleft = proc_traces[procid].len - ocb->ridx - ocb->ocb.offset;
180     else
181         nleft = proc_traces[procid].len - ocb->ridx + ocb->widx - ocb->ocb.offset;
183     nbytes = min (msg->i.nbytes, nleft);
185     /* Make sure the user has supplied a big enough buffer */
186     if (nbytes > 0) {
187         /* set up the return data IOV */
188         if (ocb->widx < ocb->ridx && ocb->ocb.offset >= proc_traces[procid].len - ocb->ridx)
189             SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ocb.offset - (proc_traces[procid].len - ocb->ridx), nbytes);
190         else
191             SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ridx + ocb->ocb.offset, nbytes);
193         /* set up the number of bytes (returned by client's read()) */
194         _IO_SET_READ_NBYTES (ctp, nbytes);
196         ocb->ocb.offset += nbytes;
198         nparts = 1;
199     }
200     else {
201         _IO_SET_READ_NBYTES (ctp, 0);
203         /* reset offset */
204         ocb->ocb.offset = 0;
206         nparts = 0;
207     }
209     /* mark the access time as invalid (we just accessed it) */
211     if (msg->i.nbytes > 0)
212         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
214     return (_RESMGR_NPARTS (nparts));
217 extern OsalSemaphore_Handle mqcopy_test_sem;
219 int syslink_unblock(resmgr_context_t *ctp, io_pulse_t *msg, syslink_ocb_t *ocb)
221     int status = _RESMGR_NOREPLY;
222     struct _msg_info info;
224     /*
225      * Try to run the default unblock for this message.
226      */
227     if ((status = iofunc_unblock_default(ctp,msg,&(ocb->ocb))) != _RESMGR_DEFAULT) {
228         return status;
229     }
231     /*
232      * Check if rcvid is still valid and still has an unblock
233      * request pending.
234      */
235     if (MsgInfo(ctp->rcvid, &info) == -1 ||
236         !(info.flags & _NTO_MI_UNBLOCK_REQ)) {
237         return _RESMGR_NOREPLY;
238     }
240     if (mqcopy_test_sem)
241         OsalSemaphore_post(mqcopy_test_sem);
243     return _RESMGR_NOREPLY;
246 IOFUNC_OCB_T *
247 syslink_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
249     syslink_ocb_t *ocb = NULL;
251     /* Allocate the OCB */
252     ocb = (syslink_ocb_t *) calloc (1, sizeof (syslink_ocb_t));
253     if (ocb == NULL){
254         errno = ENOMEM;
255         return (NULL);
256     }
258     ocb->pid = ctp->info.pid;
260     return (IOFUNC_OCB_T *)(ocb);
263 void
264 syslink_ocb_free (IOFUNC_OCB_T * i_ocb)
266     syslink_ocb_t * ocb = (syslink_ocb_t *)i_ocb;
268     if (ocb) {
269 #ifndef SYSLINK_PLATFORM_VAYU
270         GateHWSpinlock_LeaveLockForPID(ocb->pid);
271 #endif
272         free (ocb);
273     }
276 int init_syslink_trace_device(syslink_dev_t *dev)
278     resmgr_attr_t    resmgr_attr;
279     int              i;
280     syslink_attr_t * trace_attr;
281     char             trace_name[_POSIX_PATH_MAX];
282     int              status = 0;
283     unsigned int     da = 0, pa = 0;
284     unsigned int     len;
286     memset(&resmgr_attr, 0, sizeof resmgr_attr);
287     resmgr_attr.nparts_max = 10;
288     resmgr_attr.msg_max_size = 2048;
290     for (i = 0; i < syslink_num_cores; i++) {
291         iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs_trace[i],
292                          _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_trace[i]);
293         trace_attr = &dev->syslink.cattr_trace[i];
294         iofunc_attr_init(&trace_attr->attr,
295                          S_IFCHR | 0777, NULL, NULL);
296         trace_attr->attr.mount = &dev->syslink.mattr;
297         trace_attr->procid = i;
298         iofunc_time_update(&trace_attr->attr);
299         snprintf (dev->syslink.device_name, _POSIX_PATH_MAX,
300                   "/dev/ipc-trace%d", syslink_firmware[i].proc_id);
301         dev->syslink.iofuncs_trace[i].read = syslink_read;
302         snprintf (trace_name, _POSIX_PATH_MAX, "%d", 0);
303         pa = 0;
304         status = RscTable_getInfo(syslink_firmware[i].proc_id, TYPE_TRACE, 0, &da, &pa, &len);
305         if (status == 0) {
306             /* last 8 bytes are for writeIdx/readIdx */
307             proc_traces[i].len = len - (sizeof(uint32_t) * 2);
308             if (da && !pa) {
309                 /* need to translate da->pa */
310                 status = ProcMgr_translateAddr (procH[syslink_firmware[i].proc_id],
311                                                 (Ptr *) &pa,
312                                                 ProcMgr_AddrType_MasterPhys,
313                                                 (Ptr) da,
314                                                 ProcMgr_AddrType_SlaveVirt);
315             }
316             else {
317                 GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
318                                     status, "not performing ProcMgr_translate");
319             }
320             /* map length aligned to page size */
321             proc_traces[i].va =
322                     mmap_device_io (((len + 0x1000 - 1) / 0x1000) * 0x1000, pa);
323             proc_traces[i].widx = (uint32_t *)(proc_traces[i].va + \
324                                                proc_traces[i].len);
325             proc_traces[i].ridx = (uint32_t *)((uint32_t)proc_traces[i].widx + \
326                                                sizeof(uint32_t));
327             if (proc_traces[i].va == MAP_DEVICE_FAILED) {
328                 GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
329                                     status, "mmap_device_io failed");
330                 GT_1trace(curTrace, GT_4CLASS, "errno %d", errno);
331                 proc_traces[i].va = NULL;
332             }
333             proc_traces[i].firstRead = TRUE;
334         }
335         else {
336             GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
337                                 status, "RscTable_getInfo failed");
338             proc_traces[i].va = NULL;
339         }
340         if (-1 == (dev->syslink.resmgr_id_trace[i] =
341                        resmgr_attach(dev->dpp, &resmgr_attr,
342                                      dev->syslink.device_name, _FTYPE_ANY, 0,
343                                      &dev->syslink.cfuncs_trace[i],
344                                      &dev->syslink.iofuncs_trace[i],
345                                      &trace_attr->attr))) {
346             GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
347                                 status, "resmgr_attach failed");
348             return(-1);
349         }
350     }
352     return (status);
355 int deinit_syslink_trace_device(syslink_dev_t *dev)
357     int status = EOK;
358     int i = 0;
360     for (i = 0; i < syslink_num_cores; i++) {
361         status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_trace[i], 0);
362         if (status < 0) {
363             Osal_printf("syslink: resmgr_detach failed %d", errno);
364             status = errno;
365         }
366         if (proc_traces[i].va && proc_traces[i].va != MAP_DEVICE_FAILED) {
367             munmap((void *)proc_traces[i].va,
368                    ((proc_traces[i].len + 8 + 0x1000 - 1) / 0x1000) * 0x1000);
369         }
370         proc_traces[i].va = NULL;
371     }
373     return (status);
376 /* Initialize the syslink device */
377 int init_syslink_device(syslink_dev_t *dev)
379     iofunc_attr_t *  attr;
380     resmgr_attr_t    resmgr_attr;
381     int              status = 0;
383     pthread_mutex_init(&dev->lock, NULL);
385     memset(&resmgr_attr, 0, sizeof resmgr_attr);
386     resmgr_attr.nparts_max = 10;
387     resmgr_attr.msg_max_size = 2048;
389     memset(&dev->syslink.mattr, 0, sizeof(iofunc_mount_t));
390     dev->syslink.mattr.flags = ST_NOSUID | ST_NOEXEC;
391     dev->syslink.mattr.conf = IOFUNC_PC_CHOWN_RESTRICTED |
392                               IOFUNC_PC_NO_TRUNC |
393                               IOFUNC_PC_SYNC_IO;
394     dev->syslink.mattr.funcs = &dev->syslink.mfuncs;
396     memset(&dev->syslink.mfuncs, 0, sizeof(iofunc_funcs_t));
397     dev->syslink.mfuncs.nfuncs = _IOFUNC_NFUNCS;
399     iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs,
400                     _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs);
402     iofunc_attr_init(attr = &dev->syslink.cattr, S_IFCHR | 0777, NULL, NULL);
404     dev->syslink.mfuncs.ocb_calloc = syslink_ocb_calloc;
405     dev->syslink.mfuncs.ocb_free = syslink_ocb_free;
406     dev->syslink.iofuncs.devctl = syslink_devctl;
407     dev->syslink.iofuncs.unblock = syslink_unblock;
409     attr->mount = &dev->syslink.mattr;
410     iofunc_time_update(attr);
412     if (-1 == (dev->syslink.resmgr_id =
413         resmgr_attach(dev->dpp, &resmgr_attr,
414                       IPC_DEVICE_PATH, _FTYPE_ANY, 0,
415                       &dev->syslink.cfuncs,
416                       &dev->syslink.iofuncs, attr))) {
417         return(-1);
418     }
420     status = init_syslink_trace_device(dev);
421     if (status < 0) {
422         return status;
423     }
425     return(0);
428 /* De-initialize the syslink device */
429 int deinit_syslink_device(syslink_dev_t *dev)
431     int status = EOK;
433     status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id, 0);
434     if (status < 0) {
435         Osal_printf("syslink: resmgr_detach failed %d", errno);
436         status = errno;
437     }
439     status = deinit_syslink_trace_device(dev);
441     return(status);
445 /* Initialize the devices */
446 int init_devices(syslink_dev_t *dev)
448     if (init_syslink_device(dev) < 0) {
449         Osal_printf("syslink: syslink device init failed");
450         return(-1);
451     }
453     return(0);
457 /* De-initialize the devices */
458 int deinit_devices(syslink_dev_t *dev)
460     int status = EOK;
462     if ((status = deinit_syslink_device(dev)) < 0) {
463         fprintf( stderr, "syslink: syslink device de-init failed %d\n", status);
464         status = errno;
465     }
467     return(status);
470 static void ipc_recover(Ptr args)
472     syslink_dev_t * dev = (syslink_dev_t *)args;
474     deinit_ipc(dev, TRUE);
475     init_ipc(dev, syslink_firmware, TRUE);
476     deinit_syslink_trace_device(dev);
477     init_syslink_trace_device(dev);
480 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
481                       ProcMgr_State fromState, ProcMgr_State toState,
482                       ProcMgr_EventStatus status, Ptr args)
484     Int ret = 0;
485     String errString = NULL;
486     syslink_dev_t * dev = (syslink_dev_t *)args;
488     if (status == ProcMgr_EventStatus_Event) {
489         switch (toState) {
490             case ProcMgr_State_Mmu_Fault:
491                 errString = "MMU Fault";
492                 break;
493             case ProcMgr_State_Error:
494                 errString = "Exception";
495                 break;
496             case ProcMgr_State_Watchdog:
497                 errString = "Watchdog";
498                 break;
499             default:
500                 errString = "Unexpected State";
501                 ret = -1;
502                 break;
503         }
504         GT_2trace (curTrace, GT_4CLASS,
505                    "syslink_error_cb: Received Error Callback for %s : %s\n",
506                    MultiProc_getName(procId), errString);
507         /* Don't allow re-schedule of recovery until complete */
508         pthread_mutex_lock(&dev->lock);
509         if (ret != -1 && dev->recover == FALSE) {
510             /* Schedule recovery. */
511             dev->recover = TRUE;
512             /* Activate a thread to handle the recovery. */
513             GT_0trace (curTrace, GT_4CLASS,
514                        "syslink_error_cb: Scheduling recovery...");
515             OsalThread_activate(dev->ipc_recovery_work);
516         }
517         else {
518             GT_0trace (curTrace, GT_4CLASS,
519                        "syslink_error_cb: Recovery already scheduled.");
520         }
521         pthread_mutex_unlock(&dev->lock);
522     }
523     else if (status == ProcMgr_EventStatus_Canceled) {
524         GT_1trace (curTrace, GT_3CLASS,
525                    "SysLink Error Callback Cancelled for %s",
526                    MultiProc_getName(procId));
527     }
528     else {
529         GT_1trace (curTrace, GT_4CLASS,
530                    "SysLink Error Callback Unexpected Event for %s",
531                    MultiProc_getName(procId));
532     }
534     return ret;
537 #if defined(SYSLINK_PLATFORM_OMAP4430)
538 #define SYSLINK_CARVEOUT
539 #ifdef SYSLINK_CARVEOUT
540 #define IPU_MEM_SIZE  49 * 1024 * 1024
541 #define IPU_MEM_PHYS  0x97F00000
542 #else
543 #define IPU_MEM_SIZE  104 * 1024 * 1024
544 #define IPU_MEM_ALIGN 0x1000000
545 #endif
546 #endif
549 /*
550  * Initialize the syslink ipc
551  *
552  * This function sets up the "kernel"-side IPC modules, and does any special
553  * initialization required for QNX and the platform being used.  This function
554  * also registers for error notifications and initializes the recovery thread.
555  */
556 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover)
558     int status = 0;
559 #if defined(SYSLINK_PLATFORM_OMAP4430)
560     int32_t ret = 0;
561     uint32_t len = 0;
562 #ifndef SYSLINK_CARVEOUT
563     int64_t pa = 0;
564     void * da;
565 #endif
566     int64_t paddr = 0;
567 #endif
568     Ipc_Config iCfg;
569     OsalThread_Params threadParams;
570     ProcMgr_AttachParams attachParams;
571     UInt16 procId;
572     int i;
574 #if defined(SYSLINK_PLATFORM_OMAP4430)
575     /* Map a contiguous memory section for ipu - currently hard-coded */
576     if (!recover) {
577 #ifdef SYSLINK_CARVEOUT
578         dev->da_virt = mmap64(NULL, IPU_MEM_SIZE,
579                               PROT_NOCACHE | PROT_READ | PROT_WRITE,
580                               MAP_PHYS,
581                               NOFD,
582                               IPU_MEM_PHYS);
583 #else
584         dev->da_virt = mmap64(NULL, IPU_MEM_SIZE + IPU_MEM_ALIGN,
585                               PROT_NOCACHE | PROT_READ | PROT_WRITE,
586                               MAP_ANON | MAP_PHYS | MAP_SHARED,
587                               NOFD,
588                               0);
590 #endif
592         if (dev->da_virt == MAP_FAILED) {
593             status = ENOMEM;
594             goto exit;
595         }
596     }
598     if (status >= 0) {
599 #ifdef SYSLINK_CARVEOUT
600         /* Make sure the memory is contiguous */
601         ret = mem_offset64(dev->da_virt, NOFD, IPU_MEM_SIZE, &paddr, &len);
602         if (ret)
603             status = ret;
604         else if (len != IPU_MEM_SIZE)
605             status = ENOMEM;
606 #else
607         /* Make sure the memory is contiguous */
608         ret = mem_offset64(dev->da_virt, NOFD, IPU_MEM_SIZE + IPU_MEM_ALIGN,
609                            &paddr, &len);
610         if (ret)
611             status = ret;
612         else if (len != IPU_MEM_SIZE + IPU_MEM_ALIGN)
613             status = ENOMEM;
614         else {
615             pa = (paddr + IPU_MEM_ALIGN - 1) / IPU_MEM_ALIGN * IPU_MEM_ALIGN;
616             if ((pa - paddr) < 0x900000)
617                 pa += 0x900000;
618             else
619                 pa -= 0x700000;
620             da = dev->da_virt + (pa - paddr);
621         }
622 #endif
623         if (status != 0)
624             goto memoryos_fail;
625     }
626 #endif
628     if (status >= 0) {
629         if (!recover) {
630             /* Set up the MemoryOS module */
631             status = MemoryOS_setup();
632             if (status < 0)
633                 goto memoryos_fail;
634         }
636         /* Setup IPC and platform-specific items */
637 #if defined(SYSLINK_PLATFORM_OMAP4430)
638 #ifdef SYSLINK_CARVEOUT
639         iCfg.vAddr = (uint32_t)dev->da_virt;
640         iCfg.pAddr = (uint32_t)paddr;
641 #else
642         iCfg.vAddr = (uint32_t)da;
643         iCfg.pAddr = (uint32_t)pa;
644 #endif
645 #endif
646         status = Ipc_setup (&iCfg);
647         if (status < 0)
648             goto ipcsetup_fail;
650         /* NOTE: this is for handling the procmgr event notifications to userspace list */
651         if (!recover) {
652             /* Setup Fault recovery items. */
653             /* Create the thread object used for the interrupt handler. */
654             threadParams.priority     = OsalThread_Priority_Medium;
655             threadParams.priorityType = OsalThread_PriorityType_Generic;
656             threadParams.once         = FALSE;
657             dev->ipc_recovery_work = OsalThread_create ((OsalThread_CallbackFxn)
658                                                         ipc_recover,
659                                                         dev,
660                                                         &threadParams);
661             if (dev->ipc_recovery_work == NULL)
662                 goto osalthreadcreate_fail;
663         }
664         else {
665             pthread_mutex_lock(&dev->lock);
666             dev->recover = FALSE;
667             pthread_mutex_unlock(&dev->lock);
668         }
670         for (i = 0; i < syslink_num_cores; i++) {
671             procId = firmware[i].proc_id = MultiProc_getId(firmware[i].proc);
672             if (procId >= MultiProc_MAXPROCESSORS) {
673                 status = -1;
674                 fprintf(stderr, "Invalid processor name specified\n");
675                 break;
676             }
678             if (procH[procId]) {
679                 GT_setFailureReason (curTrace,
680                                      GT_4CLASS,
681                                      "init_ipc",
682                                      status,
683                                      "invalid proc!");
684                 break;
685             }
687             if (syslink_firmware[i].firmware) {
688                 rscHandle[procId] = RscTable_alloc(firmware[i].firmware, procId);
689                 if (rscHandle[procId] == NULL) {
690                     status = -1;
691                     break;
692                 }
693             }
695             status = ProcMgr_open(&procH[procId], procId);
696             if (status < 0 || procH[procId] == NULL)
697                 goto procmgropen_fail;
699             /* Load and start the remote processor. */
700             ProcMgr_getAttachParams (procH[procId], &attachParams);
701             status = ProcMgr_attach (procH[procId], &attachParams);
702             if (status < 0) {
703                 GT_setFailureReason (curTrace,
704                                      GT_4CLASS,
705                                      "init_ipc",
706                                      status,
707                                      "ProcMgr_attach failed!");
708                 goto procmgrattach_fail;
709             }
711             if (syslink_firmware[i].firmware) {
712                 status = ProcMgr_load (procH[procId],
713                                        (String)firmware[i].firmware, 0, NULL,
714                                         NULL, &procH_fileId[procId]);
715                 if (status < 0) {
716                     GT_setFailureReason (curTrace,
717                                          GT_4CLASS,
718                                          "init_ipc",
719                                          status,
720                                          "ProcMgr_load failed!");
721                     goto procmgrload_fail;
722                 }
723             }
725             status = Ipc_attach (procId);
726             if (status < 0) {
727                 GT_setFailureReason (curTrace,
728                                      GT_4CLASS,
729                                      "init_ipc",
730                                      status,
731                                      "Ipc_attach failed!");
732                 goto ipcattach_fail;
733             }
735             status = ProcMgr_start(procH[procId], NULL);
736             if (status < 0) {
737                 GT_setFailureReason (curTrace,
738                                      GT_4CLASS,
739                                      "init_ipc",
740                                      status,
741                                      "ProcMgr_start failed!");
742                 goto procmgrstart_fail;
743             }
745             status = ProcMgr_registerNotify(procH[procId], syslink_error_cb, (Ptr)dev,
746                                             -1, errStates);
747             if (status < 0)
748                 goto procmgrreg_fail;
750             continue;
752 procmgrreg_fail:
753             ProcMgr_stop(procH[procId]);
754 procmgrstart_fail:
755             Ipc_detach(procId);
756 ipcattach_fail:
757             if (syslink_firmware[i].firmware)
758                 ProcMgr_unload(procH[procId], procH_fileId[procId]);
759 procmgrload_fail:
760             ProcMgr_detach(procH[procId]);
761 procmgrattach_fail:
762             ProcMgr_close(&procH[procId]);
763             procH[procId] = NULL;
764 procmgropen_fail:
765             RscTable_free(&rscHandle[procId]);
766             break;
767         }
769         if (status < 0)
770             goto tiipcsetup_fail;
772         /* Set up rpmsg_mq */
773         status = ti_ipc_setup();
774         if (status < 0)
775             goto tiipcsetup_fail;
777         /* Set up rpmsg_rpc */
778         status = rpmsg_rpc_setup();
779         if (status < 0)
780             goto rpcsetup_fail;
782 #if defined(SYSLINK_PLATFORM_VAYU)
783         if (gatempEnabled) {
784             /* Set up NameServer for resource manager process */
785             status = NameServer_setup();
786             if (status < 0) {
787                 goto nameserversetup_fail;
788             }
790             /* Set up GateMP */
791             status = GateMP_setup();
792             if (status < 0) {
793                 goto gatempsetup_fail;
794             }
795         }
796 #endif
798         goto exit;
799     }
801 #if defined(SYSLINK_PLATFORM_VAYU)
802 gatempsetup_fail:
803     NameServer_destroy();
804 nameserversetup_fail:
805     rpmsg_rpc_destroy();
806 #endif
807 rpcsetup_fail:
808     ti_ipc_destroy(recover);
809 tiipcsetup_fail:
810     for (i-=1; i >= 0; i--) {
811         procId = firmware[i].proc_id;
812         if (procId >= MultiProc_MAXPROCESSORS) {
813             continue;
814         }
815         ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
816                                 (Ptr)dev, errStates);
817         ProcMgr_stop(procH[procId]);
818         if (procH_fileId[procId]) {
819             ProcMgr_unload(procH[procId], procH_fileId[procId]);
820             procH_fileId[procId] = 0;
821         }
822         ProcMgr_detach(procH[procId]);
823         ProcMgr_close(&procH[procId]);
824         procH[procId] = NULL;
825         RscTable_free(&rscHandle[procId]);
826         rscHandle[procId] = NULL;
827     }
828     OsalThread_delete(&dev->ipc_recovery_work);
829 osalthreadcreate_fail:
830     Ipc_destroy();
831 ipcsetup_fail:
832     MemoryOS_destroy();
833 memoryos_fail:
834 #if defined(SYSLINK_PLATFORM_OMAP4430)
835     if (dev->da_virt != MAP_FAILED)
836 #ifdef SYSLINK_CARVEOUT
837         munmap(dev->da_virt, IPU_MEM_SIZE);
838 #else
839         munmap(dev->da_virt, IPU_MEM_SIZE + IPU_MEM_ALIGN);
840 #endif
841 #endif
842 exit:
843     return status;
846 int deinit_ipc(syslink_dev_t * dev, bool recover)
848     int status = EOK;
849     uint32_t i = 0, id = 0;
851     // Stop the remote cores right away
852     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
853         if (procH[i]) {
854             GT_1trace(curTrace, GT_4CLASS, "stopping %s", MultiProc_getName(i));
855             ProcMgr_stop(procH[i]);
856         }
857     }
859 #if defined(SYSLINK_PLATFORM_VAYU)
860     if (gatempEnabled) {
861         GateMP_destroy();
863         NameServer_destroy();
864     }
865 #endif
867     rpmsg_rpc_destroy();
869     ti_ipc_destroy(recover);
871     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
872         if (procH[i]) {
873             ProcMgr_unregisterNotify (procH[i], syslink_error_cb, (Ptr)dev,
874                                       errStates);
875             Ipc_detach(i);
876             if (procH_fileId[i]) {
877                 ProcMgr_unload(procH[i], procH_fileId[i]);
878                 procH_fileId[i] = 0;
879             }
880             ProcMgr_detach(procH[i]);
881             ProcMgr_close(&procH[i]);
882             procH[i] = NULL;
883             RscTable_free(&rscHandle[i]);
884             rscHandle[i] = NULL;
885         }
886     }
888     if (!recover && dev->ipc_recovery_work != NULL) {
889         OsalThread_delete (&dev->ipc_recovery_work);
890         dev->ipc_recovery_work = NULL;
891     }
893     if (recover) {
894         static FILE *log;
895         /* Dump the trace information */
896         Osal_printf("syslink: printing remote core trace dump to"
897                     " /var/log/ducati-m3-traces.log");
898         log = fopen ("/var/log/ducati-m3-traces.log", "a+");
899         if (log) {
900             for (id = 0; id < syslink_num_cores; id++) {
901                 if (proc_traces[id].va) {
902                     /* print traces */
903                     /* wait a little bit for traces to finish dumping */
904                     sleep(1);
905                     fprintf(log, "****************************************\n");
906                     fprintf(log, "***         CORE%d TRACE DUMP         ***\n",
907                             id);
908                     fprintf(log, "****************************************\n");
909                     for (i = (*proc_traces[id].widx + 1);
910                          i < (proc_traces[id].len - 8);
911                          i++) {
912                         fprintf(log, "%c",
913                                 *(char *)((uint32_t)proc_traces[id].va + i));
914                     }
915                     for (i = 0; i < *proc_traces[id].widx; i++) {
916                         fprintf(log, "%c",
917                                 *(char *)((uint32_t)proc_traces[id].va + i));
918                     }
919                 }
920             }
921             fclose(log);
922         }
923         else {
924             GT_setFailureReason(curTrace, GT_4CLASS, "deinit_ipc", errno,
925                                 "error opening /var/log/ducati-m3-traces.log");
926         }
927     }
929     status = Ipc_destroy();
930     if (status < 0) {
931         printf("Ipc_destroy() failed 0x%x", status);
932     }
933     if (!recover) {
934         status = MemoryOS_destroy();
935         if (status < 0) {
936             printf("MemoryOS_destroy() failed 0x%x", status);
937         }
938 #if defined(SYSLINK_PLATFORM_OMAP4430)
939         if (dev->da_virt != MAP_FAILED) {
940 #ifdef SYSLINK_CARVEOUT
941             status = munmap(dev->da_virt, IPU_MEM_SIZE);
942 #else
943             status = munmap(dev->da_virt, IPU_MEM_SIZE + IPU_MEM_ALIGN);
944 #endif
945             if (status < 0) {
946                printf("munmap failed %d", errno);
947             }
948         }
949 #endif
950     }
952     return status;
956 /** print usage */
957 static Void printUsage (Char * app)
959     printf("\n\nUsage:\n");
960 #if defined(SYSLINK_PLATFORM_OMAP5430)
961     printf("\n%s: [-HT] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
962         app);
963     printf("  <core_id#> should be set to a core name (e.g. IPU, DSP)\n");
964     printf("      followed by the path to the executable to load on that core.\n");
965     printf("Options:\n");
966     printf("  -H   enable/disable hibernation, 1: ON, 0: OFF, Default: 1)\n");
967     printf("  -T   specify the hibernation timeout in ms, Default: 5000 ms)\n");
968 #else
969     printf("\n%s: [-g] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
970         app);
971     printf("  <core_id#> should be set to a core name (e.g. DSP1, IPU2)\n");
972     printf("      followed by the path to the executable to load on that core.\n");
973     printf("Options:\n");
974     printf("  -g   enable GateMP support on host\n");
975 #endif
976     exit (EXIT_SUCCESS);
979 dispatch_t * syslink_dpp = NULL;
981 int main(int argc, char *argv[])
983     syslink_dev_t * dev = NULL;
984     thread_pool_attr_t tattr;
985     int status;
986     int error = 0;
987     sigset_t set;
988     int channelid = 0;
989     int c;
990     int hib_enable = 1;
991     uint32_t hib_timeout = PM_HIB_DEFAULT_TIME;
992     char *user_parm = NULL;
993     struct stat          sbuf;
994     int i = 0;
995     char * abs_path = NULL;
997     if (-1 != stat(IPC_DEVICE_PATH, &sbuf)) {
998         printf ("Syslink Already Running...\n");
999         return EXIT_FAILURE;
1000     }
1001     printf ("Starting syslink resource manager...\n");
1003     /* Parse the input args */
1004     while (1)
1005     {
1006         c = getopt (argc, argv, "H:T:U:gv:");
1007         if (c == -1)
1008             break;
1010         switch (c)
1011         {
1012 #if defined(SYSLINK_PLATFORM_OMAP5430)
1013         case 'H':
1014             hib_enable = atoi(optarg);
1015             if (hib_enable != 0 && hib_enable != 1) {
1016                 hib_enable = -1;
1017             }
1018             break;
1019         case 'T':
1020             hib_timeout = atoi(optarg);
1021             break;
1022 #endif
1023         case 'U':
1024             user_parm = optarg;
1025             break;
1026         case 'v':
1027             verbosity++;
1028             break;
1029 #if defined(SYSLINK_PLATFORM_VAYU)
1030         case 'g':
1031             printf("GateMP support enabled on host\n");
1032             gatempEnabled = true;
1033             break;
1034 #endif
1035         default:
1036             fprintf (stderr, "Unrecognized argument\n");
1037         }
1038     }
1040     /* Now parse the operands, which should be in the format:
1041      * "<multiproc_name> <firmware_file> ..*/
1042     for (; optind + 1 < argc; optind+=2) {
1043         if (syslink_num_cores == MultiProc_MAXPROCESSORS) {
1044             printUsage(argv[0]);
1045             return (error);
1046         }
1047         syslink_firmware[syslink_num_cores].proc = argv [optind];
1048         syslink_firmware[syslink_num_cores++].firmware = argv [optind+1];
1049     }
1052     /* Get the name of the binary from the input args */
1053     if (!syslink_num_cores) {
1054         fprintf(stderr, "At least one core_id and executable must be "\
1055             "specified");
1056         printUsage(argv[0]);
1057         return (error);
1058     }
1060     /* Validate hib_enable args */
1061     if (hib_enable == -1) {
1062         fprintf (stderr, "invalid hibernation enable value\n");
1063         printUsage(argv[0]);
1064         return (error);
1065     }
1067     syslink_hib_enable = (Bool)hib_enable;
1068     syslink_hib_timeout = hib_timeout;
1070     /* Init logging for syslink */
1071     if (Osal_initlogging(verbosity) != 0) {
1072         return -1;
1073     }
1075     /* Obtain I/O privity */
1076     error = ThreadCtl_r (_NTO_TCTL_IO, 0);
1077     if (error == -1) {
1078         Osal_printf("Unable to obtain I/O privity");
1079         return (error);
1080     }
1082     /* Get the abs path for all firmware files */
1083     for (i = 0; i < syslink_num_cores; i++) {
1084         abs_path = calloc(1, PATH_MAX + 1);
1085         if (abs_path == NULL) {
1086             return -1;
1087         }
1088         if (NULL == realpath(syslink_firmware[i].firmware, abs_path)) {
1089             fprintf (stderr, "invalid path to executable\n");
1090             return -1;
1091         }
1092         syslink_firmware[i].firmware = abs_path;
1093     }
1095     /* allocate the device structure */
1096     if (NULL == (dev = calloc(1, sizeof(syslink_dev_t)))) {
1097         Osal_printf("syslink: calloc() failed");
1098         return (-1);
1099     }
1101     /* create the channel */
1102     if ((channelid = ChannelCreate_r (_NTO_CHF_UNBLOCK |
1103                                     _NTO_CHF_DISCONNECT |
1104                                     _NTO_CHF_COID_DISCONNECT |
1105                                     _NTO_CHF_REPLY_LEN |
1106                                     _NTO_CHF_SENDER_LEN)) < 0) {
1107         Osal_printf("Unable to create channel %d", channelid);
1108         return (channelid);
1109     }
1111     /* create the dispatch structure */
1112     if (NULL == (dev->dpp = syslink_dpp = dispatch_create_channel (channelid, 0))) {
1113         Osal_printf("syslink:  dispatch_create() failed");
1114         return(-1);
1115     }
1117     /*
1118      * Mask out all signals before creating a thread pool.
1119      * This prevents other threads in the thread pool
1120      * from intercepting signals such as SIGTERM.
1121      */
1122     sigfillset(&set);
1123     pthread_sigmask(SIG_BLOCK, &set, NULL);
1125     /* Initialize the thread pool */
1126     memset (&tattr, 0x00, sizeof (thread_pool_attr_t));
1127     tattr.handle = dev->dpp;
1128     tattr.context_alloc = dispatch_context_alloc;
1129     tattr.context_free = dispatch_context_free;
1130     tattr.block_func = dispatch_block;
1131     tattr.unblock_func = dispatch_unblock;
1132     tattr.handler_func = dispatch_handler;
1133     tattr.lo_water = 2;
1134     tattr.hi_water = 4;
1135     tattr.increment = 1;
1136     tattr.maximum = 10;
1138     /* Create the thread pool */
1139     if ((dev->tpool = thread_pool_create(&tattr, 0)) == NULL) {
1140         Osal_printf("syslink: thread pool create failed");
1141         return(-1);
1142     }
1144     /* init syslink */
1145     status = init_ipc(dev, syslink_firmware, FALSE);
1146     if (status < 0) {
1147         Osal_printf("syslink: IPC init failed");
1148         return(-1);
1149     }
1151     /* init the syslink device */
1152     status = init_devices(dev);
1153     if (status < 0) {
1154         Osal_printf("syslink: device init failed");
1155         return(-1);
1156     }
1158 #if (_NTO_VERSION >= 800)
1159     /* Relinquish privileges */
1160     status = procmgr_ability(  0,
1161                  DENY_ALL | PROCMGR_AID_SPAWN,
1162                  DENY_ALL | PROCMGR_AID_FORK,
1163                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PEER,
1164                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PHYS,
1165                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_INTERRUPT,
1166                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_PATHSPACE,
1167                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_RSRCDBMGR,
1168                  PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETUID,
1169                  (uint64_t)1, (uint64_t)~0,
1170                  PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETGID,
1171                  (uint64_t)1, (uint64_t)~0,
1172                  PROCMGR_ADN_ROOT | PROCMGR_AOP_DENY | PROCMGR_AOP_LOCK | PROCMGR_AID_EOL);
1174     if (status != EOK) {
1175         Osal_printf("procmgr_ability failed! errno=%d", status);
1176         return EXIT_FAILURE;
1177     }
1179     /* Reduce priority to either what defined from command line or at least nobody */
1180     if (user_parm != NULL) {
1181         if (set_ids_from_arg(user_parm) < 0) {
1182             Osal_printf("unable to set uid/gid - %s", strerror(errno));
1183             return EXIT_FAILURE;
1184         }
1185     } else {
1186         if (setuid(99) != 0) {
1187             Osal_printf("unable to set uid - %s", strerror(errno));
1188             return EXIT_FAILURE;
1189         }
1190     }
1191 #endif
1193     /* make this a daemon process */
1194     if (-1 == procmgr_daemon(EXIT_SUCCESS,
1195         PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL)) {
1196         Osal_printf("syslink:  procmgr_daemon() failed");
1197         return(-1);
1198     }
1200     /* start the thread pool */
1201     thread_pool_start(dev->tpool);
1203     /* Unmask signals to be caught */
1204     sigdelset (&set, SIGINT);
1205     sigdelset (&set, SIGTERM);
1206     pthread_sigmask (SIG_BLOCK, &set, NULL);
1208     /* Wait for one of these signals */
1209     sigemptyset (&set);
1210     sigaddset (&set, SIGINT);
1211     sigaddset (&set, SIGQUIT);
1212     sigaddset (&set, SIGTERM);
1214     Osal_printf("Syslink resource manager started");
1216     /* Wait for a signal */
1217     while (1)
1218     {
1219         switch (SignalWaitinfo (&set, NULL))
1220         {
1221             case SIGTERM:
1222             case SIGQUIT:
1223             case SIGINT:
1224                 error = EOK;
1225                 goto done;
1227             default:
1228                 break;
1229         }
1230     }
1232     error = EOK;
1234 done:
1235     GT_0trace(curTrace, GT_4CLASS, "Syslink resource manager exiting \n");
1237     error = thread_pool_destroy(dev->tpool);
1238     if (error < 0)
1239         Osal_printf("syslink: thread_pool_destroy returned an error");
1240     deinit_ipc(dev, FALSE);
1241     deinit_devices(dev);
1242     free(dev);
1243     return (EOK);