[PATCH V2 2/7] staging: vchiq_arm: Add compat ioctl for queue message
Michael Zoran
mzoran at crowfest.net
Sat Jan 21 09:48:11 PST 2017
Add compat ioctl for queue message
Signed-off-by: Michael Zoran <mzoran at crowfest.net>
---
.../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
More information about the linux-rpi-kernel
mailing list