266b0f53f015dcf6c267fe2d5861561927bf7308
[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-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)
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));
216 extern OsalSemaphore_Handle mqcopy_test_sem;
218 int syslink_unblock(resmgr_context_t *ctp, io_pulse_t *msg, syslink_ocb_t *ocb)
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;
245 IOFUNC_OCB_T *
246 syslink_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
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);
262 void
263 syslink_ocb_free (IOFUNC_OCB_T * i_ocb)
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     }
275 int init_syslink_trace_device(syslink_dev_t *dev)
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);
354 int deinit_syslink_trace_device(syslink_dev_t *dev)
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);
375 /* Initialize the syslink device */
376 int init_syslink_device(syslink_dev_t *dev)
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);
427 /* De-initialize the syslink device */
428 int deinit_syslink_device(syslink_dev_t *dev)
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);
444 /* Initialize the devices */
445 int init_devices(syslink_dev_t *dev)
447     if (init_syslink_device(dev) < 0) {
448         Osal_printf("syslink: syslink device init failed");
449         return(-1);
450     }
452     return(0);
456 /* De-initialize the devices */
457 int deinit_devices(syslink_dev_t *dev)
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);
469 static void ipc_recover(Ptr args)
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     }
481 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
482                       ProcMgr_State fromState, ProcMgr_State toState,
483                       ProcMgr_EventStatus status, Ptr args)
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;
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)
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;
757 int deinit_ipc(syslink_dev_t * dev, bool recover)
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;
855 /** print usage */
856 static Void printUsage (Char * app)
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);
879 dispatch_t * syslink_dpp = NULL;
881 int main(int argc, char *argv[])
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);