drm/amdkfd: rewrite kfd_ioctl() according to drm_ioctl()
authorOded Gabbay <oded.gabbay@amd.com>
Mon, 29 Dec 2014 12:20:05 +0000 (14:20 +0200)
committerOded Gabbay <oded.gabbay@amd.com>
Tue, 6 Jan 2015 17:44:36 +0000 (19:44 +0200)
This patch changes kfd_ioctl() to be very similar to drm_ioctl().

The patch defines an array of amdkfd_ioctls, which maps IOCTL definition to the
ioctl function.

The kfd_ioctl() uses that mapping to call the appropriate ioctl function,
through a function pointer.

This patch also declares a new typedef for the ioctl function pointer.

v2: Renamed KFD_COMMAND_(START|END) to AMDKFD_...

Signed-off-by: Oded Gabbay <oded.gabbay@amd.com>
Acked-by: Christian König <christian.koenig@amd.com>
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
drivers/gpu/drm/amd/amdkfd/kfd_priv.h

index 6fbde9e411e0406d028e95b0d1716f5c60dc53ca..fcfdf23e1913ed01663b46bebfda5eec8bc4079d 100644 (file)
@@ -482,21 +482,79 @@ static int kfd_ioctl_get_process_apertures(struct file *filp,
        return 0;
 }
 
+#define AMDKFD_IOCTL_DEF(ioctl, _func, _flags) \
+       [_IOC_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0, .name = #ioctl}
+
+/** Ioctl table */
+static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = {
+       AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_VERSION,
+                       kfd_ioctl_get_version, 0),
+
+       AMDKFD_IOCTL_DEF(AMDKFD_IOC_CREATE_QUEUE,
+                       kfd_ioctl_create_queue, 0),
+
+       AMDKFD_IOCTL_DEF(AMDKFD_IOC_DESTROY_QUEUE,
+                       kfd_ioctl_destroy_queue, 0),
+
+       AMDKFD_IOCTL_DEF(AMDKFD_IOC_SET_MEMORY_POLICY,
+                       kfd_ioctl_set_memory_policy, 0),
+
+       AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_CLOCK_COUNTERS,
+                       kfd_ioctl_get_clock_counters, 0),
+
+       AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_PROCESS_APERTURES,
+                       kfd_ioctl_get_process_apertures, 0),
+
+       AMDKFD_IOCTL_DEF(AMDKFD_IOC_UPDATE_QUEUE,
+                       kfd_ioctl_update_queue, 0),
+};
+
+#define AMDKFD_CORE_IOCTL_COUNT        ARRAY_SIZE(amdkfd_ioctls)
+
 static long kfd_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
 {
        struct kfd_process *process;
+       amdkfd_ioctl_t *func;
+       const struct amdkfd_ioctl_desc *ioctl = NULL;
+       unsigned int nr = _IOC_NR(cmd);
        char stack_kdata[128];
        char *kdata = NULL;
        unsigned int usize, asize;
        int retcode = -EINVAL;
 
-       dev_dbg(kfd_device,
-               "ioctl cmd 0x%x (#%d), arg 0x%lx\n",
-               cmd, _IOC_NR(cmd), arg);
+       if (nr >= AMDKFD_CORE_IOCTL_COUNT)
+               goto err_i1;
+
+       if ((nr >= AMDKFD_COMMAND_START) && (nr < AMDKFD_COMMAND_END)) {
+               u32 amdkfd_size;
+
+               ioctl = &amdkfd_ioctls[nr];
+
+               amdkfd_size = _IOC_SIZE(ioctl->cmd);
+               usize = asize = _IOC_SIZE(cmd);
+               if (amdkfd_size > asize)
+                       asize = amdkfd_size;
+
+               cmd = ioctl->cmd;
+       } else
+               goto err_i1;
+
+       dev_dbg(kfd_device, "ioctl cmd 0x%x (#%d), arg 0x%lx\n", cmd, nr, arg);
 
        process = kfd_get_process(current);
-       if (IS_ERR(process))
-               return PTR_ERR(process);
+       if (IS_ERR(process)) {
+               dev_dbg(kfd_device, "no process\n");
+               goto err_i1;
+       }
+
+       /* Do not trust userspace, use our own definition */
+       func = ioctl->func;
+
+       if (unlikely(!func)) {
+               dev_dbg(kfd_device, "no function\n");
+               retcode = -EINVAL;
+               goto err_i1;
+       }
 
        if (cmd & (IOC_IN | IOC_OUT)) {
                if (asize <= sizeof(stack_kdata)) {
@@ -521,55 +579,17 @@ static long kfd_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
                memset(kdata, 0, usize);
        }
 
-
-       switch (cmd) {
-       case AMDKFD_IOC_GET_VERSION:
-               retcode = kfd_ioctl_get_version(filep, process, kdata);
-               break;
-
-       case AMDKFD_IOC_CREATE_QUEUE:
-               retcode = kfd_ioctl_create_queue(filep, process,
-                                               kdata);
-               break;
-
-       case AMDKFD_IOC_DESTROY_QUEUE:
-               retcode = kfd_ioctl_destroy_queue(filep, process,
-                                               kdata);
-               break;
-
-       case AMDKFD_IOC_SET_MEMORY_POLICY:
-               retcode = kfd_ioctl_set_memory_policy(filep, process,
-                                               kdata);
-               break;
-
-       case AMDKFD_IOC_GET_CLOCK_COUNTERS:
-               retcode = kfd_ioctl_get_clock_counters(filep, process,
-                                               kdata);
-               break;
-
-       case AMDKFD_IOC_GET_PROCESS_APERTURES:
-               retcode = kfd_ioctl_get_process_apertures(filep, process,
-                                               kdata);
-               break;
-
-       case AMDKFD_IOC_UPDATE_QUEUE:
-               retcode = kfd_ioctl_update_queue(filep, process,
-                                               kdata);
-               break;
-
-       default:
-               dev_dbg(kfd_device,
-                       "unknown ioctl cmd 0x%x, arg 0x%lx)\n",
-                       cmd, arg);
-               retcode = -EINVAL;
-               break;
-       }
+       retcode = func(filep, process, kdata);
 
        if (cmd & IOC_OUT)
                if (copy_to_user((void __user *)arg, kdata, usize) != 0)
                        retcode = -EFAULT;
 
 err_i1:
+       if (!ioctl)
+               dev_dbg(kfd_device, "invalid ioctl: pid=%d, cmd=0x%02x, nr=0x%02x\n",
+                         task_pid_nr(current), cmd, nr);
+
        if (kdata != stack_kdata)
                kfree(kdata);
 
index f9fb81e3bb09b24edd7f8de6c22cf7e64a92391b..a5edb29507e310af8ebe437ef2a22fb218687ad1 100644 (file)
@@ -463,6 +463,24 @@ struct kfd_process {
        bool is_32bit_user_mode;
 };
 
+/**
+ * Ioctl function type.
+ *
+ * \param filep pointer to file structure.
+ * \param p amdkfd process pointer.
+ * \param data pointer to arg that was copied from user.
+ */
+typedef int amdkfd_ioctl_t(struct file *filep, struct kfd_process *p,
+                               void *data);
+
+struct amdkfd_ioctl_desc {
+       unsigned int cmd;
+       int flags;
+       amdkfd_ioctl_t *func;
+       unsigned int cmd_drv;
+       const char *name;
+};
+
 void kfd_process_create_wq(void);
 void kfd_process_destroy_wq(void);
 struct kfd_process *kfd_create_process(const struct task_struct *);