Linux Audio

Check our new training course

Loading...
v4.6
  1/*
  2 * Copyright 2011 Red Hat, Inc.
  3 * Copyright © 2014 The Chromium OS Authors
  4 *
  5 * Permission is hereby granted, free of charge, to any person obtaining a
  6 * copy of this software and associated documentation files (the "Software")
  7 * to deal in the software without restriction, including without limitation
  8 * on the rights to use, copy, modify, merge, publish, distribute, sub
  9 * license, and/or sell copies of the Software, and to permit persons to whom
 10 * them Software is furnished to do so, subject to the following conditions:
 11 *
 12 * The above copyright notice and this permission notice (including the next
 13 * paragraph) shall be included in all copies or substantial portions of the
 14 * Software.
 15 *
 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTIBILITY,
 18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
 19 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER
 20 * IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN
 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 22 *
 23 * Authors:
 24 *	Adam Jackson <ajax@redhat.com>
 25 *	Ben Widawsky <ben@bwidawsk.net>
 26 */
 27
 28/**
 29 * This is vgem, a (non-hardware-backed) GEM service.  This is used by Mesa's
 30 * software renderer and the X server for efficient buffer sharing.
 31 */
 32
 
 33#include <linux/module.h>
 34#include <linux/ramfs.h>
 35#include <linux/shmem_fs.h>
 36#include <linux/dma-buf.h>
 
 
 
 
 
 
 
 37#include "vgem_drv.h"
 38
 39#define DRIVER_NAME	"vgem"
 40#define DRIVER_DESC	"Virtual GEM provider"
 41#define DRIVER_DATE	"20120112"
 42#define DRIVER_MAJOR	1
 43#define DRIVER_MINOR	0
 44
 45void vgem_gem_put_pages(struct drm_vgem_gem_object *obj)
 46{
 47	drm_gem_put_pages(&obj->base, obj->pages, false, false);
 48	obj->pages = NULL;
 49}
 50
 51static void vgem_gem_free_object(struct drm_gem_object *obj)
 52{
 53	struct drm_vgem_gem_object *vgem_obj = to_vgem_bo(obj);
 54
 55	drm_gem_free_mmap_offset(obj);
 
 56
 57	if (vgem_obj->use_dma_buf && obj->dma_buf) {
 58		dma_buf_put(obj->dma_buf);
 59		obj->dma_buf = NULL;
 60	}
 61
 62	drm_gem_object_release(obj);
 63
 64	if (vgem_obj->pages)
 65		vgem_gem_put_pages(vgem_obj);
 66
 67	vgem_obj->pages = NULL;
 68
 69	kfree(vgem_obj);
 70}
 71
 72int vgem_gem_get_pages(struct drm_vgem_gem_object *obj)
 73{
 74	struct page **pages;
 75
 76	if (obj->pages || obj->use_dma_buf)
 77		return 0;
 78
 79	pages = drm_gem_get_pages(&obj->base);
 80	if (IS_ERR(pages)) {
 81		return PTR_ERR(pages);
 82	}
 83
 84	obj->pages = pages;
 85
 86	return 0;
 87}
 88
 89static int vgem_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 90{
 
 91	struct drm_vgem_gem_object *obj = vma->vm_private_data;
 92	struct drm_device *dev = obj->base.dev;
 
 
 93	loff_t num_pages;
 94	pgoff_t page_offset;
 95	int ret;
 96
 97	/* We don't use vmf->pgoff since that has the fake offset */
 98	page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >>
 99		PAGE_SHIFT;
100
101	num_pages = DIV_ROUND_UP(obj->base.size, PAGE_SIZE);
102
103	if (page_offset > num_pages)
104		return VM_FAULT_SIGBUS;
105
106	mutex_lock(&dev->struct_mutex);
107
108	ret = vm_insert_page(vma, (unsigned long)vmf->virtual_address,
109			     obj->pages[page_offset]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
111	mutex_unlock(&dev->struct_mutex);
112	switch (ret) {
113	case 0:
114		return VM_FAULT_NOPAGE;
115	case -ENOMEM:
116		return VM_FAULT_OOM;
117	case -EBUSY:
118		return VM_FAULT_RETRY;
119	case -EFAULT:
120	case -EINVAL:
121		return VM_FAULT_SIGBUS;
122	default:
123		WARN_ON(1);
124		return VM_FAULT_SIGBUS;
125	}
 
126}
127
128static const struct vm_operations_struct vgem_gem_vm_ops = {
129	.fault = vgem_gem_fault,
130	.open = drm_gem_vm_open,
131	.close = drm_gem_vm_close,
132};
133
134/* ioctls */
 
 
 
135
136static struct drm_gem_object *vgem_gem_create(struct drm_device *dev,
137					      struct drm_file *file,
138					      unsigned int *handle,
139					      unsigned long size)
 
 
 
 
 
 
 
 
 
 
 
 
140{
141	struct drm_vgem_gem_object *obj;
142	struct drm_gem_object *gem_object;
143	int err;
 
 
144
145	size = roundup(size, PAGE_SIZE);
 
 
 
 
146
147	obj = kzalloc(sizeof(*obj), GFP_KERNEL);
148	if (!obj)
149		return ERR_PTR(-ENOMEM);
150
151	gem_object = &obj->base;
 
 
 
 
152
153	err = drm_gem_object_init(dev, gem_object, size);
154	if (err)
155		goto out;
156
157	err = drm_gem_handle_create(file, gem_object, handle);
158	if (err)
159		goto handle_out;
160
161	drm_gem_object_unreference_unlocked(gem_object);
 
 
 
 
162
163	return gem_object;
 
 
 
 
 
 
164
165handle_out:
166	drm_gem_object_release(gem_object);
167out:
168	kfree(obj);
169	return ERR_PTR(err);
 
 
 
 
 
 
170}
171
172static int vgem_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
173				struct drm_mode_create_dumb *args)
174{
175	struct drm_gem_object *gem_object;
176	uint64_t size;
177	uint64_t pitch = args->width * DIV_ROUND_UP(args->bpp, 8);
178
 
179	size = args->height * pitch;
180	if (size == 0)
181		return -EINVAL;
182
183	gem_object = vgem_gem_create(dev, file, &args->handle, size);
184
185	if (IS_ERR(gem_object)) {
186		DRM_DEBUG_DRIVER("object creation failed\n");
187		return PTR_ERR(gem_object);
188	}
189
190	args->size = gem_object->size;
191	args->pitch = pitch;
192
193	DRM_DEBUG_DRIVER("Created object of size %lld\n", size);
 
 
194
195	return 0;
196}
197
198int vgem_gem_dumb_map(struct drm_file *file, struct drm_device *dev,
199		      uint32_t handle, uint64_t *offset)
200{
201	int ret = 0;
202	struct drm_gem_object *obj;
203
204	mutex_lock(&dev->struct_mutex);
205	obj = drm_gem_object_lookup(dev, file, handle);
206	if (!obj) {
207		ret = -ENOENT;
208		goto unlock;
209	}
210
211	if (!drm_vma_node_has_offset(&obj->vma_node)) {
212		ret = drm_gem_create_mmap_offset(obj);
213		if (ret)
214			goto unref;
215	}
216
217	BUG_ON(!obj->filp);
218
219	obj->filp->private_data = obj;
 
 
 
220
221	ret = vgem_gem_get_pages(to_vgem_bo(obj));
222	if (ret)
223		goto fail_get_pages;
224
225	*offset = drm_vma_node_offset_addr(&obj->vma_node);
226
227	goto unref;
228
229fail_get_pages:
230	drm_gem_free_mmap_offset(obj);
231unref:
232	drm_gem_object_unreference(obj);
233unlock:
234	mutex_unlock(&dev->struct_mutex);
235	return ret;
236}
237
238static struct drm_ioctl_desc vgem_ioctls[] = {
239};
240
241static const struct file_operations vgem_driver_fops = {
242	.owner		= THIS_MODULE,
243	.open		= drm_open,
244	.mmap		= drm_gem_mmap,
245	.poll		= drm_poll,
246	.read		= drm_read,
247	.unlocked_ioctl = drm_ioctl,
 
248	.release	= drm_release,
249};
250
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251static struct drm_driver vgem_driver = {
252	.driver_features		= DRIVER_GEM,
253	.gem_free_object		= vgem_gem_free_object,
 
 
 
254	.gem_vm_ops			= &vgem_gem_vm_ops,
255	.ioctls				= vgem_ioctls,
 
256	.fops				= &vgem_driver_fops,
 
257	.dumb_create			= vgem_gem_dumb_create,
258	.dumb_map_offset		= vgem_gem_dumb_map,
 
 
 
 
 
 
 
 
 
 
 
259	.name	= DRIVER_NAME,
260	.desc	= DRIVER_DESC,
261	.date	= DRIVER_DATE,
262	.major	= DRIVER_MAJOR,
263	.minor	= DRIVER_MINOR,
264};
265
266struct drm_device *vgem_device;
267
268static int __init vgem_init(void)
269{
270	int ret;
271
272	vgem_device = drm_dev_alloc(&vgem_driver, NULL);
273	if (!vgem_device) {
274		ret = -ENOMEM;
275		goto out;
 
 
 
 
 
276	}
277
278	drm_dev_set_unique(vgem_device, "vgem");
279
280	ret  = drm_dev_register(vgem_device, 0);
 
 
 
 
281
 
 
282	if (ret)
283		goto out_unref;
284
285	return 0;
286
287out_unref:
288	drm_dev_unref(vgem_device);
289out:
 
 
 
 
 
290	return ret;
291}
292
293static void __exit vgem_exit(void)
294{
295	drm_dev_unregister(vgem_device);
296	drm_dev_unref(vgem_device);
297}
298
299module_init(vgem_init);
300module_exit(vgem_exit);
301
302MODULE_AUTHOR("Red Hat, Inc.");
 
303MODULE_DESCRIPTION(DRIVER_DESC);
304MODULE_LICENSE("GPL and additional rights");
v5.9
  1/*
  2 * Copyright 2011 Red Hat, Inc.
  3 * Copyright © 2014 The Chromium OS Authors
  4 *
  5 * Permission is hereby granted, free of charge, to any person obtaining a
  6 * copy of this software and associated documentation files (the "Software")
  7 * to deal in the software without restriction, including without limitation
  8 * on the rights to use, copy, modify, merge, publish, distribute, sub
  9 * license, and/or sell copies of the Software, and to permit persons to whom
 10 * them Software is furnished to do so, subject to the following conditions:
 11 *
 12 * The above copyright notice and this permission notice (including the next
 13 * paragraph) shall be included in all copies or substantial portions of the
 14 * Software.
 15 *
 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTIBILITY,
 18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
 19 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER
 20 * IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN
 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 22 *
 23 * Authors:
 24 *	Adam Jackson <ajax@redhat.com>
 25 *	Ben Widawsky <ben@bwidawsk.net>
 26 */
 27
 28/**
 29 * This is vgem, a (non-hardware-backed) GEM service.  This is used by Mesa's
 30 * software renderer and the X server for efficient buffer sharing.
 31 */
 32
 33#include <linux/dma-buf.h>
 34#include <linux/module.h>
 35#include <linux/platform_device.h>
 36#include <linux/shmem_fs.h>
 37#include <linux/vmalloc.h>
 38
 39#include <drm/drm_drv.h>
 40#include <drm/drm_file.h>
 41#include <drm/drm_ioctl.h>
 42#include <drm/drm_managed.h>
 43#include <drm/drm_prime.h>
 44
 45#include "vgem_drv.h"
 46
 47#define DRIVER_NAME	"vgem"
 48#define DRIVER_DESC	"Virtual GEM provider"
 49#define DRIVER_DATE	"20120112"
 50#define DRIVER_MAJOR	1
 51#define DRIVER_MINOR	0
 52
 53static struct vgem_device {
 54	struct drm_device drm;
 55	struct platform_device *platform;
 56} *vgem_device;
 
 57
 58static void vgem_gem_free_object(struct drm_gem_object *obj)
 59{
 60	struct drm_vgem_gem_object *vgem_obj = to_vgem_bo(obj);
 61
 62	kvfree(vgem_obj->pages);
 63	mutex_destroy(&vgem_obj->pages_lock);
 64
 65	if (obj->import_attach)
 66		drm_prime_gem_destroy(obj, vgem_obj->table);
 
 
 67
 68	drm_gem_object_release(obj);
 
 
 
 
 
 
 69	kfree(vgem_obj);
 70}
 71
 72static vm_fault_t vgem_gem_fault(struct vm_fault *vmf)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 73{
 74	struct vm_area_struct *vma = vmf->vma;
 75	struct drm_vgem_gem_object *obj = vma->vm_private_data;
 76	/* We don't use vmf->pgoff since that has the fake offset */
 77	unsigned long vaddr = vmf->address;
 78	vm_fault_t ret = VM_FAULT_SIGBUS;
 79	loff_t num_pages;
 80	pgoff_t page_offset;
 81	page_offset = (vaddr - vma->vm_start) >> PAGE_SHIFT;
 
 
 
 
 82
 83	num_pages = DIV_ROUND_UP(obj->base.size, PAGE_SIZE);
 84
 85	if (page_offset >= num_pages)
 86		return VM_FAULT_SIGBUS;
 87
 88	mutex_lock(&obj->pages_lock);
 89	if (obj->pages) {
 90		get_page(obj->pages[page_offset]);
 91		vmf->page = obj->pages[page_offset];
 92		ret = 0;
 93	}
 94	mutex_unlock(&obj->pages_lock);
 95	if (ret) {
 96		struct page *page;
 97
 98		page = shmem_read_mapping_page(
 99					file_inode(obj->base.filp)->i_mapping,
100					page_offset);
101		if (!IS_ERR(page)) {
102			vmf->page = page;
103			ret = 0;
104		} else switch (PTR_ERR(page)) {
105			case -ENOSPC:
106			case -ENOMEM:
107				ret = VM_FAULT_OOM;
108				break;
109			case -EBUSY:
110				ret = VM_FAULT_RETRY;
111				break;
112			case -EFAULT:
113			case -EINVAL:
114				ret = VM_FAULT_SIGBUS;
115				break;
116			default:
117				WARN_ON(PTR_ERR(page));
118				ret = VM_FAULT_SIGBUS;
119				break;
120		}
121
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122	}
123	return ret;
124}
125
126static const struct vm_operations_struct vgem_gem_vm_ops = {
127	.fault = vgem_gem_fault,
128	.open = drm_gem_vm_open,
129	.close = drm_gem_vm_close,
130};
131
132static int vgem_open(struct drm_device *dev, struct drm_file *file)
133{
134	struct vgem_file *vfile;
135	int ret;
136
137	vfile = kzalloc(sizeof(*vfile), GFP_KERNEL);
138	if (!vfile)
139		return -ENOMEM;
140
141	file->driver_priv = vfile;
142
143	ret = vgem_fence_open(vfile);
144	if (ret) {
145		kfree(vfile);
146		return ret;
147	}
148
149	return 0;
150}
151
152static void vgem_postclose(struct drm_device *dev, struct drm_file *file)
153{
154	struct vgem_file *vfile = file->driver_priv;
155
156	vgem_fence_close(vfile);
157	kfree(vfile);
158}
159
160static struct drm_vgem_gem_object *__vgem_gem_create(struct drm_device *dev,
161						unsigned long size)
162{
163	struct drm_vgem_gem_object *obj;
164	int ret;
165
166	obj = kzalloc(sizeof(*obj), GFP_KERNEL);
167	if (!obj)
168		return ERR_PTR(-ENOMEM);
169
170	ret = drm_gem_object_init(dev, &obj->base, roundup(size, PAGE_SIZE));
171	if (ret) {
172		kfree(obj);
173		return ERR_PTR(ret);
174	}
175
176	mutex_init(&obj->pages_lock);
 
 
177
178	return obj;
179}
 
180
181static void __vgem_gem_destroy(struct drm_vgem_gem_object *obj)
182{
183	drm_gem_object_release(&obj->base);
184	kfree(obj);
185}
186
187static struct drm_gem_object *vgem_gem_create(struct drm_device *dev,
188					      struct drm_file *file,
189					      unsigned int *handle,
190					      unsigned long size)
191{
192	struct drm_vgem_gem_object *obj;
193	int ret;
194
195	obj = __vgem_gem_create(dev, size);
196	if (IS_ERR(obj))
197		return ERR_CAST(obj);
198
199	ret = drm_gem_handle_create(file, &obj->base, handle);
200	if (ret) {
201		drm_gem_object_put(&obj->base);
202		return ERR_PTR(ret);
203	}
204
205	return &obj->base;
206}
207
208static int vgem_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
209				struct drm_mode_create_dumb *args)
210{
211	struct drm_gem_object *gem_object;
212	u64 pitch, size;
 
213
214	pitch = args->width * DIV_ROUND_UP(args->bpp, 8);
215	size = args->height * pitch;
216	if (size == 0)
217		return -EINVAL;
218
219	gem_object = vgem_gem_create(dev, file, &args->handle, size);
220	if (IS_ERR(gem_object))
 
 
221		return PTR_ERR(gem_object);
 
222
223	args->size = gem_object->size;
224	args->pitch = pitch;
225
226	drm_gem_object_put(gem_object);
227
228	DRM_DEBUG("Created object of size %llu\n", args->size);
229
230	return 0;
231}
232
233static struct drm_ioctl_desc vgem_ioctls[] = {
234	DRM_IOCTL_DEF_DRV(VGEM_FENCE_ATTACH, vgem_fence_attach_ioctl, DRM_RENDER_ALLOW),
235	DRM_IOCTL_DEF_DRV(VGEM_FENCE_SIGNAL, vgem_fence_signal_ioctl, DRM_RENDER_ALLOW),
236};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
238static int vgem_mmap(struct file *filp, struct vm_area_struct *vma)
239{
240	unsigned long flags = vma->vm_flags;
241	int ret;
242
243	ret = drm_gem_mmap(filp, vma);
244	if (ret)
245		return ret;
 
 
 
 
246
247	/* Keep the WC mmaping set by drm_gem_mmap() but our pages
248	 * are ordinary and not special.
249	 */
250	vma->vm_flags = flags | VM_DONTEXPAND | VM_DONTDUMP;
251	return 0;
 
 
252}
253
 
 
 
254static const struct file_operations vgem_driver_fops = {
255	.owner		= THIS_MODULE,
256	.open		= drm_open,
257	.mmap		= vgem_mmap,
258	.poll		= drm_poll,
259	.read		= drm_read,
260	.unlocked_ioctl = drm_ioctl,
261	.compat_ioctl	= drm_compat_ioctl,
262	.release	= drm_release,
263};
264
265static struct page **vgem_pin_pages(struct drm_vgem_gem_object *bo)
266{
267	mutex_lock(&bo->pages_lock);
268	if (bo->pages_pin_count++ == 0) {
269		struct page **pages;
270
271		pages = drm_gem_get_pages(&bo->base);
272		if (IS_ERR(pages)) {
273			bo->pages_pin_count--;
274			mutex_unlock(&bo->pages_lock);
275			return pages;
276		}
277
278		bo->pages = pages;
279	}
280	mutex_unlock(&bo->pages_lock);
281
282	return bo->pages;
283}
284
285static void vgem_unpin_pages(struct drm_vgem_gem_object *bo)
286{
287	mutex_lock(&bo->pages_lock);
288	if (--bo->pages_pin_count == 0) {
289		drm_gem_put_pages(&bo->base, bo->pages, true, true);
290		bo->pages = NULL;
291	}
292	mutex_unlock(&bo->pages_lock);
293}
294
295static int vgem_prime_pin(struct drm_gem_object *obj)
296{
297	struct drm_vgem_gem_object *bo = to_vgem_bo(obj);
298	long n_pages = obj->size >> PAGE_SHIFT;
299	struct page **pages;
300
301	pages = vgem_pin_pages(bo);
302	if (IS_ERR(pages))
303		return PTR_ERR(pages);
304
305	/* Flush the object from the CPU cache so that importers can rely
306	 * on coherent indirect access via the exported dma-address.
307	 */
308	drm_clflush_pages(pages, n_pages);
309
310	return 0;
311}
312
313static void vgem_prime_unpin(struct drm_gem_object *obj)
314{
315	struct drm_vgem_gem_object *bo = to_vgem_bo(obj);
316
317	vgem_unpin_pages(bo);
318}
319
320static struct sg_table *vgem_prime_get_sg_table(struct drm_gem_object *obj)
321{
322	struct drm_vgem_gem_object *bo = to_vgem_bo(obj);
323
324	return drm_prime_pages_to_sg(bo->pages, bo->base.size >> PAGE_SHIFT);
325}
326
327static struct drm_gem_object* vgem_prime_import(struct drm_device *dev,
328						struct dma_buf *dma_buf)
329{
330	struct vgem_device *vgem = container_of(dev, typeof(*vgem), drm);
331
332	return drm_gem_prime_import_dev(dev, dma_buf, &vgem->platform->dev);
333}
334
335static struct drm_gem_object *vgem_prime_import_sg_table(struct drm_device *dev,
336			struct dma_buf_attachment *attach, struct sg_table *sg)
337{
338	struct drm_vgem_gem_object *obj;
339	int npages;
340
341	obj = __vgem_gem_create(dev, attach->dmabuf->size);
342	if (IS_ERR(obj))
343		return ERR_CAST(obj);
344
345	npages = PAGE_ALIGN(attach->dmabuf->size) / PAGE_SIZE;
346
347	obj->table = sg;
348	obj->pages = kvmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
349	if (!obj->pages) {
350		__vgem_gem_destroy(obj);
351		return ERR_PTR(-ENOMEM);
352	}
353
354	obj->pages_pin_count++; /* perma-pinned */
355	drm_prime_sg_to_page_addr_arrays(obj->table, obj->pages, NULL,
356					npages);
357	return &obj->base;
358}
359
360static void *vgem_prime_vmap(struct drm_gem_object *obj)
361{
362	struct drm_vgem_gem_object *bo = to_vgem_bo(obj);
363	long n_pages = obj->size >> PAGE_SHIFT;
364	struct page **pages;
365
366	pages = vgem_pin_pages(bo);
367	if (IS_ERR(pages))
368		return NULL;
369
370	return vmap(pages, n_pages, 0, pgprot_writecombine(PAGE_KERNEL));
371}
372
373static void vgem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
374{
375	struct drm_vgem_gem_object *bo = to_vgem_bo(obj);
376
377	vunmap(vaddr);
378	vgem_unpin_pages(bo);
379}
380
381static int vgem_prime_mmap(struct drm_gem_object *obj,
382			   struct vm_area_struct *vma)
383{
384	int ret;
385
386	if (obj->size < vma->vm_end - vma->vm_start)
387		return -EINVAL;
388
389	if (!obj->filp)
390		return -ENODEV;
391
392	ret = call_mmap(obj->filp, vma);
393	if (ret)
394		return ret;
395
396	fput(vma->vm_file);
397	vma->vm_file = get_file(obj->filp);
398	vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
399	vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
400
401	return 0;
402}
403
404static void vgem_release(struct drm_device *dev)
405{
406	struct vgem_device *vgem = container_of(dev, typeof(*vgem), drm);
407
408	platform_device_unregister(vgem->platform);
409}
410
411static struct drm_driver vgem_driver = {
412	.driver_features		= DRIVER_GEM | DRIVER_RENDER,
413	.release			= vgem_release,
414	.open				= vgem_open,
415	.postclose			= vgem_postclose,
416	.gem_free_object_unlocked	= vgem_gem_free_object,
417	.gem_vm_ops			= &vgem_gem_vm_ops,
418	.ioctls				= vgem_ioctls,
419	.num_ioctls 			= ARRAY_SIZE(vgem_ioctls),
420	.fops				= &vgem_driver_fops,
421
422	.dumb_create			= vgem_gem_dumb_create,
423
424	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
425	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
426	.gem_prime_pin = vgem_prime_pin,
427	.gem_prime_unpin = vgem_prime_unpin,
428	.gem_prime_import = vgem_prime_import,
429	.gem_prime_import_sg_table = vgem_prime_import_sg_table,
430	.gem_prime_get_sg_table = vgem_prime_get_sg_table,
431	.gem_prime_vmap = vgem_prime_vmap,
432	.gem_prime_vunmap = vgem_prime_vunmap,
433	.gem_prime_mmap = vgem_prime_mmap,
434
435	.name	= DRIVER_NAME,
436	.desc	= DRIVER_DESC,
437	.date	= DRIVER_DATE,
438	.major	= DRIVER_MAJOR,
439	.minor	= DRIVER_MINOR,
440};
441
 
 
442static int __init vgem_init(void)
443{
444	int ret;
445
446	vgem_device = kzalloc(sizeof(*vgem_device), GFP_KERNEL);
447	if (!vgem_device)
448		return -ENOMEM;
449
450	vgem_device->platform =
451		platform_device_register_simple("vgem", -1, NULL, 0);
452	if (IS_ERR(vgem_device->platform)) {
453		ret = PTR_ERR(vgem_device->platform);
454		goto out_free;
455	}
456
457	dma_coerce_mask_and_coherent(&vgem_device->platform->dev,
458				     DMA_BIT_MASK(64));
459	ret = drm_dev_init(&vgem_device->drm, &vgem_driver,
460			   &vgem_device->platform->dev);
461	if (ret)
462		goto out_unregister;
463	drmm_add_final_kfree(&vgem_device->drm, vgem_device);
464
465	/* Final step: expose the device/driver to userspace */
466	ret = drm_dev_register(&vgem_device->drm, 0);
467	if (ret)
468		goto out_put;
469
470	return 0;
471
472out_put:
473	drm_dev_put(&vgem_device->drm);
474	return ret;
475
476out_unregister:
477	platform_device_unregister(vgem_device->platform);
478out_free:
479	kfree(vgem_device);
480	return ret;
481}
482
483static void __exit vgem_exit(void)
484{
485	drm_dev_unregister(&vgem_device->drm);
486	drm_dev_put(&vgem_device->drm);
487}
488
489module_init(vgem_init);
490module_exit(vgem_exit);
491
492MODULE_AUTHOR("Red Hat, Inc.");
493MODULE_AUTHOR("Intel Corporation");
494MODULE_DESCRIPTION(DRIVER_DESC);
495MODULE_LICENSE("GPL and additional rights");