9dfb176879a3c344c92e152ac189af726b1f00ed
1 /*
2 * Copyright (c) 2012-2015 Texas Instruments Incorporated - http://www.ti.com
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 /*!
33 * @file Ipc.c
34 *
35 * @brief Starts and stops user side Ipc
36 * All setup/destroy APIs on user side will be call from this
37 * module.
38 */
40 /* standard headers */
41 #include <pthread.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <signal.h>
46 /* package headers */
47 #include <ti/ipc/Std.h>
48 #include <ti/ipc/Ipc.h>
49 #include <ti/ipc/NameServer.h>
51 /* User side headers */
52 #include <ladclient.h>
54 /* IPC startup/shutdown stuff: */
55 #include <ti/ipc/MultiProc.h>
56 #include <GateHWSpinlock.h>
57 #include <_GateMP.h>
58 #include <_MultiProc.h>
59 #include <_MessageQ.h>
60 #include <_NameServer.h>
62 /* module definition */
63 typedef struct {
64 Int refCount;
65 pthread_mutex_t gate;
66 Ipc_TransportFactoryFxns *transportFactory;
67 } Ipc_Module;
70 /* =============================================================================
71 * Globals
72 * =============================================================================
73 */
74 static Ipc_Module Ipc_module = {
75 .refCount = 0,
76 .gate = PTHREAD_MUTEX_INITIALIZER,
77 .transportFactory = NULL
78 };
80 GateHWSpinlock_Config _GateHWSpinlock_cfgParams;
81 static LAD_ClientHandle ladHandle;
84 /** ============================================================================
85 * Functions
86 * ============================================================================
87 */
88 static void cleanup(int arg);
91 /*
92 * ======== Ipc_start ========
93 */
94 Int Ipc_start(Void)
95 {
96 MessageQ_Config msgqCfg;
97 MultiProc_Config mpCfg;
98 #if defined(GATEMP_SUPPORT)
99 GateHWSpinlock_Config gateHWCfg;
100 #endif
101 Int status;
102 LAD_Status ladStatus;
104 /* function must be serialized */
105 pthread_mutex_lock(&Ipc_module.gate);
107 /* ensure only first thread performs startup procedure */
108 if (++Ipc_module.refCount > 1) {
109 status = Ipc_S_ALREADYSETUP;
110 goto exit;
111 }
113 /* make sure transport factory has been configured */
114 if (Ipc_module.transportFactory == NULL) {
115 status = Ipc_E_INVALIDSTATE;
116 goto exit;
117 }
119 /* Catch ctrl-C, and cleanup: */
120 (void) signal(SIGINT, cleanup);
122 if (getenv("IPC_DEBUG") != NULL) {
123 /* turn on tracing */
124 if (getenv("IPC_DEBUG")[0] == '1') {
125 /* level 1 enables typical user API tracing */
126 _MessageQ_verbose = TRUE;
127 _MultiProc_verbose = TRUE;
128 _NameServer_verbose = TRUE;
129 #if defined(GATEMP_SUPPORT)
130 _GateMP_verbose = TRUE;
132 _GateHWSpinlock_verbose = TRUE;
133 #endif
134 }
135 else if ((getenv("IPC_DEBUG")[0] == '2') ||
136 (getenv("IPC_DEBUG")[0] == '3')) {
137 /* levels 2 and 3 add socket and LAD client tracing */
138 _MessageQ_verbose = TRUE;
139 _MultiProc_verbose = TRUE;
140 _NameServer_verbose = TRUE;
142 #if defined(GATEMP_SUPPORT)
143 _GateMP_verbose = TRUE;
145 _GateHWSpinlock_verbose = TRUE;
146 #endif
148 /* internals - should be declared in respective _*.h files */
149 extern Bool _SocketFxns_verbose;
150 extern Bool _LAD_Client_verbose;
152 _SocketFxns_verbose = TRUE;
153 _LAD_Client_verbose = TRUE;
154 }
155 }
157 ladStatus = LAD_connect(&ladHandle);
158 if (ladStatus != LAD_SUCCESS) {
159 printf("Ipc_start: LAD_connect() failed: %d\n", ladStatus);
160 status = Ipc_E_FAIL;
161 goto exit;
162 }
164 /* Get MultiProc configuration from LAD and initialize local
165 * MultiProc config structure.
166 */
167 MultiProc_getConfig(&mpCfg);
168 _MultiProc_initCfg(&mpCfg);
170 status = NameServer_setup();
172 if (status >= 0) {
173 MessageQ_getConfig(&msgqCfg);
174 MessageQ_setup(&msgqCfg);
176 /* invoke the transport factory create method */
177 status = Ipc_module.transportFactory->createFxn();
179 if (status < 0) {
180 goto exit;
181 }
182 }
183 else {
184 printf("Ipc_start: NameServer_setup() failed: %d\n", status);
185 status = Ipc_E_FAIL;
186 }
188 /* Start GateMP only if device has support */
189 #if defined(GATEMP_SUPPORT)
190 if (GateMP_isSetup()) {
191 /*
192 * Get HWSpinlock base address and size from LAD and
193 * initialize the local config structure.
194 */
195 GateHWSpinlock_getConfig(&gateHWCfg);
196 _GateHWSpinlock_cfgParams = gateHWCfg;
198 status = GateHWSpinlock_start();
199 if (status < 0) {
200 printf("Ipc_start: GateHWSpinlock_start failed: %d\n",
201 status);
202 status = Ipc_E_FAIL;
203 goto gatehwspinlockstart_fail;
204 }
205 else {
206 status = GateMP_start();
207 if (status < 0) {
208 printf("Ipc_start: GateMP_start failed: %d\n",
209 status);
210 status = Ipc_E_FAIL;
211 goto gatempstart_fail;
212 }
213 }
214 }
215 #endif
216 /* Success */
217 goto exit;
218 #if defined(GATEMP_SUPPORT)
219 gatempstart_fail:
220 GateHWSpinlock_stop();
221 gatehwspinlockstart_fail:
222 #if 0
223 for (procId = procId - 1; (procId > 0) && (status >= 0); procId--) {
224 MessageQ_detach(procId);
225 }
226 #endif
227 #endif
229 exit:
230 /* if error, must decrement reference count */
231 if (status < 0) {
232 Ipc_module.refCount--;
233 }
235 pthread_mutex_unlock(&Ipc_module.gate);
237 return (status);
238 }
240 /*
241 * ======== Ipc_stop ========
242 */
243 Int Ipc_stop(Void)
244 {
245 Int32 status = Ipc_S_SUCCESS;
246 LAD_Status ladStatus;
247 Int i;
248 UInt16 procId;
249 UInt16 clusterSize;
250 UInt16 clusterBase;
252 /* function must be serialized */
253 pthread_mutex_lock(&Ipc_module.gate);
255 /* ensure only last thread performs stop procedure */
256 if (--Ipc_module.refCount > 0) {
257 goto exit;
258 }
260 /* invoke the transport factory delete method */
261 Ipc_module.transportFactory->deleteFxn();
263 /* needed to enumerate processors in cluster */
264 clusterSize = MultiProc_getNumProcsInCluster();
265 clusterBase = MultiProc_getBaseIdOfCluster();
267 /* detach from all remote processors, assuming they are up */
268 for (i = 0, procId = clusterBase; i < clusterSize; i++, procId++) {
270 /* no need to detach from myself */
271 if (MultiProc_self() == procId) {
272 continue;
273 }
274 #if 0
275 status = MessageQ_detach(procId);
276 if (status < 0) {
277 printf("Ipc_stop: MessageQ_detach(%d) failed: %d\n",
278 procId, status);
279 status = Ipc_E_FAIL;
280 goto exit;
281 }
282 #endif
283 }
285 status = MessageQ_destroy();
286 if (status < 0) {
287 printf("Ipc_stop: MessageQ_destroy() failed: %d\n", status);
288 status = Ipc_E_FAIL;
289 goto exit;
290 }
292 status = NameServer_destroy();
293 if (status < 0) {
294 printf("Ipc_stop: NameServer_destroy() failed: %d\n", status);
295 status = Ipc_E_FAIL;
296 goto exit;
297 }
299 ladStatus = LAD_disconnect(ladHandle);
300 if (ladStatus != LAD_SUCCESS) {
301 printf("LAD_disconnect() failed: %d\n", ladStatus);
302 status = Ipc_E_FAIL;
303 goto exit;
304 }
306 exit:
307 pthread_mutex_unlock(&Ipc_module.gate);
309 return (status);
310 }
312 /*
313 * ======== Ipc_transportConfig ========
314 */
315 Int Ipc_transportConfig(Ipc_TransportFactoryFxns *factory)
316 {
317 Int status;
319 pthread_mutex_lock(&Ipc_module.gate);
320 status = Ipc_S_SUCCESS;
322 /* transport configuration must happen before start phase */
323 if (Ipc_module.refCount != 0) {
324 status = Ipc_E_INVALIDSTATE;
325 goto exit;
326 }
328 /* store factory address in module state */
329 Ipc_module.transportFactory = factory;
331 exit:
332 pthread_mutex_unlock(&Ipc_module.gate);
334 return (status);
335 }
337 static void cleanup(int arg)
338 {
339 printf("Ipc: Caught SIGINT, calling Ipc_stop...\n");
340 Ipc_stop();
341 exit(0);
342 }