Merge tag 'iwlwifi-fixes-for-kalle-2014-12-18' of git://git.kernel.org/pub/scm/linux...
[linux-2.6-block.git] / drivers / gpu / drm / amd / amdkfd / kfd_chardev.c
index 1020faf3d703fe9f5d2be0a4a95d824d7e0a1ae9..4f7b275f2f7b0fdbb488055057c3291a1aab3a70 100644 (file)
@@ -102,15 +102,26 @@ struct device *kfd_chardev(void)
 static int kfd_open(struct inode *inode, struct file *filep)
 {
        struct kfd_process *process;
+       bool is_32bit_user_mode;
 
        if (iminor(inode) != 0)
                return -ENODEV;
 
+       is_32bit_user_mode = is_compat_task();
+
+       if (is_32bit_user_mode == true) {
+               dev_warn(kfd_device,
+                       "Process %d (32-bit) failed to open /dev/kfd\n"
+                       "32-bit processes are not supported by amdkfd\n",
+                       current->pid);
+               return -EPERM;
+       }
+
        process = kfd_create_process(current);
        if (IS_ERR(process))
                return PTR_ERR(process);
 
-       process->is_32bit_user_mode = is_compat_task();
+       process->is_32bit_user_mode = is_32bit_user_mode;
 
        dev_dbg(kfd_device, "process %d opened, compat mode (32 bit) - %d\n",
                process->pasid, process->is_32bit_user_mode);
@@ -123,7 +134,16 @@ static int kfd_open(struct inode *inode, struct file *filep)
 static long kfd_ioctl_get_version(struct file *filep, struct kfd_process *p,
                                        void __user *arg)
 {
-       return -ENODEV;
+       struct kfd_ioctl_get_version_args args;
+       int err = 0;
+
+       args.major_version = KFD_IOCTL_MAJOR_VERSION;
+       args.minor_version = KFD_IOCTL_MINOR_VERSION;
+
+       if (copy_to_user(arg, &args, sizeof(args)))
+               err = -EFAULT;
+
+       return err;
 }
 
 static int set_queue_properties_from_user(struct queue_properties *q_properties,
@@ -140,7 +160,9 @@ static int set_queue_properties_from_user(struct queue_properties *q_properties,
        }
 
        if ((args->ring_base_address) &&
-               (!access_ok(VERIFY_WRITE, args->ring_base_address, sizeof(uint64_t)))) {
+               (!access_ok(VERIFY_WRITE,
+                       (const void __user *) args->ring_base_address,
+                       sizeof(uint64_t)))) {
                pr_err("kfd: can't access ring base address\n");
                return -EFAULT;
        }
@@ -150,12 +172,16 @@ static int set_queue_properties_from_user(struct queue_properties *q_properties,
                return -EINVAL;
        }
 
-       if (!access_ok(VERIFY_WRITE, args->read_pointer_address, sizeof(uint32_t))) {
+       if (!access_ok(VERIFY_WRITE,
+                       (const void __user *) args->read_pointer_address,
+                       sizeof(uint32_t))) {
                pr_err("kfd: can't access read pointer\n");
                return -EFAULT;
        }
 
-       if (!access_ok(VERIFY_WRITE, args->write_pointer_address, sizeof(uint32_t))) {
+       if (!access_ok(VERIFY_WRITE,
+                       (const void __user *) args->write_pointer_address,
+                       sizeof(uint32_t))) {
                pr_err("kfd: can't access write pointer\n");
                return -EFAULT;
        }
@@ -227,7 +253,7 @@ static long kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,
        mutex_lock(&p->mutex);
 
        pdd = kfd_bind_process_to_device(dev, p);
-       if (IS_ERR(pdd) < 0) {
+       if (IS_ERR(pdd)) {
                err = PTR_ERR(pdd);
                goto err_bind_process;
        }
@@ -316,7 +342,9 @@ static int kfd_ioctl_update_queue(struct file *filp, struct kfd_process *p,
        }
 
        if ((args.ring_base_address) &&
-               (!access_ok(VERIFY_WRITE, args.ring_base_address, sizeof(uint64_t)))) {
+               (!access_ok(VERIFY_WRITE,
+                       (const void __user *) args.ring_base_address,
+                       sizeof(uint64_t)))) {
                pr_err("kfd: can't access ring base address\n");
                return -EFAULT;
        }
@@ -372,7 +400,7 @@ static long kfd_ioctl_set_memory_policy(struct file *filep,
        mutex_lock(&p->mutex);
 
        pdd = kfd_bind_process_to_device(dev, p);
-       if (IS_ERR(pdd) < 0) {
+       if (IS_ERR(pdd)) {
                err = PTR_ERR(pdd);
                goto out;
        }
@@ -401,14 +429,95 @@ out:
 static long kfd_ioctl_get_clock_counters(struct file *filep,
                                struct kfd_process *p, void __user *arg)
 {
-       return -ENODEV;
+       struct kfd_ioctl_get_clock_counters_args args;
+       struct kfd_dev *dev;
+       struct timespec time;
+
+       if (copy_from_user(&args, arg, sizeof(args)))
+               return -EFAULT;
+
+       dev = kfd_device_by_id(args.gpu_id);
+       if (dev == NULL)
+               return -EINVAL;
+
+       /* Reading GPU clock counter from KGD */
+       args.gpu_clock_counter = kfd2kgd->get_gpu_clock_counter(dev->kgd);
+
+       /* No access to rdtsc. Using raw monotonic time */
+       getrawmonotonic(&time);
+       args.cpu_clock_counter = (uint64_t)timespec_to_ns(&time);
+
+       get_monotonic_boottime(&time);
+       args.system_clock_counter = (uint64_t)timespec_to_ns(&time);
+
+       /* Since the counter is in nano-seconds we use 1GHz frequency */
+       args.system_clock_freq = 1000000000;
+
+       if (copy_to_user(arg, &args, sizeof(args)))
+               return -EFAULT;
+
+       return 0;
 }
 
 
 static int kfd_ioctl_get_process_apertures(struct file *filp,
                                struct kfd_process *p, void __user *arg)
 {
-       return -ENODEV;
+       struct kfd_ioctl_get_process_apertures_args args;
+       struct kfd_process_device_apertures *pAperture;
+       struct kfd_process_device *pdd;
+
+       dev_dbg(kfd_device, "get apertures for PASID %d", p->pasid);
+
+       if (copy_from_user(&args, arg, sizeof(args)))
+               return -EFAULT;
+
+       args.num_of_nodes = 0;
+
+       mutex_lock(&p->mutex);
+
+       /*if the process-device list isn't empty*/
+       if (kfd_has_process_device_data(p)) {
+               /* Run over all pdd of the process */
+               pdd = kfd_get_first_process_device_data(p);
+               do {
+                       pAperture = &args.process_apertures[args.num_of_nodes];
+                       pAperture->gpu_id = pdd->dev->id;
+                       pAperture->lds_base = pdd->lds_base;
+                       pAperture->lds_limit = pdd->lds_limit;
+                       pAperture->gpuvm_base = pdd->gpuvm_base;
+                       pAperture->gpuvm_limit = pdd->gpuvm_limit;
+                       pAperture->scratch_base = pdd->scratch_base;
+                       pAperture->scratch_limit = pdd->scratch_limit;
+
+                       dev_dbg(kfd_device,
+                               "node id %u\n", args.num_of_nodes);
+                       dev_dbg(kfd_device,
+                               "gpu id %u\n", pdd->dev->id);
+                       dev_dbg(kfd_device,
+                               "lds_base %llX\n", pdd->lds_base);
+                       dev_dbg(kfd_device,
+                               "lds_limit %llX\n", pdd->lds_limit);
+                       dev_dbg(kfd_device,
+                               "gpuvm_base %llX\n", pdd->gpuvm_base);
+                       dev_dbg(kfd_device,
+                               "gpuvm_limit %llX\n", pdd->gpuvm_limit);
+                       dev_dbg(kfd_device,
+                               "scratch_base %llX\n", pdd->scratch_base);
+                       dev_dbg(kfd_device,
+                               "scratch_limit %llX\n", pdd->scratch_limit);
+
+                       args.num_of_nodes++;
+               } while ((pdd = kfd_get_next_process_device_data(p, pdd)) != NULL &&
+                               (args.num_of_nodes < NUM_OF_SUPPORTED_GPUS));
+       }
+
+       mutex_unlock(&p->mutex);
+
+       if (copy_to_user(arg, &args, sizeof(args)))
+               return -EFAULT;
+
+       return 0;
 }
 
 static long kfd_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)