Improve MessageQ recovery on DRA7xx QNX
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / build / Qnx / resmgr / syslink_main.c
1 /*
2  *  @file       syslink_main.c
3  *
4  *  @brief      ipc main
5  *
6  *
7  *  @ver        02.00.00.46_alpha1
8  *
9  *  ============================================================================
10  *
11  *  Copyright (c) 2011-2015, Texas Instruments Incorporated
12  *
13  *  Redistribution and use in source and binary forms, with or without
14  *  modification, are permitted provided that the following conditions
15  *  are met:
16  *
17  *  *  Redistributions of source code must retain the above copyright
18  *     notice, this list of conditions and the following disclaimer.
19  *
20  *  *  Redistributions in binary form must reproduce the above copyright
21  *     notice, this list of conditions and the following disclaimer in the
22  *     documentation and/or other materials provided with the distribution.
23  *
24  *  *  Neither the name of Texas Instruments Incorporated nor the names of
25  *     its contributors may be used to endorse or promote products derived
26  *     from this software without specific prior written permission.
27  *
28  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
30  *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31  *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
32  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
35  *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
36  *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
37  *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
38  *  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  *  Contact information for paper mail:
40  *  Texas Instruments
41  *  Post Office Box 655303
42  *  Dallas, Texas 75265
43  *  Contact information:
44  *  http://www-k.ext.ti.com/sc/technical-support/product-information-centers.htm?
45  *  DCMP=TIHomeTracking&HQS=Other+OT+home_d_contact
46  *  ============================================================================
47  *
48  */
50 #include "proto.h"
52 #include <pthread.h>
53 #include <fcntl.h>
54 #include <stdint.h>
55 #include <sys/procmgr.h>
56 #include <sys/neutrino.h>
57 #include <sys/siginfo.h>
58 #include <signal.h>
59 #include <stdbool.h>
61 #include <IpcKnl.h>
63 /* OSAL & Utils headers */
64 #include <ti/syslink/utils/List.h>
65 #include <ti/syslink/utils/MemoryOS.h>
66 #include <ti/ipc/MultiProc.h>
67 #include <ti/ipc/NameServer.h>
68 #include <_MultiProc.h>
69 #include <_NameServer.h>
70 #include <_NameServer_daemon.h>
71 #include <_GateMP_daemon.h>
72 #include <OsalSemaphore.h>
73 #include <ti/syslink/utils/OsalPrint.h>
74 #if defined(IPC_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>
82 #include <ti-ipc.h>
84 #define DENY_ALL                    \
85             PROCMGR_ADN_ROOT        \
86             | PROCMGR_ADN_NONROOT   \
87             | PROCMGR_AOP_DENY      \
88             | PROCMGR_AOP_LOCK
91 static int verbosity = 2;
93 /* Disable recovery mechanism if true */
94 static int disableRecovery = false;
95 static char * logFilename = NULL;
97 /* Number of cores to attach to */
98 static int numAttach = 0;
100 #if defined(IPC_PLATFORM_VAYU)
101 static bool gatempEnabled = false;
102 static Int32 sr0OwnerProcId = -1;
103 #endif
105 // IPC hibernation global variables
106 Bool ipc_hib_enable = TRUE;
107 #if !defined(IPC_PLATFORM_OMAP5430)
108 #define PM_HIB_DEFAULT_TIME 5000
109 #endif
110 uint32_t ipc_hib_timeout = PM_HIB_DEFAULT_TIME;
111 Bool ipc_hib_hibernating = FALSE;
112 pthread_mutex_t ipc_hib_mutex = PTHREAD_MUTEX_INITIALIZER;
113 pthread_cond_t ipc_hib_cond = PTHREAD_COND_INITIALIZER;
115 extern Int rpmsg_rpc_setup (Void);
116 extern Void rpmsg_rpc_destroy (Void);
117 extern Void GateHWSpinlock_LeaveLockForPID(int pid);
119 typedef struct ipc_firmware_info_t {
120     uint16_t proc_id;
121     char * proc;
122     char * firmware;
123     bool attachOnly;
124     int  procState;  /* state of processor - index into procStateNames array */
125     int  readProcState; /* state that is currently being printed */
126     bool reload;     /* reload core during recovery */
127     bool freeString; /* Need to free previously allocated firmware string */
128 } ipc_firmware_info;
129 static ipc_firmware_info ipc_firmware[MultiProc_MAXPROCESSORS];
131 /* Number of valid entries in ipc_firmware array */
132 static unsigned int ipc_num_cores = 0;
134 int init_ipc(ipc_dev_t * dev, ipc_firmware_info * firmware,
135     bool recover);
136 int deinit_ipc(ipc_dev_t * dev, ipc_firmware_info * firmware,
137     bool recover);
138 int init_ipc_trace_device(ipc_dev_t *dev);
139 int deinit_ipc_trace_device(ipc_dev_t *dev);
141 Int ipc_error_cb (UInt16 procId, ProcMgr_Handle handle,
142                       ProcMgr_State fromState, ProcMgr_State toState,
143                       ProcMgr_EventStatus status, Ptr args);
145 static RscTable_Handle rscHandle[MultiProc_MAXPROCESSORS];
147 static ProcMgr_Handle procH[MultiProc_MAXPROCESSORS];
148 static unsigned int procH_fileId[MultiProc_MAXPROCESSORS];
149 static ProcMgr_State errStates[] = {ProcMgr_State_Mmu_Fault,
150                                     ProcMgr_State_Error,
151                                     ProcMgr_State_Watchdog,
152                                     ProcMgr_State_EndValue};
154 /* Processor states */
155 #define RESET_STATE  0
156 #define RUNNING_STATE 1
158 static String procStateNames[] = { "In reset\n",
159                                    "Running\n" };
161 typedef struct ipc_trace_info_t {
162     uintptr_t   va;
163     uint32_t    len;
164     uint32_t *  widx;
165     uint32_t *  ridx;
166     Bool        firstRead;
167 } ipc_trace_info;
169 static ipc_trace_info proc_traces[MultiProc_MAXPROCESSORS];
171 static int runSlave(ipc_dev_t *dev, uint16_t procId,
172     ipc_firmware_info * firmware_info)
174     int status = 0;
175     ProcMgr_AttachParams attachParams;
177     if (firmware_info->firmware) {
178         rscHandle[procId] = RscTable_alloc(firmware_info->firmware, procId);
179         if (rscHandle[procId] == NULL) {
180             status = -1;
181             return status;
182         }
183     }
185     status = ProcMgr_open(&procH[procId], procId);
186     if (status < 0 || procH[procId] == NULL) {
187         goto procmgropen_fail;
188     }
190     /* Load and start the remote processor. */
191     ProcMgr_getAttachParams(procH[procId], &attachParams);
192     if (firmware_info->attachOnly) {
193         attachParams.bootMode = ProcMgr_BootMode_NoBoot;
194     }
195     status = ProcMgr_attach(procH[procId], &attachParams);
196     if (status < 0) {
197         GT_setFailureReason(curTrace,
198                             GT_4CLASS,
199                             "runSlave",
200                             status,
201                             "ProcMgr_attach failed!");
202         goto procmgrattach_fail;
203     }
205     if ((firmware_info->firmware) &&
206         (!firmware_info->attachOnly)) {
207         status = ProcMgr_load(procH[procId],
208             (String)firmware_info->firmware, 0, NULL,
209              NULL, &procH_fileId[procId]);
210         if (status < 0) {
211             GT_setFailureReason(curTrace,
212                                 GT_4CLASS,
213                                 "runSlave",
214                                 status,
215                                 "ProcMgr_load failed!");
216             goto procmgrload_fail;
217         }
218     }
220     status = Ipc_attach(procId);
221     if (status < 0) {
222         GT_setFailureReason(curTrace,
223                              GT_4CLASS,
224                              "runSlave",
225                              status,
226                              "Ipc_attach failed!");
227         goto ipcattach_fail;
228     }
230     status = ProcMgr_registerNotify(procH[procId], ipc_error_cb, (Ptr)dev,
231         -1, errStates);
232     if (status < 0) {
233         goto procmgrreg_fail;
234     }
236     if (!firmware_info->attachOnly) {
237         status = ProcMgr_start(procH[procId], NULL);
238         if (status < 0) {
239             GT_setFailureReason(curTrace,
240                                 GT_4CLASS,
241                                 "runSlave",
242                                 status,
243                                 "ProcMgr_start failed!");
244             goto procmgrstart_fail;
245         }
246     }
248     Osal_printf("runSlave successful for core %d\n", procId);
250     return 0;
252 procmgrstart_fail:
253     ProcMgr_unregisterNotify(procH[procId], ipc_error_cb,
254         (Ptr)dev, errStates);
255 procmgrreg_fail:
256     Ipc_detach(procId);
257 ipcattach_fail:
258     if ((firmware_info->firmware) &&
259         (!firmware_info->attachOnly)) {
260         ProcMgr_unload(procH[procId], procH_fileId[procId]);
261     }
262 procmgrload_fail:
263     ProcMgr_detach(procH[procId]);
264 procmgrattach_fail:
265     ProcMgr_close(&procH[procId]);
266     procH[procId] = NULL;
267 procmgropen_fail:
268     RscTable_free(&rscHandle[procId]);
270     return -1;
273 static int resetSlave(ipc_dev_t *dev, uint16_t procId)
275     if ((procH[procId]) && (procH_fileId[procId])) {
276         GT_1trace(curTrace, GT_4CLASS, "stopping %s", MultiProc_getName(procId));
277         ProcMgr_stop(procH[procId]);
278     }
280     if (procH[procId]) {
281         ProcMgr_unregisterNotify(procH[procId], ipc_error_cb, (Ptr)dev,
282             errStates);
283         Ipc_detach(procId);
284         if (procH_fileId[procId]) {
285             ProcMgr_unload(procH[procId], procH_fileId[procId]);
286             procH_fileId[procId] = 0;
287         }
288         ProcMgr_detach(procH[procId]);
289         ProcMgr_close(&procH[procId]);
290         procH[procId] = NULL;
291         RscTable_free(&rscHandle[procId]);
292         rscHandle[procId] = NULL;
293     }
295     Osal_printf("resetSlave successful for core %d\n", procId);
297     return 0;
300 /* Add firmware entry after IPC is setup */
301 static void addFirmware(uint16_t procId)
303     ipc_firmware[ipc_num_cores].proc =
304         MultiProc_getName(procId);
305     ipc_firmware[ipc_num_cores].proc_id = procId;
306     ipc_firmware[ipc_num_cores].attachOnly = false;
307     ipc_firmware[ipc_num_cores].reload = false;
308     ipc_firmware[ipc_num_cores].procState = RESET_STATE;
309     ipc_firmware[ipc_num_cores].freeString = false;
310     ipc_firmware[ipc_num_cores++].firmware = NULL;
312     return;
315 static int slave_state_read(resmgr_context_t *ctp, io_read_t *msg,
316     ipc_ocb_t *ocb)
318     int             nbytes;
319     int             nparts;
320     int             status;
321     int             nleft;
322     int             i;
323     uint16_t        procId = ocb->ocb.attr->procid;
324     ipc_dev_t * dev = ocb->ocb.attr->dev;
326     if ((status = iofunc_read_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
327         return (status);
328     }
330     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
331         return (ENOSYS);
332     }
334     pthread_mutex_lock(&dev->firmwareLock);
336     for (i = 0; i < ipc_num_cores; i++) {
337         if (ipc_firmware[i].proc_id == procId) {
338             break;
339         }
340     }
341     if (i == ipc_num_cores) {
342         if ((ipc_num_cores < MultiProc_MAXPROCESSORS)) {
343             addFirmware(procId);
344         }
345         else {
346             pthread_mutex_unlock(&dev->firmwareLock);
347             return (EBADSLT);
348         }
349     }
351     if (ocb->ocb.offset == 0) {
352         /* latch onto new state, so that we print out complete strings */
353         ipc_firmware[i].readProcState = ipc_firmware[i].procState;
354     }
356     nleft = strlen(procStateNames[ipc_firmware[i].readProcState])
357         - ocb->ocb.offset; /* the state is expressed in one byte */
358     nbytes = min(msg->i.nbytes, nleft);
360     /* Make sure the user has supplied a big enough buffer */
361     if (nbytes > 0) {
362         /* set up the return data IOV */
363         SETIOV(ctp->iov,
364             (char *)procStateNames[ipc_firmware[i].readProcState]
365             + ocb->ocb.offset, nbytes);
367         pthread_mutex_unlock(&dev->firmwareLock);
369         /* set up the number of bytes (returned by client's read()) */
370         _IO_SET_READ_NBYTES(ctp, nbytes);
372         ocb->ocb.offset += nbytes;
374         nparts = 1;
375     }
376     else {
377         pthread_mutex_unlock(&dev->firmwareLock);
379         _IO_SET_READ_NBYTES (ctp, 0);
381         /* reset offset */
382         ocb->ocb.offset = 0;
384         nparts = 0;
385     }
387     /* mark the access time as invalid (we just accessed it) */
389     if (msg->i.nbytes > 0) {
390         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
391     }
393     return (_RESMGR_NPARTS(nparts));
396 static int slave_state_write(resmgr_context_t *ctp, io_write_t *msg,
397     ipc_ocb_t *ocb)
399     int             status;
400     char *          buf;
401     uint16_t        procId = ocb->ocb.attr->procid;
402     int             i;
403     char *          ptr;
404     ipc_dev_t * dev = ocb->ocb.attr->dev;
405     Int32           sr0ProcId;
407     if ((status = iofunc_write_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
408         return (status);
409     }
411     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
412         return (ENOSYS);
413     }
415     /* set up the number of bytes (returned by client's write()) */
416     _IO_SET_WRITE_NBYTES (ctp, msg->i.nbytes);
418     buf = (char *) malloc(msg->i.nbytes + 1);
419     if (buf == NULL) {
420         return (ENOMEM);
421     }
423     /*
424      *  Read the data from the sender's message buffer.
425      */
426     resmgr_msgread(ctp, buf, msg->i.nbytes, sizeof(msg->i));
427     buf[msg->i.nbytes] = '\0'; /* just in case the text is not NULL terminated */
428     if((ptr = strchr(buf, '\n')) != NULL) { /* Remove line feed if any */
429         *ptr = '\0';
430     }
432     pthread_mutex_lock(&dev->firmwareLock);
433     for (i = 0; i < ipc_num_cores; i++) {
434         if (ipc_firmware[i].proc_id == procId) {
435             break;
436         }
437     }
438     if (i == ipc_num_cores) {
439         if ((ipc_num_cores < MultiProc_MAXPROCESSORS)) {
440             addFirmware(procId);
441         }
442         else {
443             pthread_mutex_unlock(&dev->firmwareLock);
444             return (EBADSLT);
445         }
446     }
448     if (strcmp("1", buf) == 0) {
449         if ((ipc_firmware[i].procState == RESET_STATE) &&
450            (ipc_firmware[i].firmware != NULL)) {
451             status = runSlave(ocb->ocb.attr->dev, procId, &ipc_firmware[i]);
452             if (status < 0) {
453                 pthread_mutex_unlock(&dev->firmwareLock);
454                 free(buf);
455                 fprintf(stderr, "IPC: failed to run slave core %s\n",
456                     MultiProc_getName(procId));
457                 return (EIO);
458             }
459 #if defined(IPC_PLATFORM_VAYU)
460             if (gatempEnabled) {
461                 if (sr0OwnerProcId == -1) {
462                     /* Set up GateMP */
463                     status = GateMP_setup(&sr0ProcId);
464                     if ((status < 0) && (status != GateMP_E_NOTFOUND)) {
465                         resetSlave(ocb->ocb.attr->dev, procId);
466                         pthread_mutex_unlock(&dev->firmwareLock);
467                         free(buf);
468                         fprintf(stderr, "GateMP_setup failed\n");
469                         return (EIO);
470                     }
471                     else if (status == 0) {
472                         /* We have discovered an owner for SR0 */
473                         sr0OwnerProcId = sr0ProcId;
474                     }
475                 }
476                 else {
477                     /*
478                      * We have already identified SR0 owner and setup GateMP.
479                      * Do nothing.
480                      */
481                 }
482             }
483 #endif
484             printf("Core is now running with image '%s'\n",
485                 ipc_firmware[i].firmware);
486             ipc_firmware[i].procState = RUNNING_STATE;
487             ipc_firmware[i].reload = true;
488             status = init_ipc_trace_device(dev);
489             if (status < 0) {
490 #if defined(IPC_PLATFORM_VAYU)
491                 if ((gatempEnabled) && (procId == sr0OwnerProcId)) {
492                     sr0OwnerProcId = -1;
493                     GateMP_destroy(FALSE);
494                 }
495 #endif
496                 resetSlave(ocb->ocb.attr->dev, procId);
497                 pthread_mutex_unlock(&dev->firmwareLock);
498                 free(buf);
499                 fprintf(stderr, "IPC: init_ipc_trace_device failed %d\n",
500                     status);
501                 return (EIO);
502             }
503             printf("Core %s has been started.\n", MultiProc_getName(procId));
504         }
505     }
506     else if (strcmp("0", buf) == 0) {
507         if (ipc_firmware[i].procState == RUNNING_STATE) {
508 #if defined(IPC_PLATFORM_VAYU)
509             if ((gatempEnabled) && (procId == sr0OwnerProcId)) {
510                 sr0OwnerProcId = -1;
511                 status = GateMP_destroy(FALSE);
512                 if (status < 0) {
513                     pthread_mutex_unlock(&dev->firmwareLock);
514                     free(buf);
515                     fprintf(stderr, "Core %s cannot be reset. GateMP may still"
516                         " be in use by host\n", MultiProc_getName(procId));
517                     return (EIO);
518                 }
519             }
520 #endif
521             status = resetSlave(ocb->ocb.attr->dev, procId);
522             if (status < 0) {
523                 pthread_mutex_unlock(&dev->firmwareLock);
524                 free(buf);
525                 fprintf(stderr, "IPC: failed to reset slave core %s\n",
526                     MultiProc_getName(procId));
527                 return (EIO);
528             }
529             ipc_firmware[i].procState = RESET_STATE;
530             ipc_firmware[i].reload = false;
531             status = deinit_ipc_trace_device(dev);
532             if (status < 0) {
533                 pthread_mutex_unlock(&dev->firmwareLock);
534                 free(buf);
535                 fprintf(stderr, "IPC: deinit_ipc_trace_device failed %d\n",
536                     status);
537                 return (EIO);
538             }
539             printf("Core %s has been reset.\n", MultiProc_getName(procId));
540         }
541     }
542     else {
543         /* ignore the input as it is not recognized */
544         fprintf(stderr, "Unrecognized input\n");
545     }
547     pthread_mutex_unlock(&dev->firmwareLock);
549     free(buf);
551     if (msg->i.nbytes > 0) {
552         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_MTIME | IOFUNC_ATTR_CTIME;
553     }
555     return (_RESMGR_NPARTS(0));
558 static int slave_file_read(resmgr_context_t *ctp, io_read_t *msg,
559     ipc_ocb_t *ocb)
561     int             nbytes;
562     int             nparts;
563     int             status;
564     int             nleft;
565     int             i;
566     uint16_t        procId = ocb->ocb.attr->procid;
567     ipc_dev_t * dev = ocb->ocb.attr->dev;
569     if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK) {
570         return (status);
571     }
573     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
574         return (ENOSYS);
575     }
577     pthread_mutex_lock(&dev->firmwareLock);
578     for (i = 0; i < ipc_num_cores; i++) {
579         if (ipc_firmware[i].proc_id == procId) {
580             break;
581         }
582     }
584     if (i == ipc_num_cores) {
585         if ((ipc_num_cores < MultiProc_MAXPROCESSORS)) {
586             addFirmware(procId);
587         }
588         else {
589             pthread_mutex_unlock(&dev->firmwareLock);
590             return (EBADSLT);
591         }
592     }
594     if (ipc_firmware[i].firmware == NULL) {
595         nbytes = 0;
596     }
597     else {
598         nleft = strlen(ipc_firmware[i].firmware)
599             - ocb->ocb.offset + 1; /* Add one byte for carriage return */
600         nbytes = min(msg->i.nbytes, nleft);
601     }
603     /* Make sure the user has supplied a big enough buffer */
604     if (nbytes > 0) {
605         if (nbytes == nleft) {
606             /* set up the return data IOV */
607             SETIOV(&ctp->iov[0], (char *)ipc_firmware[i].firmware
608                 + ocb->ocb.offset, nbytes - 1);
610             /* add a carriage return */
611             SETIOV(&ctp->iov[1], "\n", 1);
613             nparts = 2;
614         }
615         else {
616             /* set up the return data IOV */
617             SETIOV(ctp->iov, (char *)ipc_firmware[i].firmware
618                 + ocb->ocb.offset, nbytes);
620             nparts = 1;
621         }
623         /* set up the number of bytes (returned by client's read()) */
624         _IO_SET_READ_NBYTES(ctp, nbytes);
626         ocb->ocb.offset += nbytes;
627     }
628     else {
629         _IO_SET_READ_NBYTES (ctp, 0);
631         /* reset offset */
632         ocb->ocb.offset = 0;
634         nparts = 0;
635     }
637     pthread_mutex_unlock(&dev->firmwareLock);
639     /* mark the access time as invalid (we just accessed it) */
641     if (msg->i.nbytes > 0) {
642         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
643     }
645     return (_RESMGR_NPARTS(nparts));
648 static int slave_file_write(resmgr_context_t *ctp, io_write_t *msg,
649     ipc_ocb_t *ocb)
651     int             status;
652     char *          buf;
653     uint16_t        procId = ocb->ocb.attr->procid;
654     int             i;
655     char *          absPath;
656     char *          ptr;
657     ipc_dev_t * dev = ocb->ocb.attr->dev;
659     if ((status = iofunc_write_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
660         return (status);
661     }
663     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
664         return (ENOSYS);
665     }
667     /* set up the number of bytes (returned by client's write()) */
668     _IO_SET_WRITE_NBYTES (ctp, msg->i.nbytes);
670     buf = (char *) malloc(msg->i.nbytes + 1);
671     if (buf == NULL) {
672         return (ENOMEM);
673     }
675     /*
676      *  Read the data from the sender's message buffer.
677      */
678     resmgr_msgread(ctp, buf, msg->i.nbytes, sizeof(msg->i));
679     buf[msg->i.nbytes] = '\0'; /* just in case the text is not NULL terminated */
680     if((ptr = strchr(buf, '\n')) != NULL) { /* Remove line feed if any */
681         *ptr = '\0';
682     }
684     /* Get the abs path for all firmware files */
685     absPath = calloc(1, PATH_MAX + 1);
686     if (absPath == NULL) {
687         free(buf);
688         return (ENOMEM);
689     }
690     if (NULL == realpath(buf, absPath)) {
691         fprintf(stderr, "invalid path to executable: %d\n", errno);
692         fprintf(stderr, "make sure you are specifying the full path to the "
693             "file.\n");
694         free(absPath);
695         free(buf);
696         return (ENOENT);
697     }
698     free(buf);
700     pthread_mutex_lock(&dev->firmwareLock);
702     /*
703      * Check if an entry in ipc_firmware already exists for this core.
704      * If not, create one. Otherwise just update the firmware path.
705      */
706     for (i = 0; i < ipc_num_cores; i++) {
707         if (ipc_firmware[i].proc_id == procId) {
708             break;
709         }
710     }
711     if (i == ipc_num_cores) {
712         if (ipc_num_cores < MultiProc_MAXPROCESSORS) {
713             addFirmware(procId);
714             ipc_firmware[ipc_num_cores - 1].freeString = true;
715             ipc_firmware[ipc_num_cores - 1].firmware = absPath;
716         }
717         else {
718             pthread_mutex_unlock(&dev->firmwareLock);
719             free(absPath);
720             return (EBADSLT);
721         }
722     }
723     else {
724         /* Free previously allocated string */
725         if ((ipc_firmware[i].freeString) &&
726            (ipc_firmware[i].firmware)) {
727             free(ipc_firmware[i].firmware);
728         }
729         ipc_firmware[i].firmware = absPath;
730     }
732     pthread_mutex_unlock(&dev->firmwareLock);
734     if (msg->i.nbytes > 0) {
735         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_MTIME | IOFUNC_ATTR_CTIME;
736     }
738     return (_RESMGR_NPARTS(0));
741 int ipc_read(resmgr_context_t *ctp, io_read_t *msg, ipc_ocb_t *ocb)
743     int         nbytes;
744     int         nparts;
745     int         status;
746     int         nleft;
747     uint32_t    len;
748     uint16_t    procid = ocb->ocb.attr->procid;
750     if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK)
751         return (status);
753     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE)
754         return (ENOSYS);
756     /* check to see where the trace buffer is */
757     if (proc_traces[procid].va == NULL) {
758         return (ENOSYS);
759     }
760     if (ocb->ocb.offset == 0) {
761         ocb->widx = *(proc_traces[procid].widx);
762         ocb->ridx = *(proc_traces[procid].ridx);
763         *(proc_traces[procid].ridx) = ocb->widx;
764     }
766     /* Check for wrap-around */
767     if (ocb->widx < ocb->ridx)
768         len = proc_traces[procid].len - ocb->ridx + ocb->widx;
769     else
770         len = ocb->widx - ocb->ridx;
772     /* Determine the amount left to print */
773     if (ocb->widx >= ocb->ridx)
774         nleft = len - ocb->ocb.offset;
775     else if (ocb->ocb.offset < proc_traces[procid].len - ocb->ridx)
776         nleft = proc_traces[procid].len - ocb->ridx - ocb->ocb.offset;
777     else
778         nleft = proc_traces[procid].len - ocb->ridx + ocb->widx - ocb->ocb.offset;
780     nbytes = min (msg->i.nbytes, nleft);
782     /* Make sure the user has supplied a big enough buffer */
783     if (nbytes > 0) {
784         /* set up the return data IOV */
785         if (ocb->widx < ocb->ridx && ocb->ocb.offset >= proc_traces[procid].len - ocb->ridx)
786             SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ocb.offset - (proc_traces[procid].len - ocb->ridx), nbytes);
787         else
788             SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ridx + ocb->ocb.offset, nbytes);
790         /* set up the number of bytes (returned by client's read()) */
791         _IO_SET_READ_NBYTES (ctp, nbytes);
793         ocb->ocb.offset += nbytes;
795         nparts = 1;
796     }
797     else {
798         _IO_SET_READ_NBYTES (ctp, 0);
800         /* reset offset */
801         ocb->ocb.offset = 0;
803         nparts = 0;
804     }
806     /* mark the access time as invalid (we just accessed it) */
808     if (msg->i.nbytes > 0)
809         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
811     return (_RESMGR_NPARTS (nparts));
814 extern OsalSemaphore_Handle mqcopy_test_sem;
816 int ipc_unblock(resmgr_context_t *ctp, io_pulse_t *msg, ipc_ocb_t *ocb)
818     int status = _RESMGR_NOREPLY;
819     struct _msg_info info;
821     /*
822      * Try to run the default unblock for this message.
823      */
824     if ((status = iofunc_unblock_default(ctp,msg,&(ocb->ocb))) != _RESMGR_DEFAULT) {
825         return status;
826     }
828     /*
829      * Check if rcvid is still valid and still has an unblock
830      * request pending.
831      */
832     if (MsgInfo(ctp->rcvid, &info) == -1 ||
833         !(info.flags & _NTO_MI_UNBLOCK_REQ)) {
834         return _RESMGR_NOREPLY;
835     }
837     if (mqcopy_test_sem)
838         OsalSemaphore_post(mqcopy_test_sem);
840     return _RESMGR_NOREPLY;
843 IOFUNC_OCB_T *
844 ipc_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
846     ipc_ocb_t *ocb = NULL;
848     /* Allocate the OCB */
849     ocb = (ipc_ocb_t *) calloc (1, sizeof (ipc_ocb_t));
850     if (ocb == NULL){
851         errno = ENOMEM;
852         return (NULL);
853     }
855     ocb->pid = ctp->info.pid;
857     return (IOFUNC_OCB_T *)(ocb);
860 void
861 ipc_ocb_free (IOFUNC_OCB_T * i_ocb)
863     ipc_ocb_t * ocb = (ipc_ocb_t *)i_ocb;
865     if (ocb) {
866 #ifndef IPC_PLATFORM_VAYU
867         GateHWSpinlock_LeaveLockForPID(ocb->pid);
868 #endif
869         free (ocb);
870     }
873 int init_slave_devices(ipc_dev_t *dev)
875     resmgr_attr_t    resmgr_attr;
876     int              i;
877     ipc_attr_t * slave_attr;
878     int              status = 0;
880     memset(&resmgr_attr, 0, sizeof resmgr_attr);
881     resmgr_attr.nparts_max = 2;
882     resmgr_attr.msg_max_size = _POSIX_PATH_MAX;
884     /* Populate the /dev/ipc-state namespace */
885     for (i = 1; i < MultiProc_getNumProcessors(); i++) {
886         iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->ipc.cfuncs_state[i],
887                          _RESMGR_IO_NFUNCS, &dev->ipc.iofuncs_state[i]);
888         slave_attr = &dev->ipc.cattr_slave[i];
889         iofunc_attr_init(&slave_attr->attr,
890                          S_IFCHR | 0777, NULL, NULL);
891         slave_attr->attr.mount = &dev->ipc.mattr;
892         slave_attr->procid = i;
893         slave_attr->dev = (Ptr)dev;
894         iofunc_time_update(&slave_attr->attr);
895         snprintf(dev->ipc.device_name, _POSIX_PATH_MAX,
896                   "%s-state/%s", IPC_DEVICE_PATH, MultiProc_getName(i));
897         dev->ipc.iofuncs_state[i].read = slave_state_read;
898         dev->ipc.iofuncs_state[i].write = slave_state_write;
900         if (-1 == (dev->ipc.resmgr_id_state[i] =
901             resmgr_attach(dev->dpp, &resmgr_attr,
902                 dev->ipc.device_name, _FTYPE_ANY, 0,
903                 &dev->ipc.cfuncs_state[i],
904                 &dev->ipc.iofuncs_state[i],
905                 &slave_attr->attr))) {
906             GT_setFailureReason(curTrace, GT_4CLASS, "init_slave_devices",
907                 status, "resmgr_attach failed");
908             return (-1);
909         }
910     }
912     /* Populate the /dev/ipc-file namespace */
913     for (i = 1; i < MultiProc_getNumProcessors(); i++) {
914         iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->ipc.cfuncs_file[i],
915                          _RESMGR_IO_NFUNCS, &dev->ipc.iofuncs_file[i]);
916         slave_attr = &dev->ipc.cattr_slave[i];
917         iofunc_attr_init(&slave_attr->attr,
918                          S_IFCHR | 0777, NULL, NULL);
919         slave_attr->attr.mount = &dev->ipc.mattr;
920         slave_attr->procid = i;
921         slave_attr->dev = (Ptr)dev;
922         iofunc_time_update(&slave_attr->attr);
923         snprintf(dev->ipc.device_name, _POSIX_PATH_MAX,
924                   "%s-file/%s", IPC_DEVICE_PATH, MultiProc_getName(i));
925         dev->ipc.iofuncs_file[i].read = slave_file_read;
926         dev->ipc.iofuncs_file[i].write = slave_file_write;
928         if (-1 == (dev->ipc.resmgr_id_file[i] =
929             resmgr_attach(dev->dpp, &resmgr_attr,
930                 dev->ipc.device_name, _FTYPE_ANY, 0,
931                 &dev->ipc.cfuncs_file[i],
932                 &dev->ipc.iofuncs_file[i],
933                 &slave_attr->attr))) {
934             GT_setFailureReason(curTrace, GT_4CLASS, "init_slave_devices",
935                 status, "resmgr_attach failed");
936             return (-1);
937         }
938     }
940     return (status);
943 int deinit_slave_devices(ipc_dev_t *dev)
945     int status = EOK;
946     int i = 0;
948     for (i = 1; i < MultiProc_getNumProcessors(); i++) {
949         status = resmgr_detach(dev->dpp, dev->ipc.resmgr_id_state[i], 0);
950         if (status < 0) {
951             Osal_printf("IPC: resmgr_detach of state device %d failed: %d",
952                 i, errno);
953         }
954         status = resmgr_detach(dev->dpp, dev->ipc.resmgr_id_file[i], 0);
955         if (status < 0) {
956             Osal_printf("IPC: resmgr_detach of file device %d failed: %d",
957                 i, errno);
958         }
959     }
961     return (status);
964 int init_ipc_trace_device(ipc_dev_t *dev)
966     resmgr_attr_t    resmgr_attr;
967     int              i;
968     ipc_attr_t * trace_attr;
969     char             trace_name[_POSIX_PATH_MAX];
970     int              status = 0;
971     unsigned int     da = 0, pa = 0;
972     unsigned int     len;
974     memset(&resmgr_attr, 0, sizeof resmgr_attr);
975     resmgr_attr.nparts_max = 10;
976     resmgr_attr.msg_max_size = 2048;
978     for (i = 0; i < ipc_num_cores; i++) {
979         /*
980          * Initialize trace device only for cores that are running and their
981          * device is not yet setup.
982          */
983         if ((ipc_firmware[i].procState == RUNNING_STATE) &&
984             (proc_traces[i].va == NULL)) {
985             iofunc_func_init(_RESMGR_CONNECT_NFUNCS,
986                 &dev->ipc.cfuncs_trace[i],
987                 _RESMGR_IO_NFUNCS, &dev->ipc.iofuncs_trace[i]);
988             trace_attr = &dev->ipc.cattr_trace[i];
989             iofunc_attr_init(&trace_attr->attr,
990                          S_IFCHR | 0777, NULL, NULL);
991             trace_attr->attr.mount = &dev->ipc.mattr;
992             trace_attr->procid = i;
993             iofunc_time_update(&trace_attr->attr);
994             snprintf(dev->ipc.device_name, _POSIX_PATH_MAX,
995                 "%s-trace/%s", IPC_DEVICE_PATH,
996                 MultiProc_getName(ipc_firmware[i].proc_id));
997             dev->ipc.iofuncs_trace[i].read = ipc_read;
998             snprintf (trace_name, _POSIX_PATH_MAX, "%d", 0);
999             pa = 0;
1000             status = RscTable_getInfo(ipc_firmware[i].proc_id, TYPE_TRACE,
1001                 0, &da, &pa, &len);
1002             if (status == 0) {
1003                 /* last 8 bytes are for writeIdx/readIdx */
1004                 proc_traces[i].len = len - (sizeof(uint32_t) * 2);
1005                 if (da && !pa) {
1006                     /* need to translate da->pa */
1007                     status = ProcMgr_translateAddr(
1008                         procH[ipc_firmware[i].proc_id],
1009                         (Ptr *) &pa,
1010                         ProcMgr_AddrType_MasterPhys,
1011                         (Ptr) da,
1012                         ProcMgr_AddrType_SlaveVirt);
1013                 }
1014                 else {
1015                     GT_setFailureReason(curTrace, GT_4CLASS,
1016                         "init_ipc_trace_device",
1017                         status, "not performing ProcMgr_translate");
1018                 }
1019                 /* map length aligned to page size */
1020                 proc_traces[i].va =
1021                     mmap_device_io (((len + 0x1000 - 1) / 0x1000) * 0x1000, pa);
1022                 proc_traces[i].widx = (uint32_t *)(proc_traces[i].va + \
1023                                                proc_traces[i].len);
1024                 proc_traces[i].ridx = (uint32_t *)((uint32_t)proc_traces[i].widx
1025                     + sizeof(uint32_t));
1026                 if (proc_traces[i].va == MAP_DEVICE_FAILED) {
1027                     GT_setFailureReason(curTrace, GT_4CLASS,
1028                         "init_ipc_trace_device",
1029                         status, "mmap_device_io failed");
1030                     GT_1trace(curTrace, GT_4CLASS, "errno %d", errno);
1031                     proc_traces[i].va = NULL;
1032                 }
1033                 proc_traces[i].firstRead = TRUE;
1034             }
1035             else {
1036                 GT_setFailureReason(curTrace, GT_4CLASS,
1037                     "init_ipc_trace_device",
1038                     status, "RscTable_getInfo failed");
1039                 proc_traces[i].va = NULL;
1040             }
1041             if (-1 == (dev->ipc.resmgr_id_trace[i] =
1042                        resmgr_attach(dev->dpp, &resmgr_attr,
1043                                      dev->ipc.device_name, _FTYPE_ANY, 0,
1044                                      &dev->ipc.cfuncs_trace[i],
1045                                      &dev->ipc.iofuncs_trace[i],
1046                                      &trace_attr->attr))) {
1047                 GT_setFailureReason(curTrace, GT_4CLASS,
1048                     "init_ipc_trace_device",
1049                     status, "resmgr_attach failed");
1050                 return(-1);
1051             }
1052         }
1053     }
1055     return (status);
1058 int deinit_ipc_trace_device(ipc_dev_t *dev)
1060     int status = EOK;
1061     int i = 0;
1063     for (i = 0; i < ipc_num_cores; i++) {
1064         /* Only disable trace device on cores in RESET state */
1065         if ((ipc_firmware[i].procState == RESET_STATE) &&
1066             (proc_traces[i].va != NULL)) {
1067             status = resmgr_detach(dev->dpp, dev->ipc.resmgr_id_trace[i],
1068                 0);
1069             if (status < 0) {
1070                 Osal_printf("IPC: resmgr_detach of trace device %d failed: %d",
1071                     i, errno);
1072                 status = errno;
1073             }
1074             if (proc_traces[i].va && proc_traces[i].va != MAP_DEVICE_FAILED) {
1075                 munmap((void *)proc_traces[i].va,
1076                    ((proc_traces[i].len + 8 + 0x1000 - 1) / 0x1000) * 0x1000);
1077             }
1078             proc_traces[i].va = NULL;
1079         }
1080     }
1082     return (status);
1085 /* Initialize the ipc device */
1086 int init_ipc_device(ipc_dev_t *dev)
1088     iofunc_attr_t *  attr;
1089     resmgr_attr_t    resmgr_attr;
1090     int              status = 0;
1092     pthread_mutex_init(&dev->lock, NULL);
1093     pthread_mutex_init(&dev->firmwareLock, NULL);
1095     memset(&resmgr_attr, 0, sizeof resmgr_attr);
1096     resmgr_attr.nparts_max = 10;
1097     resmgr_attr.msg_max_size = 2048;
1099     memset(&dev->ipc.mattr, 0, sizeof(iofunc_mount_t));
1100     dev->ipc.mattr.flags = ST_NOSUID | ST_NOEXEC;
1101     dev->ipc.mattr.conf = IOFUNC_PC_CHOWN_RESTRICTED |
1102                               IOFUNC_PC_NO_TRUNC |
1103                               IOFUNC_PC_SYNC_IO;
1104     dev->ipc.mattr.funcs = &dev->ipc.mfuncs;
1106     memset(&dev->ipc.mfuncs, 0, sizeof(iofunc_funcs_t));
1107     dev->ipc.mfuncs.nfuncs = _IOFUNC_NFUNCS;
1109     iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->ipc.cfuncs,
1110                     _RESMGR_IO_NFUNCS, &dev->ipc.iofuncs);
1112     iofunc_attr_init(attr = &dev->ipc.cattr, S_IFCHR | 0777, NULL, NULL);
1114     dev->ipc.mfuncs.ocb_calloc = ipc_ocb_calloc;
1115     dev->ipc.mfuncs.ocb_free = ipc_ocb_free;
1116     dev->ipc.iofuncs.devctl = ipc_devctl;
1117     dev->ipc.iofuncs.unblock = ipc_unblock;
1119     attr->mount = &dev->ipc.mattr;
1120     iofunc_time_update(attr);
1122     if (-1 == (dev->ipc.resmgr_id =
1123         resmgr_attach(dev->dpp, &resmgr_attr,
1124                       IPC_DEVICE_PATH, _FTYPE_ANY, 0,
1125                       &dev->ipc.cfuncs,
1126                       &dev->ipc.iofuncs, attr))) {
1127         return(-1);
1128     }
1130     status = init_slave_devices(dev);
1131     if (status < 0) {
1132         return status;
1133     }
1135     status = init_ipc_trace_device(dev);
1136     if (status < 0) {
1137         return status;
1138     }
1140     return(0);
1143 /* De-initialize the ipc device */
1144 int deinit_ipc_device(ipc_dev_t *dev)
1146     int status = EOK;
1148     status = resmgr_detach(dev->dpp, dev->ipc.resmgr_id, 0);
1149     if (status < 0) {
1150         Osal_printf("IPC: resmgr_detach of %s failed: %d",
1151             IPC_DEVICE_PATH, errno);
1152         status = errno;
1153     }
1155     status = deinit_ipc_trace_device(dev);
1156     if (status < 0) {
1157         Osal_printf("IPC: deinit_ipc_trace_device failed %d", status);
1158     }
1160     status = deinit_slave_devices(dev);
1161     if (status < 0) {
1162         Osal_printf("IPC: deinit_slave_devices failed %d", status);
1163     }
1165     pthread_mutex_destroy(&dev->lock);
1166     pthread_mutex_destroy(&dev->firmwareLock);
1168     return(status);
1172 /* Initialize the devices */
1173 int init_devices(ipc_dev_t *dev)
1175     if (init_ipc_device(dev) < 0) {
1176         Osal_printf("IPC: device init failed");
1177         return(-1);
1178     }
1180     return(0);
1184 /* De-initialize the devices */
1185 int deinit_devices(ipc_dev_t *dev)
1187     int status = EOK;
1189     if ((status = deinit_ipc_device(dev)) < 0) {
1190         fprintf( stderr, "IPC: device de-init failed %d\n", status);
1191         status = errno;
1192     }
1194     return(status);
1197 static void ipc_recover(Ptr args)
1199     ipc_dev_t * dev = (ipc_dev_t *)args;
1201     if (!disableRecovery) {
1202         /* Protect the ipc_firmware array as we recover */
1203         pthread_mutex_lock(&dev->firmwareLock);
1204         deinit_ipc(dev, ipc_firmware, TRUE);
1205         deinit_ipc_trace_device(dev);
1206         init_ipc(dev, ipc_firmware, TRUE);
1207         init_ipc_trace_device(dev);
1208         pthread_mutex_unlock(&dev->firmwareLock);
1209     }
1210     else {
1211         GT_0trace(curTrace, GT_4CLASS,
1212                   "ipc_recover: Recovery disabled.\n");
1213     }
1216 Int ipc_error_cb (UInt16 procId, ProcMgr_Handle handle,
1217                       ProcMgr_State fromState, ProcMgr_State toState,
1218                       ProcMgr_EventStatus status, Ptr args)
1220     Int ret = 0;
1221     String errString = NULL;
1222     ipc_dev_t * dev = (ipc_dev_t *)args;
1224     if (status == ProcMgr_EventStatus_Event) {
1225         switch (toState) {
1226             case ProcMgr_State_Mmu_Fault:
1227                 errString = "MMU Fault";
1228                 break;
1229             case ProcMgr_State_Error:
1230                 errString = "Exception";
1231                 break;
1232             case ProcMgr_State_Watchdog:
1233                 errString = "Watchdog";
1234                 break;
1235             default:
1236                 errString = "Unexpected State";
1237                 ret = -1;
1238                 break;
1239         }
1240         GT_2trace (curTrace, GT_4CLASS,
1241                    "ipc_error_cb: Received Error Callback for %s : %s\n",
1242                    MultiProc_getName(procId), errString);
1243         /* Don't allow re-schedule of recovery until complete */
1244         pthread_mutex_lock(&dev->lock);
1245         if (ret != -1 && dev->recover == FALSE) {
1246             /* Schedule recovery. */
1247             dev->recover = TRUE;
1248             /* Activate a thread to handle the recovery. */
1249             GT_0trace (curTrace, GT_4CLASS,
1250                        "ipc_error_cb: Scheduling recovery...");
1251             OsalThread_activate(dev->ipc_recovery_work);
1252         }
1253         else {
1254             GT_0trace (curTrace, GT_4CLASS,
1255                        "ipc_error_cb: Recovery already scheduled.");
1256         }
1257         pthread_mutex_unlock(&dev->lock);
1258     }
1259     else if (status == ProcMgr_EventStatus_Canceled) {
1260         GT_1trace (curTrace, GT_3CLASS,
1261                    "Ipc Error Callback Cancelled for %s",
1262                    MultiProc_getName(procId));
1263     }
1264     else {
1265         GT_1trace (curTrace, GT_4CLASS,
1266                    "Ipc Error Callback Unexpected Event for %s",
1267                    MultiProc_getName(procId));
1268     }
1270     return ret;
1273 /*
1274  * Initialize ipc
1275  *
1276  * This function sets up the "kernel"-side IPC modules, and does any special
1277  * initialization required for QNX and the platform being used.  This function
1278  * also registers for error notifications and initializes the recovery thread.
1279  */
1280 int init_ipc(ipc_dev_t * dev, ipc_firmware_info * firmware, bool recover)
1282     int status = 0;
1283     Ipc_Config iCfg;
1284     OsalThread_Params threadParams;
1285     UInt16 procId;
1286     int i;
1288     if (status >= 0) {
1289         if (!recover) {
1290             /* Set up the MemoryOS module */
1291             status = MemoryOS_setup();
1292             if (status < 0)
1293                 goto memoryos_fail;
1294         }
1296         /* Setup IPC and platform-specific items */
1297         status = Ipc_setup (&iCfg);
1298         if (status < 0)
1299             goto ipcsetup_fail;
1301         /* NOTE: this is for handling the procmgr event notifications to userspace list */
1302         if (!recover) {
1303             /* Setup Fault recovery items. */
1304             /* Create the thread object used for the interrupt handler. */
1305             threadParams.priority     = OsalThread_Priority_Medium;
1306             threadParams.priorityType = OsalThread_PriorityType_Generic;
1307             threadParams.once         = FALSE;
1308             dev->ipc_recovery_work = OsalThread_create ((OsalThread_CallbackFxn)
1309                                                         ipc_recover,
1310                                                         dev,
1311                                                         &threadParams);
1312             if (dev->ipc_recovery_work == NULL)
1313                 goto osalthreadcreate_fail;
1314         }
1315         else {
1316             pthread_mutex_lock(&dev->lock);
1317             dev->recover = FALSE;
1318             pthread_mutex_unlock(&dev->lock);
1319         }
1321         memset(procH_fileId, 0, sizeof(procH_fileId));
1323         for (i = 0; i < ipc_num_cores; i++) {
1324             procId = firmware[i].proc_id = MultiProc_getId(firmware[i].proc);
1325             if (procId >= MultiProc_MAXPROCESSORS) {
1326                 status = -1;
1327                 fprintf(stderr, "Invalid processor name specified\n");
1328                 break;
1329             }
1331             if (procH[procId]) {
1332                 GT_setFailureReason (curTrace,
1333                                      GT_4CLASS,
1334                                      "init_ipc",
1335                                      status,
1336                                      "invalid proc!");
1337                 break;
1338             }
1340             if (recover) {
1341                 /*
1342                  * if we are in recovery, we load the cores we previously
1343                  * attached to
1344                  */
1345                 firmware[i].attachOnly = false;
1346             }
1348             if ((!recover) || (firmware[i].reload)) {
1349                 status = runSlave(dev, procId, &firmware[i]);
1350                 if (status == 0) {
1351                     firmware[i].procState = RUNNING_STATE;
1352                     continue;
1353                 }
1354                 else {
1355                     fprintf(stderr, "Failed to run core %s\n",
1356                         MultiProc_getName(procId));
1357                     break;
1358                 }
1359             }
1360             else {
1361                 /*
1362                  * During recovery, do not run cores unless they were previously
1363                  * running
1364                  */
1365                 continue;
1366             }
1367         }
1369         if (status < 0)
1370             goto tiipcsetup_fail;
1372         /* Set up rpmsg_mq */
1373         status = ti_ipc_setup(recover);
1374         if (status < 0)
1375             goto tiipcsetup_fail;
1377         /* Set up rpmsg_rpc */
1378         status = rpmsg_rpc_setup();
1379         if (status < 0)
1380             goto rpcsetup_fail;
1382         if (recover) {
1383             /* Notify NameServer that recovery is done */
1384             status = NameServer_postRecovery();
1385             if (status < 0) {
1386                 fprintf(stderr, "NameServer could not recover\n");
1387                 NameServer_destroy();
1388                 goto nameserversetup_fail;
1389             }
1390         }
1391         else {
1392             /* Set up NameServer for resource manager process */
1393             status = NameServer_setup();
1394             if (status < 0) {
1395                 goto nameserversetup_fail;
1396             }
1397         }
1399 #if defined(IPC_PLATFORM_VAYU)
1400         if (gatempEnabled) {
1401             Int32 sr0ProcId;
1403             /* Set up GateMP */
1404             status = GateMP_setup(&sr0ProcId);
1405             if ((status < 0) && (status != GateMP_E_NOTFOUND)) {
1406                 goto gatempsetup_fail;
1407             }
1408             else if (status == 0) {
1409                 sr0OwnerProcId = sr0ProcId;
1410             }
1411             else {
1412                 /*
1413                  * If we did not find the default gate, perhaps SR0 is
1414                  * not yet loaded. This is ok.
1415                  */
1416                 status = 0;
1417             }
1418         }
1419 #endif
1421         goto exit;
1422     }
1424 #if defined(IPC_PLATFORM_VAYU)
1425 gatempsetup_fail:
1426     NameServer_destroy();
1427 #endif
1428 nameserversetup_fail:
1429     rpmsg_rpc_destroy();
1430 rpcsetup_fail:
1431     ti_ipc_destroy(recover);
1432 tiipcsetup_fail:
1433     for (i-=1; i >= 0; i--) {
1434         procId = firmware[i].proc_id;
1435         if (procId >= MultiProc_MAXPROCESSORS) {
1436             continue;
1437         }
1438         ProcMgr_unregisterNotify(procH[procId], ipc_error_cb,
1439                                 (Ptr)dev, errStates);
1440         if (!firmware[i].attachOnly) {
1441             ProcMgr_stop(procH[procId]);
1442             if (procH_fileId[procId]) {
1443                 ProcMgr_unload(procH[procId], procH_fileId[procId]);
1444                 procH_fileId[procId] = 0;
1445             }
1446         }
1447         ProcMgr_detach(procH[procId]);
1448         ProcMgr_close(&procH[procId]);
1449         procH[procId] = NULL;
1450         RscTable_free(&rscHandle[procId]);
1451         rscHandle[procId] = NULL;
1452     }
1453     OsalThread_delete(&dev->ipc_recovery_work);
1454 osalthreadcreate_fail:
1455     Ipc_destroy();
1456 ipcsetup_fail:
1457     MemoryOS_destroy();
1458 memoryos_fail:
1459 exit:
1460     return status;
1463 int deinit_ipc(ipc_dev_t * dev, ipc_firmware_info * firmware,
1464     bool recover)
1466     int status = EOK;
1467     uint32_t i = 0, id = 0;
1469     if (logFilename) {
1470         /* wait a little bit for traces to finish dumping */
1471         sleep(1);
1472     }
1474     // Stop the remote cores right away
1475     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
1476         if (procH[i]) {
1477             resetSlave(dev, i);
1478         }
1479     }
1481 #if defined(IPC_PLATFORM_VAYU)
1482     if (gatempEnabled) {
1483         GateMP_destroy(TRUE);
1484     }
1485 #endif
1487     if (recover) {
1488         /*
1489          * We do not destroy NameServer during recovery, so that all
1490          * clients can continue to call its API.
1491          *
1492          * We will simply notify the module so that it does not
1493          * attempt any remote lookups.
1494          */
1495         NameServer_preRecovery();
1496     }
1497     else {
1498         NameServer_destroy();
1499     }
1501     rpmsg_rpc_destroy();
1503     ti_ipc_destroy(recover);
1505     if (!recover && dev->ipc_recovery_work != NULL) {
1506         OsalThread_delete (&dev->ipc_recovery_work);
1507         dev->ipc_recovery_work = NULL;
1508     }
1510     if (recover) {
1511         static FILE *log = NULL;
1512         if (logFilename) {
1513             /* Dump the trace information */
1514             Osal_printf("IPC: printing remote core trace dump");
1515             log = fopen(logFilename, "a+");
1516             if (log) {
1517                 for (id = 0; id < ipc_num_cores; id++) {
1518                     if (firmware[id].procState == RUNNING_STATE) {
1519                         if (proc_traces[id].va) {
1520                             /* print traces */
1521                             fprintf(log, "*************************************\n");
1522                             fprintf(log, "***        %s TRACE DUMP        ***\n",
1523                                 firmware[id].proc);
1524                             fprintf(log, "*************************************\n");
1525                             for (i = (*proc_traces[id].widx + 1);
1526                                 i < (proc_traces[id].len - 8);
1527                                 i++) {
1528                                 fprintf(log, "%c",
1529                                     *(char *)((uint32_t)proc_traces[id].va + i));
1530                             }
1531                             for (i = 0; (i < *proc_traces[id].widx) && (i < proc_traces[id].len - 8); i++) {
1532                                 fprintf(log, "%c",
1533                                     *(char *)((uint32_t)proc_traces[id].va + i));
1534                             }
1535                         }
1536                     }
1537                 }
1538                 fflush(log);
1539                 fclose(log);
1540             }
1541             else {
1542                 fprintf(stderr, "\nERROR: unable to open crash dump file %s\n",
1543                     logFilename);
1544                 exit(EXIT_FAILURE);
1545             }
1546         }
1547     }
1549     /* After printing trace, set all processor states to RESET */
1550     for (id = 0; id < ipc_num_cores; id++) {
1551         firmware[id].procState = RESET_STATE;
1552     }
1554     status = Ipc_destroy();
1555     if (status < 0) {
1556         printf("Ipc_destroy() failed 0x%x", status);
1557     }
1558     if (!recover) {
1559         status = MemoryOS_destroy();
1560         if (status < 0) {
1561             printf("MemoryOS_destroy() failed 0x%x", status);
1562         }
1563     }
1565     return status;
1569 /** print usage */
1570 static Void printUsage (Char * app)
1572     printf("\n\nUsage:\n");
1573 #if defined(IPC_PLATFORM_OMAP5430)
1574     printf("\n%s: [-HTdca] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
1575         app);
1576     printf("  <core_id#> should be set to a core name (e.g. IPU, DSP)\n");
1577     printf("      followed by the path to the executable to load on that core.\n");
1578     printf("Options:\n");
1579     printf("  -H <arg>    enable/disable hibernation, 1: ON, 0: OFF,"
1580         " Default: 1)\n");
1581     printf("  -T <arg>    specify the hibernation timeout in ms, Default:"
1582         " 5000 ms)\n");
1583 #else
1584     printf("\n%s: [-gdca] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
1585         app);
1586     printf("  <core_id#> should be set to a core name (e.g. DSP1, DSP2, IPU1, IPU2)\n");
1587     printf("      followed by the path to the executable to load on that core.\n");
1588     printf("Options:\n");
1589     printf("  -g   enable GateMP support on host\n");
1590 #endif
1591     printf("  -d   disable recovery\n");
1592     printf("  -c <file>   generate dump of slave trace during crashes (use\n");
1593     printf("              absolute path for filename)\n");
1594     printf("  -a<n> specify that the first n cores have been pre-loaded\n");
1595     printf("        and started. Perform late-attach to these cores.\n");
1597     exit (EXIT_SUCCESS);
1600 dispatch_t * ipc_dpp = NULL;
1602 int main(int argc, char *argv[])
1604     ipc_dev_t * dev = NULL;
1605     thread_pool_attr_t tattr;
1606     int status;
1607     int error = EOK;
1608     sigset_t set;
1609     int channelid = 0;
1610     int c;
1611     int hib_enable = 1;
1612     uint32_t hib_timeout = PM_HIB_DEFAULT_TIME;
1613     struct stat          sbuf;
1614     int i = 0;
1615     char * abs_path = NULL;
1617     if (-1 != stat(IPC_DEVICE_PATH, &sbuf)) {
1618         printf ("IPC Already Running...\n");
1619         return EXIT_FAILURE;
1620     }
1621     printf ("Starting IPC resource manager...\n");
1623     /* Parse the input args */
1624     while (1)
1625     {
1626         c = getopt (argc, argv, "H:T:gc:dv:a:");
1627         if (c == -1)
1628             break;
1630         switch (c)
1631         {
1632 #if defined(IPC_PLATFORM_OMAP5430)
1633         case 'H':
1634             hib_enable = atoi(optarg);
1635             if (hib_enable != 0 && hib_enable != 1) {
1636                 hib_enable = -1;
1637             }
1638             break;
1639         case 'T':
1640             hib_timeout = atoi(optarg);
1641             break;
1642 #endif
1643         case 'd':
1644             disableRecovery = true;
1645             break;
1646         case 'c':
1647             logFilename = optarg;
1648             break;
1649         case 'a':
1650             numAttach = atoi(optarg);
1651             printf("Late-attaching to %d core(s)\n", numAttach);
1652             break;
1653         case 'v':
1654             verbosity++;
1655             break;
1656 #if defined(IPC_PLATFORM_VAYU)
1657         case 'g':
1658             printf("GateMP support enabled on host\n");
1659             gatempEnabled = true;
1660             break;
1661 #endif
1662         default:
1663             fprintf (stderr, "Unrecognized argument\n");
1664         }
1665     }
1667     /* Now parse the operands, which should be in the format:
1668      * "<multiproc_name> <firmware_file> ..*/
1669     for (; optind + 1 < argc; optind+=2) {
1670         if (ipc_num_cores == MultiProc_MAXPROCESSORS) {
1671             printUsage(argv[0]);
1672             return (error);
1673         }
1675         ipc_firmware[ipc_num_cores].proc = argv [optind];
1676         ipc_firmware[ipc_num_cores].attachOnly =
1677             ((numAttach-- > 0) ? true : false);
1678         ipc_firmware[ipc_num_cores].reload = true;
1679         ipc_firmware[ipc_num_cores].freeString = false;
1680         ipc_firmware[ipc_num_cores++].firmware = argv [optind+1];
1681     }
1683     /* Validate hib_enable args */
1684     if (hib_enable == -1) {
1685         fprintf (stderr, "invalid hibernation enable value\n");
1686         printUsage(argv[0]);
1687         return (error);
1688     }
1690     ipc_hib_enable = (Bool)hib_enable;
1691     ipc_hib_timeout = hib_timeout;
1693     /* Init logging for ipc */
1694     if (Osal_initlogging(verbosity) != 0) {
1695         return -1;
1696     }
1698     /* Obtain I/O privity */
1699     error = ThreadCtl_r (_NTO_TCTL_IO, 0);
1700     if (error == -1) {
1701         Osal_printf("Unable to obtain I/O privity");
1702         return (error);
1703     }
1705     /* Get the abs path for all firmware files */
1706     for (i = 0; i < ipc_num_cores; i++) {
1707         abs_path = calloc(1, PATH_MAX + 1);
1708         if (abs_path == NULL) {
1709             return -1;
1710         }
1711         if (NULL == realpath(ipc_firmware[i].firmware, abs_path)) {
1712             fprintf (stderr, "invalid path to executable\n");
1713             return -1;
1714         }
1715         ipc_firmware[i].firmware = abs_path;
1716     }
1718     /* allocate the device structure */
1719     if (NULL == (dev = calloc(1, sizeof(ipc_dev_t)))) {
1720         Osal_printf("IPC: calloc() failed");
1721         return (-1);
1722     }
1724     /* create the channel */
1725     if ((channelid = ChannelCreate_r (_NTO_CHF_UNBLOCK |
1726                                     _NTO_CHF_DISCONNECT |
1727                                     _NTO_CHF_COID_DISCONNECT |
1728                                     _NTO_CHF_REPLY_LEN |
1729                                     _NTO_CHF_SENDER_LEN)) < 0) {
1730         Osal_printf("Unable to create channel %d", channelid);
1731         return (channelid);
1732     }
1734     /* create the dispatch structure */
1735     if (NULL == (dev->dpp = ipc_dpp = dispatch_create_channel (channelid, 0))) {
1736         Osal_printf("IPC: dispatch_create() failed");
1737         return(-1);
1738     }
1740     /*
1741      * Mask out all signals before creating a thread pool.
1742      * This prevents other threads in the thread pool
1743      * from intercepting signals such as SIGTERM.
1744      */
1745     sigfillset(&set);
1746     pthread_sigmask(SIG_BLOCK, &set, NULL);
1748     /* Initialize the thread pool */
1749     memset (&tattr, 0x00, sizeof (thread_pool_attr_t));
1750     tattr.handle = dev->dpp;
1751     tattr.context_alloc = dispatch_context_alloc;
1752     tattr.context_free = dispatch_context_free;
1753     tattr.block_func = dispatch_block;
1754     tattr.unblock_func = dispatch_unblock;
1755     tattr.handler_func = dispatch_handler;
1756     tattr.lo_water = 2;
1757     tattr.hi_water = 4;
1758     tattr.increment = 1;
1759     tattr.maximum = 10;
1761     /* Create the thread pool */
1762     if ((dev->tpool = thread_pool_create(&tattr, 0)) == NULL) {
1763         Osal_printf("IPC: thread pool create failed");
1764         return(-1);
1765     }
1767     /* init ipc */
1768     status = init_ipc(dev, ipc_firmware, FALSE);
1769     if (status < 0) {
1770         Osal_printf("IPC: init failed");
1771         return(-1);
1772     }
1774     /* init the ipc device */
1775     status = init_devices(dev);
1776     if (status < 0) {
1777         Osal_printf("IPC: device init failed");
1778         return(-1);
1779     }
1781     /* make this a daemon process */
1782     if (-1 == procmgr_daemon(EXIT_SUCCESS,
1783         PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL)) {
1784         Osal_printf("IPC: procmgr_daemon() failed");
1785         return(-1);
1786     }
1788     /* start the thread pool */
1789     thread_pool_start(dev->tpool);
1791     /* Unmask signals to be caught */
1792     sigdelset (&set, SIGINT);
1793     sigdelset (&set, SIGTERM);
1794     pthread_sigmask (SIG_BLOCK, &set, NULL);
1796     /* Wait for one of these signals */
1797     sigemptyset (&set);
1798     sigaddset (&set, SIGINT);
1799     sigaddset (&set, SIGQUIT);
1800     sigaddset (&set, SIGTERM);
1802     Osal_printf("IPC resource manager started");
1804     /* Wait for a signal */
1805     while (1)
1806     {
1807         switch (SignalWaitinfo (&set, NULL))
1808         {
1809             case SIGTERM:
1810             case SIGQUIT:
1811             case SIGINT:
1812                 error = EOK;
1813                 goto done;
1815             default:
1816                 break;
1817         }
1818     }
1820     error = EOK;
1822 done:
1823     GT_0trace(curTrace, GT_4CLASS, "IPC resource manager exiting \n");
1825     error = thread_pool_destroy(dev->tpool);
1826     if (error < 0) {
1827         Osal_printf("IPC: thread_pool_destroy returned an error");
1828     }
1829     deinit_ipc(dev, ipc_firmware, FALSE);
1830     deinit_devices(dev);
1831     free(dev);
1833     /* Free the abs path of firmware files if necessary */
1834     for (i = 0; i < ipc_num_cores; i++) {
1835         if ((ipc_firmware[i].freeString) &&
1836             (ipc_firmware[i].firmware)) {
1837             free(ipc_firmware[i].firmware);
1838         }
1839     }
1841     return (error);