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