/*
 *  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 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;
		printk(KERN_ALERT "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;

	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;
		}
	}

	/* 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;

	/* 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->slave_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->slave_config);
	}

	/* 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) {
		printk(KERN_ERR "sysmgr_setup : platform_mem_setup "
			"failed [0x%x]\n", status);
	} else {
		printk(KERN_ERR "platform_mem_setup_setup : status [0x%x]\n" ,
			status);
	}

	/* Override the platform specific configuration */
	platform_override_config(config);

	status = multiproc_setup(&(config->multiproc_cfg));
	if (status < 0) {
		printk(KERN_ERR "sysmgr_setup : multiproc_setup "
			"failed [0x%x]\n", status);
	} else {
		printk(KERN_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) {
			printk(KERN_ERR "sysmgr_setup : proc_mgr_setup "
				"failed [0x%x]\n", status);
		} else {
			printk(KERN_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) {
			printk(KERN_ERR "sysmgr_setup : sharedregion_setup "
				"failed [0x%x]\n", status);
		} else {
			printk(KERN_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) {
			printk(KERN_ERR "sysmgr_setup : notify_setup "
				"failed [0x%x]\n", status);
		} else {
			printk(KERN_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) {
			printk(KERN_ERR "sysmgr_setup : nameserver_setup "
				"failed [0x%x]\n", status);
		} else {
			printk(KERN_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) {
			printk(KERN_ERR "sysmgr_setup : gatepeterson_setup "
				"failed [0x%x]\n", status);
		} else {
			printk(KERN_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) {
			printk(KERN_ERR "sysmgr_setup : messageq_setup "
				"failed [0x%x]\n", status);
		} else {
			printk(KERN_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) {
			printk(KERN_ERR "sysmgr_setup : heapbuf_setup "
				"failed [0x%x]\n", status);
		} else {
			printk(KERN_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) {
			printk(KERN_ERR "sysmgr_setup : "
				"listmp_sharedmemory_setup failed [0x%x]\n",
				status);
		} else {
			printk(KERN_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) {
			printk(KERN_ERR "sysmgr_setup : "
				"messageq_transportshm_setup failed [0x%x]\n",
				status);
		} else {
			printk(KERN_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) {
			printk(KERN_ERR "sysmgr_setup : "
				"notify_ducatidrv_setup failed [0x%x]\n",
				status);
		} else {
			printk(KERN_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) {
			printk(KERN_ERR "sysmgr_setup : "
				"nameserver_remotenotify_setup failed [0x%x]\n",
				status);
		} else {
			printk(KERN_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) {
			printk(KERN_ERR "sysmgr_setup : platform_setup "
				"failed [0x%x]\n", status);
		} else {
			printk(KERN_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) {
			printk(KERN_ERR "sysmgr_destroy : platform_destroy "
				"failed [0x%x]", 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) {
			printk(KERN_ERR "sysmgr_destroy : "
				"nameserver_remotenotify_destroy failed [0x%x]",
				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) {
			printk(KERN_ERR "sysmgr_destroy : "
				"notify_ducatidrv_destroy failed [0x%x]",
				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) {
			printk(KERN_ERR "sysmgr_destroy : "
				"messageq_transportshm_destroy failed [0x%x]",
				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) {
			printk(KERN_ERR "sysmgr_destroy : "
				"listmp_sharedmemory_destroy failed [0x%x]",
				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) {
			printk(KERN_ERR "sysmgr_destroy : heapbuf_destroy "
				"failed [0x%x]", status);
		} else {
			sysmgr_state.heapbuf_init_flag = false;
		}
	}

	/* Finalize MessageQ module */
	if (sysmgr_state.messageq_init_flag == true) {
		status = messageq_destroy();
		if (status < 0) {
			printk(KERN_ERR "sysmgr_destroy : messageq_destroy "
				"failed [0x%x]", status);
		} else {
			sysmgr_state.messageq_init_flag = false;
		}
	}

	/* Finalize GatePeterson module */
	if (sysmgr_state.gatepeterson_init_flag == true) {
		status = gatepeterson_destroy();
		if (status < 0) {
			printk(KERN_ERR "sysmgr_destroy : "
				"gatepeterson_destroy failed [0x%x]", status);
		} else {
			sysmgr_state.gatepeterson_init_flag = false;
		}
	}

	/* Finalize NameServer module */
	if (sysmgr_state.nameserver_init_flag == true) {
		status = nameserver_destroy();
		if (status < 0) {
			printk(KERN_ERR "sysmgr_destroy : nameserver_destroy "
				"failed [0x%x]", status);
		} else {
			sysmgr_state.nameserver_init_flag = false;
		}
	}

	/* Finalize Notify module */
	if (sysmgr_state.notify_init_flag == true) {
		status = notify_destroy();
		if (status < 0) {
			printk(KERN_ERR "sysmgr_destroy : sysmgr_destroy "
				"failed [0x%x]", status);
		} else {
			sysmgr_state.notify_init_flag = false;
		}
	}

	/* Finalize SharedRegion module */
	if (sysmgr_state.sharedregion_init_flag == true) {
		status = sharedregion_destroy();
		if (status < 0) {
			printk(KERN_ERR "sysmgr_destroy : "
				"sharedregion_destroy failed [0x%x]", 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) {
			printk(KERN_ERR "sysmgr_destroy : proc_mgr_destroy "
				"failed [0x%x]", 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) {
			printk(KERN_ERR "sysmgr_destroy : multiproc_destroy "
				"failed [0x%x]", status);
		} else {
			sysmgr_state.proc_mgr_init_flag = false;
		}
	}

	atomic_set(&sysmgr_state.ref_count, SYSMGR_MAKE_MAGICSTAMP(0));

exit:
	if (status < 0) {
		printk(KERN_ERR "sysmgr_destroy : Module was not initialized "
			"status = 0x%x]", 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;

	/* 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 = \
		sysmgr_state.boot_load_page[proc_id];

	printk(KERN_ERR "sysmgr_wait_for_scalability_info: BF while temp->handshake:%x\n",
		temp->handshake);

	while (temp->handshake != SYSMGR_SCALABILITYHANDSHAKESTAMP)
		;

	printk(KERN_ERR "sysmgr_wait_for_scalability_info:AF while temp->handshake:%x\n",
		temp->handshake);

}


/*
 * ======== 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 = \
		sysmgr_state.boot_load_page[proc_id];

	while (temp->handshake != SYSMGR_SETUPHANDSHAKESTAMP)
		;
}