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 <_MultiProc.h>
71 #include <rprcfmt.h>
72 #include <OsalSemaphore.h>
73 #include <ti/syslink/utils/OsalPrint.h>
74 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
75 #include <_ipu_pm.h>
76 #endif
77 #include <ti/syslink/utils/Trace.h>
78 #include <ti/syslink/ProcMgr.h>
79 #include <Bitops.h>
80 #include <RscTable.h>
81 #if (_NTO_VERSION >= 800)
82 #include <slog2.h>
83 #endif
85 #include <ti-ipc.h>
87 #define DENY_ALL \
88 PROCMGR_ADN_ROOT \
89 | PROCMGR_ADN_NONROOT \
90 | PROCMGR_AOP_DENY \
91 | PROCMGR_AOP_LOCK
93 // Ducati trace to slog2 static variables and defines
94 #define TRACE_BUFFER_SIZE 4096
95 // polling interval in microseconds
96 #define TRACE_POLLING_INTERVAL_US 1000000
98 #if (_NTO_VERSION >= 800)
99 static int verbosity = SLOG2_ERROR;
100 static slog2_buffer_t buffer_handle;
101 #else
102 static int verbosity = 2;
103 #endif
104 static char trace_buffer[TRACE_BUFFER_SIZE];
105 static pthread_mutex_t trace_mutex = PTHREAD_MUTEX_INITIALIZER;
106 static Bool trace_active;
107 static pthread_t thread_traces;
109 // Syslink hibernation global variables
110 Bool syslink_hib_enable = TRUE;
111 #if !defined(SYSLINK_PLATFORM_OMAP4430) && !defined(SYSLINK_PLATFORM_OMAP5430)
112 #define PM_HIB_DEFAULT_TIME 5000
113 #endif
114 uint32_t syslink_hib_timeout = PM_HIB_DEFAULT_TIME;
115 Bool syslink_hib_hibernating = FALSE;
116 pthread_mutex_t syslink_hib_mutex = PTHREAD_MUTEX_INITIALIZER;
117 pthread_cond_t syslink_hib_cond = PTHREAD_COND_INITIALIZER;
119 extern int rpmsg_omx_setup (void);
120 extern void rpmsg_omx_destroy (void);
121 extern int rpmsg_resmgr_setup (void);
122 extern void rpmsg_resmgr_destroy (void);
123 extern Int rpmsg_dce_setup (Void);
124 extern Void rpmsg_dce_destroy (Void);
125 extern Void GateHWSpinlock_LeaveLockForPID(int pid);
127 typedef struct syslink_firmware_info_t {
128 uint16_t proc_id;
129 char * proc;
130 char * firmware;
131 } syslink_firmware_info;
132 static syslink_firmware_info syslink_firmware[MultiProc_MAXPROCESSORS];
133 static unsigned int syslink_num_cores = 0;
135 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover);
136 int deinit_ipc(syslink_dev_t * dev, bool recover);
138 static RscTable_Handle rscHandle[MultiProc_MAXPROCESSORS];
140 static ProcMgr_Handle procH[MultiProc_MAXPROCESSORS];
141 static unsigned int procH_fileId[MultiProc_MAXPROCESSORS];
142 static ProcMgr_State errStates[] = {ProcMgr_State_Mmu_Fault,
143 ProcMgr_State_Error,
144 ProcMgr_State_Watchdog,
145 ProcMgr_State_EndValue};
147 typedef struct syslink_trace_info_t {
148 uintptr_t va;
149 uint32_t len;
150 uint32_t * widx;
151 uint32_t * ridx;
152 Bool firstRead;
153 } syslink_trace_info;
155 static syslink_trace_info proc_traces[NUM_REMOTE_PROCS];
157 int syslink_read(resmgr_context_t *ctp, io_read_t *msg, syslink_ocb_t *ocb)
158 {
159 int nbytes;
160 int nparts;
161 int status;
162 int nleft;
163 uint32_t len;
164 uint16_t procid = ocb->ocb.attr->procid;
166 if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK)
167 return (status);
169 if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE)
170 return (ENOSYS);
172 /* check to see where the trace buffer is */
173 if (proc_traces[procid].va == NULL) {
174 return (ENOSYS);
175 }
177 /* need to abort ducati trace thread if it is running as only want one reader */
178 pthread_mutex_lock(&trace_mutex);
179 if (trace_active == TRUE) {
180 trace_active = FALSE;
181 pthread_mutex_unlock(&trace_mutex);
182 // Wake up if waiting on hibernation
183 pthread_mutex_lock(&syslink_hib_mutex);
184 syslink_hib_hibernating = FALSE;
185 pthread_cond_broadcast(&syslink_hib_cond);
186 pthread_mutex_unlock(&syslink_hib_mutex);
187 pthread_join(thread_traces, NULL);
188 } else {
189 pthread_mutex_unlock(&trace_mutex);
190 }
192 if (ocb->ocb.offset == 0) {
193 ocb->widx = *(proc_traces[procid].widx);
194 ocb->ridx = *(proc_traces[procid].ridx);
195 *(proc_traces[procid].ridx) = ocb->widx;
196 }
198 /* Check for wrap-around */
199 if (ocb->widx < ocb->ridx)
200 len = proc_traces[procid].len - ocb->ridx + ocb->widx;
201 else
202 len = ocb->widx - ocb->ridx;
204 /* Determine the amount left to print */
205 if (ocb->widx >= ocb->ridx)
206 nleft = len - ocb->ocb.offset;
207 else if (ocb->ocb.offset < proc_traces[procid].len - ocb->ridx)
208 nleft = proc_traces[procid].len - ocb->ridx - ocb->ocb.offset;
209 else
210 nleft = proc_traces[procid].len - ocb->ridx + ocb->widx - ocb->ocb.offset;
212 nbytes = min (msg->i.nbytes, nleft);
214 /* Make sure the user has supplied a big enough buffer */
215 if (nbytes > 0) {
216 /* set up the return data IOV */
217 if (ocb->widx < ocb->ridx && ocb->ocb.offset >= proc_traces[procid].len - ocb->ridx)
218 SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ocb.offset - (proc_traces[procid].len - ocb->ridx), nbytes);
219 else
220 SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ridx + ocb->ocb.offset, nbytes);
222 /* set up the number of bytes (returned by client's read()) */
223 _IO_SET_READ_NBYTES (ctp, nbytes);
225 ocb->ocb.offset += nbytes;
227 nparts = 1;
228 }
229 else {
230 _IO_SET_READ_NBYTES (ctp, 0);
232 /* reset offset */
233 ocb->ocb.offset = 0;
235 nparts = 0;
236 }
238 /* mark the access time as invalid (we just accessed it) */
240 if (msg->i.nbytes > 0)
241 ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
243 return (_RESMGR_NPARTS (nparts));
244 }
246 extern OsalSemaphore_Handle mqcopy_test_sem;
248 int syslink_unblock(resmgr_context_t *ctp, io_pulse_t *msg, syslink_ocb_t *ocb)
249 {
250 int status = _RESMGR_NOREPLY;
251 struct _msg_info info;
253 /*
254 * Try to run the default unblock for this message.
255 */
256 if ((status = iofunc_unblock_default(ctp,msg,&(ocb->ocb))) != _RESMGR_DEFAULT) {
257 return status;
258 }
260 /*
261 * Check if rcvid is still valid and still has an unblock
262 * request pending.
263 */
264 if (MsgInfo(ctp->rcvid, &info) == -1 ||
265 !(info.flags & _NTO_MI_UNBLOCK_REQ)) {
266 return _RESMGR_NOREPLY;
267 }
269 if (mqcopy_test_sem)
270 OsalSemaphore_post(mqcopy_test_sem);
272 return _RESMGR_NOREPLY;
273 }
275 IOFUNC_OCB_T *
276 syslink_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
277 {
278 syslink_ocb_t *ocb = NULL;
280 /* Allocate the OCB */
281 ocb = (syslink_ocb_t *) calloc (1, sizeof (syslink_ocb_t));
282 if (ocb == NULL){
283 errno = ENOMEM;
284 return (NULL);
285 }
287 ocb->pid = ctp->info.pid;
289 return (IOFUNC_OCB_T *)(ocb);
290 }
292 void
293 syslink_ocb_free (IOFUNC_OCB_T * i_ocb)
294 {
295 syslink_ocb_t * ocb = (syslink_ocb_t *)i_ocb;
297 if (ocb) {
298 GateHWSpinlock_LeaveLockForPID(ocb->pid);
299 free (ocb);
300 }
301 }
303 /* Initialize the syslink device */
304 int init_syslink_device(syslink_dev_t *dev)
305 {
306 iofunc_attr_t * attr;
307 syslink_attr_t * trace_attr;
308 resmgr_attr_t resmgr_attr;
309 int i;
310 char trace_name[_POSIX_PATH_MAX];
311 int status = 0;
312 u32 da = 0, pa = 0;
313 u32 len;
315 pthread_mutex_init(&dev->lock, NULL);
317 memset(&resmgr_attr, 0, sizeof resmgr_attr);
318 resmgr_attr.nparts_max = 10;
319 resmgr_attr.msg_max_size = 2048;
321 memset(&dev->syslink.mattr, 0, sizeof(iofunc_mount_t));
322 dev->syslink.mattr.flags = ST_NOSUID | ST_NOEXEC;
323 dev->syslink.mattr.conf = IOFUNC_PC_CHOWN_RESTRICTED |
324 IOFUNC_PC_NO_TRUNC |
325 IOFUNC_PC_SYNC_IO;
326 dev->syslink.mattr.funcs = &dev->syslink.mfuncs;
328 memset(&dev->syslink.mfuncs, 0, sizeof(iofunc_funcs_t));
329 dev->syslink.mfuncs.nfuncs = _IOFUNC_NFUNCS;
331 iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs,
332 _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs);
334 iofunc_attr_init(attr = &dev->syslink.cattr, S_IFCHR | 0777, NULL, NULL);
336 dev->syslink.mfuncs.ocb_calloc = syslink_ocb_calloc;
337 dev->syslink.mfuncs.ocb_free = syslink_ocb_free;
338 dev->syslink.iofuncs.devctl = syslink_devctl;
339 dev->syslink.iofuncs.unblock = syslink_unblock;
341 attr->mount = &dev->syslink.mattr;
342 iofunc_time_update(attr);
344 if (-1 == (dev->syslink.resmgr_id =
345 resmgr_attach(dev->dpp, &resmgr_attr,
346 IPC_DEVICE_PATH, _FTYPE_ANY, 0,
347 &dev->syslink.cfuncs,
348 &dev->syslink.iofuncs, attr))) {
349 return(-1);
350 }
352 for (i = 0; i < syslink_num_cores; i++) {
353 iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs_trace[i],
354 _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_trace[i]);
355 trace_attr = &dev->syslink.cattr_trace[i];
356 iofunc_attr_init(&trace_attr->attr,
357 S_IFCHR | 0777, NULL, NULL);
358 trace_attr->attr.mount = &dev->syslink.mattr;
359 trace_attr->procid = i;
360 iofunc_time_update(&trace_attr->attr);
361 snprintf (dev->syslink.device_name, _POSIX_PATH_MAX,
362 "/dev/syslink-trace%d", syslink_firmware[i].proc_id);
363 dev->syslink.iofuncs_trace[i].read = syslink_read;
364 snprintf (trace_name, _POSIX_PATH_MAX, "%d", 0);
365 pa = 0;
366 status = RscTable_getInfo(syslink_firmware[i].proc_id, TYPE_TRACE, 0, &da, &pa, &len);
367 if (status == 0) {
368 /* last 8 bytes are for writeIdx/readIdx */
369 proc_traces[i].len = len - (sizeof(uint32_t) * 2);
370 if (da && !pa) {
371 /* need to translate da->pa */
372 status = ProcMgr_translateAddr (procH[syslink_firmware[i].proc_id],
373 (Ptr *) &pa,
374 ProcMgr_AddrType_MasterPhys,
375 (Ptr) da,
376 ProcMgr_AddrType_SlaveVirt);
377 }
378 /* map length aligned to page size */
379 proc_traces[i].va =
380 mmap_device_io (((len + 0x1000 - 1) / 0x1000) * 0x1000, pa);
381 proc_traces[i].widx = (uint32_t *)(proc_traces[i].va + \
382 proc_traces[i].len);
383 proc_traces[i].ridx = (uint32_t *)((uint32_t)proc_traces[i].widx + \
384 sizeof(uint32_t));
385 if (proc_traces[i].va == MAP_DEVICE_FAILED) {
386 proc_traces[i].va = NULL;
387 }
388 proc_traces[i].firstRead = TRUE;
389 }
390 else {
391 proc_traces[i].va = NULL;
392 }
393 if (-1 == (dev->syslink.resmgr_id_trace[i] =
394 resmgr_attach(dev->dpp, &resmgr_attr,
395 dev->syslink.device_name, _FTYPE_ANY, 0,
396 &dev->syslink.cfuncs_trace[i],
397 &dev->syslink.iofuncs_trace[i],
398 &trace_attr->attr))) {
399 return(-1);
400 }
401 }
403 return(0);
404 }
406 /* De-initialize the syslink device */
407 int deinit_syslink_device(syslink_dev_t *dev)
408 {
409 int status = EOK;
410 int i = 0;
412 status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id, 0);
413 if (status < 0) {
414 Osal_printf("syslink: resmgr_detach failed %d", errno);
415 status = errno;
416 }
418 for (i = 0; i < syslink_num_cores; i++) {
419 status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_trace[i], 0);
420 if (status < 0) {
421 Osal_printf("syslink: resmgr_detach failed %d", errno);
422 status = errno;
423 }
424 if (proc_traces[i].va && proc_traces[i].va != MAP_DEVICE_FAILED)
425 munmap((void *)proc_traces[i].va,
426 ((proc_traces[i].len + 8 + 0x1000 - 1) / 0x1000) * 0x1000);
427 proc_traces[i].va = NULL;
428 }
430 return(status);
431 }
434 /* Initialize the devices */
435 int init_devices(syslink_dev_t *dev)
436 {
437 if (init_syslink_device(dev) < 0) {
438 Osal_printf("syslink: syslink device init failed");
439 return(-1);
440 }
442 return(0);
443 }
446 /* De-initialize the devices */
447 int deinit_devices(syslink_dev_t *dev)
448 {
449 int status = EOK;
451 if ((status = deinit_syslink_device(dev)) < 0) {
452 fprintf( stderr, "syslink: syslink device de-init failed %d\n", status);
453 status = errno;
454 }
456 return(status);
457 }
459 static void ipc_recover(Ptr args)
460 {
461 syslink_dev_t * dev = (syslink_dev_t *)args;
463 deinit_ipc(dev, TRUE);
464 init_ipc(dev, syslink_firmware, TRUE);
465 }
467 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
468 ProcMgr_State fromState, ProcMgr_State toState,
469 ProcMgr_EventStatus status, Ptr args)
470 {
471 Int ret = 0;
472 String errString = NULL;
473 syslink_dev_t * dev = (syslink_dev_t *)args;
475 if (status == ProcMgr_EventStatus_Event) {
476 switch (toState) {
477 case ProcMgr_State_Mmu_Fault:
478 errString = "MMU Fault";
479 break;
480 case ProcMgr_State_Error:
481 errString = "Exception";
482 break;
483 case ProcMgr_State_Watchdog:
484 errString = "Watchdog";
485 break;
486 default:
487 errString = "Unexpected State";
488 ret = -1;
489 break;
490 }
491 GT_2trace (curTrace, GT_4CLASS,
492 "syslink_error_cb: Received Error Callback for %s : %s\n",
493 MultiProc_getName(procId), errString);
494 /* Don't allow re-schedule of recovery until complete */
495 pthread_mutex_lock(&dev->lock);
496 if (ret != -1 && dev->recover == FALSE) {
497 /* Schedule recovery. */
498 dev->recover = TRUE;
499 /* Activate a thread to handle the recovery. */
500 GT_0trace (curTrace, GT_4CLASS,
501 "syslink_error_cb: Scheduling recovery...");
502 OsalThread_activate(dev->ipc_recovery_work);
503 }
504 else {
505 GT_0trace (curTrace, GT_4CLASS,
506 "syslink_error_cb: Recovery already scheduled.");
507 }
508 pthread_mutex_unlock(&dev->lock);
509 }
510 else if (status == ProcMgr_EventStatus_Canceled) {
511 GT_1trace (curTrace, GT_3CLASS,
512 "SysLink Error Callback Cancelled for %s",
513 MultiProc_getName(procId));
514 }
515 else {
516 GT_1trace (curTrace, GT_4CLASS,
517 "SysLink Error Callback Unexpected Event for %s",
518 MultiProc_getName(procId));
519 }
521 return ret;
522 }
524 #if defined(SYSLINK_PLATFORM_OMAP4430)
525 #define SYSLINK_CARVEOUT
526 #ifdef SYSLINK_CARVEOUT
527 #define IPU_MEM_SIZE 49 * 1024 * 1024
528 #define IPU_MEM_PHYS 0x97F00000
529 #else
530 #define IPU_MEM_SIZE 104 * 1024 * 1024
531 #define IPU_MEM_ALIGN 0x1000000
532 #endif
533 #else
534 // only need mem for DEVMEM entries, rest is allocated dynamically
535 #define IPU_MEM_SIZE 90 * 1024 * 1024
536 #define IPU_MEM_ALIGN 0x0
538 #endif
540 unsigned int syslink_ipu_mem_size = IPU_MEM_SIZE;
541 #if defined(SYSLINK_PLATFORM_OMAP5430)
542 unsigned int syslink_dsp_mem_size = IPU_MEM_SIZE;
543 #endif
545 /*
546 * Initialize the syslink ipc
547 *
548 * This function sets up the "kernel"-side IPC modules, and does any special
549 * initialization required for QNX and the platform being used. This function
550 * also registers for error notifications and initializes the recovery thread.
551 */
552 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover)
553 {
554 int status = 0;
555 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
556 int32_t ret = 0;
557 uint32_t len = 0;
558 #ifndef SYSLINK_CARVEOUT
559 int64_t pa = 0;
560 void * da;
561 #endif
562 int64_t paddr = 0;
563 #endif
564 Ipc_Config iCfg;
565 OsalThread_Params threadParams;
566 ProcMgr_AttachParams attachParams;
567 UInt16 procId;
568 int i;
570 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
571 /* Map a contiguous memory section for ipu - currently hard-coded */
572 if (!recover) {
573 #ifdef SYSLINK_CARVEOUT
574 dev->da_virt = mmap64(NULL, IPU_MEM_SIZE,
575 PROT_NOCACHE | PROT_READ | PROT_WRITE,
576 MAP_PHYS,
577 NOFD,
578 IPU_MEM_PHYS);
579 #else
580 #if defined(SYSLINK_PLATFORM_OMAP5430)
581 dev->da_tesla_virt =
582 #endif
583 dev->da_virt = mmap64(NULL, IPU_MEM_SIZE + IPU_MEM_ALIGN,
584 PROT_NOCACHE | PROT_READ | PROT_WRITE,
585 MAP_ANON | MAP_PHYS | MAP_SHARED,
586 NOFD,
587 0);
589 #endif
591 if (dev->da_virt == MAP_FAILED) {
592 status = ENOMEM;
593 goto exit;
594 }
595 }
597 if (status >= 0) {
598 #ifdef SYSLINK_CARVEOUT
599 /* Make sure the memory is contiguous */
600 ret = mem_offset64(dev->da_virt, NOFD, IPU_MEM_SIZE, &paddr, &len);
601 if (ret)
602 status = ret;
603 else if (len != IPU_MEM_SIZE)
604 status = ENOMEM;
605 #else
606 /* Make sure the memory is contiguous */
607 ret = mem_offset64(dev->da_virt, NOFD, IPU_MEM_SIZE + IPU_MEM_ALIGN,
608 &paddr, &len);
609 if (ret)
610 status = ret;
611 else if (len != IPU_MEM_SIZE + IPU_MEM_ALIGN)
612 status = ENOMEM;
613 else {
614 #if defined(SYSLINK_PLATFORM_OMAP4430)
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 #else
622 pa = paddr;
623 da = dev->da_virt;
624 #endif
625 }
626 #endif
627 if (status != 0)
628 goto memoryos_fail;
629 }
630 #endif
632 #if defined(SYSLINK_PLATFORM_OMAP5430)
633 if (status >= 0) {
634 iCfg.pAddr_dsp = (uint32_t)pa;
635 iCfg.vAddr_dsp = (uint32_t)da;
636 }
637 #endif
638 if (status >= 0) {
639 if (!recover) {
640 /* Set up the MemoryOS module */
641 status = MemoryOS_setup();
642 if (status < 0)
643 goto memoryos_fail;
644 }
646 /* Setup IPC and platform-specific items */
647 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
648 #ifdef SYSLINK_CARVEOUT
649 iCfg.vAddr = (uint32_t)dev->da_virt;
650 iCfg.pAddr = (uint32_t)paddr;
651 #else
652 iCfg.vAddr = (uint32_t)da;
653 iCfg.pAddr = (uint32_t)pa;
654 #endif
655 #endif
656 status = Ipc_setup (&iCfg);
657 if (status < 0)
658 goto ipcsetup_fail;
660 /* NOTE: this is for handling the procmgr event notifications to userspace list */
661 if (!recover) {
662 /* Setup Fault recovery items. */
663 /* Create the thread object used for the interrupt handler. */
664 threadParams.priority = OsalThread_Priority_Medium;
665 threadParams.priorityType = OsalThread_PriorityType_Generic;
666 threadParams.once = FALSE;
667 dev->ipc_recovery_work = OsalThread_create ((OsalThread_CallbackFxn)
668 ipc_recover,
669 dev,
670 &threadParams);
671 if (dev->ipc_recovery_work == NULL)
672 goto osalthreadcreate_fail;
673 }
674 else {
675 pthread_mutex_lock(&dev->lock);
676 dev->recover = FALSE;
677 pthread_mutex_unlock(&dev->lock);
678 }
680 for (i = 0; i < syslink_num_cores; i++) {
681 procId = firmware[i].proc_id = MultiProc_getId(firmware[i].proc);
682 if (procId >= MultiProc_MAXPROCESSORS || procH[procId]) {
683 GT_setFailureReason (curTrace,
684 GT_4CLASS,
685 "init_ipc",
686 status,
687 "invalid proc!");
688 break;
689 }
691 if (syslink_firmware[i].firmware) {
692 rscHandle[procId] = RscTable_alloc(firmware[i].firmware, procId);
693 if (rscHandle[procId] == NULL) {
694 status = -1;
695 break;
696 }
697 }
699 status = ProcMgr_open(&procH[procId], procId);
700 if (status < 0 || procH[procId] == NULL)
701 goto procmgropen_fail;
703 /* Load and start the remote processor. */
704 ProcMgr_getAttachParams (procH[procId], &attachParams);
705 status = ProcMgr_attach (procH[procId], &attachParams);
706 if (status < 0) {
707 GT_setFailureReason (curTrace,
708 GT_4CLASS,
709 "init_ipc",
710 status,
711 "ProcMgr_attach failed!");
712 goto procmgrattach_fail;
713 }
715 if (syslink_firmware[i].firmware) {
716 status = ProcMgr_load (procH[procId],
717 (String)firmware[i].firmware, 0, NULL,
718 NULL, &procH_fileId[procId]);
719 if (status < 0) {
720 GT_setFailureReason (curTrace,
721 GT_4CLASS,
722 "init_ipc",
723 status,
724 "ProcMgr_load failed!");
725 goto procmgrload_fail;
726 }
727 }
729 status = Ipc_attach (procId);
730 if (status < 0) {
731 GT_setFailureReason (curTrace,
732 GT_4CLASS,
733 "init_ipc",
734 status,
735 "Ipc_attach failed!");
736 goto ipcattach_fail;
737 }
739 status = ProcMgr_start(procH[procId], NULL);
740 if (status < 0) {
741 GT_setFailureReason (curTrace,
742 GT_4CLASS,
743 "init_ipc",
744 status,
745 "ProcMgr_start failed!");
746 goto procmgrstart_fail;
747 }
749 status = ProcMgr_registerNotify(procH[procId], syslink_error_cb, (Ptr)dev,
750 -1, errStates);
751 if (status < 0)
752 goto procmgrreg_fail;
754 continue;
756 procmgrreg_fail:
757 ProcMgr_stop(procH[procId]);
758 procmgrstart_fail:
759 Ipc_detach(procId);
760 ipcattach_fail:
761 if (syslink_firmware[i].firmware)
762 ProcMgr_unload(procH[procId], procH_fileId[procId]);
763 procmgrload_fail:
764 ProcMgr_detach(procH[procId]);
765 procmgrattach_fail:
766 ProcMgr_close(&procH[procId]);
767 procH[procId] = NULL;
768 procmgropen_fail:
769 RscTable_free(&rscHandle[procId]);
770 break;
771 }
773 if (status < 0)
774 goto resmgrsetup_fail;
776 /* Set up the resmgr */
777 status = rpmsg_resmgr_setup();
778 if (status < 0)
779 goto resmgrsetup_fail;
781 /* Set up rpmsg_omx */
782 status = rpmsg_omx_setup();
783 if (status < 0)
784 goto omxsetup_fail;
786 /* Set up rpmsg_dce */
787 status = rpmsg_dce_setup();
788 if (status < 0)
789 goto dcesetup_fail;
791 /* Set up rpmsg_mq */
792 status = ti_ipc_setup();
793 if (status < 0)
794 goto tiipcsetup_fail;
796 goto exit;
797 }
799 tiipcsetup_fail:
800 rpmsg_dce_destroy();
801 dcesetup_fail:
802 rpmsg_omx_destroy();
803 omxsetup_fail:
804 rpmsg_resmgr_destroy();
805 resmgrsetup_fail:
806 for (i-=1; i >= 0; i--) {
807 procId = firmware[i].proc_id;
808 ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
809 (Ptr)dev, errStates);
810 ProcMgr_stop(procH[procId]);
811 if (procH_fileId[procId]) {
812 ProcMgr_unload(procH[procId], procH_fileId[procId]);
813 procH_fileId[procId] = 0;
814 }
815 ProcMgr_detach(procH[procId]);
816 ProcMgr_close(&procH[procId]);
817 procH[procId] = NULL;
818 RscTable_free(&rscHandle[procId]);
819 rscHandle[procId] = NULL;
820 }
821 OsalThread_delete(&dev->ipc_recovery_work);
822 osalthreadcreate_fail:
823 Ipc_destroy();
824 ipcsetup_fail:
825 MemoryOS_destroy();
826 memoryos_fail:
827 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
828 if (dev->da_virt != MAP_FAILED)
829 #ifdef SYSLINK_CARVEOUT
830 munmap(dev->da_virt, IPU_MEM_SIZE);
831 #else
832 munmap(dev->da_virt, IPU_MEM_SIZE + IPU_MEM_ALIGN);
833 #endif
834 #endif
835 exit:
836 return status;
837 }
839 int deinit_ipc(syslink_dev_t * dev, bool recover)
840 {
841 int status = EOK;
842 uint32_t i = 0, id = 0;
844 // Stop the remote cores right away
845 for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
846 if (procH[i]) {
847 GT_1trace(curTrace, GT_4CLASS, "stopping %s", MultiProc_getName(i));
848 ProcMgr_stop(procH[i]);
849 }
850 }
852 ti_ipc_destroy(recover);
854 rpmsg_dce_destroy();
856 rpmsg_omx_destroy();
858 rpmsg_resmgr_destroy();
860 for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
861 if (procH[i]) {
862 ProcMgr_unregisterNotify (procH[i], syslink_error_cb, (Ptr)dev,
863 errStates);
864 Ipc_detach(i);
865 if (procH_fileId[i]) {
866 ProcMgr_unload(procH[i], procH_fileId[i]);
867 procH_fileId[i] = 0;
868 }
869 ProcMgr_detach(procH[i]);
870 ProcMgr_close(&procH[i]);
871 procH[i] = NULL;
872 RscTable_free(&rscHandle[i]);
873 rscHandle[i] = NULL;
874 }
875 }
877 if (!recover && dev->ipc_recovery_work != NULL) {
878 OsalThread_delete (&dev->ipc_recovery_work);
879 dev->ipc_recovery_work = NULL;
880 }
882 if (recover) {
883 static FILE *log;
884 /* Dump the trace information */
885 Osal_printf("syslink: printing remote core trace dump to"
886 " /var/log/ducati-m3-traces.log");
887 log = fopen ("/var/log/ducati-m3-traces.log", "a+");
888 if (log) {
889 for (id = 0; id < syslink_num_cores; id++) {
890 if (proc_traces[id].va) {
891 /* print traces */
892 /* wait a little bit for traces to finish dumping */
893 sleep(1);
894 fprintf(log, "****************************************\n");
895 fprintf(log, "*** CORE%d TRACE DUMP ***\n",
896 id);
897 fprintf(log, "****************************************\n");
898 for (i = (*proc_traces[id].widx + 1);
899 i < (proc_traces[id].len - 8);
900 i++) {
901 fprintf(log, "%c",
902 *(char *)((uint32_t)proc_traces[id].va + i));
903 }
904 for (i = 0; i < *proc_traces[id].widx; i++) {
905 fprintf(log, "%c",
906 *(char *)((uint32_t)proc_traces[id].va + i));
907 }
908 }
909 }
910 fclose(log);
911 }
912 else {
913 GT_setFailureReason(curTrace, GT_4CLASS, "deinit_ipc", errno,
914 "error opening /var/log/ducati-m3-traces.log");
915 }
916 }
918 status = Ipc_destroy();
919 if (status < 0) {
920 printf("Ipc_destroy() failed 0x%x", status);
921 }
922 if (!recover) {
923 status = MemoryOS_destroy();
924 if (status < 0) {
925 printf("MemoryOS_destroy() failed 0x%x", status);
926 }
927 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
928 if (dev->da_virt != MAP_FAILED) {
929 #ifdef SYSLINK_CARVEOUT
930 status = munmap(dev->da_virt, IPU_MEM_SIZE);
931 #else
932 status = munmap(dev->da_virt, IPU_MEM_SIZE + IPU_MEM_ALIGN);
933 #endif
934 if (status < 0) {
935 printf("munmap failed %d", errno);
936 }
937 }
938 #endif
939 }
941 return status;
942 }
945 /* Read next line of available data for given 'core' and store it in buffer.
946 * Returns the number of bytes that were written or -1 on error
947 */
948 static int readNextTrace(int core, char* buffer, int bufSize)
949 {
950 char* readPtr;
951 uint32_t readBytes, ridx, widx;
952 syslink_trace_info* tinfo = &proc_traces[core];
954 /* Make sure it is valid */
955 if ( (tinfo == NULL) || (tinfo->va == NULL) ) {
956 return -1;
957 }
959 /* Check to see if something to read */
960 if (tinfo->ridx == tinfo->widx) {
961 return 0;
962 }
964 readPtr = (char*) tinfo->va;
965 ridx = *tinfo->ridx;
966 widx = *tinfo->widx;
968 /* If first read, make sure that core is ready by validating ridx, widx */
969 if ( (tinfo->firstRead == TRUE) && ((ridx != 0) || (widx >= tinfo->len)) ) {
970 // not ready - will try again later
971 return 0;
972 }
974 /* Sanity check ridx/widx to make sure they point inside the buffer */
975 if ( (ridx >= tinfo->len) || (widx >= tinfo->len) ) {
976 Osal_printf("C%d: widx=%d, ridx=%d, len=%d - out of range",
977 core, widx, ridx, tinfo->len);
978 return -1;
979 }
981 readBytes = 0;
982 tinfo->firstRead = FALSE;
983 /* Read until we hit newline indicating end of trace */
984 while ( (readPtr[ridx] != '\n') && (ridx != widx) && (readBytes < bufSize)) {
985 buffer[readBytes] = readPtr[ridx];
986 readBytes++;
987 ridx++;
988 // Check for wrap-around
989 if (ridx == tinfo->len) {
990 ridx = 0;
991 }
992 }
994 /* If did not find newline, abort since either not enough info or no room in buffer */
995 if (readPtr[ridx] != '\n') {
996 if (readBytes >= bufSize) {
997 Osal_printf("C%d: Insufficient size of buffer; read %d, buf %d",
998 core, readBytes, bufSize);
999 return -1;
1000 }
1001 return 0;
1002 }
1004 /* Newline may not be valid data if this was not ready to be read */
1005 if (ridx == widx) {
1006 return 0;
1007 }
1009 /* We read a full line - null terminate and update ridx to mark data read */
1010 if (readBytes < bufSize) {
1011 buffer[readBytes] = '\0';
1012 } else {
1013 Osal_printf("C%d: No room to write NULL character", core);
1014 return -1;
1015 }
1016 readBytes++;
1017 ridx++;
1018 if (ridx == tinfo->len) {
1019 ridx = 0;
1020 }
1021 *tinfo->ridx = ridx;
1023 return readBytes;
1024 }
1026 /* Thread reading ducati traces and writing them out to slog2 */
1027 static void *ducatiTraceThread(void *parm)
1028 {
1029 int32_t bytesRead;
1030 int core;
1031 int err;
1032 Bool exit = FALSE;
1034 pthread_setname_np(0, "ducati-trace");
1036 pthread_mutex_lock(&trace_mutex);
1037 while ( (trace_active == TRUE) && (exit == FALSE) ) {
1038 for (core = 0; core < NUM_REMOTE_PROCS; core++) {
1039 while ((bytesRead = readNextTrace(core, trace_buffer, TRACE_BUFFER_SIZE)) > 0) {
1040 #if (_NTO_VERSION >= 800)
1041 slog2f(buffer_handle, 0, 0, "C%d:%s", core, trace_buffer);
1042 #else
1043 slogf(42, _SLOG_NOTICE, "C%d:%s", core, trace_buffer);
1044 #endif
1045 if (trace_active == FALSE) {
1046 break;
1047 }
1048 }
1049 // Abort trace logger on errors as these should not occur
1050 if (bytesRead < 0) {
1051 trace_active = FALSE;
1052 }
1053 if (trace_active == FALSE) {
1054 break;
1055 }
1056 }
1057 if (trace_active == FALSE) {
1058 continue;
1059 }
1060 pthread_mutex_unlock(&trace_mutex);
1062 // No interrupts/events to trigger reading traces, so need to periodically poll
1063 usleep(TRACE_POLLING_INTERVAL_US);
1065 // If we are in hibernation, wait on condvar for end of hibernation
1066 pthread_mutex_lock(&syslink_hib_mutex);
1067 while ((syslink_hib_enable == TRUE) && (syslink_hib_hibernating == TRUE) ) {
1068 err = pthread_cond_wait(&syslink_hib_cond, &syslink_hib_mutex);
1069 if (err != EOK) {
1070 Osal_printf("pthread_cond_wait failed with err=%d", err);
1071 exit = TRUE;
1072 break;
1073 }
1074 }
1075 pthread_mutex_unlock(&syslink_hib_mutex);
1077 pthread_mutex_lock(&trace_mutex);
1078 }
1079 pthread_mutex_unlock(&trace_mutex);
1080 Osal_printf("ducati trace thread exited");
1081 return NULL;
1082 }
1084 /* Initialize slog2 for Ducati traces */
1085 static int init_ducati_slog2(void)
1086 {
1087 #if (_NTO_VERSION >= 800)
1088 slog2_buffer_set_config_t buffer_config;
1089 const char * buffer_set_name = "ducati";
1090 const char * buffer_name = "ducati_buffer";
1092 // Use command line verbosity for default verbosity level
1093 uint8_t verbosity_level = (uint8_t) verbosity;
1094 if ( verbosity_level > SLOG2_DEBUG2) {
1095 verbosity_level = SLOG2_DEBUG2;
1096 }
1098 // Initialize the buffer configuration
1099 buffer_config.buffer_set_name = (char *) buffer_set_name;
1100 buffer_config.num_buffers = 1;
1101 buffer_config.verbosity_level = verbosity_level;
1102 buffer_config.buffer_config[0].buffer_name = (char *) buffer_name;
1103 buffer_config.buffer_config[0].num_pages = 8;
1105 // Register the Buffer Set
1106 if( slog2_register( &buffer_config, &buffer_handle, 0 ) == -1 ) {
1107 Osal_printf("syslink error registering slogger2 buffer for Ducati!");
1108 return -1;
1109 }
1110 #endif
1112 return 0;
1113 }
1115 /** print usage */
1116 static Void printUsage (Char * app)
1117 {
1118 printf ("\n%s: [-fHT]\n", app);
1119 printf (" -f specify the binary file to load to the remote cores)\n");
1120 #if defined(SYSLINK_PLATFORM_OMAP5430)
1121 printf (" -d specify the binary file to load to the dsp)\n");
1122 #endif
1123 printf (" -H enable/disable hibernation, 1: ON, 0: OFF, Default: 1)\n");
1124 printf (" -T specify the hibernation timeout in ms, Default: 5000 ms)\n");
1126 exit (EXIT_SUCCESS);
1127 }
1129 dispatch_t * syslink_dpp = NULL;
1131 int main(int argc, char *argv[])
1132 {
1133 syslink_dev_t * dev = NULL;
1134 thread_pool_attr_t tattr;
1135 int status;
1136 int error = 0;
1137 sigset_t set;
1138 int channelid = 0;
1139 int c;
1140 int hib_enable = 1;
1141 uint32_t hib_timeout = PM_HIB_DEFAULT_TIME;
1142 char *user_parm = NULL;
1143 struct stat sbuf;
1145 if (-1 != stat("/dev/syslink", &sbuf)) {
1146 printf ("Syslink Already Running...\n");
1147 return EXIT_FAILURE;
1148 }
1149 printf ("Starting syslink resource manager...\n");
1151 /* Parse the input args */
1152 while (1)
1153 {
1154 c = getopt (argc, argv, "f:d:H:T:U:v:");
1155 if (c == -1)
1156 break;
1158 switch (c)
1159 {
1160 case 'f':
1161 /* for backward compatibility, "-f" option loaded Ducati/Benelli */
1162 syslink_firmware[syslink_num_cores].firmware = optarg;
1163 #if defined(SYSLINK_PLATFORM_OMAP4430)
1164 syslink_firmware[syslink_num_cores].proc = "SYSM3";
1165 #else
1166 syslink_firmware[syslink_num_cores].proc = "CORE0";
1167 #endif
1168 syslink_num_cores++;
1169 #ifndef SYSLINK_SYSBIOS_SMP
1170 syslink_firmware[syslink_num_cores].firmware = NULL;
1171 #if defined(SYSLINK_PLATFORM_OMAP4430)
1172 syslink_firmware[syslink_num_cores].proc = "APPM3";
1173 #else
1174 syslink_firmware[syslink_num_cores].proc = "CORE1";
1175 #endif
1176 syslink_num_cores++;
1177 #endif
1178 break;
1179 #if defined(SYSLINK_PLATFORM_OMAP5430)
1180 case 'd':
1181 syslink_firmware[syslink_num_cores].firmware = optarg;
1182 syslink_firmware[syslink_num_cores].proc = "DSP";
1183 syslink_num_cores++;
1184 break;
1185 #endif
1186 case 'H':
1187 hib_enable = atoi(optarg);
1188 if (hib_enable != 0 && hib_enable != 1) {
1189 hib_enable = -1;
1190 }
1191 break;
1192 case 'T':
1193 hib_timeout = atoi(optarg);
1194 break;
1195 case 'U':
1196 user_parm = optarg;
1197 break;
1198 case 'v':
1199 verbosity++;
1200 break;
1201 default:
1202 fprintf (stderr, "Unrecognized argument\n");
1203 }
1204 }
1206 /* Now parse the operands, which should be in the format:
1207 * "<multiproc_name> <firmware_file> ..*/
1208 for (; optind + 1 < argc; optind+=2) {
1209 if (syslink_num_cores == MultiProc_MAXPROCESSORS) {
1210 printUsage(argv[0]);
1211 return (error);
1212 }
1213 syslink_firmware[syslink_num_cores].proc = argv [optind];
1214 syslink_firmware[syslink_num_cores++].firmware = argv [optind+1];
1215 }
1218 /* Get the name of the binary from the input args */
1219 if (!syslink_num_cores) {
1220 fprintf(stderr, "-f or -d or <core_id> option must be specified");
1221 printUsage(argv[0]);
1222 return (error);
1223 }
1225 /* Validate hib_enable args */
1226 if (hib_enable == -1) {
1227 fprintf (stderr, "invalid hibernation enable value\n");
1228 printUsage(argv[0]);
1229 return (error);
1230 }
1232 syslink_hib_enable = (Bool)hib_enable;
1233 syslink_hib_timeout = hib_timeout;
1235 /* Init logging for syslink */
1236 if (Osal_initlogging(verbosity) != 0) {
1237 return -1;
1238 }
1240 /* Obtain I/O privity */
1241 error = ThreadCtl_r (_NTO_TCTL_IO, 0);
1242 if (error == -1) {
1243 Osal_printf("Unable to obtain I/O privity");
1244 return (error);
1245 }
1247 /* allocate the device structure */
1248 if (NULL == (dev = calloc(1, sizeof(syslink_dev_t)))) {
1249 Osal_printf("syslink: calloc() failed");
1250 return (-1);
1251 }
1253 /* create the channel */
1254 if ((channelid = ChannelCreate_r (_NTO_CHF_UNBLOCK |
1255 _NTO_CHF_DISCONNECT |
1256 _NTO_CHF_COID_DISCONNECT |
1257 _NTO_CHF_REPLY_LEN |
1258 _NTO_CHF_SENDER_LEN)) < 0) {
1259 Osal_printf("Unable to create channel %d", channelid);
1260 return (channelid);
1261 }
1263 /* create the dispatch structure */
1264 if (NULL == (dev->dpp = syslink_dpp = dispatch_create_channel (channelid, 0))) {
1265 Osal_printf("syslink: dispatch_create() failed");
1266 return(-1);
1267 }
1269 /* Initialize the thread pool */
1270 memset (&tattr, 0x00, sizeof (thread_pool_attr_t));
1271 tattr.handle = dev->dpp;
1272 tattr.context_alloc = dispatch_context_alloc;
1273 tattr.context_free = dispatch_context_free;
1274 tattr.block_func = dispatch_block;
1275 tattr.unblock_func = dispatch_unblock;
1276 tattr.handler_func = dispatch_handler;
1277 tattr.lo_water = 2;
1278 tattr.hi_water = 4;
1279 tattr.increment = 1;
1280 tattr.maximum = 10;
1282 /* Create the thread pool */
1283 if ((dev->tpool = thread_pool_create(&tattr, 0)) == NULL) {
1284 Osal_printf("syslink: thread pool create failed");
1285 return(-1);
1286 }
1288 /* init syslink */
1289 status = init_ipc(dev, syslink_firmware, FALSE);
1290 if (status < 0) {
1291 Osal_printf("syslink: IPC init failed");
1292 return(-1);
1293 }
1295 /* init the syslink device */
1296 status = init_devices(dev);
1297 if (status < 0) {
1298 Osal_printf("syslink: device init failed");
1299 return(-1);
1300 }
1302 #if (_NTO_VERSION >= 800)
1303 /* Relinquish privileges */
1304 status = procmgr_ability( 0,
1305 DENY_ALL | PROCMGR_AID_SPAWN,
1306 DENY_ALL | PROCMGR_AID_FORK,
1307 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PEER,
1308 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PHYS,
1309 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_INTERRUPT,
1310 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_PATHSPACE,
1311 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_RSRCDBMGR,
1312 PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETUID,
1313 (uint64_t)1, (uint64_t)~0,
1314 PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETGID,
1315 (uint64_t)1, (uint64_t)~0,
1316 PROCMGR_ADN_ROOT | PROCMGR_AOP_DENY | PROCMGR_AOP_LOCK | PROCMGR_AID_EOL);
1318 if (status != EOK) {
1319 Osal_printf("procmgr_ability failed! errno=%d", status);
1320 return EXIT_FAILURE;
1321 }
1323 /* Reduce priority to either what defined from command line or at least nobody */
1324 if (user_parm != NULL) {
1325 if (set_ids_from_arg(user_parm) < 0) {
1326 Osal_printf("unable to set uid/gid - %s", strerror(errno));
1327 return EXIT_FAILURE;
1328 }
1329 } else {
1330 if (setuid(99) != 0) {
1331 Osal_printf("unable to set uid - %s", strerror(errno));
1332 return EXIT_FAILURE;
1333 }
1334 }
1335 #endif
1337 /* make this a daemon process */
1338 if (-1 == procmgr_daemon(EXIT_SUCCESS,
1339 PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL)) {
1340 Osal_printf("syslink: procmgr_daemon() failed");
1341 return(-1);
1342 }
1344 /* start the thread pool */
1345 thread_pool_start(dev->tpool);
1347 /* Init slog2 and thread for Ducati traces */
1348 if (init_ducati_slog2() != 0) {
1349 return -1;
1350 }
1351 trace_active = TRUE;
1352 status = pthread_create (&thread_traces, NULL, ducatiTraceThread, NULL);
1353 if (status != EOK) {
1354 Osal_printf("pthread_create for trace thread failed err=%d", status);
1355 trace_active = FALSE;
1356 }
1358 /* Mask out unnecessary signals */
1359 sigfillset (&set);
1360 sigdelset (&set, SIGINT);
1361 sigdelset (&set, SIGTERM);
1362 pthread_sigmask (SIG_BLOCK, &set, NULL);
1364 /* Wait for one of these signals */
1365 sigemptyset (&set);
1366 sigaddset (&set, SIGINT);
1367 sigaddset (&set, SIGQUIT);
1368 sigaddset (&set, SIGTERM);
1370 Osal_printf("Syslink resource manager started");
1372 /* Wait for a signal */
1373 while (1)
1374 {
1375 switch (SignalWaitinfo (&set, NULL))
1376 {
1377 case SIGTERM:
1378 case SIGQUIT:
1379 case SIGINT:
1380 error = EOK;
1381 goto done;
1383 default:
1384 break;
1385 }
1386 }
1388 error = EOK;
1390 done:
1391 GT_0trace(curTrace, GT_4CLASS, "Syslink resource manager exiting \n");
1392 /* Stop ducatiTraceThread if running */
1393 pthread_mutex_lock(&trace_mutex);
1394 if (trace_active) {
1395 trace_active = FALSE;
1396 pthread_mutex_unlock(&trace_mutex);
1397 // Wake up if waiting on hibernation
1398 pthread_mutex_lock(&syslink_hib_mutex);
1399 syslink_hib_hibernating = FALSE;
1400 pthread_cond_broadcast(&syslink_hib_cond);
1401 pthread_mutex_unlock(&syslink_hib_mutex);
1402 error = pthread_join(thread_traces, NULL);
1403 if (error < 0) {
1404 Osal_printf("syslink: pthread_join failed with err=%d", error);
1405 }
1406 } else {
1407 pthread_mutex_unlock(&trace_mutex);
1408 }
1410 error = thread_pool_destroy(dev->tpool);
1411 if (error < 0)
1412 Osal_printf("syslink: thread_pool_destroy returned an error");
1413 deinit_ipc(dev, FALSE);
1414 deinit_devices(dev);
1415 free(dev);
1416 return (EOK);
1417 }