diff --git a/arch/arm/plat-omap/include/syslink/_sysmgr.h b/arch/arm/plat-omap/include/syslink/_sysmgr.h new file mode 100644 index 0000000000000000000000000000000000000000..f7faa22f794210a7c80786d5aebafc4aeae0ef0d --- /dev/null +++ b/arch/arm/plat-omap/include/syslink/_sysmgr.h @@ -0,0 +1,38 @@ +/* + * _sysmgr.h + * + * Defines for system manager functions + * + * 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. + */ + +#ifndef __SYSMGR_H_ +#define __SYSMGR_H_ + + +/* Function to set the boot load page address for a slave */ +void sysmgr_set_boot_load_page(u16 proc_id, u32 boot_load_page); + +/* Function to get configuration values for a host object(component/instance) */ +u32 sysmgr_get_object_config(u16 proc_id, void *config, u32 cmd_id, u32 size); + +/* Function to put configuration values for a slave object(component/instance)*/ +u32 sysmgr_put_object_config(u16 proc_id, void *config, u32 cmd_id, u32 size); + +/* Function to wait for scalability handshake value. */ +void sysmgr_wait_for_scalability_info(u16 proc_id); + +/* Function to wait for slave to complete setup */ +void sysmgr_wait_for_slave_setup(u16 proc_id); + + +#endif /* ifndef __SYSMGR_H_ */ diff --git a/arch/arm/plat-omap/include/syslink/platform.h b/arch/arm/plat-omap/include/syslink/platform.h new file mode 100644 index 0000000000000000000000000000000000000000..298d20f7ab5dea4ddc527f824accbbe73a5d9e02 --- /dev/null +++ b/arch/arm/plat-omap/include/syslink/platform.h @@ -0,0 +1,45 @@ +/* + * platform.h + * + * Defines the platform functions to be used by SysMgr module. + * + * 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. + */ + +#ifndef _PLATFORM_H_ +#define _PLATFORM_H_ + +/* Module headers */ +#include <sysmgr.h> + +/* ============================================================================= + * APIs + * ============================================================================= + */ +/* Function to setup the platform */ +s32 platform_setup(struct sysmgr_config *config); + +/* Function to destroy the platform */ +s32 platform_destroy(void); + +/* Function called when slave is loaded with executable */ +void platform_load_callback(void *arg); + +/* Function called when slave is in started state*/ +void platform_start_callback(void *arg); + +/* Function called when slave is stopped state */ +void platform_stop_callback(void *arg); + +s32 platform_override_config(struct sysmgr_config *config); + +#endif /* ifndef _PLATFORM_H_ */ diff --git a/arch/arm/plat-omap/include/syslink/sysmemmgr.h b/arch/arm/plat-omap/include/syslink/sysmemmgr.h new file mode 100644 index 0000000000000000000000000000000000000000..34c3b4182288c95a86c70871ace7453a33be4177 --- /dev/null +++ b/arch/arm/plat-omap/include/syslink/sysmemmgr.h @@ -0,0 +1,179 @@ +/* + * sysmemmgr.h + * + * Manager for the Slave system memory. Slave system level memory is allocated + * through this module. + * + * 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. + */ + + +#ifndef _SYSTEMMEMORYMANAGER_H_ +#define _SYSTEMMEMORYMANAGER_H_ + + +/*! + * @def SYSMEMMGR_MODULEID + * @brief Module identifier for System memory manager. + */ +#define SYSMEMMGR_MODULEID (0xb53d) + +/*! + * @def SYSMEMMGR_STATUSCODEBASE + * @brief Error code base for system memory manager module. + */ +#define SYSMEMMGR_STATUSCODEBASE (SYSMEMMGR_MODULEID << 12u) + +/*! + * @def SYSMEMMGR_MAKE_ERROR + * @brief Macro to make error code. + */ +#define SYSMEMMGR_MAKE_ERROR(x) ((int)(0x80000000 + \ + (SYSMEMMGR_STATUSCODEBASE + \ + (x)))) + +/*! + * @def SYSMEMMGR_MAKE_SUCCESS + * @brief Macro to make success code. + */ +#define SYSMEMMGR_MAKE_SUCCESS(x) (SYSMEMMGR_STATUSCODEBASE + (x)) + +/*! + * @def SYSMEMMGR_E_CREATEALLOCATOR + * @brief Static allocator creation failed. + */ +#define SYSMEMMGR_E_CREATEALLOCATOR SYSMEMMGR_MAKE_ERROR(1) + +/*! + * @def SYSMEMMGR_E_CREATELOCK + * @brief Mutex lock creation failed. + */ +#define SYSMEMMGR_E_CREATELOCK SYSMEMMGR_MAKE_ERROR(2) + +/*! + * @def SYSMEMMGR_E_INVALIDSTATE + * @brief Module is not initialized. + */ +#define SYSMEMMGR_E_INVALIDSTATE SYSMEMMGR_MAKE_ERROR(3) + +/*! + * @def SYSMEMMGR_E_INVALIDARG + * @brief Argument passed to a function is invalid. + */ +#define SYSMEMMGR_E_INVALIDARG SYSMEMMGR_MAKE_ERROR(4) + +/*! + * @def SYSMEMMGR_E_BPAFREE + * @brief Freeing to buddy allocator failed. + */ +#define SYSMEMMGR_E_BPAFREE SYSMEMMGR_MAKE_ERROR(5) + +/*! + * @def SYSMEMMGR_E_MEMORY + * @brief Memory allocation failed. + */ +#define SYSMEMMGR_E_MEMORY SYSMEMMGR_MAKE_ERROR(6) + +/*! + * @def SYSMEMMGR_SUCCESS + * @brief Operation successful. + */ +#define SYSMEMMGR_SUCCESS SYSMEMMGR_MAKE_SUCCESS(0) + +/*! + * @def SYSMEMMGR_S_ALREADYSETUP + * @brief Module already initialized. + */ +#define SYSMEMMGR_S_ALREADYSETUP SYSMEMMGR_MAKE_SUCCESS(1) + +/*! + * @def SYSMEMMGR_S_DRVALREADYOPENED + * @brief Internal OS Driver is already opened. + */ +#define SYSMEMMGR_S_DRVALREADYOPENED SYSMEMMGR_MAKE_SUCCESS(2) + +/*! + * @brief Configuration data structure of system memory manager. + */ +struct sysmemmgr_config { + u32 sizeof_valloc; + /* Total size for virtual memory allocation */ + u32 sizeof_palloc; + /* Total size for physical memory allocation */ + u32 static_phys_base_addr; + /* Physical address of static memory region */ + u32 static_virt_base_addr; + /* Virtual address of static memory region */ + u32 static_mem_size; + /* size of static memory region */ + u32 page_size; + /* Page size */ + u32 event_no; + /* Event number to be used */ +}; + +/*! + * @brief Flag used for allocating memory blocks. + */ +enum sysmemmgr_allocflag { + sysmemmgr_allocflag_uncached = 0u, + /* Flag used for allocating uncacheable block */ + sysmemmgr_allocflag_cached = 1u, + /* Flag used for allocating cacheable block */ + sysmemmgr_allocflag_physical = 2u, + /* Flag used for allocating physically contiguous block */ + sysmemmgr_allocflag_virtual = 3u, + /* Flag used for allocating virtually contiguous block */ + sysmemmgr_allocflag_dma = 4u + /* Flag used for allocating DMAable (physically contiguous) block */ +}; + +/*! + * @brief Flag used for translating address. + */ +enum sysmemmgr_xltflag { + sysmemmgr_xltflag_kvirt2phys = 0x0001u, + /* Flag used for converting Kernel virtual address to physical + * address */ + sysmemmgr_xltflag_kvirt2uvirt = 0x0002u, + /* Flag used for converting Kernel virtual address to user virtual + * address */ + sysmemmgr_xltflag_uvirt2phys = 0x0003u, + /* Flag used for converting user virtual address to physical address */ + sysmemmgr_xltflag_uvirt2kvirt = 0x0004u, + /* Flag used for converting user virtual address to Kernel virtual + * address */ + sysmemmgr_xltflag_phys2kvirt = 0x0005u, + /* Flag used for converting physical address to user virtual address */ + sysmemmgr_xltflag_phys2uvirt = 0x0006u + /* Flag used for converting physical address to Kernel virtual + * address */ +}; + + +/* Function prototypes */ +void sysmemmgr_get_config(struct sysmemmgr_config *config); + +int sysmemmgr_setup(struct sysmemmgr_config *params); + +int sysmemmgr_destroy(void); + +int sysmemmgr_attach(u16 slave_id); + +void *sysmemmgr_alloc(u32 size, enum sysmemmgr_allocflag flag); + +int sysmemmgr_free(void *blk, u32 size, enum sysmemmgr_allocflag flag); + +void *sysmemmgr_translate(void *srcAddr, enum sysmemmgr_xltflag flag); + + +#endif /* _SYSTEMMEMORYMANAGER_H_ */ diff --git a/arch/arm/plat-omap/include/syslink/sysmemmgr_ioctl.h b/arch/arm/plat-omap/include/syslink/sysmemmgr_ioctl.h new file mode 100644 index 0000000000000000000000000000000000000000..4b0d99615560cbe6a54f9bcff1e3e1e8b3ebf4b9 --- /dev/null +++ b/arch/arm/plat-omap/include/syslink/sysmemmgr_ioctl.h @@ -0,0 +1,130 @@ +/* + * sysmemmgr_ioctl.h + * + * Definitions of sysmemmgr driver types and structures.. + * + * Copyright (C) 2008-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. + */ + +#ifndef _SYSMEMMGR_IOCTL_H_ +#define _SYSMEMMGR_IOCTL_H_ + +/* Standard headers */ +#include <linux/types.h> + +/* Syslink headers */ +#include <ipc_ioctl.h> +#include <sysmgr.h> + + +/* ============================================================================= + * Macros and types + * ============================================================================= + */ +/* ---------------------------------------------------------------------------- + * IOCTL command IDs for sysmemmgr + * ---------------------------------------------------------------------------- + */ +/* IOC Magic Number for sysmemmgr */ +#define SYSMEMMGR_IOC_MAGIC IPC_IOC_MAGIC + +/* IOCTL command numbers for sysmemmgr */ +enum sysmemmgr_drv_cmd { + SYSMEMMGR_GETCONFIG = SYSMEMMGR_BASE_CMD, + SYSMEMMGR_SETUP, + SYSMEMMGR_DESTROY, + SYSMEMMGR_ALLOC, + SYSMEMMGR_FREE, + SYSMEMMGR_TRANSLATE +}; + +/* Command for sysmemmgr_getConfig */ +#define CMD_SYSMEMMGR_GETCONFIG \ + _IOWR(SYSMEMMGR_IOC_MAGIC, SYSMEMMGR_GETCONFIG, \ + struct sysmemmgr_cmd_args) + +/* Command for sysmemmgr_setup */ +#define CMD_SYSMEMMGR_SETUP \ + _IOWR(SYSMEMMGR_IOC_MAGIC, SYSMEMMGR_SETUP, \ + struct sysmemmgr_cmd_args) + +/* Command for sysmemmgr_destroy */ +#define CMD_SYSMEMMGR_DESTROY \ + _IOWR(SYSMEMMGR_IOC_MAGIC, SYSMEMMGR_DESTROY, \ + struct sysmemmgr_cmd_args) + +/* Command for sysmemmgr_alloc */ +#define CMD_SYSMEMMGR_ALLOC \ + _IOWR(SYSMEMMGR_IOC_MAGIC, SYSMEMMGR_ALLOC, \ + struct sysmemmgr_cmd_args) + +/* Command for sysmemmgr_free */ +#define CMD_SYSMEMMGR_FREE \ + _IOWR(SYSMEMMGR_IOC_MAGIC, SYSMEMMGR_FREE, \ + struct sysmemmgr_cmd_args) + +/* Command for sysmemmgr_translate */ +#define CMD_SYSMEMMGR_TRANSLATE \ + _IOWR(SYSMEMMGR_IOC_MAGIC, SYSMEMMGR_TRANSLATE, \ + struct sysmemmgr_cmd_args) + + +/* ---------------------------------------------------------------------------- + * Command arguments for sysmemmgr + * ---------------------------------------------------------------------------- + */ +/* Command arguments for sysmemmgr */ +struct sysmemmgr_cmd_args { + union { + struct { + struct sysmemmgr_config *config; + } get_config; + + struct { + struct sysmemmgr_config *config; + } setup; + + struct { + u32 size; + void *buf; + void *phys; + void *kbuf; + enum sysmemmgr_allocflag flags; + } alloc; + + struct { + u32 size; + void *buf; + void *phys; + void *kbuf; + enum sysmemmgr_allocflag flags; + } free; + + struct { + void *buf; + void *ret_ptr; + enum sysmemmgr_xltflag flags; + } translate; + } args; + + s32 api_status; +}; + +/* ---------------------------------------------------------------------------- + * IOCTL functions for sysmemmgr module + * ---------------------------------------------------------------------------- + */ +/* ioctl interface function for sysmemmgr */ +int sysmemmgr_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long args); + +#endif /* SYSMEMMGR_DRVDEFS_H_0xF414 */ diff --git a/arch/arm/plat-omap/include/syslink/sysmgr.h b/arch/arm/plat-omap/include/syslink/sysmgr.h new file mode 100644 index 0000000000000000000000000000000000000000..19fab220b2c4f8c9e0bfa4d04f6354a902bd4d44 --- /dev/null +++ b/arch/arm/plat-omap/include/syslink/sysmgr.h @@ -0,0 +1,182 @@ +/* + * sysmgr.h + * + * Defines for 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. + */ + +#ifndef _SYSMGR_H_ +#define _SYSMGR_H_ + + +/* Module headers */ +#include <multiproc.h> +#include <gatepeterson.h> +#include <sharedregion.h> +#include <listmp.h> +#include <listmp_sharedmemory.h> +#include <messageq.h> +#include <messageq_transportshm.h> +#include <notify.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> +#include <sysmemmgr.h> + + +/*! + * @def SYSMGR_MODULEID + * @brief Unique module ID. + */ +#define SYSMGR_MODULEID (0xF086) + + +/* ============================================================================= + * Module Success and Failure codes + * ============================================================================= + */ +/*! + * @def SYSMGR_STATUSCODEBASE + * @brief Error code base for System manager. + */ +#define SYSMGR_STATUSCODEBASE (SYSMGR_MODULEID << 12u) + +/*! + * @def SYSMGR_MAKE_FAILURE + * @brief Macro to make error code. + */ +#define SYSMGR_MAKE_FAILURE(x) ((s32)(0x80000000 + \ + (SYSMGR_STATUSCODEBASE + \ + (x)))) + +/*! + * @def SYSMGR_MAKE_SUCCESS + * @brief Macro to make success code. + */ +#define SYSMGR_MAKE_SUCCESS(x) (SYSMGR_STATUSCODEBASE + (x)) + +/*! + * @def SYSMGR_E_INVALIDARG + * @brief Argument passed to a function is invalid. + */ +#define SYSMGR_E_INVALIDARG SYSMGR_MAKE_FAILURE(1) + +/*! + * @def SYSMGR_E_MEMORY + * @brief Memory allocation failed. + */ +#define SYSMGR_E_MEMORY SYSMGR_MAKE_FAILURE(2) + +/*! + * @def SYSMGR_E_FAIL + * @brief General failure. + */ +#define SYSMGR_E_FAIL SYSMGR_MAKE_FAILURE(3) + +/*! + * @def SYSMGR_E_INVALIDSTATE + * @brief Module is in invalid state. + */ +#define SYSMGR_E_INVALIDSTATE SYSMGR_MAKE_FAILURE(4) + +/*! + * @def SYSMGR_E_OSFAILURE + * @brief Failure in OS call. + */ +#define SYSMGR_E_OSFAILURE SYSMGR_MAKE_FAILURE(5) + +/*! + * @def SYSMGR_S_ALREADYSETUP + * @brief Module is already initialized. + */ +#define SYSMGR_S_ALREADYSETUP SYSMGR_MAKE_SUCCESS(1) + +/*! + * @def SYSMGR_CMD_SCALABILITY + * @brief Command ID for scalability info. + */ +#define SYSMGR_CMD_SCALABILITY (0x00000000) + +/*! + * @def SYSMGR_CMD_SHAREDREGION_ENTRY_BASE + * @brief Base of command IDs for entries used by Shared region. + */ +#define SYSMGR_CMD_SHAREDREGION_ENTRY_START (0x00000001) +#define SYSMGR_CMD_SHAREDREGION_ENTRY_END (0x00001000) + + +/* ============================================================================= + * Structures & Enums + * ============================================================================= + */ +/*! + * @brief Structure defining config parameters for overall System. + */ +struct sysmgr_config { + struct sysmemmgr_config sysmemmgr_cfg; + /*!< System memory manager config parameter */ + + struct multiproc_config multiproc_cfg; + /*!< Multiproc config parameter */ + + struct gatepeterson_config gatepeterson_cfg; + /*!< Gatepeterson config parameter */ + + struct sharedregion_config sharedregion_cfg; + /*!< SharedRegion config parameter */ + + struct messageq_config messageq_cfg; + /*!< MessageQ config parameter */ + + struct notify_config notify_cfg; + /*!< Notify config parameter */ + + struct proc_mgr_config proc_mgr_cfg; + /*!< Processor manager config parameter */ + + struct heapbuf_config heapbuf_cfg; + /*!< Heap Buf config parameter */ + + struct listmp_config listmp_sharedmemory_cfg; + /*!< ListMPSharedMemory config parameter */ + + struct messageq_transportshm_config messageq_transportshm_cfg; + /*!< MessageQTransportShm config parameter */ + + struct notify_ducatidrv_config notify_ducatidrv_cfg; + /*!< NotifyDriverShm config parameter */ + + struct nameserver_remotenotify_config nameserver_remotenotify_cfg; + /*!< NameServerRemoteNotify config parameter */ +}; + + +/* ============================================================================= + * APIs + * ============================================================================= + */ +/* Function to initialize the parameter structure */ +void sysmgr_get_config(struct sysmgr_config *config); + +/* Function to initialize sysmgr module */ +s32 sysmgr_setup(const struct sysmgr_config *config); + +/* Function to Finalize sysmgr module */ +s32 sysmgr_destroy(void); + + +#endif /* ifndef SYSMGR_H_0xF086 */ diff --git a/arch/arm/plat-omap/include/syslink/sysmgr_ioctl.h b/arch/arm/plat-omap/include/syslink/sysmgr_ioctl.h new file mode 100644 index 0000000000000000000000000000000000000000..1ec7d15b478545dd0cf0f4a62d5b7fa7980df1c0 --- /dev/null +++ b/arch/arm/plat-omap/include/syslink/sysmgr_ioctl.h @@ -0,0 +1,80 @@ +/* + * sysmgr_ioctl.h + * + * Definitions of sysmgr driver types and structures.. + * + * Copyright (C) 2008-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. + */ + +#ifndef _SYSMGR_IOCTL_H_ +#define _SYSMGR_IOCTL_H_ + +/* Standard headers */ +#include <linux/types.h> + +/* Syslink headers */ +#include <ipc_ioctl.h> +#include <sysmgr.h> + + +/* ============================================================================= + * Macros and types + * ============================================================================= + */ +/* ---------------------------------------------------------------------------- + * IOCTL command IDs for sysmgr + * ---------------------------------------------------------------------------- + */ +/* IOC Magic Number for sysmgr */ +#define SYSMGR_IOC_MAGIC IPC_IOC_MAGIC + +/* IOCTL command numbers for sysmgr */ +enum sysmgr_drv_cmd { + SYSMGR_SETUP = SYSMGR_BASE_CMD, + SYSMGR_DESTROY +}; + +/* Command for sysmgr_setup */ +#define CMD_SYSMGR_SETUP \ + _IOWR(SYSMGR_IOC_MAGIC, SYSMGR_SETUP, \ + struct sysmgr_cmd_args) + +/* Command for sysmgr_destroy */ +#define CMD_SYSMGR_DESTROY \ + _IOWR(SYSMGR_IOC_MAGIC, SYSMGR_DESTROY, \ + struct sysmgr_cmd_args) + + +/* ---------------------------------------------------------------------------- + * Command arguments for sysmgr + * ---------------------------------------------------------------------------- + */ +/* Command arguments for sysmgr */ +struct sysmgr_cmd_args { + union { + struct { + struct sysmgr_config *config; + } setup; + } args; + + s32 api_status; +}; + +/* ---------------------------------------------------------------------------- + * IOCTL functions for sysmgr module + * ---------------------------------------------------------------------------- + */ +/* ioctl interface function for sysmgr */ +int sysmgr_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long args); + +#endif /* _SYSMGR_IOCTL_H_ */ diff --git a/drivers/dsp/syslink/multicore_ipc/platform.c b/drivers/dsp/syslink/multicore_ipc/platform.c new file mode 100644 index 0000000000000000000000000000000000000000..40d4b51cb3d160549e3f666b0285be959b613a18 --- /dev/null +++ b/drivers/dsp/syslink/multicore_ipc/platform.c @@ -0,0 +1,927 @@ +/* + * platform.c + * + * Implementation of platform initialization logic for Syslink IPC. + * + * Copyright (C) 2008-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 header files */ +#include <linux/types.h> +#include <linux/module.h> + + +/* Utilities & Osal headers */ +/*#include <Gate.h> +#include <GateMutex.h> +#include <Memory.h>*/ + +/* SysLink device specific headers */ +#include "../procmgr/proc4430/proc4430.h" + +/* Module level headers */ +#include <multiproc.h> +#include <sysmgr.h> +#include <_sysmgr.h> +#include <sysmemmgr.h> +#include <platform.h> +#include <gatepeterson.h> +#include <sharedregion.h> +#include <listmp.h> +#include <messageq.h> +#include <messageq_transportshm.h> +#include <notify.h> +/*#include <NotifyDriver.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> + +#include <platform_mem.h> + + +/** ============================================================================ + * Application specific configuration, please change these value according to + * your application's need. + * ============================================================================ + */ +/* App defines */ +#define HEAPID 0 +#define HEAPNAME "myHeap" + +/*! + * @brief Interrupt ID of physical interrupt handled by the Notify driver to + * receive events. + */ +#define BASE_DUCATI2ARM_INTID 26 + +/*! + * @brief Interrupt ID of physical interrupt handled by the Notify driver to + * send events. + */ +#define BASE_ARM2DUCATI_INTID 50 + +/*! + * @brief Maximum events supported by Notify component + */ +#define NOTIFY_MAX_EVENTS 32 + +/*! + * @brief Number of event reserved i.e. can not be used by application + */ +#define NOTIFY_NUMRESERVEDEVENTS 0 + +/*! + * @brief Wait for this much poll count when sending event + */ +#define NOTIFY_SENDEVENTPOLLCOUNT ((u32) -1) + +/*! + * @brief Align buffer in Heap + */ +#define HEAPBUF_ALIGN 128 + +/*! + * @brief Number of blocks in the heap + */ +#define HEAPBUF_NUMBLOCKS 16 + +/*! + * @brief Size of each blocks in heap + */ +#define HEAPBUF_BLOCKSIZE 256 + +/*! @brief Start of shared memory */ +#define SHAREDMEMORY_BASEADDR 0x87100000 +#define SHAREDMEMORY_BASESIZE 0x0007F000 + +/*! @brief Start of Boot load page */ +#define BOOTLOADPAGE_BASEADDR 0x8717F000 +#define BOOTLOADPAGE_BASESIZE 0x00001000 + +/*! @brief Start of shared memory */ +#define SHAREDMEMORY_BASEADDR_APPM3 0x87180000 +#define SHAREDMEMORY_BASESIZE_APPM3 0x0007F000 + +/*! @brief Start of Boot load page */ +#define BOOTLOADPAGE_BASEADDR_APPM3 0x8718F000 +#define BOOTLOADPAGE_BASESIZE_APPM3 0x0000F000 + +/*! + * @brief Size of the shared memory heap, this heap is used for providing + * shared memory to drivers/instances. Should not be used for any other purpose. + */ +#define SMHEAP_SIZE 0x10000 + +/*! + * @brief Shared region index for Shared memory heap. + */ +#define SMHEAP_SRINDEX 0 + +/*! + * @brief Event no used by sysmemmgr + */ +#define PLATFORM_SYSMEMMGR_EVENTNO 31 + + +/** ============================================================================ + * Command Id used by bootloadpage logic to transfer info + * ============================================================================ + */ +/*! + * @brief Command ID for notify driver. + */ +#define PLATFORM_CMD_NOTIFYDRIVER SYSMGR_CMD_SHAREDREGION_ENTRY_END + +/*! + * @brief Command ID for GatePeterson used by nameserverremotenotify. + */ +#define PLATFORM_CMD_GPNSRN (PLATFORM_CMD_NOTIFYDRIVER + 1) + +/*! + * @brief Command ID for nameserverremotenotify. + */ +#define PLATFORM_CMD_NSRN (PLATFORM_CMD_NOTIFYDRIVER + 2) + +/*! + * @brief Command ID for GatePeterson used by HeapBuf. + */ +#define PLATFORM_CMD_GPHEAPBUF (PLATFORM_CMD_NOTIFYDRIVER + 3) + +/*! + * @brief Command ID for HeapBuf. + */ +#define PLATFORM_CMD_HEAPBUF (PLATFORM_CMD_NOTIFYDRIVER + 4) + +/*! + * @brief Command ID for GatePeterson used by MessageQTransportShm. + */ +#define PLATFORM_CMD_GPMQT (PLATFORM_CMD_NOTIFYDRIVER + 5) + +/*! + * @brief Command ID for MessageQTransportShm. + */ +#define PLATFORM_CMD_MQT (PLATFORM_CMD_NOTIFYDRIVER + 6) + + +/** ============================================================================ + * Handles used by platform logic + * ============================================================================ + */ +void *platform_nsrn_gate_handle; +void *platform_nsrn_handle; +void *platform_notifydrv_handle; +void *platform_heap_gate_handle; +void *platform_heap_handle; +void *platform_mqt_gate_handle; +void *platform_transport_shm_handle; +void *platform_messageq; + +/** ============================================================================ + * Struct & Enums. + * ============================================================================ + */ +/* Struct for reading platform specific gate peterson configuration values */ +struct platform_gaterpeterson_params { + u32 shared_mem_addr; /* Shared memory address */ + u32 shared_mem_size; /* Shared memory size */ + u32 remote_proc_id; /* Remote processor identifier */ +}; + +struct platform_notify_ducatidrv_params { + u32 shared_mem_addr; /* Shared memory address */ + u32 shared_mem_size; /* Shared memory size */ + u16 remote_proc_id; /* Remote processor identifier */ +}; + +struct platform_nameserver_remotenotify_params { + u32 shared_mem_addr; /* Shared memory address */ + u32 shared_mem_size; /* Shared memory size */ + u32 notify_event_no; /* Notify Event number to used */ +}; + +struct platform_heapbuf_params { + u32 shared_mem_addr; /* Shared memory address */ + u32 shared_mem_size; /* Shared memory size */ + u32 shared_buf_addr; /* Shared memory address */ + u32 shared_buf_size; /* Shared memory size */ + u32 num_blocks; + u32 block_size; +}; + +struct platform_messageq_transportshm_params { + u32 shared_mem_addr; /* Shared memory address */ + u32 shared_mem_size; /* Shared memory size */ + u32 notify_event_no; /* Notify Event number */ +}; + +struct platform_proc_config_params { + u32 reserved1; + u32 use_notify; + u32 use_messageq; + u32 use_heapbuf; + u32 use_listmp; + u32 use_nameserver; + u32 reserved2; +}; + + +/** ============================================================================ + * Macros and types + * ============================================================================ + */ +/*! + * @brief Number of slave memory entries for OMAP4430. + */ +#define NUM_MEM_ENTRIES 2 + +/*! + * @brief Position of reset vector memory region in the memEntries array. + */ +#define RESET_VECTOR_ENTRY_ID 0 + + +/** ============================================================================ + * Globals + * ============================================================================ + */ +/*! + * @brief Array of memory entries for OMAP4430 + */ +static struct proc4430_mem_entry mem_entries[NUM_MEM_ENTRIES] = { + { + "DUCATI_SHM", /* NAME : Name of the memory region */ + 0x87100000, /* PHYSADDR : Physical address */ + 0x98000000, /* SLAVEVIRTADDR : Slave virtual address */ + (u32) -1u, + /* MASTERVIRTADDR : Master virtual address (if known) */ + 0x80000, /* SIZE : Size of the memory region */ + true, /* SHARE : Shared access memory? */ + }, + { + "DUCATI_SHM1", /* NAME : Name of the memory region */ + 0x87180000, /* PHYSADDR : Physical address */ + 0x98080000, /* SLAVEVIRTADDR : Slave virtual address */ + (u32) -1u, + /* MASTERVIRTADDR : Master virtual address (if known) */ + 0x80000, /* SIZE : Size of the memory region */ + true, /* SHARE : Shared access memory? */ + } +}; + + +/*! + * @brief Handle to the ProcMgr instance used. + */ +void *procmgr_handle; + +/*! + * @brief Handle to the Processor instance used. + */ +void *procmgr_proc_handle; + +/*! + * @brief File ID of the file loaded. + */ +u32 procmgr_file_id; + +/*! + * @brief Shared memory heap virtual address. + */ +void *platform_sm_heap_virt_addr; + +/*! + * @brief Shared memory heap physical address. + */ +void *platform_sm_heap_phys_addr; + +/*! + * @brief Scalability info + */ +struct platform_proc_config_params pc_params; + +/* ============================================================================= + * APIS + * ============================================================================= + */ +/* + * ======== platform_setup ======== + * Purpose: + * TBD: logic would change completely in the final system. + */ +s32 platform_setup(struct sysmgr_config *config) +{ + s32 status = 0; + struct proc4430_config proc_config; + struct proc_mgr_params params; + struct proc4430_params proc_params; + u16 proc_id; + struct sysmemmgr_config sysmemmgr_cfg; + struct platform_mem_map_info info; + + if (WARN_ON(config == NULL)) { + /*! @retval SYSMGR_E_INVALIDARG Argument of type + * (GatePeterson_Config *) passed is null*/ + status = -EINVAL; + goto invalid_config_fail; + } + + /* Map the static region */ + info.src = SHAREDMEMORY_BASEADDR; + info.size = SHAREDMEMORY_BASESIZE; + info.is_cached = false; + status = platform_mem_map(&info); + if (status < 0) + goto mem_map_fail; + + /* Get default config for System memory manager */ + sysmemmgr_get_config(&sysmemmgr_cfg); + /* Initialize the System memory manager */ + sysmemmgr_cfg.static_mem_size = SHAREDMEMORY_BASESIZE; + sysmemmgr_cfg.static_phys_base_addr = SHAREDMEMORY_BASEADDR; + sysmemmgr_cfg.static_virt_base_addr = info.dst; + sysmemmgr_cfg.event_no = PLATFORM_SYSMEMMGR_EVENTNO; + status = sysmemmgr_setup(&sysmemmgr_cfg); + if (status < 0) + goto sysmemmgr_setup_fail; + + platform_sm_heap_virt_addr = sysmemmgr_alloc(SMHEAP_SIZE, + sysmemmgr_allocflag_physical); + if (platform_sm_heap_virt_addr == NULL) + goto sysmemmgr_alloc_fail; + + /* Create the shared region entry for the SM heap */ + sharedregion_add(SMHEAP_SRINDEX, platform_sm_heap_virt_addr, + SMHEAP_SIZE); + /* Zero out the shared memory */ + memset((void *) platform_sm_heap_virt_addr, 0, SMHEAP_SIZE); + + proc4430_get_config(&proc_config); + status = proc4430_setup(&proc_config); + if (status < 0) + goto proc_setup_fail; + + /* Get MultiProc ID by name. */ + proc_id = multiproc_get_id("SysM3"); + + /* Create an instance of the Processor object for OMAP4430 */ + proc4430_params_init(NULL, &proc_params); + proc_params.num_mem_entries = NUM_MEM_ENTRIES; + proc_params.mem_entries = (struct proc4430_mem_entry *) &mem_entries; + proc_params.reset_vector_mem_entry = RESET_VECTOR_ENTRY_ID; + + procmgr_proc_handle = proc4430_create(proc_id, &proc_params); + if (procmgr_proc_handle == NULL) { + status = SYSMGR_E_FAIL; + goto proc_create_fail; + } + + /* Initialize parameters */ + proc_mgr_params_init(NULL, ¶ms); + params.proc_handle = procmgr_proc_handle; + procmgr_handle = proc_mgr_create(proc_id, ¶ms); + if (procmgr_handle == NULL) { + status = SYSMGR_E_FAIL; + goto proc_mgr_create_fail; + } + +proc_mgr_create_fail: + printk(KERN_ERR "platform_setup: proc_mgr_create failed [0x%x]", + status); + goto exit; +proc_create_fail: + printk(KERN_ERR "platform_setup: proc4430_create failed [0x%x]", + status); + goto exit; +proc_setup_fail: + printk(KERN_ERR "platform_setup: proc4430_setup failed [0x%x]", + status); + goto exit; +sysmemmgr_alloc_fail: + printk(KERN_ERR "platform_setup: sysmemmgr_alloc failed [0x%x]", + status); + goto exit; +sysmemmgr_setup_fail: + printk(KERN_ERR "platform_setup: sysmemmgr_setup failed [0x%x]", + status); + goto exit; +mem_map_fail: + printk(KERN_ERR "platform_setup: platform_mem_map failed [0x%x]", + status); + goto exit; +invalid_config_fail: + printk(KERN_ERR "platform_setup: Argument of type (sysmgr_get_config *)" + " passed is null [0x%x]", status); +exit: + return status; +} + + +/* + * ======== platform_destroy ======== + * Purpose: + * Function to finalize the platform. + */ +s32 platform_destroy(void) +{ + s32 status = 0; + struct platform_mem_unmap_info u_info; + + /* Delete the Processor instances */ + if (procmgr_proc_handle != NULL) { + status = proc4430_delete(&procmgr_proc_handle); + WARN_ON(status < 0); + } + + if (procmgr_handle != NULL) { + status = proc_mgr_delete(&procmgr_handle); + WARN_ON(status < 0); + } + + status = proc4430_destroy(); + WARN_ON(status < 0); + + /* Delete the memory map */ + u_info.addr = (u32) platform_sm_heap_virt_addr; + platform_mem_unmap(&u_info); + + status = sysmemmgr_destroy(); + WARN_ON(status < 0); + + return status; +} + + +/* + * ======== platform_load_callback ======== + * Purpose: + * Function called by proc_mgr when slave is in loaded state. + */ +void platform_load_callback(void *arg) +{ + s32 status = 0; + u16 proc_id = (u32) arg; + u16 local_id = MULTIPROC_INVALIDID; + struct sharedregion_info info; + u32 boot_load_page; + u32 sh_addr_base; + u32 nwrite; + + /* Get the boot load page address */ + /* TBD: + boot_load_page = Proc_getBootLoadPage (procmgr_handle); */ + boot_load_page = BOOTLOADPAGE_BASEADDR; + status = proc_mgr_translate_addr(procmgr_handle, + (void *) &sh_addr_base, + PROC_MGR_ADDRTYPE_MASTERKNLVIRT, + (void *) boot_load_page, + PROC_MGR_ADDRTYPE_SLAVEVIRT); + if (status < 0) { + printk(KERN_ERR "proc_mgr_translate_addr [0x%x]\n", + status); + } else { + /* Zero out the boot load page */ + memset((void *) sh_addr_base, 0, BOOTLOADPAGE_BASESIZE); + + /* Set the boot load page address */ + sysmgr_set_boot_load_page(proc_id, sh_addr_base); + + /* Get the written entry */ + local_id = multiproc_get_id(NULL); + sharedregion_get_table_info(SMHEAP_SRINDEX, local_id, &info); + platform_sm_heap_phys_addr = sysmemmgr_translate( + platform_sm_heap_virt_addr, + sysmemmgr_xltflag_kvirt2phys); + info.base = (void *) platform_sm_heap_phys_addr; + + /* Write info the boot load page */ + nwrite = sysmgr_put_object_config(proc_id, + (void *) &info, + SYSMGR_CMD_SHAREDREGION_ENTRY_START, + sizeof(struct sharedregion_info)); + WARN_ON(nwrite != sizeof(struct sharedregion_info)); + } +} +EXPORT_SYMBOL(platform_load_callback); + + +/* + * ======== platform_start_callback ======== + * Purpose: + * Function called by proc_mgr when slave is in started state. + * FIXME: logic would change completely in the final system. + */ +void platform_start_callback(void *arg) +{ + s32 status = 0; + u16 local_id = MULTIPROC_INVALIDID; + u16 proc_id = (u32) arg; + u32 nread = 0; + u32 i = 0; + u32 cmd_id; + u32 sh_addr; + + struct notify_ducatidrv_params notify_shm_params; + struct gatepeterson_params gate_params; + struct nameserver_remotenotify_params nsr_params; + struct heapbuf_params heap_params; + struct messageq_transportshm_params msgqt_params; + struct sharedregion_config sr_config; + struct sharedregion_info info; + + struct platform_notify_ducatidrv_params pnds_params; + struct platform_heapbuf_params phb_params; + struct platform_gaterpeterson_params pgp_params; + struct platform_nameserver_remotenotify_params pnsrn_params; + struct platform_messageq_transportshm_params pmqt_params; + /*u32 proc_ids[2];*/ + + /* Wait for slave to write the scalability info */ + sysmgr_wait_for_scalability_info(proc_id); + /* Read the scalability info */ + do { + nread = sysmgr_get_object_config(proc_id, (void *) &pc_params, + SYSMGR_CMD_SCALABILITY, + sizeof(struct platform_proc_config_params)); + } while (nread != sizeof(struct platform_proc_config_params)); + + if (status >= 0) { + local_id = multiproc_get_id(NULL); + status = multiproc_set_local_id(local_id); + if (status < 0) { + status = SYSMGR_E_FAIL; + goto multiproc_fail; + } + } + + if (pc_params.use_notify) { + do { + nread = sysmgr_get_object_config(proc_id, + (void *) &pnds_params, + PLATFORM_CMD_NOTIFYDRIVER, + sizeof(struct \ + platform_notify_ducatidrv_params)); + } while (nread != \ + sizeof(struct platform_notify_ducatidrv_params)); + sh_addr = (u32)sharedregion_get_ptr((u32 *) + pnds_params.shared_mem_addr); + if (sh_addr == (u32)NULL) { + status = SYSMGR_E_FAIL; + goto sharedregion_getptr_fail; + } + notify_ducatidrv_params_init(NULL, ¬ify_shm_params); + notify_shm_params.shared_addr = sh_addr; + notify_shm_params.shared_addr_size = \ + pnds_params.shared_mem_size; + notify_shm_params.num_events = NOTIFY_MAX_EVENTS; + notify_shm_params.num_reserved_events = \ + NOTIFY_NUMRESERVEDEVENTS; + notify_shm_params.send_event_poll_count = \ + NOTIFY_SENDEVENTPOLLCOUNT; + notify_shm_params.recv_int_id = BASE_DUCATI2ARM_INTID; + notify_shm_params.send_int_id = BASE_ARM2DUCATI_INTID; + notify_shm_params.remote_proc_id = proc_id; + + /* Create instance of Notify Ducati Driver */ + platform_notifydrv_handle = notify_ducatidrv_create( + "NOTIFYDRIVER_DUCATI", + ¬ify_shm_params); + if (platform_notifydrv_handle == NULL) { + status = SYSMGR_E_FAIL; + goto notify_ducatidrv_create_fail; + } + } + + if (pc_params.use_nameserver) { + do { + nread = sysmgr_get_object_config(proc_id, + (void *) &pgp_params, + PLATFORM_CMD_GPNSRN, + sizeof(struct \ + platform_gaterpeterson_params)); + } while (nread != sizeof(struct platform_gaterpeterson_params)); + sh_addr = (u32)sharedregion_get_ptr((u32 *) + pgp_params.shared_mem_addr); + if (sh_addr == (u32)NULL) { + status = SYSMGR_E_FAIL; + goto sharedregion_getptr_fail; + } + gatepeterson_params_init(NULL, &gate_params); + gate_params.shared_addr = (void *) sh_addr; + gate_params.shared_addr_size = pgp_params.shared_mem_size; + do { + status = gatepeterson_open(&platform_nsrn_gate_handle, + &gate_params); + } while (status == -ENXIO); + + if (status < 0) { + status = SYSMGR_E_FAIL; + goto gatepeterson_open_fail; + } + + do { + nread = sysmgr_get_object_config(proc_id, + (void *) &pnsrn_params, + PLATFORM_CMD_NSRN, + sizeof(struct \ + platform_nameserver_remotenotify_params)); + } while (nread != \ + sizeof(struct platform_nameserver_remotenotify_params)); + sh_addr = (u32) sharedregion_get_ptr((u32 *) + pnsrn_params.shared_mem_addr); + if (sh_addr == (u32)NULL) { + status = SYSMGR_E_FAIL; + goto sharedregion_getptr_fail; + } + /* + * Create the NameServerRemote implementation that is used to + * communicate with the remote processor. It uses some shared + * memory and the Notify module. + * + * Note that this implementation uses Notify to communicate, so + * interrupts need to be enabled. + */ + nameserver_remotenotify_params_init(NULL, &nsr_params); + nsr_params.notify_driver = platform_notifydrv_handle; + nsr_params.notify_event_no = pnsrn_params.notify_event_no; + nsr_params.shared_addr = (void *) sh_addr; + nsr_params.shared_addr_size = pnsrn_params.shared_mem_size; + nsr_params.gate = (void *) platform_nsrn_gate_handle; + platform_nsrn_handle = nameserver_remotenotify_create(proc_id, + &nsr_params); + if (platform_nsrn_handle == NULL) { + status = SYSMGR_E_FAIL; + goto nameserver_remotenotify_create_fail; + } + } + + if (pc_params.use_heapbuf) { + do { + nread = sysmgr_get_object_config(proc_id, + (void *) &pgp_params, + PLATFORM_CMD_GPHEAPBUF, + sizeof(struct \ + platform_gaterpeterson_params)); + } while (nread != sizeof(struct platform_gaterpeterson_params)); + sh_addr = (u32) sharedregion_get_ptr((u32 *) + pgp_params.shared_mem_addr); + if (sh_addr == (u32)NULL) { + status = SYSMGR_E_FAIL; + goto sharedregion_getptr_fail; + } + gatepeterson_params_init(NULL, &gate_params); + gate_params.shared_addr = (void *) sh_addr; + gate_params.shared_addr_size = pgp_params.shared_mem_size; + do { + status = gatepeterson_open(&platform_heap_gate_handle, + &gate_params); + } while (status == -ENXIO); + if (status < 0) { + status = SYSMGR_E_FAIL; + goto gatepeterson_open_fail; + } + + do { + nread = sysmgr_get_object_config(proc_id, + (void *) &phb_params, + PLATFORM_CMD_HEAPBUF, + sizeof(struct platform_heapbuf_params)); + } while (nread != sizeof(struct platform_heapbuf_params)); + /* Create the heap. */ + sh_addr = (u32) sharedregion_get_ptr((u32 *) + phb_params.shared_mem_addr); + if (sh_addr == (u32)NULL) { + status = SYSMGR_E_FAIL; + goto sharedregion_getptr_fail; + } + heapbuf_params_init(NULL, &heap_params); + heap_params.name = HEAPNAME; + heap_params.shared_addr = (void *) sh_addr; + heap_params.align = HEAPBUF_ALIGN; + heap_params.num_blocks = phb_params.num_blocks; + heap_params.block_size = phb_params.block_size; + sh_addr = (u32) sharedregion_get_ptr((u32 *) + phb_params.shared_buf_size); + if (sh_addr == (u32)NULL) { + status = SYSMGR_E_FAIL; + goto sharedregion_getptr_fail; + } + heap_params.shared_buf_size = phb_params.shared_buf_size; + heap_params.shared_buf = (void *) sh_addr; + heap_params.gate = platform_heap_gate_handle; + heap_params.shared_addr_size = phb_params.shared_mem_size; + do { + status = heapbuf_open(&platform_heap_handle, + &heap_params); + } while (status == -ENXIO); + if (status < 0) { + status = SYSMGR_E_FAIL; + goto heapbuf_open_fail; + } + } + + if (pc_params.use_messageq) { + do { + nread = sysmgr_get_object_config(proc_id, &pgp_params, + PLATFORM_CMD_GPMQT, + sizeof(struct \ + platform_gaterpeterson_params)); + } while (nread != sizeof(struct platform_gaterpeterson_params)); + sh_addr = (u32) sharedregion_get_ptr((u32 *) + pgp_params.shared_mem_addr); + if (sh_addr == (u32)NULL) { + status = SYSMGR_E_FAIL; + goto sharedregion_getptr_fail; + } + gatepeterson_params_init(NULL, &gate_params); + gate_params.shared_addr = (void *) sh_addr; + gate_params.shared_addr_size = pgp_params.shared_mem_size; + do { + status = gatepeterson_open(&platform_mqt_gate_handle, + &gate_params); + } while (status == -ENXIO); + if (status < 0) { + status = SYSMGR_E_FAIL; + goto gatepeterson_open_fail; + } + + do { + nread = sysmgr_get_object_config(proc_id, + (void *) &pmqt_params, PLATFORM_CMD_MQT, + sizeof(struct \ + platform_messageq_transportshm_params)); + } while (nread != sizeof( + struct platform_messageq_transportshm_params)); + /* Register this heap with platform_messageq */ + messageq_register_heap(platform_heap_handle, HEAPID); + sh_addr = (u32) sharedregion_get_ptr((u32 *) + pmqt_params.shared_mem_addr); + if (sh_addr == (u32)NULL) { + status = SYSMGR_E_FAIL; + goto sharedregion_getptr_fail; + } + messageq_transportshm_params_init(NULL, &msgqt_params); + msgqt_params.shared_addr = (void *) sh_addr; + msgqt_params.notify_event_no = pmqt_params.notify_event_no; + msgqt_params.notify_driver = platform_notifydrv_handle; + msgqt_params.shared_addr_size = pmqt_params.shared_mem_size; + msgqt_params.gate = platform_mqt_gate_handle; + platform_transport_shm_handle = messageq_transportshm_create( + proc_id, &msgqt_params); + if (platform_transport_shm_handle == NULL) { + status = SYSMGR_E_FAIL; + goto messageq_transportshm_create_fail; + } + } + + if (status >= 0) { + /* Wait for slave to complete the setup */ + sysmgr_wait_for_slave_setup(proc_id); + + /* Now get the Shared region entries that may have been created + * by Slave, but actual physical memory is not assigned to + * those entries, only virtual DSP memory exists. + */ + sharedregion_get_config(&sr_config); + for (i = 0; i < sr_config.max_regions; i++) { + cmd_id = SYSMGR_CMD_SHAREDREGION_ENTRY_START + i; + nread = sysmgr_get_object_config(proc_id, + (void *) &info, cmd_id, + sizeof(struct sharedregion_info)); + if (nread == sizeof(struct sharedregion_info)) { + /* FIXME: Do the DMM and convert the entry into + * kernel virtual address and put it in the + * shared region for host */ + } + } + } + +messageq_transportshm_create_fail: + printk(KERN_ERR "platform_start_callback: " + "messageq_transportshm_create failed status[0x%x]", status); + goto exit; +heapbuf_open_fail: + printk(KERN_ERR "platform_start_callback: gatepeterson_open " + "failed status[0x%x]", status); + goto exit; +nameserver_remotenotify_create_fail: + printk(KERN_ERR "platform_start_callback: " + "nameserver_remotenotify_create failed status[0x%x]", status); + goto exit; +gatepeterson_open_fail: + printk(KERN_ERR "platform_start_callback: gatepeterson_open " + "failed status[0x%x]", status); + goto exit; +notify_ducatidrv_create_fail: + printk(KERN_ERR "platform_start_callback: notify_ducatidrv_create " + "failed status[0x%x]", status); + goto exit; +sharedregion_getptr_fail: + printk(KERN_ERR "platform_start_callback: sharedregion_get_ptr failed" + " status[0x%x]", status); + goto exit; +multiproc_fail: + printk(KERN_ERR "platform_start_callback: multiproc_set_local_id failed" + " status[0x%x]", status); +exit: + return; +} +EXPORT_SYMBOL(platform_start_callback); +/* FIXME: since application has to call this API for now */ + + +/* + * ======== platform_stop_callback ======== + * Purpose: + * Function called by proc_mgr when slave is in stopped state. + * FIXME: logic would change completely in the final system. + */ +void platform_stop_callback(void *arg) +{ + s32 status = 0; + + if (pc_params.use_messageq) { + /* Finalize drivers */ + status = gatepeterson_close(&platform_mqt_gate_handle); + if (status < 0) { + printk(KERN_ERR "platform_stop_callback : mqt " + "gatepeterson_close failed [0x%x]", status); + } + + status = messageq_transportshm_delete( + &platform_transport_shm_handle); + if (status < 0) { + printk(KERN_ERR "platform_stop_callback : " + "messageq_transportshm_delete failed [0x%x]", + status); + } + } + + if (pc_params.use_nameserver) { + status = gatepeterson_close(&platform_nsrn_gate_handle); + if (status < 0) { + printk(KERN_ERR "platform_stop_callback : nsrn" + "gatepeterson_close failed [0x%x]", status); + } + + status = nameserver_remotenotify_delete(&platform_nsrn_handle); + if (status < 0) { + printk(KERN_ERR "platform_stop_callback : " + "nameserver_remotenotify_delete failed [0x%x]", + status); + } + } + + if (pc_params.use_heapbuf) { + status = messageq_unregister_heap(HEAPID); + if (status < 0) { + printk(KERN_ERR "platform_stop_callback : " + "messageq_unregister_heap failed [0x%x]", + status); + } + + status = gatepeterson_close(&platform_heap_gate_handle); + if (status < 0) { + printk(KERN_ERR "platform_stop_callback : heap" + "gatepeterson_close failed [0x%x]", status); + } + + status = heapbuf_close(&platform_heap_handle); + if (status < 0) { + printk(KERN_ERR "platform_stop_callback : " + "heapbuf_close failed [0x%x]", status); + } + } + + if (pc_params.use_notify) { + status = notify_ducatidrv_delete( + (struct notify_driver_object **) + &platform_notifydrv_handle); + if (status < 0) { + printk(KERN_ERR "platform_stop_callback : " + "notify_ducatidrv_delete failed [0x%x]", + status); + } + } + + status = sharedregion_remove(0); + if (status < 0) { + printk(KERN_ERR "platform_stop_callback : " + "sharedregion_remove failed [0x%x]", status); + } +} +EXPORT_SYMBOL(platform_stop_callback); +/* FIXME: since application has to call this API for now */ diff --git a/drivers/dsp/syslink/multicore_ipc/platformcfg.c b/drivers/dsp/syslink/multicore_ipc/platformcfg.c new file mode 100644 index 0000000000000000000000000000000000000000..2302dcf77c95583f49b8f5ee0b812828b0747bc2 --- /dev/null +++ b/drivers/dsp/syslink/multicore_ipc/platformcfg.c @@ -0,0 +1,87 @@ +/* + * platformcfg.c + * + * Implementation of platform specific configuration for Syslink. + * + * Copyright (C) 2008-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> + +/* Utilities headers */ +#include <linux/string.h> + + +/* Module headers */ +#include <sysmgr.h> + +/* ============================================================================= + * APIS + * ============================================================================= + */ +/* + * ======== platform_override_config ======== + * Purpose: + * Function to override the default confiuration values. + */ +int platform_override_config(struct sysmgr_config *config) +{ + int status = 0; + + if (WARN_ON(config == NULL)) { + status = -EINVAL; + goto failure; + } + + /* Override the multiproc default config */ + config->multiproc_cfg.max_processors = 4; + config->multiproc_cfg.id = 0; + strcpy(config->multiproc_cfg.name_list[0], "MPU"); + strcpy(config->multiproc_cfg.name_list[1], "Tesla"); + strcpy(config->multiproc_cfg.name_list[2], "SysM3"); + strcpy(config->multiproc_cfg.name_list[3], "AppM3"); + + /* Override the gatepeterson default config */ + + /* Override the sharedregion default config */ + config->sharedregion_cfg.gate_handle = NULL; + config->sharedregion_cfg.heap_handle = NULL; + config->sharedregion_cfg.max_regions = 4; + + /* Override the listmp default config */ + + /* Override the messageq default config */ + + /* Override the notify default config */ + config->notify_cfg.maxDrivers = 2; + + /* Override the procmgr default config */ + + /* Override the heapbuf default config */ + + /* Override the listmp_sharedmemory default config */ + + /* Override the messageq_transportshm default config */ + + /* Override the notify ducati driver default config */ + + /* Override the nameserver remotenotify default config */ + goto success; + +failure: + printk(KERN_ERR "platform_override_config failed [0x%x]", status); +success: + return status; +} diff --git a/drivers/dsp/syslink/multicore_ipc/sysmemmgr.c b/drivers/dsp/syslink/multicore_ipc/sysmemmgr.c new file mode 100644 index 0000000000000000000000000000000000000000..60bdad0c188fcd0d020a65362348b23f6078d8c9 --- /dev/null +++ b/drivers/dsp/syslink/multicore_ipc/sysmemmgr.c @@ -0,0 +1,459 @@ +/* + * sysmemmgr.c + * + * Manager for the Slave system memory. Slave system level memory is allocated + * through this modules. + * + * Copyright (C) 2008-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> + +/* Utils headers */ +#include <linux/vmalloc.h> +#include <syslink/atomic_linux.h> +#include <syslink/platform_mem.h> +/*#include <GateMutex.h> +#include <Memory.h> +#include <Trace.h>*/ + + +/* Module level headers */ +#include <sysmemmgr.h> +/*#include <BuddyPageAllocator.h>*/ + + +/* ============================================================================= + * Macros + * ============================================================================= + */ +/*! @brief Event reserved for System memory manager */ +#define SYSMEMMGR_EVENTNO 12 + +/* Macro to make a correct module magic number with ref_count */ +#define SYSMEMMGR_MAKE_MAGICSTAMP(x) ((SYSMEMMGR_MODULEID << 12) | (x)) + +/* ============================================================================= + * Structs & Enums + * ============================================================================= + */ +/*! @brief Structure containing list of buffers. The list is kept sorted by + * address. */ +struct sysmemmgr_static_mem_struct { + struct sysmemmgr_static_mem_struct *next; + /*!< Pointer to next entry */ + u32 address; + /*!< Address of this entry */ + u32 size; + /*!< Size of this entry */ +}; + + +/*! @brief Static memory manager object. */ +struct sysmemmgr_static_mem_mgr_obj { + struct sysmemmgr_static_mem_struct head; + /*!< Pointer to head entry */ + struct sysmemmgr_static_mem_struct tail; + /*!< Pointer to tail entry */ +}; + +/*! + * @brief Structure defining state object of system memory manager. + */ +struct sysmemmgr_module_object { + atomic_t ref_count; + /*!< Reference count */ + struct sysmemmgr_static_mem_mgr_obj static_mem_obj; + /*!< Static memory manager object */ + struct mutex *gate_handle; + /*!< Pointer to lock */ + struct sysmemmgr_config cfg; + /*!< Current configuration values */ + struct sysmemmgr_config default_cfg; + /*!< Default configuration values */ +}; + + +/*! + * @brief Object containing state of the system memory manager. + */ +static struct sysmemmgr_module_object sysmemmgr_state = { + .default_cfg.sizeof_valloc = 0x100000, + .default_cfg.sizeof_palloc = 0x100000, + .default_cfg.page_size = 0x1000, + .default_cfg.event_no = SYSMEMMGR_EVENTNO, +}; + + +/* ============================================================================= + * APIS + * ============================================================================= + */ +/* + * ======== sysmemmgr_get_config ======== + * Purpose: + * Function to get the default values for configuration. + */ +void sysmemmgr_get_config(struct sysmemmgr_config *config) +{ + if (WARN_ON(config == NULL)) + goto err_exit; + + if (atomic_cmpmask_and_lt(&(sysmemmgr_state.ref_count), + SYSMEMMGR_MAKE_MAGICSTAMP(0), + SYSMEMMGR_MAKE_MAGICSTAMP(1)) == true) + memcpy((void *) config, (void *)(&sysmemmgr_state.default_cfg), + sizeof(struct sysmemmgr_config)); + else + memcpy((void *) config, (void *)(&sysmemmgr_state.cfg), + sizeof(struct sysmemmgr_config)); + + return; + +err_exit: + printk(KERN_ERR "sysmemmgr_get_config: Argument of type " + "(struct sysmemmgr_config *) passed is NULL\n"); + return; +} + + +/* + * ======== sysmemmgr_setup ======== + * Purpose: + * Function to get the default values for configuration. + */ +int sysmemmgr_setup(struct sysmemmgr_config *config) +{ + int status = 0; + struct sysmemmgr_static_mem_mgr_obj *smmObj = 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(&sysmemmgr_state.ref_count, + SYSMEMMGR_MAKE_MAGICSTAMP(0), SYSMEMMGR_MAKE_MAGICSTAMP(0)); + + if (atomic_inc_return(&sysmemmgr_state.ref_count) != \ + SYSMEMMGR_MAKE_MAGICSTAMP(1)) { + status = SYSMEMMGR_S_ALREADYSETUP; + goto exit; + } + + if (WARN_ON(config == NULL)) { + /* Config parameters are not provided */ + status = -EINVAL; + goto err_config; + } + if (WARN_ON((config->static_virt_base_addr == (u32) NULL) + && (config->static_mem_size != 0))) { + /* Virtual Base address of static memory region is NULL */ + status = -EINVAL; + goto err_virt_addr; + } + if (WARN_ON((config->static_phys_base_addr == (u32) NULL) + && (config->static_mem_size != 0))) { + /*Physical Base address of static memory region is NULL */ + status = -EINVAL; + goto err_phys_addr; + } + + /* Copy the config parameters to the module state */ + memcpy((void *)(&sysmemmgr_state.cfg), (void *) config, + sizeof(struct sysmemmgr_config)); + + /* Create the static memory allocator */ + if (config->static_mem_size != 0) { + smmObj = &sysmemmgr_state.static_mem_obj; + smmObj->head.address = config->static_virt_base_addr; + smmObj->head.size = 0; + smmObj->tail.address = (config->static_virt_base_addr + \ + config->static_mem_size); + smmObj->tail.size = 0; + smmObj->head.next = &smmObj->tail; + smmObj->tail.next = NULL; + } + + /* Create the lock */ + sysmemmgr_state.gate_handle = kzalloc(sizeof(struct mutex), GFP_KERNEL); + if (sysmemmgr_state.gate_handle == NULL) { + /* Failed to create gate handle */ + status = -ENOMEM; + goto err_mem_gate; + } + return 0; + +err_mem_gate: + printk(KERN_ERR "sysmemmgr_setup: Failed to create gate handle\n"); + goto exit; + +err_phys_addr: + printk(KERN_ERR "sysmemmgr_setup: Physical Base address of static " + "memory region is NULL\n"); + goto exit; + +err_virt_addr: + printk(KERN_ERR "sysmemmgr_setup: Virtual Base address of static " + "memory region is NULL\n"); + goto exit; + +err_config: + printk(KERN_ERR "sysmemmgr_setup: Argument of type " + "(struct sysmemmgr_config *) passed is NULL\n"); + goto exit; + +exit: + if (status < 0) { + atomic_set(&sysmemmgr_state.ref_count, + SYSMEMMGR_MAKE_MAGICSTAMP(0)); + } + return status; +} + + +/* + * ======== sysmemmgr_destroy ======== + * Purpose: + * Function to finalize the system memory manager module. + */ +int sysmemmgr_destroy(void) +{ + int status = 0; + + if (atomic_cmpmask_and_lt(&(sysmemmgr_state.ref_count), + SYSMEMMGR_MAKE_MAGICSTAMP(0), SYSMEMMGR_MAKE_MAGICSTAMP(1)) == \ + true) { + /*! @retval SYSMEMMGR_E_INVALIDSTATE Module was not + * initialized */ + status = SYSMEMMGR_E_INVALIDSTATE; + goto err_exit; + } + + if (atomic_dec_return(&sysmemmgr_state.ref_count) == \ + SYSMEMMGR_MAKE_MAGICSTAMP(0)) { + /* Delete the lock */ + kfree(sysmemmgr_state.gate_handle); + } + return 0; + +err_exit: + printk(KERN_ERR "sysmemgr_destroy: Module was not initialized\n"); + return status; +} + + +/* + * ======== sysmemmgr_alloc ======== + * Purpose: + * Function to allocate a memory block. + */ +void *sysmemmgr_alloc(u32 size, enum sysmemmgr_allocflag flag) +{ + int status = 0; + struct sysmemmgr_static_mem_mgr_obj *smObj = NULL; + struct sysmemmgr_static_mem_struct *ptr = NULL; + struct sysmemmgr_static_mem_struct *newptr = NULL; + void *ret_ptr = NULL; + + if (atomic_cmpmask_and_lt(&(sysmemmgr_state.ref_count), + SYSMEMMGR_MAKE_MAGICSTAMP(0), SYSMEMMGR_MAKE_MAGICSTAMP(1)) == \ + true) { + /*! @retval SYSMEMMGR_E_INVALIDSTATE Module was not + * initialized */ + status = SYSMEMMGR_E_INVALIDSTATE; + goto err_exit; + } + + if ((flag & sysmemmgr_allocflag_physical) && \ + !(flag & sysmemmgr_allocflag_dma)) { + /* TBD: works with DMM + ret_ptr = platform_mem_alloc (size, 0, + MemoryOS_MemTypeFlags_Physical); */ + if (ret_ptr == NULL) { + if (sysmemmgr_state.cfg.static_mem_size == 0) { + /* Memory pool is not configured. */ + status = -ENOMEM; + goto exit; + } + + smObj = &sysmemmgr_state.static_mem_obj; + ptr = &smObj->head; + while (ptr && ptr->next) { + if (((ptr->next->address - \ + (ptr->address + ptr->size)) >= size)) + break; + ptr = ptr->next; + } + + if (ptr->next == NULL) { + status = -ENOMEM; + goto exit; + } + + newptr = vmalloc( + sizeof(struct sysmemmgr_static_mem_struct)); + if (newptr != NULL) { + newptr->address = ptr->address + ptr->size; + newptr->size = size; + newptr->next = ptr->next; + ptr->next = newptr; + ret_ptr = (void *) newptr->address; + } else { + status = -ENOMEM; + } + } + goto exit; + } + + if (flag & sysmemmgr_allocflag_physical) { + ret_ptr = kmalloc(size, GFP_KERNEL); + if (ret_ptr == NULL) + status = -ENOMEM; + goto exit; + } + + if (flag & sysmemmgr_allocflag_dma) { + ret_ptr = kmalloc(size, GFP_KERNEL | GFP_DMA); + if (ret_ptr == NULL) + status = -ENOMEM; + goto exit; + } + + ret_ptr = vmalloc(size); + if (ret_ptr == NULL) { + status = -ENOMEM; + goto exit; + } + +err_exit: + printk(KERN_ERR "sysmemgr_alloc: Module was not initialized\n"); +exit: + if (WARN_ON(ret_ptr == NULL)) + printk(KERN_ERR "sysmemmgr_alloc: Allocation failed\n"); + return ret_ptr; +} + + +/* + * ======== sysmemmgr_free ======== + * Purpose: + * Function to de-allocate a previous allocated memory block. + */ +int sysmemmgr_free(void *blk, u32 size, enum sysmemmgr_allocflag flag) +{ + int status = 0; + struct sysmemmgr_static_mem_mgr_obj *smObj = NULL; + struct sysmemmgr_static_mem_struct *ptr = NULL; + struct sysmemmgr_static_mem_struct *prev = NULL; + + if (atomic_cmpmask_and_lt(&(sysmemmgr_state.ref_count), + SYSMEMMGR_MAKE_MAGICSTAMP(0), SYSMEMMGR_MAKE_MAGICSTAMP(1)) == \ + true) { + /*! @retval SYSMEMMGR_E_INVALIDSTATE Module was not + * initialized */ + status = SYSMEMMGR_E_INVALIDSTATE; + goto err_exit; + } + + if ((flag & sysmemmgr_allocflag_physical) && \ + !(flag & sysmemmgr_allocflag_dma)) { + if (((u32) blk >= sysmemmgr_state.cfg.static_virt_base_addr) + && ((u32) blk < \ + (sysmemmgr_state.cfg.static_virt_base_addr + \ + sysmemmgr_state.cfg.static_mem_size))) { + smObj = &sysmemmgr_state.static_mem_obj; + ptr = &smObj->head; + while (ptr && ptr->next) { + if (ptr->next->address == (u32) blk) + break; + ptr = ptr->next; + } + prev = ptr; + ptr = ptr->next; + prev->next = ptr->next; + + /* Free the node */ + vfree(ptr); + } else { + kfree(blk); + } + } else if (flag & sysmemmgr_allocflag_physical) { + kfree(blk); + } else if (flag & sysmemmgr_allocflag_dma) { + kfree(blk); + } else { + vfree(blk); + } + return 0; + +err_exit: + printk(KERN_ERR "sysmemgr_free: Module was not initialized\n"); + return status; +} + + +/* + * ======== sysmemmgr_setup ======== + * Purpose: + * Function to translate an address among different address spaces. + */ +void *sysmemmgr_translate(void *src_addr, enum sysmemmgr_xltflag flags) +{ + void *ret_ptr = NULL; + + switch (flags) { + case sysmemmgr_xltflag_kvirt2phys: + { + if (((u32) src_addr >= \ + sysmemmgr_state.cfg.static_virt_base_addr) && \ + ((u32) src_addr < \ + (sysmemmgr_state.cfg.static_virt_base_addr + \ + sysmemmgr_state.cfg.static_mem_size))) { + ret_ptr = (void *)(((u32) src_addr - \ + sysmemmgr_state.cfg.static_virt_base_addr) + \ + (sysmemmgr_state.cfg.static_phys_base_addr)); + } else { + ret_ptr = platform_mem_translate(src_addr, + PLATFORM_MEM_XLT_FLAGS_VIRT2PHYS); + } + } + break; + + case sysmemmgr_xltflag_phys2kvirt: + { + if (((u32) src_addr >= \ + sysmemmgr_state.cfg.static_phys_base_addr) && \ + ((u32) src_addr < \ + (sysmemmgr_state.cfg.static_phys_base_addr + \ + sysmemmgr_state.cfg.static_mem_size))) { + ret_ptr = (void *)(((u32) src_addr - \ + sysmemmgr_state.cfg.static_phys_base_addr) + \ + (sysmemmgr_state.cfg.static_virt_base_addr)); + } else { + ret_ptr = platform_mem_translate(src_addr, + PLATFORM_MEM_XLT_FLAGS_PHYS2VIRT); + } + } + break; + + default: + { + printk(KERN_ALERT "sysmemmgr_translate: Unhandled translation " + "flag\n"); + } + break; + } + + return ret_ptr; +} diff --git a/drivers/dsp/syslink/multicore_ipc/sysmemmgr_ioctl.c b/drivers/dsp/syslink/multicore_ipc/sysmemmgr_ioctl.c new file mode 100644 index 0000000000000000000000000000000000000000..725779045caf694f10c4a06668cd497ccae6dfd3 --- /dev/null +++ b/drivers/dsp/syslink/multicore_ipc/sysmemmgr_ioctl.c @@ -0,0 +1,223 @@ +/* + * sysmemmgr_ioctl.c + * + * This file implements all the ioctl operations required on the sysmemmgr + * module. + * + * Copyright (C) 2008-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> + +/* Linux headers */ +#include <linux/uaccess.h> +#include <linux/bug.h> +#include <linux/fs.h> +#include <linux/mm.h> + +/* Module Headers */ +#include <sysmemmgr.h> +#include <sysmemmgr_ioctl.h> + + +/* + * ======== sysmemmgr_ioctl_get_config ======== + * Purpose: + * This ioctl interface to sysmemmgr_get_config function + */ +static inline int sysmemmgr_ioctl_get_config(struct sysmemmgr_cmd_args *cargs) +{ + s32 retval = 0; + unsigned long size; + struct sysmemmgr_config config; + + sysmemmgr_get_config(&config); + size = copy_to_user(cargs->args.get_config.config, &config, + sizeof(struct sysmemmgr_config)); + if (size) { + retval = -EFAULT; + goto exit; + } + + cargs->api_status = 0; +exit: + return retval; +} + +/* + * ======== sysmemmgr_ioctl_setup ======== + * Purpose: + * This ioctl interface to sysmemmgr_setup function + */ +static inline int sysmemmgr_ioctl_setup(struct sysmemmgr_cmd_args *cargs) +{ + s32 retval = 0; + unsigned long size; + struct sysmemmgr_config config; + + if (cargs->args.setup.config == NULL) { + cargs->api_status = sysmemmgr_setup(NULL); + goto exit; + } + + size = copy_from_user(&config, cargs->args.setup.config, + sizeof(struct sysmemmgr_config)); + if (size) { + retval = -EFAULT; + goto exit; + } + + cargs->api_status = sysmemmgr_setup(&config); + +exit: + return retval; +} + +/* + * ======== sysmemmgr_ioctl_destroy ======== + * Purpose: + * This ioctl interface to sysmemmgr_destroy function + */ +static inline int sysmemmgr_ioctl_destroy(struct sysmemmgr_cmd_args *cargs) +{ + cargs->api_status = sysmemmgr_destroy(); + return 0; +} + +/* + * ======== sysmemmgr_ioctl_alloc ======== + * Purpose: + * This ioctl interface to sysmemmgr_alloc function + */ +static inline int sysmemmgr_ioctl_alloc(struct sysmemmgr_cmd_args *cargs) +{ + void *kbuf = NULL; + void *phys = NULL; + + kbuf = sysmemmgr_alloc(cargs->args.alloc.size, + cargs->args.alloc.flags); + if (unlikely(kbuf == NULL)) + goto exit; + + /* If the flag is not virtually contiguous */ + if (cargs->args.alloc.flags != sysmemmgr_allocflag_virtual) + phys = sysmemmgr_translate(kbuf, sysmemmgr_xltflag_kvirt2phys); + cargs->api_status = 0; + +exit: + cargs->args.alloc.kbuf = kbuf; + cargs->args.alloc.kbuf = phys; + return 0; +} + +/* + * ======== sysmemmgr_ioctl_free ======== + * Purpose: + * This ioctl interface to sysmemmgr_free function + */ +static inline int sysmemmgr_ioctl_free(struct sysmemmgr_cmd_args *cargs) +{ + cargs->api_status = sysmemmgr_free(cargs->args.free.kbuf, + cargs->args.free.size, + cargs->args.alloc.flags); + return 0; +} + +/* + * ======== sysmemmgr_ioctl_translate ======== + * Purpose: + * This ioctl interface to sysmemmgr_translate function + */ +static inline int sysmemmgr_ioctl_translate(struct sysmemmgr_cmd_args *cargs) +{ + cargs->args.translate.ret_ptr = sysmemmgr_translate( + cargs->args.translate.buf, + cargs->args.translate.flags); + WARN_ON(cargs->args.translate.ret_ptr == NULL); + cargs->api_status = 0; + return 0; +} + +/* + * ======== sysmemmgr_ioctl ======== + * Purpose: + * ioctl interface function for sysmemmgr module + */ +int sysmemmgr_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long args) +{ + int os_status = 0; + struct sysmemmgr_cmd_args __user *uarg = + (struct sysmemmgr_cmd_args __user *)args; + struct sysmemmgr_cmd_args cargs; + unsigned long size; + + if (_IOC_DIR(cmd) & _IOC_READ) + os_status = !access_ok(VERIFY_WRITE, uarg, _IOC_SIZE(cmd)); + else if (_IOC_DIR(cmd) & _IOC_WRITE) + os_status = !access_ok(VERIFY_READ, uarg, _IOC_SIZE(cmd)); + if (os_status) { + os_status = -EFAULT; + goto exit; + } + + /* Copy the full args from user-side */ + size = copy_from_user(&cargs, uarg, sizeof(struct sysmemmgr_cmd_args)); + if (size) { + os_status = -EFAULT; + goto exit; + } + + switch (cmd) { + case CMD_SYSMEMMGR_GETCONFIG: + os_status = sysmemmgr_ioctl_get_config(&cargs); + break; + + case CMD_SYSMEMMGR_SETUP: + os_status = sysmemmgr_ioctl_setup(&cargs); + break; + + case CMD_SYSMEMMGR_DESTROY: + os_status = sysmemmgr_ioctl_destroy(&cargs); + break; + + case CMD_SYSMEMMGR_ALLOC: + os_status = sysmemmgr_ioctl_alloc(&cargs); + break; + + case CMD_SYSMEMMGR_FREE: + os_status = sysmemmgr_ioctl_free(&cargs); + break; + + case CMD_SYSMEMMGR_TRANSLATE: + os_status = sysmemmgr_ioctl_translate(&cargs); + break; + + default: + WARN_ON(cmd); + os_status = -ENOTTY; + break; + } + if (os_status < 0) + goto exit; + + /* Copy the full args to the user-side. */ + size = copy_to_user(uarg, &cargs, sizeof(struct sysmemmgr_cmd_args)); + if (size) { + os_status = -EFAULT; + goto exit; + } + +exit: + return os_status; +} diff --git a/drivers/dsp/syslink/multicore_ipc/sysmgr.c b/drivers/dsp/syslink/multicore_ipc/sysmgr.c new file mode 100644 index 0000000000000000000000000000000000000000..331a25cf5d5455d825de4049554b7d981cad9921 --- /dev/null +++ b/drivers/dsp/syslink/multicore_ipc/sysmgr.c @@ -0,0 +1,765 @@ +/* + * 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> + +/* Utilities headers */ +/*#include <linux/string.h> +#include <linux/list.h> +#include <linux/slab.h> +#include <linux/semaphore.h>*/ + +/* Utilities & Osal headers */ +/*#include <Gate.h> +#include <GateMutex.h>*/ +#include <syslink/atomic_linux.h> + +/* Module headers */ +#include <multiproc.h> +#include <sysmemmgr.h> +#include <sysmgr.h> +#include <_sysmgr.h> +#include <platform.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)) + +/* FIXME: Using macro for minimum checkpatch errors */ +#define VOLATILE volatile + +/* ============================================================================= + * 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); +} + + +/* + * ======== 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 = SYSMGR_S_ALREADYSETUP; + 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; + } + + /* 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]", status); + } else { + 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]", status); + } else { + 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]", status); + } else { + 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]", status); + } else { + 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]", status); + } else { + 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]", status); + } else { + 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]", status); + } else { + 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]", status); + } else { + 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]", + status); + } else { + 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]", + status); + } else { + 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]", + status); + } else { + 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]", + status); + } else { + 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]", status); + } else { + sysmgr_state.platform_init_flag = true; + } + } + +exit: + if (status < 0) + atomic_set(&sysmgr_state.ref_count, SYSMGR_MAKE_MAGICSTAMP(0)); + + return status; +} + + +/* + * ======== 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)) + 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; +} + + +/* + * ======== 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]; + + while (temp->handshake != SYSMGR_SCALABILITYHANDSHAKESTAMP) + ; +} + + +/* + * ======== 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) + ; +} diff --git a/drivers/dsp/syslink/multicore_ipc/sysmgr_ioctl.c b/drivers/dsp/syslink/multicore_ipc/sysmgr_ioctl.c new file mode 100644 index 0000000000000000000000000000000000000000..c8d0e58f493eb00e22dbd5ae819f759020bdc5aa --- /dev/null +++ b/drivers/dsp/syslink/multicore_ipc/sysmgr_ioctl.c @@ -0,0 +1,123 @@ +/* + * sysmgr_ioctl.c + * + * This file implements all the ioctl operations required on the sysmgr + * module. + * + * Copyright (C) 2008-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> + +/* Linux headers */ +#include <linux/uaccess.h> +#include <linux/bug.h> +#include <linux/fs.h> +#include <linux/mm.h> + +/* Module Headers */ +#include <sysmgr.h> +#include <sysmgr_ioctl.h> + +/* + * ======== sysmgr_ioctl_setup ======== + * Purpose: + * This ioctl interface to sysmgr_setup function + */ +static inline int sysmgr_ioctl_setup(struct sysmgr_cmd_args *cargs) +{ + s32 retval = 0; + unsigned long size; + struct sysmgr_config config; + + size = copy_from_user(&config, cargs->args.setup.config, + sizeof(struct sysmgr_config)); + if (size) { + retval = -EFAULT; + goto exit; + } + + cargs->api_status = sysmgr_setup(&config); + +exit: + return retval; +} + +/* + * ======== sysmgr_ioctl_destroy ======== + * Purpose: + * This ioctl interface to sysmgr_destroy function + */ +static inline int sysmgr_ioctl_destroy(struct sysmgr_cmd_args *cargs) +{ + cargs->api_status = sysmgr_destroy(); + return 0; +} + +/* + * ======== sysmgr_ioctl ======== + * Purpose: + * ioctl interface function for sysmgr module + */ +int sysmgr_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long args) +{ + int os_status = 0; + struct sysmgr_cmd_args __user *uarg = + (struct sysmgr_cmd_args __user *)args; + struct sysmgr_cmd_args cargs; + unsigned long size; + + if (_IOC_DIR(cmd) & _IOC_READ) + os_status = !access_ok(VERIFY_WRITE, uarg, _IOC_SIZE(cmd)); + else if (_IOC_DIR(cmd) & _IOC_WRITE) + os_status = !access_ok(VERIFY_READ, uarg, _IOC_SIZE(cmd)); + if (os_status) { + os_status = -EFAULT; + goto exit; + } + + /* Copy the full args from user-side */ + size = copy_from_user(&cargs, uarg, sizeof(struct sysmgr_cmd_args)); + if (size) { + os_status = -EFAULT; + goto exit; + } + + switch (cmd) { + case CMD_SYSMGR_SETUP: + os_status = sysmgr_ioctl_setup(&cargs); + break; + + case CMD_SYSMGR_DESTROY: + os_status = sysmgr_ioctl_destroy(&cargs); + break; + + default: + WARN_ON(cmd); + os_status = -ENOTTY; + break; + } + if (os_status < 0) + goto exit; + + /* Copy the full args to the user-side. */ + size = copy_to_user(uarg, &cargs, sizeof(struct sysmgr_cmd_args)); + if (size) { + os_status = -EFAULT; + goto exit; + } + +exit: + return os_status; +}