amdkfd: Add amdkfd skeleton driver
[linux-2.6-block.git] / drivers / gpu / drm / amd / amdkfd / kfd_chardev.c
1 /*
2  * Copyright 2014 Advanced Micro Devices, Inc.
3  *
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:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
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.
21  */
22
23 #include <linux/device.h>
24 #include <linux/export.h>
25 #include <linux/err.h>
26 #include <linux/fs.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>
33 #include <linux/mm.h>
34 #include <linux/uaccess.h>
35 #include <uapi/asm-generic/mman-common.h>
36 #include <asm/processor.h>
37 #include "kfd_priv.h"
38
39 static long kfd_ioctl(struct file *, unsigned int, unsigned long);
40 static int kfd_open(struct inode *, struct file *);
41
42 static const char kfd_dev_name[] = "kfd";
43
44 static const struct file_operations kfd_fops = {
45         .owner = THIS_MODULE,
46         .unlocked_ioctl = kfd_ioctl,
47         .compat_ioctl = kfd_ioctl,
48         .open = kfd_open,
49 };
50
51 static int kfd_char_dev_major = -1;
52 static struct class *kfd_class;
53 struct device *kfd_device;
54
55 int kfd_chardev_init(void)
56 {
57         int err = 0;
58
59         kfd_char_dev_major = register_chrdev(0, kfd_dev_name, &kfd_fops);
60         err = kfd_char_dev_major;
61         if (err < 0)
62                 goto err_register_chrdev;
63
64         kfd_class = class_create(THIS_MODULE, kfd_dev_name);
65         err = PTR_ERR(kfd_class);
66         if (IS_ERR(kfd_class))
67                 goto err_class_create;
68
69         kfd_device = device_create(kfd_class, NULL,
70                                         MKDEV(kfd_char_dev_major, 0),
71                                         NULL, kfd_dev_name);
72         err = PTR_ERR(kfd_device);
73         if (IS_ERR(kfd_device))
74                 goto err_device_create;
75
76         return 0;
77
78 err_device_create:
79         class_destroy(kfd_class);
80 err_class_create:
81         unregister_chrdev(kfd_char_dev_major, kfd_dev_name);
82 err_register_chrdev:
83         return err;
84 }
85
86 void kfd_chardev_exit(void)
87 {
88         device_destroy(kfd_class, MKDEV(kfd_char_dev_major, 0));
89         class_destroy(kfd_class);
90         unregister_chrdev(kfd_char_dev_major, kfd_dev_name);
91 }
92
93 struct device *kfd_chardev(void)
94 {
95         return kfd_device;
96 }
97
98
99 static int kfd_open(struct inode *inode, struct file *filep)
100 {
101         if (iminor(inode) != 0)
102                 return -ENODEV;
103
104         return 0;
105 }
106
107 static long kfd_ioctl_get_version(struct file *filep, struct kfd_process *p,
108                                         void __user *arg)
109 {
110         return -ENODEV;
111 }
112
113 static long kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,
114                                         void __user *arg)
115 {
116         return -ENODEV;
117 }
118
119 static int kfd_ioctl_destroy_queue(struct file *filp, struct kfd_process *p,
120                                         void __user *arg)
121 {
122         return -ENODEV;
123 }
124
125 static int kfd_ioctl_update_queue(struct file *filp, struct kfd_process *p,
126                                         void __user *arg)
127 {
128         return -ENODEV;
129 }
130
131 static long kfd_ioctl_set_memory_policy(struct file *filep,
132                                 struct kfd_process *p, void __user *arg)
133 {
134         return -ENODEV;
135 }
136
137 static long kfd_ioctl_get_clock_counters(struct file *filep,
138                                 struct kfd_process *p, void __user *arg)
139 {
140         return -ENODEV;
141 }
142
143
144 static int kfd_ioctl_get_process_apertures(struct file *filp,
145                                 struct kfd_process *p, void __user *arg)
146 {
147         return -ENODEV;
148 }
149
150 static long kfd_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
151 {
152         struct kfd_process *process;
153         long err = -EINVAL;
154
155         dev_dbg(kfd_device,
156                 "ioctl cmd 0x%x (#%d), arg 0x%lx\n",
157                 cmd, _IOC_NR(cmd), arg);
158
159         /* TODO: add function that retrieves process */
160         process = NULL;
161
162         switch (cmd) {
163         case KFD_IOC_GET_VERSION:
164                 err = kfd_ioctl_get_version(filep, process, (void __user *)arg);
165                 break;
166         case KFD_IOC_CREATE_QUEUE:
167                 err = kfd_ioctl_create_queue(filep, process,
168                                                 (void __user *)arg);
169                 break;
170
171         case KFD_IOC_DESTROY_QUEUE:
172                 err = kfd_ioctl_destroy_queue(filep, process,
173                                                 (void __user *)arg);
174                 break;
175
176         case KFD_IOC_SET_MEMORY_POLICY:
177                 err = kfd_ioctl_set_memory_policy(filep, process,
178                                                 (void __user *)arg);
179                 break;
180
181         case KFD_IOC_GET_CLOCK_COUNTERS:
182                 err = kfd_ioctl_get_clock_counters(filep, process,
183                                                 (void __user *)arg);
184                 break;
185
186         case KFD_IOC_GET_PROCESS_APERTURES:
187                 err = kfd_ioctl_get_process_apertures(filep, process,
188                                                 (void __user *)arg);
189                 break;
190
191         case KFD_IOC_UPDATE_QUEUE:
192                 err = kfd_ioctl_update_queue(filep, process,
193                                                 (void __user *)arg);
194                 break;
195
196         default:
197                 dev_err(kfd_device,
198                         "unknown ioctl cmd 0x%x, arg 0x%lx)\n",
199                         cmd, arg);
200                 err = -EINVAL;
201                 break;
202         }
203
204         if (err < 0)
205                 dev_err(kfd_device,
206                         "ioctl error %ld for ioctl cmd 0x%x (#%d)\n",
207                         err, cmd, _IOC_NR(cmd));
208
209         return err;
210 }