]>
Commit | Line | Data |
---|---|---|
c2806d43 AM |
1 | diff -urNp -x '*.orig' linux-4.4/drivers/gpu/Makefile linux-4.4/drivers/gpu/Makefile |
2 | --- linux-4.4/drivers/gpu/Makefile 2016-01-11 00:01:32.000000000 +0100 | |
3 | +++ linux-4.4/drivers/gpu/Makefile 2021-02-24 17:38:24.865178977 +0100 | |
4 | @@ -2,5 +2,5 @@ | |
5 | # taken to initialize them in the correct order. Link order is the only way | |
6 | # to ensure this currently. | |
7 | obj-$(CONFIG_TEGRA_HOST1X) += host1x/ | |
514e5dae AM |
8 | -obj-y += drm/ vga/ |
9 | +obj-y += drm/ vga/ misc/ | |
c2806d43 AM |
10 | obj-$(CONFIG_IMX_IPUV3_CORE) += ipu-v3/ |
11 | diff -urNp -x '*.orig' linux-4.4/drivers/gpu/misc/Kconfig linux-4.4/drivers/gpu/misc/Kconfig | |
12 | --- linux-4.4/drivers/gpu/misc/Kconfig 1970-01-01 01:00:00.000000000 +0100 | |
13 | +++ linux-4.4/drivers/gpu/misc/Kconfig 2021-02-24 17:38:24.865178977 +0100 | |
af0f7570 KK |
14 | @@ -0,0 +1,8 @@ |
15 | +config VIRTIOGL | |
16 | + tristate "Virtio userspace memory transport" | |
17 | + depends on VIRTIO_PCI | |
18 | + default n | |
19 | + help | |
20 | + A Driver to facilitate transferring data from userspace to a | |
21 | + hypervisor (eg. qemu) | |
22 | + | |
c2806d43 AM |
23 | diff -urNp -x '*.orig' linux-4.4/drivers/gpu/misc/Makefile linux-4.4/drivers/gpu/misc/Makefile |
24 | --- linux-4.4/drivers/gpu/misc/Makefile 1970-01-01 01:00:00.000000000 +0100 | |
25 | +++ linux-4.4/drivers/gpu/misc/Makefile 2021-02-24 17:38:24.865178977 +0100 | |
af0f7570 KK |
26 | @@ -0,0 +1 @@ |
27 | +obj-$(CONFIG_VIRTIOGL) += virtio-gl.o | |
c2806d43 AM |
28 | diff -urNp -x '*.orig' linux-4.4/drivers/gpu/misc/virtio-gl.c linux-4.4/drivers/gpu/misc/virtio-gl.c |
29 | --- linux-4.4/drivers/gpu/misc/virtio-gl.c 1970-01-01 01:00:00.000000000 +0100 | |
30 | +++ linux-4.4/drivers/gpu/misc/virtio-gl.c 2021-02-24 17:38:24.865178977 +0100 | |
392086de | 31 | @@ -0,0 +1,315 @@ |
af0f7570 KK |
32 | +/* |
33 | + * Copyright (C) 2010 Intel Corporation | |
34 | + * | |
35 | + * Author: Ian Molton <ian.molton@collabora.co.uk> | |
36 | + * | |
37 | + * This program is free software; you can redistribute it and/or modify | |
38 | + * it under the terms of the GNU General Public License as published by | |
39 | + * the Free Software Foundation; either version 2 of the License, or | |
40 | + * (at your option) any later version. | |
41 | + * | |
42 | + * This program is distributed in the hope that it will be useful, | |
43 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
44 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
45 | + * GNU General Public License for more details. | |
46 | + * | |
47 | + * You should have received a copy of the GNU General Public License | |
48 | + * along with this program; if not, write to the Free Software | |
49 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
50 | + */ | |
af0f7570 KK |
51 | +#include <linux/kernel.h> |
52 | +#include <linux/module.h> | |
53 | +#include <linux/fs.h> | |
54 | +#include <linux/dma-mapping.h> | |
55 | +#include <linux/sched.h> | |
56 | +#include <linux/slab.h> | |
57 | +#include <linux/miscdevice.h> | |
c2c0f25c | 58 | +#include <linux/vmalloc.h> |
af0f7570 KK |
59 | +#include <linux/virtio.h> |
60 | +#include <linux/virtio_ids.h> | |
61 | +#include <linux/virtio_config.h> | |
62 | + | |
63 | +#define DEVICE_NAME "glmem" | |
64 | + | |
65 | +/* Define to use debugging checksums on transfers */ | |
66 | +#undef DEBUG_GLIO | |
67 | + | |
68 | +struct virtio_gl_data { | |
69 | + char *buffer; | |
70 | + int pages; | |
71 | + unsigned int pid; | |
72 | +}; | |
73 | + | |
74 | +struct virtio_gl_header { | |
75 | + int pid; | |
76 | + int buf_size; | |
77 | + int r_buf_size; | |
78 | +#ifdef DEBUG_GLIO | |
79 | + int sum; | |
80 | +#endif | |
81 | + char buffer; | |
82 | +} __packed; | |
83 | + | |
84 | +#define to_virtio_gl_data(a) ((struct virtio_gl_data *)(a)->private_data) | |
85 | + | |
86 | +#ifdef DEBUG_GLIO | |
87 | +#define SIZE_OUT_HEADER (sizeof(int)*4) | |
88 | +#define SIZE_IN_HEADER (sizeof(int)*2) | |
89 | +#else | |
90 | +#define SIZE_OUT_HEADER (sizeof(int)*3) | |
91 | +#define SIZE_IN_HEADER sizeof(int) | |
92 | +#endif | |
93 | + | |
94 | +static struct virtqueue *vq; | |
95 | + | |
96 | + | |
97 | +/* This is videobuf_vmalloc_to_sg() from videobuf-dma-sg.c with | |
98 | + * some modifications | |
99 | + */ | |
100 | +static struct scatterlist *vmalloc_to_sg(struct scatterlist *sg_list, | |
101 | + unsigned char *virt, unsigned int pages) | |
102 | +{ | |
103 | + struct page *pg; | |
104 | + | |
105 | + /* unaligned */ | |
106 | + BUG_ON((ulong)virt & ~PAGE_MASK); | |
107 | + | |
108 | + /* Fill with elements for the data */ | |
109 | + while (pages) { | |
110 | + pg = vmalloc_to_page(virt); | |
111 | + if (!pg) | |
112 | + goto err; | |
113 | + | |
114 | + sg_set_page(sg_list, pg, PAGE_SIZE, 0); | |
115 | + virt += PAGE_SIZE; | |
116 | + sg_list++; | |
117 | + pages--; | |
118 | + } | |
119 | + | |
120 | + return sg_list; | |
121 | + | |
122 | +err: | |
123 | + kfree(sg_list); | |
124 | + return NULL; | |
125 | +} | |
126 | + | |
127 | +static int put_data(struct virtio_gl_data *gldata) | |
128 | +{ | |
129 | + struct scatterlist *sg, *sg_list; | |
130 | + unsigned int count, ret, o_page, i_page, sg_entries; | |
131 | + struct virtio_gl_header *header = | |
132 | + (struct virtio_gl_header *)gldata->buffer; | |
133 | + | |
134 | + ret = header->buf_size; | |
135 | + | |
136 | + o_page = (header->buf_size + PAGE_SIZE-1) >> PAGE_SHIFT; | |
137 | + i_page = (header->r_buf_size + PAGE_SIZE-1) >> PAGE_SHIFT; | |
138 | + | |
139 | + header->pid = gldata->pid; | |
140 | + | |
141 | + if ((o_page && i_page) && | |
142 | + (o_page > gldata->pages || i_page > gldata->pages)) { | |
143 | + i_page = 0; | |
144 | + } | |
145 | + | |
146 | + if (o_page > gldata->pages) | |
147 | + o_page = gldata->pages; | |
148 | + | |
149 | + if (i_page > gldata->pages) | |
150 | + i_page = gldata->pages; | |
151 | + | |
152 | + if (!o_page) | |
153 | + o_page = 1; | |
154 | + | |
155 | + sg_entries = o_page + i_page; | |
156 | + | |
157 | + sg_list = kcalloc(sg_entries, sizeof(struct scatterlist), GFP_KERNEL); | |
158 | + | |
159 | + if (!sg_list) { | |
160 | + ret = -EIO; | |
161 | + goto out; | |
162 | + } | |
163 | + | |
164 | + sg_init_table(sg_list, sg_entries); | |
165 | + | |
166 | + sg = vmalloc_to_sg(sg_list, gldata->buffer, o_page); | |
167 | + sg = vmalloc_to_sg(sg, gldata->buffer, i_page); | |
168 | + | |
169 | + if (!sg) { | |
170 | + ret = -EIO; | |
171 | + goto out_free; | |
172 | + } | |
173 | + | |
174 | + /* Transfer data */ | |
392086de AM |
175 | + struct scatterlist *sgs[2]; |
176 | + sgs[0] = &sg_list[0]; | |
177 | + sgs[1] = &sg_list[1]; | |
178 | + if (virtqueue_add_sgs(vq, sgs, o_page, i_page, (void *)1, GFP_ATOMIC) >= 0) { | |
af0f7570 KK |
179 | + virtqueue_kick(vq); |
180 | + /* Chill out until it's done with the buffer. */ | |
181 | + while (!virtqueue_get_buf(vq, &count)) | |
182 | + cpu_relax(); | |
183 | + } | |
184 | + | |
185 | +out_free: | |
186 | + kfree(sg_list); | |
187 | +out: | |
188 | + return ret; | |
189 | +} | |
190 | + | |
191 | +static void free_buffer(struct virtio_gl_data *gldata) | |
192 | +{ | |
193 | + if (gldata->buffer) { | |
194 | + vfree(gldata->buffer); | |
195 | + gldata->buffer = NULL; | |
196 | + } | |
197 | +} | |
198 | + | |
199 | +static int glmem_open(struct inode *inode, struct file *file) | |
200 | +{ | |
201 | + struct virtio_gl_data *gldata = kzalloc(sizeof(struct virtio_gl_data), | |
202 | + GFP_KERNEL); | |
203 | + | |
204 | + if (!gldata) | |
205 | + return -ENXIO; | |
206 | + | |
207 | + gldata->pid = pid_nr(task_pid(current)); | |
208 | + | |
209 | + file->private_data = gldata; | |
210 | + | |
211 | + return 0; | |
212 | +} | |
213 | + | |
214 | +static int glmem_mmap(struct file *filp, struct vm_area_struct *vma) | |
215 | +{ | |
216 | + struct virtio_gl_data *gldata = to_virtio_gl_data(filp); | |
217 | + int pages = (vma->vm_end - vma->vm_start) / PAGE_SIZE; | |
218 | + | |
219 | + /* Set a reasonable limit */ | |
220 | + if (pages > 16) | |
221 | + return -ENOMEM; | |
222 | + | |
223 | + /* for now, just allow one buffer to be mmap()ed. */ | |
224 | + if (gldata->buffer) | |
225 | + return -EIO; | |
226 | + | |
227 | + gldata->buffer = vmalloc_user(pages*PAGE_SIZE); | |
228 | + | |
229 | + if (!gldata->buffer) | |
230 | + return -ENOMEM; | |
231 | + | |
232 | + gldata->pages = pages; | |
233 | + | |
234 | + if (remap_vmalloc_range(vma, gldata->buffer, 0) < 0) { | |
235 | + vfree(gldata->buffer); | |
236 | + return -EIO; | |
237 | + } | |
238 | + | |
239 | + vma->vm_flags |= VM_DONTEXPAND; | |
240 | + | |
241 | + return 0; | |
242 | +} | |
243 | + | |
7c99cdc1 | 244 | +static int glmem_fsync(struct file *filp, loff_t unused1, loff_t unused2, int datasync) |
af0f7570 KK |
245 | +{ |
246 | + struct virtio_gl_data *gldata = to_virtio_gl_data(filp); | |
247 | + | |
248 | + put_data(gldata); | |
249 | + | |
250 | + return 0; | |
251 | +} | |
252 | + | |
253 | +static int glmem_release(struct inode *inode, struct file *file) | |
254 | +{ | |
255 | + struct virtio_gl_data *gldata = to_virtio_gl_data(file); | |
256 | + | |
257 | + if (gldata && gldata->buffer) { | |
258 | + struct virtio_gl_header *header = | |
259 | + (struct virtio_gl_header *)gldata->buffer; | |
260 | + | |
261 | + /* Make sure the host hears about the process ending / dying */ | |
262 | + header->pid = gldata->pid; | |
263 | + header->buf_size = SIZE_OUT_HEADER + 2; | |
264 | + header->r_buf_size = SIZE_IN_HEADER; | |
265 | + *(short *)(&header->buffer) = -1; | |
266 | + | |
267 | + put_data(gldata); | |
268 | + free_buffer(gldata); | |
269 | + } | |
270 | + | |
271 | + kfree(gldata); | |
272 | + | |
273 | + return 0; | |
274 | +} | |
275 | + | |
276 | +static const struct file_operations glmem_fops = { | |
277 | + .owner = THIS_MODULE, | |
278 | + .open = glmem_open, | |
279 | + .mmap = glmem_mmap, | |
280 | + .fsync = glmem_fsync, | |
281 | + .release = glmem_release, | |
282 | +}; | |
283 | + | |
284 | +static struct miscdevice glmem_dev = { | |
285 | + MISC_DYNAMIC_MINOR, | |
286 | + DEVICE_NAME, | |
287 | + &glmem_fops | |
288 | +}; | |
289 | + | |
290 | +static int glmem_probe(struct virtio_device *vdev) | |
291 | +{ | |
292 | + int ret; | |
293 | + | |
294 | + /* We expect a single virtqueue. */ | |
295 | + vq = virtio_find_single_vq(vdev, NULL, "output"); | |
296 | + if (IS_ERR(vq)) | |
297 | + return PTR_ERR(vq); | |
298 | + | |
299 | + ret = misc_register(&glmem_dev); | |
300 | + if (ret) { | |
301 | + printk(KERN_ERR "glmem: cannot register glmem_dev as misc"); | |
302 | + return -ENODEV; | |
303 | + } | |
304 | + | |
305 | + return 0; | |
306 | +} | |
307 | + | |
1716fcea | 308 | +static void glmem_remove(struct virtio_device *vdev) |
af0f7570 KK |
309 | +{ |
310 | + vdev->config->reset(vdev); | |
311 | + misc_deregister(&glmem_dev); | |
312 | + vdev->config->del_vqs(vdev); | |
313 | +} | |
314 | + | |
315 | +static struct virtio_device_id id_table[] = { | |
316 | + { VIRTIO_ID_GL, VIRTIO_DEV_ANY_ID }, | |
317 | + { 0 }, | |
318 | +}; | |
319 | + | |
320 | +static struct virtio_driver virtio_gl_driver = { | |
321 | + .driver = { | |
322 | + .name = KBUILD_MODNAME, | |
323 | + .owner = THIS_MODULE, | |
324 | + }, | |
325 | + .id_table = id_table, | |
326 | + .probe = glmem_probe, | |
1716fcea | 327 | + .remove = glmem_remove, |
af0f7570 KK |
328 | +}; |
329 | + | |
330 | +static int __init glmem_init(void) | |
331 | +{ | |
332 | + return register_virtio_driver(&virtio_gl_driver); | |
333 | +} | |
334 | + | |
335 | +static void __exit glmem_exit(void) | |
336 | +{ | |
337 | + unregister_virtio_driver(&virtio_gl_driver); | |
338 | +} | |
339 | + | |
340 | +module_init(glmem_init); | |
341 | +module_exit(glmem_exit); | |
342 | + | |
343 | +MODULE_DEVICE_TABLE(virtio, id_table); | |
344 | +MODULE_DESCRIPTION("Virtio gl passthrough driver"); | |
345 | +MODULE_LICENSE("GPL v2"); | |
346 | + | |
c2806d43 AM |
347 | diff -urNp -x '*.orig' linux-4.4/drivers/video/Kconfig linux-4.4/drivers/video/Kconfig |
348 | --- linux-4.4/drivers/video/Kconfig 2016-01-11 00:01:32.000000000 +0100 | |
349 | +++ linux-4.4/drivers/video/Kconfig 2021-02-24 17:38:24.865178977 +0100 | |
350 | @@ -29,6 +29,7 @@ source "drivers/video/fbdev/Kconfig" | |
ea0aec88 | 351 | endmenu |
af0f7570 | 352 | |
ea0aec88 | 353 | source "drivers/video/backlight/Kconfig" |
af0f7570 KK |
354 | +source "drivers/gpu/misc/Kconfig" |
355 | ||
356 | config VGASTATE | |
357 | tristate | |
c2806d43 AM |
358 | diff -urNp -x '*.orig' linux-4.4/include/uapi/linux/virtio_ids.h linux-4.4/include/uapi/linux/virtio_ids.h |
359 | --- linux-4.4/include/uapi/linux/virtio_ids.h 2016-01-11 00:01:32.000000000 +0100 | |
360 | +++ linux-4.4/include/uapi/linux/virtio_ids.h 2021-02-24 17:38:24.865178977 +0100 | |
92d182d2 | 361 | @@ -34,6 +34,7 @@ |
af0f7570 | 362 | #define VIRTIO_ID_CONSOLE 3 /* virtio console */ |
c2806d43 | 363 | #define VIRTIO_ID_RNG 4 /* virtio rng */ |
af0f7570 KK |
364 | #define VIRTIO_ID_BALLOON 5 /* virtio balloon */ |
365 | +#define VIRTIO_ID_GL 6 /* virtio usermem */ | |
92d182d2 AM |
366 | #define VIRTIO_ID_RPMSG 7 /* virtio remote processor messaging */ |
367 | #define VIRTIO_ID_SCSI 8 /* virtio scsi */ | |
af0f7570 | 368 | #define VIRTIO_ID_9P 9 /* 9p virtio console */ |