diff options
Diffstat (limited to 'drivers/dsp/syslink/multicore_ipc/listmp_sharedmemory_ioctl.c')
-rw-r--r-- | drivers/dsp/syslink/multicore_ipc/listmp_sharedmemory_ioctl.c | 689 |
1 files changed, 689 insertions, 0 deletions
diff --git a/drivers/dsp/syslink/multicore_ipc/listmp_sharedmemory_ioctl.c b/drivers/dsp/syslink/multicore_ipc/listmp_sharedmemory_ioctl.c new file mode 100644 index 000000000000..0328ee53d2fb --- /dev/null +++ b/drivers/dsp/syslink/multicore_ipc/listmp_sharedmemory_ioctl.c @@ -0,0 +1,689 @@ +/* + * listmp_sharedmemory_ioctl.c + * + * This file implements all the ioctl operations required on the + * listmp_sharedmemory 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 <listmp.h> +#include <listmp_sharedmemory.h> +#include <listmp_sharedmemory_ioctl.h> +#include <sharedregion.h> + +/* + * ======== listmp_sharedmemory_ioctl_get_config ======== + * Purpose: + * This ioctl interface to listmp_sharedmemory_get_config function + */ +static inline int listmp_sharedmemory_ioctl_get_config( + struct listmp_sharedmemory_cmd_args *cargs) +{ + s32 retval = 0; + int status = 0; + unsigned long size; + struct listmp_config config; + + status = listmp_sharedmemory_get_config(&config); + if (unlikely(status)) + goto exit; + + size = copy_to_user(cargs->args.get_config.config, &config, + sizeof(struct listmp_config)); + if (size) { + retval = -EFAULT; + goto exit; + } + + cargs->api_status = 0; +exit: + return retval; +} + +/* + * ======== listmp_sharedmemory_ioctl_setup ======== + * Purpose: + * This ioctl interface to listmp_sharedmemory_setup function + */ +static inline int listmp_sharedmemory_ioctl_setup( + struct listmp_sharedmemory_cmd_args *cargs) +{ + s32 retval = 0; + int status = 0; + unsigned long size; + struct listmp_config config; + + size = copy_from_user(&config, cargs->args.setup.config, + sizeof(struct listmp_config)); + if (size) { + retval = -EFAULT; + goto exit; + } + + status = listmp_sharedmemory_setup(&config); + cargs->api_status = status; + if (unlikely(status)) + goto exit; +exit: + return retval; +} + +/* + * ======== listmp_sharedmemory_ioctl_destroy ======== + * Purpose: + * This ioctl interface to listmp_sharedmemory_destroy function + */ +static inline int listmp_sharedmemory_ioctl_destroy( + struct listmp_sharedmemory_cmd_args *cargs) +{ + cargs->api_status = listmp_sharedmemory_destroy(); + return 0; +} + +/* + * ======== listmp_sharedmemory_ioctl_params_init ======== + * Purpose: + * This ioctl interface to listmp_sharedmemory_params_init function + */ +static inline int listmp_sharedmemory_ioctl_params_init( + struct listmp_sharedmemory_cmd_args *cargs) +{ + s32 retval = 0; + int status = 0; + unsigned long size; + listmp_sharedmemory_params params; + + size = copy_from_user(¶ms, + cargs->args.params_init.params, + sizeof(listmp_sharedmemory_params)); + if (size) { + retval = -EFAULT; + goto exit; + } + + listmp_sharedmemory_params_init( + cargs->args.params_init.listmp_handle, ¶ms); + size = copy_to_user(cargs->args.params_init.params, ¶ms, + sizeof(listmp_sharedmemory_params)); + if (size) { + retval = -EFAULT; + goto exit; + } + +exit: + cargs->api_status = status; + return retval; +} + +/* + * ======== listmp_sharedmemory_ioctl_create ======== + * Purpose: + * This ioctl interface to listmp_sharedmemory_create function + */ +static inline int listmp_sharedmemory_ioctl_create( + struct listmp_sharedmemory_cmd_args *cargs) +{ + s32 retval = 0; + unsigned long size; + listmp_sharedmemory_params params; + + size = copy_from_user(¶ms, cargs->args.create.params, + sizeof(listmp_sharedmemory_params)); + if (size) { + retval = -EFAULT; + goto exit; + } + + /* Allocate memory for the name */ + if (cargs->args.create.name_len > 0) { + params.name = kmalloc(cargs->args.create.name_len, GFP_KERNEL); + if (params.name == NULL) { + retval = -ENOMEM; + goto exit; + } + /* Copy the name */ + size = copy_from_user(params.name, + cargs->args.create.params->name, + cargs->args.create.name_len); + if (size) { + retval = -EFAULT; + goto free_name; + } + } + + params.shared_addr = sharedregion_get_ptr( + (u32 *)cargs->args.create.shared_addr_srptr); + if (unlikely(params.shared_addr == NULL)) + goto free_name; + + /* Update gate in params. */ + params.gate = cargs->args.create.knl_gate; + cargs->args.create.listmp_handle = listmp_sharedmemory_create(¶ms); + + size = copy_to_user(cargs->args.create.params, ¶ms, + sizeof(listmp_sharedmemory_params)); + if (!size) + goto free_name; + + /* Error copying, so delete the handle */ + retval = -EFAULT; + if (cargs->args.create.listmp_handle) + listmp_sharedmemory_delete(&cargs->args.create.listmp_handle); + +free_name: + if (cargs->args.create.name_len > 0) + kfree(params.name); + + cargs->api_status = 0; +exit: + return retval; +} + +/* + * ======== listmp_sharedmemory_ioctl_delete ======== + * Purpose: + * This ioctl interface to listmp_sharedmemory_delete function + */ +static inline int listmp_sharedmemory_ioctl_delete( + struct listmp_sharedmemory_cmd_args *cargs) +{ + cargs->api_status = listmp_sharedmemory_delete( + &(cargs->args.delete_listmp.listmp_handle)); + return 0; +} + +/* + * ======== listmp_sharedmemory_ioctl_open ======== + * Purpose: + * This ioctl interface to listmp_sharedmemory_open function + */ +static inline int listmp_sharedmemory_ioctl_open( + struct listmp_sharedmemory_cmd_args *cargs) +{ + s32 retval = 0; + int status = 0; + unsigned long size; + listmp_sharedmemory_params params; + void *listmp_handle = NULL; + + size = copy_from_user(¶ms, cargs->args.open.params, + sizeof(listmp_sharedmemory_params)); + if (size) { + retval = -EFAULT; + goto exit; + } + + if (cargs->args.open.name_len > 0) { + params.name = kmalloc(cargs->args.open.name_len, GFP_KERNEL); + if (params.name != NULL) { + retval = -ENOMEM; + goto exit; + } + /* Copy the name */ + size = copy_from_user(params.name, + cargs->args.open.params->name, + cargs->args.open.name_len); + if (size) { + retval = -EFAULT; + goto free_name; + } + } + + /* For open by name, the shared_add_srptr may be invalid */ + if (cargs->args.open.shared_addr_srptr != \ + (u32)SHAREDREGION_INVALIDSRPTR) { + params.shared_addr = sharedregion_get_ptr( + (u32 *)cargs->args.open.shared_addr_srptr); + } + if (unlikely(params.shared_addr == NULL)) + goto free_name; + + /* Update gate in params. */ + params.gate = cargs->args.open.knl_gate; + status = listmp_sharedmemory_open(&listmp_handle, ¶ms); + if (status < 0) + goto free_name; + cargs->args.open.listmp_handle = listmp_handle; + + size = copy_to_user(cargs->args.open.params, ¶ms, + sizeof(listmp_sharedmemory_params)); + if (!size) + goto free_name; + + /* Error copying, so close the handle */ + retval = -EFAULT; + if (cargs->args.open.listmp_handle) + listmp_sharedmemory_close(cargs->args.open.listmp_handle); + +free_name: + if (cargs->args.open.name_len > 0) + kfree(params.name); + + cargs->api_status = status; +exit: + return retval; +} + +/* + * ======== listmp_sharedmemory_ioctl_close ======== + * Purpose: + * This ioctl interface to listmp_sharedmemory_close function + */ +static inline int listmp_sharedmemory_ioctl_close( + struct listmp_sharedmemory_cmd_args *cargs) +{ + cargs->api_status = \ + listmp_sharedmemory_close(cargs->args.close.listmp_handle); + return 0; +} + +/* + * ======== listmp_sharedmemory_ioctl_is_empty ======== + * Purpose: + * This ioctl interface to listmp_sharedmemory_empty function + */ +static inline int listmp_sharedmemory_ioctl_empty( + struct listmp_sharedmemory_cmd_args *cargs) +{ + cargs->args.is_empty.is_empty = \ + listmp_sharedmemory_empty(cargs->args.is_empty.listmp_handle); + cargs->api_status = 0; + return 0; +} + +/* + * ======== listmp_sharedmemory_ioctl_get_head ======== + * Purpose: + * This ioctl interface to listmp_sharedmemory_get_head function + */ +static inline int listmp_sharedmemory_ioctl_get_head( + struct listmp_sharedmemory_cmd_args *cargs) +{ + struct listmp_elem *elem; + u32 *elem_srptr = SHAREDREGION_INVALIDSRPTR; + int index; + + cargs->api_status = LISTMPSHAREDMEMORY_E_FAIL; + + elem = listmp_sharedmemory_get_head(cargs->args.get_head.listmp_handle); + if (unlikely(elem == NULL)) + goto exit; + + index = sharedregion_get_index(elem); + if (unlikely(index < 0)) + goto exit; + + elem_srptr = sharedregion_get_srptr((void *)elem, index); + + cargs->api_status = 0; +exit: + cargs->args.get_head.elem_srptr = elem_srptr; + return 0; +} + +/* + * ======== listmp_sharedmemory_ioctl_get_tail ======== + * Purpose: + * This ioctl interface to listmp_sharedmemory_get_tail function + */ +static inline int listmp_sharedmemory_ioctl_get_tail( + struct listmp_sharedmemory_cmd_args *cargs) +{ + struct listmp_elem *elem; + u32 *elem_srptr = SHAREDREGION_INVALIDSRPTR; + int index; + + cargs->api_status = LISTMPSHAREDMEMORY_E_FAIL; + + elem = listmp_sharedmemory_get_tail(cargs->args.get_tail.listmp_handle); + if (unlikely(elem == NULL)) + goto exit; + + index = sharedregion_get_index(elem); + if (unlikely(index < 0)) + goto exit; + + elem_srptr = sharedregion_get_srptr((void *)elem, index); + + cargs->api_status = 0; +exit: + cargs->args.get_tail.elem_srptr = elem_srptr; + return 0; +} + +/* + * ======== listmp_sharedmemory_ioctl_put_head ======== + * Purpose: + * This ioctl interface to listmp_sharedmemory_put_head function + */ +static inline int listmp_sharedmemory_ioctl_put_head( + struct listmp_sharedmemory_cmd_args *cargs) +{ + struct listmp_elem *elem; + + cargs->api_status = LISTMPSHAREDMEMORY_E_FAIL; + + elem = (struct listmp_elem *) sharedregion_get_ptr( + cargs->args.put_head.elem_srptr); + if (unlikely(elem == NULL)) + goto exit; + + cargs->api_status = listmp_sharedmemory_put_head( + cargs->args.put_head.listmp_handle, elem); +exit: + return 0; +} + +/* + * ======== listmp_sharedmemory_ioctl_put_tail ======== + * Purpose: + * This ioctl interface to listmp_sharedmemory_put_tail function + */ +static inline int listmp_sharedmemory_ioctl_put_tail( + struct listmp_sharedmemory_cmd_args *cargs) +{ + struct listmp_elem *elem; + + cargs->api_status = LISTMPSHAREDMEMORY_E_FAIL; + + elem = (struct listmp_elem *) sharedregion_get_ptr( + cargs->args.put_tail.elem_srptr); + if (unlikely(elem == NULL)) + goto exit; + + cargs->api_status = listmp_sharedmemory_put_tail( + cargs->args.put_head.listmp_handle, elem); +exit: + return 0; +} + +/* + * ======== listmp_sharedmemory_ioctl_insert ======== + * Purpose: + * This ioctl interface to listmp_sharedmemory_insert function + */ +static inline int listmp_sharedmemory_ioctl_insert( + struct listmp_sharedmemory_cmd_args *cargs) +{ + struct listmp_elem *new_elem; + struct listmp_elem *cur_elem; + + new_elem = (struct listmp_elem *) sharedregion_get_ptr( + cargs->args.insert.new_elem_srptr); + if (unlikely(new_elem == NULL)) + goto exit; + + cur_elem = (struct listmp_elem *) sharedregion_get_ptr( + cargs->args.insert.cur_elem_srptr); + if (unlikely(cur_elem == NULL)) + goto exit; + + cargs->api_status = listmp_sharedmemory_insert( + cargs->args.insert.listmp_handle, new_elem, cur_elem); +exit: + return 0; +} + +/* + * ======== listmp_sharedmemory_ioctl_remove ======== + * Purpose: + * This ioctl interface to listmp_sharedmemory_remove function + */ +static inline int listmp_sharedmemory_ioctl_remove( + struct listmp_sharedmemory_cmd_args *cargs) +{ + struct listmp_elem *elem; + + elem = (struct listmp_elem *) sharedregion_get_ptr( + cargs->args.remove.elem_srptr); + if (unlikely(elem == NULL)) + goto exit; + + cargs->api_status = listmp_sharedmemory_remove( + cargs->args.get_head.listmp_handle, elem); + +exit: + return 0; +} + +/* + * ======== listmp_sharedmemory_ioctl_next ======== + * Purpose: + * This ioctl interface to listmp_sharedmemory_next function + */ +static inline int listmp_sharedmemory_ioctl_next( + struct listmp_sharedmemory_cmd_args *cargs) +{ + struct listmp_elem *elem = NULL; + struct listmp_elem *ret_elem = NULL; + u32 *next_elem_srptr = SHAREDREGION_INVALIDSRPTR; + int index; + + if (cargs->args.next.elem_srptr != NULL) { + elem = (struct listmp_elem *) sharedregion_get_ptr( + cargs->args.next.elem_srptr); + } + ret_elem = (struct listmp_elem *) listmp_sharedmemory_next( + cargs->args.next.listmp_handle, elem); + if (unlikely(ret_elem == NULL)) + goto exit; + + index = sharedregion_get_index(ret_elem); + if (unlikely(index < 0)) + goto exit; + + next_elem_srptr = sharedregion_get_srptr((void *)ret_elem, index); + + cargs->api_status = 0; +exit: + cargs->args.next.next_elem_srptr = next_elem_srptr; + return 0; +} + +/* + * ======== listmp_sharedmemory_ioctl_prev ======== + * Purpose: + * This ioctl interface to listmp_sharedmemory_prev function + */ +static inline int listmp_sharedmemory_ioctl_prev( + struct listmp_sharedmemory_cmd_args *cargs) +{ + struct listmp_elem *elem = NULL; + struct listmp_elem *ret_elem = NULL; + u32 *prev_elem_srptr = SHAREDREGION_INVALIDSRPTR; + int index; + + if (cargs->args.next.elem_srptr != NULL) { + elem = (struct listmp_elem *) sharedregion_get_ptr( + cargs->args.prev.elem_srptr); + } + ret_elem = (struct listmp_elem *) listmp_sharedmemory_prev( + cargs->args.prev.listmp_handle, elem); + if (unlikely(ret_elem == NULL)) + goto exit; + + index = sharedregion_get_index(ret_elem); + if (unlikely(index < 0)) + goto exit; + + prev_elem_srptr = sharedregion_get_srptr((void *)ret_elem, index); + + cargs->api_status = 0; +exit: + cargs->args.prev.prev_elem_srptr = prev_elem_srptr; + return 0; + +} + +/* + * ======== listmp_sharedmemory_ioctl_shared_memreq ======== + * Purpose: + * This ioctl interface to listmp_sharedmemory_shared_memreq function + */ +static inline int listmp_sharedmemory_ioctl_shared_memreq( + struct listmp_sharedmemory_cmd_args *cargs) +{ + s32 retval = 0; + unsigned long size; + listmp_sharedmemory_params params; + + size = copy_from_user(¶ms, cargs->args.shared_memreq.params, + sizeof(listmp_sharedmemory_params)); + if (size) { + retval = -EFAULT; + goto exit; + } + + cargs->args.shared_memreq.bytes = + listmp_sharedmemory_shared_memreq(¶ms); + + cargs->api_status = 0; +exit: + return retval; +} + +/* + * ======== listmp_sharedmemory_ioctl ======== + * Purpose: + * ioctl interface function for listmp_sharedmemory module + */ +int listmp_sharedmemory_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long args) +{ + int os_status = 0; + struct listmp_sharedmemory_cmd_args __user *uarg = + (struct listmp_sharedmemory_cmd_args __user *)args; + struct listmp_sharedmemory_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 listmp_sharedmemory_cmd_args)); + if (size) { + os_status = -EFAULT; + goto exit; + } + + switch (cmd) { + case CMD_LISTMP_SHAREDMEMORY_GETCONFIG: + os_status = listmp_sharedmemory_ioctl_get_config(&cargs); + break; + + case CMD_LISTMP_SHAREDMEMORY_SETUP: + os_status = listmp_sharedmemory_ioctl_setup(&cargs); + break; + + case CMD_LISTMP_SHAREDMEMORY_DESTROY: + os_status = listmp_sharedmemory_ioctl_destroy(&cargs); + break; + + case CMD_LISTMP_SHAREDMEMORY_PARAMS_INIT: + os_status = listmp_sharedmemory_ioctl_params_init(&cargs); + break; + + case CMD_LISTMP_SHAREDMEMORY_CREATE: + os_status = listmp_sharedmemory_ioctl_create(&cargs); + break; + + case CMD_LISTMP_SHAREDMEMORY_DELETE: + os_status = listmp_sharedmemory_ioctl_delete(&cargs); + break; + + case CMD_LISTMP_SHAREDMEMORY_OPEN: + os_status = listmp_sharedmemory_ioctl_open(&cargs); + break; + + case CMD_LISTMP_SHAREDMEMORY_CLOSE: + os_status = listmp_sharedmemory_ioctl_close(&cargs); + break; + + case CMD_LISTMP_SHAREDMEMORY_ISEMPTY: + os_status = listmp_sharedmemory_ioctl_empty(&cargs); + break; + + case CMD_LISTMP_SHAREDMEMORY_GETHEAD: + os_status = listmp_sharedmemory_ioctl_get_head(&cargs); + break; + + case CMD_LISTMP_SHAREDMEMORY_GETTAIL: + os_status = listmp_sharedmemory_ioctl_get_tail(&cargs); + break; + + case CMD_LISTMP_SHAREDMEMORY_PUTHEAD: + os_status = listmp_sharedmemory_ioctl_put_head(&cargs); + break; + + case CMD_LISTMP_SHAREDMEMORY_PUTTAIL: + os_status = listmp_sharedmemory_ioctl_put_tail(&cargs); + break; + + case CMD_LISTMP_SHAREDMEMORY_INSERT: + os_status = listmp_sharedmemory_ioctl_insert(&cargs); + break; + + case CMD_LISTMP_SHAREDMEMORY_REMOVE: + os_status = listmp_sharedmemory_ioctl_remove(&cargs); + break; + + case CMD_LISTMP_SHAREDMEMORY_NEXT: + os_status = listmp_sharedmemory_ioctl_next(&cargs); + break; + + case CMD_LISTMP_SHAREDMEMORY_PREV: + os_status = listmp_sharedmemory_ioctl_prev(&cargs); + break; + + case CMD_LISTMP_SHAREDMEMORY_SHAREDMEMREQ: + os_status = listmp_sharedmemory_ioctl_shared_memreq(&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 listmp_sharedmemory_cmd_args)); + if (size) { + os_status = -EFAULT; + goto exit; + } + return os_status; + +exit: + printk(KERN_ERR "listmp_sharedmemory_ioctl failed: status = 0x%x\n", + os_status); + return os_status; +} |