diff --git a/linux/src/api/Ipc.c b/linux/src/api/Ipc.c
index d91be3e2f3fd07fc0c83254147376de31195a608..9dfb176879a3c344c92e152ac189af726b1f00ed 100644 (file)
--- a/linux/src/api/Ipc.c
+++ b/linux/src/api/Ipc.c
/*
- * Copyright (c) 2012-2013, Texas Instruments Incorporated
+ * Copyright (c) 2012-2015 Texas Instruments Incorporated - http://www.ti.com
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* @brief Starts and stops user side Ipc
* All setup/destroy APIs on user side will be call from this
* module.
- *
- * @ver 0002
- *
*/
-/* Standard headers */
+/* standard headers */
+#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
-#include <Std.h>
-/* Common IPC headers: */
+/* package headers */
+#include <ti/ipc/Std.h>
#include <ti/ipc/Ipc.h>
#include <ti/ipc/NameServer.h>
/* IPC startup/shutdown stuff: */
#include <ti/ipc/MultiProc.h>
+#include <GateHWSpinlock.h>
+#include <_GateMP.h>
+#include <_MultiProc.h>
#include <_MessageQ.h>
#include <_NameServer.h>
+/* module definition */
+typedef struct {
+ Int refCount;
+ pthread_mutex_t gate;
+ Ipc_TransportFactoryFxns *transportFactory;
+} Ipc_Module;
+
+
+/* =============================================================================
+ * Globals
+ * =============================================================================
+ */
+static Ipc_Module Ipc_module = {
+ .refCount = 0,
+ .gate = PTHREAD_MUTEX_INITIALIZER,
+ .transportFactory = NULL
+};
+
+GateHWSpinlock_Config _GateHWSpinlock_cfgParams;
static LAD_ClientHandle ladHandle;
-static void cleanup(int arg);
/** ============================================================================
* Functions
* ============================================================================
*/
-/* Function to start Ipc */
-Int Ipc_start (Void)
+static void cleanup(int arg);
+
+
+/*
+ * ======== Ipc_start ========
+ */
+Int Ipc_start(Void)
{
- MessageQ_Config msgqCfg;
- Int32 status = Ipc_S_SUCCESS;
- LAD_Status ladStatus;
- UInt16 rprocId;
+ MessageQ_Config msgqCfg;
+ MultiProc_Config mpCfg;
+#if defined(GATEMP_SUPPORT)
+ GateHWSpinlock_Config gateHWCfg;
+#endif
+ Int status;
+ LAD_Status ladStatus;
+
+ /* function must be serialized */
+ pthread_mutex_lock(&Ipc_module.gate);
+
+ /* ensure only first thread performs startup procedure */
+ if (++Ipc_module.refCount > 1) {
+ status = Ipc_S_ALREADYSETUP;
+ goto exit;
+ }
+
+ /* make sure transport factory has been configured */
+ if (Ipc_module.transportFactory == NULL) {
+ status = Ipc_E_INVALIDSTATE;
+ goto exit;
+ }
/* Catch ctrl-C, and cleanup: */
(void) signal(SIGINT, cleanup);
+ if (getenv("IPC_DEBUG") != NULL) {
+ /* turn on tracing */
+ if (getenv("IPC_DEBUG")[0] == '1') {
+ /* level 1 enables typical user API tracing */
+ _MessageQ_verbose = TRUE;
+ _MultiProc_verbose = TRUE;
+ _NameServer_verbose = TRUE;
+#if defined(GATEMP_SUPPORT)
+ _GateMP_verbose = TRUE;
+
+ _GateHWSpinlock_verbose = TRUE;
+#endif
+ }
+ else if ((getenv("IPC_DEBUG")[0] == '2') ||
+ (getenv("IPC_DEBUG")[0] == '3')) {
+ /* levels 2 and 3 add socket and LAD client tracing */
+ _MessageQ_verbose = TRUE;
+ _MultiProc_verbose = TRUE;
+ _NameServer_verbose = TRUE;
+
+#if defined(GATEMP_SUPPORT)
+ _GateMP_verbose = TRUE;
+
+ _GateHWSpinlock_verbose = TRUE;
+#endif
+
+ /* internals - should be declared in respective _*.h files */
+ extern Bool _SocketFxns_verbose;
+ extern Bool _LAD_Client_verbose;
+
+ _SocketFxns_verbose = TRUE;
+ _LAD_Client_verbose = TRUE;
+ }
+ }
+
ladStatus = LAD_connect(&ladHandle);
if (ladStatus != LAD_SUCCESS) {
printf("Ipc_start: LAD_connect() failed: %d\n", ladStatus);
goto exit;
}
+ /* Get MultiProc configuration from LAD and initialize local
+ * MultiProc config structure.
+ */
+ MultiProc_getConfig(&mpCfg);
+ _MultiProc_initCfg(&mpCfg);
+
status = NameServer_setup();
+
if (status >= 0) {
MessageQ_getConfig(&msgqCfg);
MessageQ_setup(&msgqCfg);
- /* Now attach to all remote processors, assuming they are up. */
- for (rprocId = 0;
- (rprocId < MultiProc_getNumProcessors()) && (status >= 0);
- rprocId++) {
- if (0 == rprocId) {
- /* Skip host, which should always be 0th entry. */
- continue;
- }
- status = MessageQ_attach (rprocId, NULL);
- if (status < 0) {
- printf("Ipc_start: MessageQ_attach(%d) failed: %d\n",
- rprocId, status);
- status = Ipc_E_FAIL;
- }
+ /* invoke the transport factory create method */
+ status = Ipc_module.transportFactory->createFxn();
+
+ if (status < 0) {
+ goto exit;
}
}
else {
status = Ipc_E_FAIL;
}
+ /* Start GateMP only if device has support */
+#if defined(GATEMP_SUPPORT)
+ if (GateMP_isSetup()) {
+ /*
+ * Get HWSpinlock base address and size from LAD and
+ * initialize the local config structure.
+ */
+ GateHWSpinlock_getConfig(&gateHWCfg);
+ _GateHWSpinlock_cfgParams = gateHWCfg;
+
+ status = GateHWSpinlock_start();
+ if (status < 0) {
+ printf("Ipc_start: GateHWSpinlock_start failed: %d\n",
+ status);
+ status = Ipc_E_FAIL;
+ goto gatehwspinlockstart_fail;
+ }
+ else {
+ status = GateMP_start();
+ if (status < 0) {
+ printf("Ipc_start: GateMP_start failed: %d\n",
+ status);
+ status = Ipc_E_FAIL;
+ goto gatempstart_fail;
+ }
+ }
+ }
+#endif
+ /* Success */
+ goto exit;
+#if defined(GATEMP_SUPPORT)
+gatempstart_fail:
+ GateHWSpinlock_stop();
+gatehwspinlockstart_fail:
+#if 0
+ for (procId = procId - 1; (procId > 0) && (status >= 0); procId--) {
+ MessageQ_detach(procId);
+ }
+#endif
+#endif
+
exit:
+ /* if error, must decrement reference count */
+ if (status < 0) {
+ Ipc_module.refCount--;
+ }
+
+ pthread_mutex_unlock(&Ipc_module.gate);
+
return (status);
}
-
-/* Function to stop Ipc */
-Int Ipc_stop (Void)
+/*
+ * ======== Ipc_stop ========
+ */
+Int Ipc_stop(Void)
{
- Int32 status = Ipc_S_SUCCESS;
- LAD_Status ladStatus;
- UInt16 rprocId;
-
- /* Now detach from all remote processors, assuming they are up. */
- for (rprocId = 0;
- (rprocId < MultiProc_getNumProcessors()) && (status >= 0);
- rprocId++) {
- if (0 == rprocId) {
- /* Skip host, which should always be 0th entry. */
- continue;
+ Int32 status = Ipc_S_SUCCESS;
+ LAD_Status ladStatus;
+ Int i;
+ UInt16 procId;
+ UInt16 clusterSize;
+ UInt16 clusterBase;
+
+ /* function must be serialized */
+ pthread_mutex_lock(&Ipc_module.gate);
+
+ /* ensure only last thread performs stop procedure */
+ if (--Ipc_module.refCount > 0) {
+ goto exit;
+ }
+
+ /* invoke the transport factory delete method */
+ Ipc_module.transportFactory->deleteFxn();
+
+ /* needed to enumerate processors in cluster */
+ clusterSize = MultiProc_getNumProcsInCluster();
+ clusterBase = MultiProc_getBaseIdOfCluster();
+
+ /* detach from all remote processors, assuming they are up */
+ for (i = 0, procId = clusterBase; i < clusterSize; i++, procId++) {
+
+ /* no need to detach from myself */
+ if (MultiProc_self() == procId) {
+ continue;
}
- status = MessageQ_detach(rprocId);
+#if 0
+ status = MessageQ_detach(procId);
if (status < 0) {
printf("Ipc_stop: MessageQ_detach(%d) failed: %d\n",
- rprocId, status);
+ procId, status);
status = Ipc_E_FAIL;
goto exit;
}
+#endif
}
status = MessageQ_destroy();
}
exit:
+ pthread_mutex_unlock(&Ipc_module.gate);
+
+ return (status);
+}
+
+/*
+ * ======== Ipc_transportConfig ========
+ */
+Int Ipc_transportConfig(Ipc_TransportFactoryFxns *factory)
+{
+ Int status;
+
+ pthread_mutex_lock(&Ipc_module.gate);
+ status = Ipc_S_SUCCESS;
+
+ /* transport configuration must happen before start phase */
+ if (Ipc_module.refCount != 0) {
+ status = Ipc_E_INVALIDSTATE;
+ goto exit;
+ }
+
+ /* store factory address in module state */
+ Ipc_module.transportFactory = factory;
+
+exit:
+ pthread_mutex_unlock(&Ipc_module.gate);
+
return (status);
}