Add compat ioctl for queue message Signed-off-by: Michael Zoran <mzoran@xxxxxxxxxxxx> --- .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 185 ++++++++++++++------- 1 file changed, 129 insertions(+), 56 deletions(-) diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index a5f5d5b6f938..a42ae448e519 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -477,36 +477,6 @@ vchiq_ioc_copy_element_data( return bytes_this_round; } -/************************************************************************** - * - * vchiq_ioc_queue_message - * - **************************************************************************/ -static VCHIQ_STATUS_T -vchiq_ioc_queue_message(VCHIQ_SERVICE_HANDLE_T handle, - VCHIQ_ELEMENT_T *elements, - unsigned long count) -{ - struct vchiq_io_copy_callback_context context; - unsigned long i; - size_t total_size = 0; - - context.current_element = elements; - context.current_element_offset = 0; - context.elements_to_go = count; - context.current_offset = 0; - - for (i = 0; i < count; i++) { - if (!elements[i].data && elements[i].size != 0) - return -EFAULT; - - total_size += elements[i].size; - } - - return vchiq_queue_message(handle, vchiq_ioc_copy_element_data, - &context, total_size); -} - struct vchiq_ioctl_ctxt; typedef long (*vchiq_ioctl_cpyret_handler_t)(struct vchiq_ioctl_ctxt *ctxt); @@ -755,6 +725,129 @@ vchiq_ioctl_compat_create_service(struct vchiq_ioctl_ctxt *ctxt) #endif +static long +vchiq_ioctl_queue_message(struct vchiq_ioctl_ctxt *ctxt) +{ + VCHIQ_CREATE_SERVICE_T __user *puargs = + (VCHIQ_CREATE_SERVICE_T __user *)ctxt->arg; + VCHIQ_QUEUE_MESSAGE_T args; + VCHIQ_ELEMENT_T elements[MAX_ELEMENTS]; + struct vchiq_io_copy_callback_context context; + int i; + size_t total_size = 0; + + if (copy_from_user(&args, puargs, sizeof(args))) + return -EFAULT; + + ctxt->service = find_service_for_instance(ctxt->instance, args.handle); + + if (!ctxt->service) + return -EINVAL; + + if (args.count > MAX_ELEMENTS) + return -EINVAL; + + if (copy_from_user(elements, args.elements, + args.count * sizeof(VCHIQ_ELEMENT_T))) + return -EFAULT; + + context.current_element = elements; + context.current_element_offset = 0; + context.elements_to_go = args.count; + context.current_offset = 0; + + for (i = 0; i < args.count; i++) { + size_t prev_total_size = total_size; + + if (!elements[i].data && elements[i].size != 0) + return -EFAULT; + + total_size += elements[i].size; + + if (total_size < prev_total_size) + return -EINVAL; + } + + ctxt->status = + vchiq_queue_message(args.handle, vchiq_ioc_copy_element_data, + &context, total_size); + + return vchiq_map_status(ctxt->status); +} + +#if defined(CONFIG_COMPAT) + +struct vchiq_element32 { + compat_uptr_t data; + unsigned int size; +}; + +struct vchiq_queue_message32 { + unsigned int handle; + unsigned int count; + compat_uptr_t elements; +}; + +#define VCHIQ_IOC_QUEUE_MESSAGE32 \ + _IOW(VCHIQ_IOC_MAGIC, 4, struct vchiq_queue_message32) + +static long +vchiq_ioctl_compat_queue_message(struct vchiq_ioctl_ctxt *ctxt) +{ + struct vchiq_queue_message32 __user *puargs32 = + (struct vchiq_queue_message32 __user *)ctxt->arg; + struct vchiq_queue_message32 args32; + VCHIQ_ELEMENT_T elements[MAX_ELEMENTS]; + struct vchiq_element32 elements32[MAX_ELEMENTS]; + struct vchiq_io_copy_callback_context context; + int i; + size_t total_size = 0; + + if (copy_from_user(&args32, puargs32, sizeof(args32))) + return -EFAULT; + + if (args32.count > MAX_ELEMENTS) + return -EINVAL; + + ctxt->service = find_service_for_instance(ctxt->instance, + args32.handle); + + if (!ctxt->service) + return -EINVAL; + + if (copy_from_user(elements32, compat_ptr(args32.elements), + args32.count * sizeof(struct vchiq_element32))) + return -EFAULT; + + context.current_element = elements; + context.current_element_offset = 0; + context.elements_to_go = args32.count; + context.current_offset = 0; + + for (i = 0; i < args32.count; i++) { + size_t prev_total_size = total_size; + + elements[i].data = compat_ptr(elements32[i].data); + elements[i].size = elements32[i].size; + + if (!elements[i].data && elements[i].size != 0) + return -EFAULT; + + total_size += elements[i].size; + + if (total_size < prev_total_size) + return -EINVAL; + } + + ctxt->status = + vchiq_queue_message(args32.handle, vchiq_ioc_copy_element_data, + &context, total_size); + + return vchiq_map_status(ctxt->status); +} + +#endif + /**************************************************************************** * * vchiq_ioctl @@ -774,6 +867,9 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case VCHIQ_IOC_CREATE_SERVICE: return vchiq_dispatch_ioctl(vchiq_ioctl_create_service, file, cmd, arg); + case VCHIQ_IOC_QUEUE_MESSAGE: + return vchiq_dispatch_ioctl(vchiq_ioctl_queue_message, + file, cmd, arg); default: break; } @@ -912,32 +1008,6 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ret = -EINVAL; } break; - case VCHIQ_IOC_QUEUE_MESSAGE: { - VCHIQ_QUEUE_MESSAGE_T args; - if (copy_from_user - (&args, (const void __user *)arg, - sizeof(args)) != 0) { - ret = -EFAULT; - break; - } - - service = find_service_for_instance(instance, args.handle); - - if ((service != NULL) && (args.count <= MAX_ELEMENTS)) { - /* Copy elements into kernel space */ - VCHIQ_ELEMENT_T elements[MAX_ELEMENTS]; - if (copy_from_user(elements, args.elements, - args.count * sizeof(VCHIQ_ELEMENT_T)) == 0) - status = vchiq_ioc_queue_message - (args.handle, - elements, args.count); - else - ret = -EFAULT; - } else { - ret = -EINVAL; - } - } break; - case VCHIQ_IOC_QUEUE_BULK_TRANSMIT: case VCHIQ_IOC_QUEUE_BULK_RECEIVE: { VCHIQ_QUEUE_BULK_TRANSFER_T args; @@ -1400,6 +1470,9 @@ vchiq_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) case VCHIQ_IOC_CREATE_SERVICE32: return vchiq_dispatch_ioctl(vchiq_ioctl_compat_create_service, file, cmd, arg); + case VCHIQ_IOC_QUEUE_MESSAGE32: + return vchiq_dispatch_ioctl(vchiq_ioctl_compat_queue_message, + file, cmd, arg); default: return vchiq_ioctl(file, cmd, arg); } -- 2.11.0 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel