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