Commit 71f5bf9a authored by Suman Anna's avatar Suman Anna Committed by Hari Kanigeri

SYSLINK: ipc - Add SysMgr & SysMemMgr

This patch adds the preliminary source code for SysMgr & SysMemMgr.
This patch includes only the source code and needs revisions to
adapt to the latest loader and OMAP4430.

The patch has one checkpatch warnings due to the usage of volatile keyword.
The warnings were minimized by using a macro for volatile.
Signed-off-by: default avatarSuman Anna <s-anna@ti.com>
parent 5d036924
/*
* _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_ */
/*
* 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_ */
/*
* 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_ */
/*
* 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 */
/*
* 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 */
/*
* 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_ */
/*
* 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, &params);
params.proc_handle = procmgr_proc_handle;
procmgr_handle = proc_mgr_create(proc_id, &params);
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, &notify_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",
&notify_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 */
/*
* 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;
}
/*
* 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;
}
/*
* 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;
}
/*
* 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)
;
}
/*
* 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;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment