2 * Copyright 2014 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
23 #include <linux/device.h>
24 #include <linux/export.h>
25 #include <linux/err.h>
27 #include <linux/sched.h>
28 #include <linux/slab.h>
29 #include <linux/uaccess.h>
30 #include <linux/compat.h>
31 #include <uapi/linux/kfd_ioctl.h>
32 #include <linux/time.h>
34 #include <linux/uaccess.h>
35 #include <uapi/asm-generic/mman-common.h>
36 #include <asm/processor.h>
39 static long kfd_ioctl(struct file
*, unsigned int, unsigned long);
40 static int kfd_open(struct inode
*, struct file
*);
41 static int kfd_mmap(struct file
*, struct vm_area_struct
*);
43 static const char kfd_dev_name
[] = "kfd";
45 static const struct file_operations kfd_fops
= {
47 .unlocked_ioctl
= kfd_ioctl
,
48 .compat_ioctl
= kfd_ioctl
,
53 static int kfd_char_dev_major
= -1;
54 static struct class *kfd_class
;
55 struct device
*kfd_device
;
57 int kfd_chardev_init(void)
61 kfd_char_dev_major
= register_chrdev(0, kfd_dev_name
, &kfd_fops
);
62 err
= kfd_char_dev_major
;
64 goto err_register_chrdev
;
66 kfd_class
= class_create(THIS_MODULE
, kfd_dev_name
);
67 err
= PTR_ERR(kfd_class
);
68 if (IS_ERR(kfd_class
))
69 goto err_class_create
;
71 kfd_device
= device_create(kfd_class
, NULL
,
72 MKDEV(kfd_char_dev_major
, 0),
74 err
= PTR_ERR(kfd_device
);
75 if (IS_ERR(kfd_device
))
76 goto err_device_create
;
81 class_destroy(kfd_class
);
83 unregister_chrdev(kfd_char_dev_major
, kfd_dev_name
);
88 void kfd_chardev_exit(void)
90 device_destroy(kfd_class
, MKDEV(kfd_char_dev_major
, 0));
91 class_destroy(kfd_class
);
92 unregister_chrdev(kfd_char_dev_major
, kfd_dev_name
);
95 struct device
*kfd_chardev(void)
101 static int kfd_open(struct inode
*inode
, struct file
*filep
)
103 struct kfd_process
*process
;
105 if (iminor(inode
) != 0)
108 process
= kfd_create_process(current
);
110 return PTR_ERR(process
);
112 process
->is_32bit_user_mode
= is_compat_task();
114 dev_dbg(kfd_device
, "process %d opened, compat mode (32 bit) - %d\n",
115 process
->pasid
, process
->is_32bit_user_mode
);
117 kfd_init_apertures(process
);
122 static long kfd_ioctl_get_version(struct file
*filep
, struct kfd_process
*p
,
128 static long kfd_ioctl_create_queue(struct file
*filep
, struct kfd_process
*p
,
134 static int kfd_ioctl_destroy_queue(struct file
*filp
, struct kfd_process
*p
,
140 static int kfd_ioctl_update_queue(struct file
*filp
, struct kfd_process
*p
,
146 static long kfd_ioctl_set_memory_policy(struct file
*filep
,
147 struct kfd_process
*p
, void __user
*arg
)
152 static long kfd_ioctl_get_clock_counters(struct file
*filep
,
153 struct kfd_process
*p
, void __user
*arg
)
159 static int kfd_ioctl_get_process_apertures(struct file
*filp
,
160 struct kfd_process
*p
, void __user
*arg
)
165 static long kfd_ioctl(struct file
*filep
, unsigned int cmd
, unsigned long arg
)
167 struct kfd_process
*process
;
171 "ioctl cmd 0x%x (#%d), arg 0x%lx\n",
172 cmd
, _IOC_NR(cmd
), arg
);
174 process
= kfd_get_process(current
);
176 return PTR_ERR(process
);
179 case KFD_IOC_GET_VERSION
:
180 err
= kfd_ioctl_get_version(filep
, process
, (void __user
*)arg
);
182 case KFD_IOC_CREATE_QUEUE
:
183 err
= kfd_ioctl_create_queue(filep
, process
,
187 case KFD_IOC_DESTROY_QUEUE
:
188 err
= kfd_ioctl_destroy_queue(filep
, process
,
192 case KFD_IOC_SET_MEMORY_POLICY
:
193 err
= kfd_ioctl_set_memory_policy(filep
, process
,
197 case KFD_IOC_GET_CLOCK_COUNTERS
:
198 err
= kfd_ioctl_get_clock_counters(filep
, process
,
202 case KFD_IOC_GET_PROCESS_APERTURES
:
203 err
= kfd_ioctl_get_process_apertures(filep
, process
,
207 case KFD_IOC_UPDATE_QUEUE
:
208 err
= kfd_ioctl_update_queue(filep
, process
,
214 "unknown ioctl cmd 0x%x, arg 0x%lx)\n",
222 "ioctl error %ld for ioctl cmd 0x%x (#%d)\n",
223 err
, cmd
, _IOC_NR(cmd
));
228 static int kfd_mmap(struct file
*filp
, struct vm_area_struct
*vma
)
230 struct kfd_process
*process
;
232 process
= kfd_get_process(current
);
234 return PTR_ERR(process
);
236 return kfd_doorbell_mmap(process
, vma
);