summaryrefslogtreecommitdiff
path: root/drivers/dsp/syslink/multicore_ipc/sysmgr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dsp/syslink/multicore_ipc/sysmgr.c')
-rw-r--r--drivers/dsp/syslink/multicore_ipc/sysmgr.c846
1 files changed, 846 insertions, 0 deletions
diff --git a/drivers/dsp/syslink/multicore_ipc/sysmgr.c b/drivers/dsp/syslink/multicore_ipc/sysmgr.c
new file mode 100644
index 00000000000..13bcce110ba
--- /dev/null
+++ b/drivers/dsp/syslink/multicore_ipc/sysmgr.c
@@ -0,0 +1,846 @@
+/*
+ * sysmgr.c
+ *
+ * Implementation of System manager.
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ */
+
+
+/* Standard headers */
+#include <linux/types.h>
+#include <linux/module.h>
+
+#include <syslink/atomic_linux.h>
+
+/* Module headers */
+#include <multiproc.h>
+#include <sysmemmgr.h>
+#include <sysmgr.h>
+#include <_sysmgr.h>
+#include <platform.h>
+#include <platform_mem.h>
+
+#include <gatepeterson.h>
+#include <sharedregion.h>
+#include <listmp.h>
+#include <messageq.h>
+#include <messageq_transportshm.h>
+#include <notify.h>
+/*#include <notify_driver.h>*/
+#include <notify_ducatidriver.h>
+
+#include <nameserver.h>
+#include <nameserver_remote.h>
+#include <nameserver_remotenotify.h>
+#include <procmgr.h>
+#include <heap.h>
+#include <heapbuf.h>
+
+/* =============================================================================
+ * Macros
+ * =============================================================================
+ */
+/*!
+ * @def BOOTLOADPAGESIZE
+ * @brief Error code base for System manager.
+ */
+#define BOOTLOADPAGESIZE (0x1000) /* 4K page size */
+
+/*!
+ * @def SYSMGR_ENTRYVALIDITYSTAMP
+ * @brief Validity stamp for boot load page entries.
+ */
+#define SYSMGR_ENTRYVALIDITYSTAMP (0xBABAC0C0)
+
+/*!
+ * @def SYSMGR_ENTRYVALIDSTAMP
+ * @brief Validity stamp for boot load page entries.
+ */
+#define SYSMGR_ENTRYVALIDSTAMP (0xBABAC0C0)
+
+/*!
+ * @def SYSMGR_SCALABILITYHANDSHAKESTAMP
+ * @brief scalability configuration handshake value.
+ */
+#define SYSMGR_SCALABILITYHANDSHAKESTAMP (0xBEEF0000)
+
+/*!
+ * @def SYSMGR_SETUPHANDSHAKESTAMP
+ * @brief Platform configured handshake value.
+ */
+#define SYSMGR_SETUPHANDSHAKESTAMP (0xBEEF0001)
+
+/*!
+ * @def SYSMGR_DESTROYHANDSHAKESTAMP
+ * @brief Destroy handshake value.
+ */
+#define SYSMGR_DESTROYHANDSHAKESTAMP (0xBEEF0002)
+
+/*!
+ * @def SYSMGR_BOOTLOADPAGESIZE
+ * @brief Boot load page size.
+ */
+#define SYSMGR_BOOTLOADPAGESIZE (0x00001000)
+
+/* Macro to make a correct module magic number with ref_count */
+#define SYSMGR_MAKE_MAGICSTAMP(x) ((SYSMGR_MODULEID << 12) | (x))
+
+
+/* =============================================================================
+ * Structures & Enums
+ * =============================================================================
+ */
+/*! @brief structure for System manager boot load page entry */
+struct sysmgr_bootload_page_entry {
+ VOLATILE u32 offset;
+ /* Offset of next entry (-1 if not present) */
+ VOLATILE u32 valid;
+ /* Validity of the entry */
+ VOLATILE u32 size;
+ /* Size of the entry data */
+ VOLATILE u32 cmd_id;
+ /* Command ID */
+};
+
+/*! @brief structure containg system manager state object */
+struct sysmgr_boot_load_page {
+ VOLATILE struct sysmgr_bootload_page_entry host_config;
+ /* First entry, host specific configuration in the boot load page */
+ u8 padding1[(BOOTLOADPAGESIZE/2) - \
+ sizeof(struct sysmgr_bootload_page_entry)];
+ /* Padding1 */
+ VOLATILE u32 handshake;
+ /* Handshake variable, wrote by slave to indicate configuration done. */
+ VOLATILE struct sysmgr_bootload_page_entry slave_config;
+ /* First entry, slave specific configuration in the boot load page */
+ u8 padding2[(BOOTLOADPAGESIZE/2) - \
+ sizeof(struct sysmgr_bootload_page_entry) - \
+ sizeof(u32)];
+ /* Padding2 */
+};
+
+/*! @brief structure for System manager module state */
+struct sysmgr_module_object {
+ atomic_t ref_count;
+ /* Reference count */
+ struct sysmgr_config config;
+ /* Overall system configuration */
+ struct sysmgr_boot_load_page *boot_load_page[MULTIPROC_MAXPROCESSORS];
+ /* Boot load page of the slaves */
+ bool platform_mem_init_flag;
+ /* Platform memory manager initialize flag */
+ bool multiproc_init_flag;
+ /* Multiproc Initialize flag */
+ bool gatepeterson_init_flag;
+ /* Gatepeterson Initialize flag */
+ bool sharedregion_init_flag;
+ /* Sharedregion Initialize flag */
+ bool listmp_init_flag;
+ /* Listmp Initialize flag */
+ bool messageq_init_flag;
+ /* Messageq Initialize flag */
+ bool notify_init_flag;
+ /* Notify Initialize flag */
+ bool proc_mgr_init_flag;
+ /* Processor manager Initialize flag */
+ bool heapbuf_init_flag;
+ /* Heapbuf Initialize flag */
+ bool nameserver_init_flag;
+ /* Nameserver_remotenotify Initialize flag */
+ bool listmp_sharedmemory_init_flag;
+ /* Listmp_sharedmemory Initialize flag */
+ bool messageq_transportshm_init_flag;
+ /* Messageq_transportshm Initialize flag */
+ bool notify_ducatidrv_init_flag;
+ /* notify_ducatidrv Initialize flag */
+ bool nameserver_remotenotify_init_flag;
+ /* nameserver_remotenotify Initialize flag */
+ bool platform_init_flag;
+ /* Flag to indicate platform initialization status */
+};
+
+
+/* =============================================================================
+ * Globals
+ * =============================================================================
+ */
+/*!
+ * @var sysmgr_state
+ *
+ * @brief Variable holding state of system manager.
+ */
+static struct sysmgr_module_object sysmgr_state;
+
+
+/* =============================================================================
+ * APIS
+ * =============================================================================
+ */
+/*
+ * ======== sysmgr_get_config ========
+ * Purpose:
+ * Function to get the default values for configuration.
+ */
+void sysmgr_get_config(struct sysmgr_config *config)
+{
+ s32 status = 0;
+
+ if (WARN_ON(config == NULL)) {
+ status = -EINVAL;
+ pr_err("sysmgr_get_config [0x%x] : Argument of type"
+ " (sysmgr_get_config *) passed is null!",
+ status);
+ return;
+ }
+
+ /* Get the gatepeterson default config */
+ multiproc_get_config(&config->multiproc_cfg);
+
+ /* Get the gatepeterson default config */
+ gatepeterson_get_config(&config->gatepeterson_cfg);
+
+ /* Get the sharedregion default config */
+ sharedregion_get_config(&config->sharedregion_cfg);
+
+ /* Get the messageq default config */
+ messageq_get_config(&config->messageq_cfg);
+
+ /* Get the notify default config */
+ notify_get_config(&config->notify_cfg);
+
+ /* Get the proc_mgr default config */
+ proc_mgr_get_config(&config->proc_mgr_cfg);
+
+ /* Get the heapbuf default config */
+ heapbuf_get_config(&config->heapbuf_cfg);
+
+ /* Get the listmp_sharedmemory default config */
+ listmp_sharedmemory_get_config(&config->listmp_sharedmemory_cfg);
+
+ /* Get the messageq_transportshm default config */
+ messageq_transportshm_get_config(&config->messageq_transportshm_cfg);
+
+ /* Get the notify_ducati driver default config */
+ notify_ducatidrv_getconfig(&config->notify_ducatidrv_cfg);
+
+ /* Get the nameserver_remotenotify default config */
+ nameserver_remotenotify_get_config(
+ &config->nameserver_remotenotify_cfg);
+}
+EXPORT_SYMBOL(sysmgr_get_config);
+
+/*
+ * ======== sysmgr_get_object_config ========
+ * Purpose:
+ * Function to get the SysMgr Object configuration from Slave.
+ */
+u32 sysmgr_get_object_config(u16 proc_id, void *config, u32 cmd_id, u32 size)
+{
+ struct sysmgr_bootload_page_entry *entry = NULL;
+ u32 offset = 0;
+ u32 ret = 0;
+ struct sysmgr_boot_load_page *blp = NULL;
+
+ if ((proc_id < 0) || (proc_id >= MULTIPROC_MAXPROCESSORS)) {
+ ret = 0;
+ goto exit;
+ }
+
+ blp = (struct sysmgr_boot_load_page *)
+ sysmgr_state.boot_load_page[proc_id];
+
+ entry = (struct sysmgr_bootload_page_entry *) &blp->slave_config;
+ while (entry->valid == SYSMGR_ENTRYVALIDSTAMP) {
+ if (entry->cmd_id == cmd_id) {
+ if (size == entry->size) {
+ memcpy(config, (void *)((u32)entry + \
+ sizeof(struct sysmgr_bootload_page_entry)),
+ size);
+ ret = size;
+ break;
+ }
+ }
+ if (entry->offset != -1) {
+ offset += entry->offset;
+ entry = (struct sysmgr_bootload_page_entry *)
+ ((u32) &blp->slave_config + entry->offset);
+ } else {
+ break;
+ }
+ }
+
+exit:
+ /* return number of bytes wrote to the boot load page */
+ return ret;
+}
+
+
+/*
+ * ======== sysmgr_put_object_config ========
+ * Purpose:
+ * Function to put the SysMgr Object configuration to Slave.
+ */
+u32 sysmgr_put_object_config(u16 proc_id, void *config, u32 cmd_id, u32 size)
+{
+ struct sysmgr_bootload_page_entry *entry = NULL;
+ struct sysmgr_bootload_page_entry *prev = NULL;
+ u32 offset = 0;
+ struct sysmgr_boot_load_page *blp = NULL;
+
+ if ((proc_id < 0) || (proc_id >= MULTIPROC_MAXPROCESSORS)) {
+ size = 0;
+ goto exit;
+ }
+
+ /* Get the boot load page pointer */
+ blp = sysmgr_state.boot_load_page[proc_id];
+
+ /* Put the entry at the end of list */
+ entry = (struct sysmgr_bootload_page_entry *) &blp->host_config;
+ while (entry->valid == SYSMGR_ENTRYVALIDSTAMP) {
+ prev = entry;
+ if (entry->offset != -1) {
+ offset += entry->offset;
+ entry = (struct sysmgr_bootload_page_entry *)
+ ((u32) &blp->host_config + entry->offset);
+ } else {
+ break;
+ }
+ }
+
+ /* First entry has prev set to NULL */
+ if (prev == NULL) {
+ entry->offset = -1;
+ entry->cmd_id = cmd_id;
+ entry->size = size;
+ memcpy((void *)((u32)entry + \
+ sizeof(struct sysmgr_bootload_page_entry)),
+ config, size);
+ entry->valid = SYSMGR_ENTRYVALIDSTAMP;
+ } else {
+ entry = (struct sysmgr_bootload_page_entry *)((u32)entry + \
+ sizeof(struct sysmgr_bootload_page_entry) + \
+ entry->size);
+ entry->offset = -1;
+ entry->cmd_id = cmd_id;
+ entry->size = size;
+ memcpy((void *)((u32)entry + \
+ sizeof(struct sysmgr_bootload_page_entry)),
+ config, size);
+ entry->valid = SYSMGR_ENTRYVALIDSTAMP;
+
+ /* Attach the new created entry */
+ prev->offset = ((u32) entry - (u32) &blp->host_config);
+ }
+
+exit:
+ /* return number of bytes wrote to the boot load page */
+ return size;
+}
+
+
+/*
+ * ======== sysmgr_setup ========
+ * Purpose:
+ * Function to setup the System.
+ */
+s32 sysmgr_setup(const struct sysmgr_config *cfg)
+{
+ s32 status = 0;
+ struct sysmgr_config *config = NULL;
+
+ /* This sets the ref_count variable is not initialized, upper 16 bits is
+ * written with module Id to ensure correctness of ref_count variable.
+ */
+ atomic_cmpmask_and_set(&sysmgr_state.ref_count,
+ SYSMGR_MAKE_MAGICSTAMP(0),
+ SYSMGR_MAKE_MAGICSTAMP(0));
+
+ if (atomic_inc_return(&sysmgr_state.ref_count)
+ != SYSMGR_MAKE_MAGICSTAMP(1)) {
+ status = 1;
+ goto exit;
+ }
+
+ if (cfg == NULL) {
+ sysmgr_get_config(&sysmgr_state.config);
+ config = &sysmgr_state.config;
+ } else {
+ memcpy((void *) (&sysmgr_state.config), (void *) cfg,
+ sizeof(struct sysmgr_config));
+ config = (struct sysmgr_config *) cfg;
+ }
+
+ /* Initialize PlatformMem */
+ status = platform_mem_setup();
+ if (status < 0) {
+ pr_err("sysmgr_setup : platform_mem_setup "
+ "failed [0x%x]\n", status);
+ } else {
+ pr_err("platform_mem_setup : status [0x%x]\n" ,
+ status);
+ sysmgr_state.platform_mem_init_flag = true;
+ }
+
+ /* Override the platform specific configuration */
+ platform_override_config(config);
+
+ status = multiproc_setup(&(config->multiproc_cfg));
+ if (status < 0) {
+ pr_err("sysmgr_setup : multiproc_setup "
+ "failed [0x%x]\n", status);
+ } else {
+ pr_err("sysmgr_setup : status [0x%x]\n" , status);
+ sysmgr_state.multiproc_init_flag = true;
+ }
+
+ /* Initialize ProcMgr */
+ if (status >= 0) {
+ status = proc_mgr_setup(&(config->proc_mgr_cfg));
+ if (status < 0) {
+ pr_err("sysmgr_setup : proc_mgr_setup "
+ "failed [0x%x]\n", status);
+ } else {
+ pr_err("proc_mgr_setup : status [0x%x]\n" ,
+ status);
+ sysmgr_state.proc_mgr_init_flag = true;
+ }
+ }
+
+ /* Initialize SharedRegion */
+ if (status >= 0) {
+ status = sharedregion_setup(&config->sharedregion_cfg);
+ if (status < 0) {
+ pr_err("sysmgr_setup : sharedregion_setup "
+ "failed [0x%x]\n", status);
+ } else {
+ pr_err("sharedregion_setup : status [0x%x]\n" ,
+ status);
+ sysmgr_state.sharedregion_init_flag = true;
+ }
+ }
+
+ /* Initialize Notify */
+ if (status >= 0) {
+ status = notify_setup(&config->notify_cfg);
+ if (status < 0) {
+ pr_err("sysmgr_setup : notify_setup "
+ "failed [0x%x]\n", status);
+ } else {
+ pr_err("notify_setup : status [0x%x]\n" ,
+ status);
+ sysmgr_state.notify_init_flag = true;
+ }
+ }
+
+ /* Initialize NameServer */
+ if (status >= 0) {
+ status = nameserver_setup();
+ if (status < 0) {
+ pr_err("sysmgr_setup : nameserver_setup "
+ "failed [0x%x]\n", status);
+ } else {
+ pr_err("nameserver_setup : status [0x%x]\n" ,
+ status);
+ sysmgr_state.nameserver_init_flag = true;
+ }
+ }
+
+ /* Initialize GatePeterson */
+ if (status >= 0) {
+ status = gatepeterson_setup(&config->gatepeterson_cfg);
+ if (status < 0) {
+ pr_err("sysmgr_setup : gatepeterson_setup "
+ "failed [0x%x]\n", status);
+ } else {
+ pr_err("gatepeterson_setup : status [0x%x]\n" ,
+ status);
+ sysmgr_state.gatepeterson_init_flag = true;
+ }
+ }
+
+ /* Intialize MessageQ */
+ if (status >= 0) {
+ status = messageq_setup(&config->messageq_cfg);
+ if (status < 0) {
+ pr_err("sysmgr_setup : messageq_setup "
+ "failed [0x%x]\n", status);
+ } else {
+ pr_err("messageq_setup : status [0x%x]\n" ,
+ status);
+ sysmgr_state.messageq_init_flag = true;
+ }
+ }
+
+ /* Intialize HeapBuf */
+ if (status >= 0) {
+ status = heapbuf_setup(&config->heapbuf_cfg);
+ if (status < 0) {
+ pr_err("sysmgr_setup : heapbuf_setup "
+ "failed [0x%x]\n", status);
+ } else {
+ pr_err("heapbuf_setup : status [0x%x]\n" ,
+ status);
+ sysmgr_state.heapbuf_init_flag = true;
+ }
+ }
+
+ /* Initialize ListMPSharedMemory */
+ if (status >= 0) {
+ status = listmp_sharedmemory_setup(
+ &config->listmp_sharedmemory_cfg);
+ if (status < 0) {
+ pr_err("sysmgr_setup : "
+ "listmp_sharedmemory_setup failed [0x%x]\n",
+ status);
+ } else {
+ pr_err("listmp_sharedmemory_setup : "
+ "status [0x%x]\n" , status);
+ sysmgr_state.listmp_sharedmemory_init_flag = true;
+ }
+ }
+
+ /* Initialize MessageQTransportShm */
+ if (status >= 0) {
+ status = messageq_transportshm_setup(
+ &config->messageq_transportshm_cfg);
+ if (status < 0) {
+ pr_err("sysmgr_setup : "
+ "messageq_transportshm_setup failed [0x%x]\n",
+ status);
+ } else {
+ pr_err("messageq_transportshm_setup : "
+ "status [0x%x]\n", status);
+ sysmgr_state.messageq_transportshm_init_flag = true;
+ }
+ }
+
+ /* Initialize Notify DucatiDriver */
+ if (status >= 0) {
+ status = notify_ducatidrv_setup(&config->notify_ducatidrv_cfg);
+ if (status < 0) {
+ pr_err("sysmgr_setup : "
+ "notify_ducatidrv_setup failed [0x%x]\n",
+ status);
+ } else {
+ pr_err("notify_ducatidrv_setup : "
+ "status [0x%x]\n" , status);
+ sysmgr_state.notify_ducatidrv_init_flag = true;
+ }
+ }
+
+ /* Initialize NameServerRemoteNotify */
+ if (status >= 0) {
+ status = nameserver_remotenotify_setup(
+ &config->nameserver_remotenotify_cfg);
+ if (status < 0) {
+ pr_err("sysmgr_setup : "
+ "nameserver_remotenotify_setup failed [0x%x]\n",
+ status);
+ } else {
+ pr_err("nameserver_remotenotify_setup : "
+ "status [0x%x]\n" , status);
+ sysmgr_state.nameserver_remotenotify_init_flag = true;
+ }
+ }
+
+ if (status >= 0) {
+ /* Call platform setup function */
+ status = platform_setup(config);
+ if (status < 0) {
+ pr_err("sysmgr_setup : platform_setup "
+ "failed [0x%x]\n", status);
+ } else {
+ pr_err("platform_setup : status [0x%x]\n" ,
+ status);
+ sysmgr_state.platform_init_flag = true;
+ }
+ }
+
+exit:
+ if (status < 0)
+ atomic_set(&sysmgr_state.ref_count, SYSMGR_MAKE_MAGICSTAMP(0));
+
+ return status;
+}
+EXPORT_SYMBOL(sysmgr_setup);
+
+/*
+ * ======== sysmgr_setup ========
+ * Purpose:
+ * Function to finalize the System.
+ */
+s32 sysmgr_destroy(void)
+{
+ s32 status = 0;
+
+ if (atomic_cmpmask_and_lt(&(sysmgr_state.ref_count),
+ SYSMGR_MAKE_MAGICSTAMP(0),
+ SYSMGR_MAKE_MAGICSTAMP(1)) != false) {
+ /*! @retval SYSMGR_E_INVALIDSTATE Module was not initialized */
+ status = SYSMGR_E_INVALIDSTATE;
+ goto exit;
+ }
+
+ if (atomic_dec_return(&sysmgr_state.ref_count)
+ != SYSMGR_MAKE_MAGICSTAMP(0)) {
+ status = 1;
+ goto exit;
+ }
+
+ /* Finalize Platform module*/
+ if (sysmgr_state.platform_init_flag == true) {
+ status = platform_destroy();
+ if (status < 0) {
+ pr_err("sysmgr_destroy : platform_destroy "
+ "failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.platform_init_flag = false;
+ }
+ }
+
+ /* Finalize NameServerRemoteNotify module */
+ if (sysmgr_state.nameserver_remotenotify_init_flag == true) {
+ status = nameserver_remotenotify_destroy();
+ if (status < 0) {
+ pr_err("sysmgr_destroy : "
+ "nameserver_remotenotify_destroy "
+ "failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.nameserver_remotenotify_init_flag \
+ = false;
+ }
+ }
+
+ /* Finalize Notify Ducati Driver module */
+ if (sysmgr_state.notify_ducatidrv_init_flag == true) {
+ status = notify_ducatidrv_destroy();
+ if (status < 0) {
+ pr_err("sysmgr_destroy : "
+ "notify_ducatidrv_destroy failed [0x%x]\n",
+ status);
+ } else {
+ sysmgr_state.notify_ducatidrv_init_flag = false;
+ }
+ }
+
+ /* Finalize MessageQTransportShm module */
+ if (sysmgr_state.messageq_transportshm_init_flag == true) {
+ status = messageq_transportshm_destroy();
+ if (status < 0) {
+ pr_err("sysmgr_destroy : "
+ "messageq_transportshm_destroy failed [0x%x]\n",
+ status);
+ } else {
+ sysmgr_state.messageq_transportshm_init_flag = \
+ false;
+ }
+ }
+
+ /* Finalize ListMPSharedMemory module */
+ if (sysmgr_state.listmp_sharedmemory_init_flag == true) {
+ status = listmp_sharedmemory_destroy();
+ if (status < 0) {
+ pr_err("sysmgr_destroy : "
+ "listmp_sharedmemory_destroy failed [0x%x]\n",
+ status);
+ } else {
+ sysmgr_state.listmp_sharedmemory_init_flag = \
+ false;
+ }
+ }
+
+ /* Finalize HeapBuf module */
+ if (sysmgr_state.heapbuf_init_flag == true) {
+ status = heapbuf_destroy();
+ if (status < 0) {
+ pr_err("sysmgr_destroy : heapbuf_destroy "
+ "failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.heapbuf_init_flag = false;
+ }
+ }
+
+ /* Finalize MessageQ module */
+ if (sysmgr_state.messageq_init_flag == true) {
+ status = messageq_destroy();
+ if (status < 0) {
+ pr_err("sysmgr_destroy : messageq_destroy "
+ "failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.messageq_init_flag = false;
+ }
+ }
+
+ /* Finalize GatePeterson module */
+ if (sysmgr_state.gatepeterson_init_flag == true) {
+ status = gatepeterson_destroy();
+ if (status < 0) {
+ pr_err("sysmgr_destroy : "
+ "gatepeterson_destroy failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.gatepeterson_init_flag = false;
+ }
+ }
+
+ /* Finalize NameServer module */
+ if (sysmgr_state.nameserver_init_flag == true) {
+ status = nameserver_destroy();
+ if (status < 0) {
+ pr_err("sysmgr_destroy : nameserver_destroy "
+ "failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.nameserver_init_flag = false;
+ }
+ }
+
+ /* Finalize Notify module */
+ if (sysmgr_state.notify_init_flag == true) {
+ status = notify_destroy();
+ if (status < 0) {
+ pr_err("sysmgr_destroy : sysmgr_destroy "
+ "failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.notify_init_flag = false;
+ }
+ }
+
+ /* Finalize SharedRegion module */
+ if (sysmgr_state.sharedregion_init_flag == true) {
+ status = sharedregion_destroy();
+ if (status < 0) {
+ pr_err("sysmgr_destroy : "
+ "sharedregion_destroy failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.sharedregion_init_flag = false;
+ }
+ }
+
+ /* Finalize ProcMgr module */
+ if (sysmgr_state.proc_mgr_init_flag == true) {
+ status = proc_mgr_destroy();
+ if (status < 0) {
+ pr_err("sysmgr_destroy : proc_mgr_destroy "
+ "failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.proc_mgr_init_flag = false;
+ }
+ }
+
+ /* Finalize MultiProc module */
+ if (sysmgr_state.multiproc_init_flag == true) {
+ status = multiproc_destroy();
+ if (status < 0) {
+ pr_err("sysmgr_destroy : multiproc_destroy "
+ "failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.proc_mgr_init_flag = false;
+ }
+ }
+
+ /* Finalize PlatformMem module */
+ if (sysmgr_state.platform_mem_init_flag == true) {
+ status = platform_mem_destroy();
+ if (status < 0) {
+ pr_err("sysmgr_destroy : platform_mem_destroy "
+ "failed [0x%x]\n", status);
+ } else {
+ sysmgr_state.platform_mem_init_flag = false;
+ }
+ }
+
+ atomic_set(&sysmgr_state.ref_count, SYSMGR_MAKE_MAGICSTAMP(0));
+
+exit:
+ if (status < 0) {
+ pr_err("sysmgr_destroy : failed with "
+ "status = [0x%x]\n", status);
+ }
+ return status;
+}
+EXPORT_SYMBOL(sysmgr_destroy);
+
+/*
+ * ======== sysmgr_set_boot_load_page ========
+ * Purpose:
+ * Function to set the boot load page address for a slave.
+ */
+void sysmgr_set_boot_load_page(u16 proc_id, u32 boot_load_page)
+{
+ struct sysmgr_boot_load_page *temp = \
+ (struct sysmgr_boot_load_page *) boot_load_page;
+
+ if ((proc_id < 0) || (proc_id >= MULTIPROC_MAXPROCESSORS)) {
+ pr_err(
+ "sysmgr_set_boot_load_page failed: Invalid proc_id passed\n");
+ return;
+ }
+
+ /* Initialize the host config area */
+ sysmgr_state.boot_load_page[proc_id] = temp;
+ temp->host_config.offset = -1;
+ temp->host_config.valid = 0;
+ temp->handshake = 0;
+}
+
+
+/*
+ * ======== sysmgr_wait_for_scalability_info ========
+ * Purpose:
+ * Function to wait for scalability handshake value.
+ */
+void sysmgr_wait_for_scalability_info(u16 proc_id)
+{
+ VOLATILE struct sysmgr_boot_load_page *temp = NULL;
+
+ if ((proc_id < 0) || (proc_id >= MULTIPROC_MAXPROCESSORS)) {
+ pr_err("sysmgr_wait_for_scalability_info failed: "
+ "Invalid proc_id passed\n");
+ return;
+ }
+ temp = sysmgr_state.boot_load_page[proc_id];
+
+ pr_err("sysmgr_wait_for_scalability_info: BF while temp->handshake:%x\n",
+ temp->handshake);
+ while (temp->handshake != SYSMGR_SCALABILITYHANDSHAKESTAMP)
+ ;
+ pr_err("sysmgr_wait_for_scalability_info:AF while temp->handshake:%x\n",
+ temp->handshake);
+
+ /* Reset the handshake value for reverse synchronization */
+ temp->handshake = 0;
+}
+
+
+/*
+ * ======== sysmgr_wait_for_slave_setup ========
+ * Purpose:
+ * Function to wait for slave to complete setup.
+ */
+void sysmgr_wait_for_slave_setup(u16 proc_id)
+{
+ VOLATILE struct sysmgr_boot_load_page *temp = NULL;
+
+ if ((proc_id < 0) || (proc_id >= MULTIPROC_MAXPROCESSORS)) {
+ pr_err("sysmgr_wait_for_slave_setup failed: "
+ "Invalid proc_id passed\n");
+ return;
+ }
+ temp = sysmgr_state.boot_load_page[proc_id];
+
+ while (temp->handshake != SYSMGR_SETUPHANDSHAKESTAMP)
+ ;
+
+ /* Reset the handshake value for reverse synchronization */
+ temp->handshake = 0;
+}