[kernel] Add patch and config change for vgem.ko

Josh Boyer jwboyer at fedoraproject.org
Wed Feb 15 23:56:57 UTC 2012


commit 53271754a7adc9989fcf9cf2ebfe6fd497ef9f9f
Author: Adam Jackson <ajax at redhat.com>
Date:   Wed Feb 15 14:46:26 2012 -0500

    Add patch and config change for vgem.ko

 config-generic |    1 +
 drm-vgem.patch |  492 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 kernel.spec    |    5 +
 3 files changed, 498 insertions(+), 0 deletions(-)
---
diff --git a/config-generic b/config-generic
index 6cfc1c4..0cfc756 100644
--- a/config-generic
+++ b/config-generic
@@ -2415,6 +2415,7 @@ CONFIG_DRM_NOUVEAU_DEBUG=y
 CONFIG_DRM_I2C_CH7006=m
 CONFIG_DRM_I2C_SIL164=m
 CONFIG_DRM_VMWGFX=m
+CONFIG_DRM_VGEM=m
 
 #
 # PCMCIA character devices
diff --git a/drm-vgem.patch b/drm-vgem.patch
new file mode 100644
index 0000000..3610c8b
--- /dev/null
+++ b/drm-vgem.patch
@@ -0,0 +1,492 @@
+diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
+index 2418429..566c468 100644
+--- a/drivers/gpu/drm/Kconfig
++++ b/drivers/gpu/drm/Kconfig
+@@ -159,6 +159,14 @@ config DRM_SAVAGE
+ 	  Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister
+ 	  chipset. If M is selected the module will be called savage.
+ 
++config DRM_VGEM
++	tristate "Virtual GEM provider"
++	depends on DRM
++	help
++	  Choose this option to get a virtual graphics memory manager,
++	  as used by Mesa's software renderer for enhanced performance.
++	  If M is selected the module will be called vgem.
++
+ source "drivers/gpu/drm/exynos/Kconfig"
+ 
+ source "drivers/gpu/drm/vmwgfx/Kconfig"
+diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
+index 0cde1b8..021bf8a 100644
+--- a/drivers/gpu/drm/Makefile
++++ b/drivers/gpu/drm/Makefile
+@@ -34,6 +34,7 @@ obj-$(CONFIG_DRM_SIS)   += sis/
+ obj-$(CONFIG_DRM_SAVAGE)+= savage/
+ obj-$(CONFIG_DRM_VMWGFX)+= vmwgfx/
+ obj-$(CONFIG_DRM_VIA)	+=via/
++obj-$(CONFIG_DRM_VGEM)	+= vgem/
+ obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/
+ obj-$(CONFIG_DRM_EXYNOS) +=exynos/
+ obj-$(CONFIG_DRM_GMA500) += gma500/
+diff --git a/drivers/gpu/drm/vgem/Makefile b/drivers/gpu/drm/vgem/Makefile
+new file mode 100644
+index 0000000..3f4c7b8
+--- /dev/null
++++ b/drivers/gpu/drm/vgem/Makefile
+@@ -0,0 +1,4 @@
++ccflags-y := -Iinclude/drm
++vgem-y := vgem_drv.o
++
++obj-$(CONFIG_DRM_VGEM)	+= vgem.o
+diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c
+new file mode 100644
+index 0000000..16f88ee
+--- /dev/null
++++ b/drivers/gpu/drm/vgem/vgem_drv.c
+@@ -0,0 +1,377 @@
++/*
++ * Copyright 2011 Red Hat, Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software")
++ * to deal in the software without restriction, including without limitation
++ * on the rights to use, copy, modify, merge, publish, distribute, sub
++ * license, and/or sell copies of the Software, and to permit persons to whom
++ * them Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTIBILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER
++ * IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * Authors:
++ *	Adam Jackson <ajax at redhat.com>
++ */
++
++/**
++ * This is vgem, a (non-hardware-backed) GEM service.  This is used by Mesa's
++ * software renderer and the X server for efficient buffer sharing.
++ */
++
++#include "drmP.h"
++#include "drm.h"
++#include "vgem_drm.h"
++#include <linux/module.h>
++#include <linux/ramfs.h>
++#include <linux/shmem_fs.h>
++
++#define DRIVER_NAME	"vgem"
++#define DRIVER_DESC	"Virtual GEM provider"
++#define DRIVER_DATE	"20120112"
++#define DRIVER_MAJOR	1
++#define DRIVER_MINOR	0
++
++#define to_vgem_bo(x) container_of(x, struct drm_vgem_gem_object, base)
++
++struct drm_vgem_gem_object {
++	struct drm_gem_object base;
++	struct page **pages;
++};
++
++static int vgem_load(struct drm_device *dev, unsigned long flags)
++{
++	return 0;
++}
++
++static int vgem_unload(struct drm_device *dev)
++{
++	return 0;
++}
++
++static void vgem_preclose(struct drm_device *dev, struct drm_file *file)
++{
++}
++
++static void vgem_lastclose(struct drm_device *dev)
++{
++}
++
++static int vgem_gem_init_object(struct drm_gem_object *obj)
++{
++	return 0;
++}
++
++static void vgem_gem_put_pages(struct drm_vgem_gem_object *obj)
++{
++	int num_pages = obj->base.size / PAGE_SIZE;
++	int i;
++
++	for (i = 0; i < num_pages; i++) {
++		page_cache_release(obj->pages[i]);
++	}
++
++	drm_free_large(obj->pages);
++	obj->pages = NULL;
++}
++
++static void vgem_gem_free_object(struct drm_gem_object *obj)
++{
++	struct drm_vgem_gem_object *vgem_obj = to_vgem_bo(obj);
++
++	if (obj)
++		drm_gem_free_mmap_offset(obj);
++
++	drm_gem_object_release(obj);
++
++	if (vgem_obj->pages)
++		vgem_gem_put_pages(vgem_obj);
++
++	kfree(vgem_obj);
++}
++
++static int vgem_gem_get_pages(struct drm_vgem_gem_object *obj)
++{
++	struct address_space *mapping;
++	gfp_t gfpmask = __GFP_NORETRY | __GFP_NOWARN;
++	int num_pages, i, ret = 0;
++
++	num_pages = obj->base.size / PAGE_SIZE;
++
++	if (!obj->pages) {
++		obj->pages = drm_malloc_ab(num_pages, sizeof(struct page *));
++		if (obj->pages == NULL)
++			return -ENOMEM;
++	}
++
++	mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;
++	gfpmask |= mapping_gfp_mask(mapping);
++
++	if (WARN_ON(mapping == NULL))
++		return VM_FAULT_SIGBUS;
++
++	for (i = 0; i < num_pages; i++) {
++		struct page *page;
++		page = shmem_read_mapping_page_gfp(mapping, i, gfpmask);
++		if (IS_ERR(page)) {
++			ret = PTR_ERR(page);
++			goto err_out;
++		}
++		obj->pages[i] = page;
++	}
++
++	return ret;
++
++err_out:
++	while (i--)
++		page_cache_release(obj->pages[i]);
++	drm_free_large(obj->pages);
++	obj->pages = NULL;
++	return ret;
++}
++
++static int vgem_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
++{
++	struct drm_vgem_gem_object *obj = to_vgem_bo(vma->vm_private_data);
++	loff_t num_pages;
++	pgoff_t page_offset;
++	int ret;
++
++	/* We don't use vmf->pgoff since that has the fake offset */
++	page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >>
++		PAGE_SHIFT;
++
++	num_pages = obj->base.size / PAGE_SIZE;
++
++	if (WARN_ON(page_offset > num_pages))
++		return VM_FAULT_SIGBUS;
++
++	ret = vgem_gem_get_pages(obj);
++	if (ret)
++		return ret;
++
++	ret = vm_insert_page(vma, (unsigned long)vmf->virtual_address,
++			     obj->pages[page_offset]);
++
++	/* Pretty dumb handler for now */
++	switch (ret) {
++	case 0:
++	case -ERESTARTSYS:
++	case -EINTR:
++		return VM_FAULT_NOPAGE;
++	default:
++		return VM_FAULT_SIGBUS;
++	}
++}
++
++static const struct vm_operations_struct vgem_gem_vm_ops = {
++	.fault = vgem_gem_fault,
++	.open = drm_gem_vm_open,
++	.close = drm_gem_vm_close,
++};
++
++/* ioctls */
++
++static struct drm_gem_object *vgem_gem_create(struct drm_device *dev,
++					      struct drm_file *file,
++					      unsigned int *handle,
++					      unsigned long size)
++{
++	struct drm_vgem_gem_object *obj;
++	struct drm_gem_object *gem_object;
++	int err;
++
++	size = roundup(size, PAGE_SIZE);
++
++	obj = kzalloc(sizeof(*obj), GFP_KERNEL);
++	if (!obj)
++		return ERR_PTR(-ENOMEM);
++
++	gem_object = &obj->base;
++
++	if ((err = drm_gem_object_init(dev, gem_object, size)))
++		goto out;
++
++	if ((err = drm_gem_create_mmap_offset(gem_object)))
++		goto mmap_out;
++
++	if ((err = drm_gem_handle_create(file, gem_object, handle)))
++		goto handle_out;
++
++	drm_gem_object_unreference_unlocked(gem_object);
++
++	return gem_object;
++
++handle_out:
++	drm_gem_free_mmap_offset(gem_object);
++
++mmap_out:
++	drm_gem_object_release(gem_object);
++
++out:
++	kfree(gem_object);
++
++	return ERR_PTR(err);
++}
++
++static int vgem_gem_create_ioctl(struct drm_device *dev, void *data,
++				 struct drm_file *file)
++{
++	struct vgem_gem_create *args = data;
++	struct drm_gem_object *gem_object;
++
++	gem_object = vgem_gem_create(dev, file, &args->handle, args->size);
++
++	if (IS_ERR(gem_object))
++		return PTR_ERR(gem_object);
++
++	return 0;
++}
++
++static int vgem_gem_mmap_ioctl(struct drm_device *dev, void *data,
++			       struct drm_file *file)
++{
++	struct vgem_gem_mmap *args = data;
++	struct drm_gem_object *obj;
++
++	obj = drm_gem_object_lookup(dev, file, args->handle);
++	if (!obj)
++		return -ENOENT;
++
++	obj->filp->private_data = obj;
++
++	BUG_ON(!obj->map_list.map);
++
++	args->mapped = (uint64_t)obj->map_list.hash.key << PAGE_SHIFT;
++
++	drm_gem_object_unreference_unlocked(obj);
++
++	return 0;
++}
++
++static int vgem_gem_getparam_ioctl(struct drm_device *dev, void *data,
++				 struct drm_file *file)
++{
++	struct vgem_gem_getparam *args = data;
++	int value=0, ret;
++
++	switch (args->param) {
++	case VGEM_PARAM_IS_VGEM:
++		value = 1;
++	}
++
++	ret = copy_to_user(args->value, &value, sizeof(int));
++	if (ret)
++		return ret;
++
++	return 0;
++}
++
++
++static struct drm_ioctl_desc vgem_ioctls[] = {
++	DRM_IOCTL_DEF_DRV(VGEM_GEM_CREATE, vgem_gem_create_ioctl,
++			  DRM_UNLOCKED | DRM_AUTH),
++	DRM_IOCTL_DEF_DRV(VGEM_GEM_MMAP, vgem_gem_mmap_ioctl,
++			  DRM_UNLOCKED | DRM_AUTH),
++	DRM_IOCTL_DEF_DRV(VGEM_GEM_GETPARAM, vgem_gem_getparam_ioctl,
++			  DRM_UNLOCKED),
++};
++
++static const struct file_operations vgem_driver_fops = {
++	.owner		= THIS_MODULE,
++	.open		= drm_open,
++	.mmap		= drm_gem_mmap,
++	.poll		= drm_poll,
++	.read		= drm_read,
++	.unlocked_ioctl = drm_ioctl,
++	.release	= drm_release,
++};
++
++static struct drm_driver vgem_driver = {
++	.driver_features	= DRIVER_BUS_PLATFORM | DRIVER_GEM,
++	.load			= vgem_load,
++	.unload			= vgem_unload,
++	.preclose		= vgem_preclose,
++	.lastclose		= vgem_lastclose,
++	.gem_init_object	= vgem_gem_init_object,
++	.gem_free_object	= vgem_gem_free_object,
++	.gem_vm_ops		= &vgem_gem_vm_ops,
++	.ioctls			= vgem_ioctls,
++	.fops			= &vgem_driver_fops,
++	.name	= DRIVER_NAME,
++	.desc	= DRIVER_DESC,
++	.date	= DRIVER_DATE,
++	.major	= DRIVER_MAJOR,
++	.minor	= DRIVER_MINOR,
++};
++
++static int vgem_platform_probe(struct platform_device *pdev)
++{
++	vgem_driver.num_ioctls = DRM_ARRAY_SIZE(vgem_ioctls);
++
++	return drm_platform_init(&vgem_driver, pdev);
++}
++
++static int vgem_platform_remove(struct platform_device *pdev)
++{
++	drm_platform_exit(&vgem_driver, pdev);
++
++	return 0;
++}
++
++static struct platform_driver vgem_platform_driver = {
++	.probe		= vgem_platform_probe,
++	.remove		= __devexit_p(vgem_platform_remove),
++	.driver		= {
++		.owner	= THIS_MODULE,
++		.name	= DRIVER_NAME,
++	},
++};
++
++static struct platform_device *vgem_device;
++
++static int __init vgem_init(void)
++{
++	int ret;
++
++	if ((ret = platform_driver_register(&vgem_platform_driver)))
++		return ret;
++
++	vgem_device = platform_device_alloc("vgem", -1);
++	if (!vgem_device) {
++		ret = -ENOMEM;
++		goto out;
++	}
++
++	ret = platform_device_add(vgem_device);
++	if (!ret)
++		return 0;
++
++out:
++	platform_device_put(vgem_device);
++	platform_driver_unregister(&vgem_platform_driver);
++
++	return ret;
++}
++
++static void __exit vgem_exit(void)
++{
++	platform_device_unregister(vgem_device);
++	platform_driver_unregister(&vgem_platform_driver);
++}
++
++module_init(vgem_init);
++module_exit(vgem_exit);
++
++MODULE_AUTHOR("Red Hat, Inc.");
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_LICENSE("GPL and additional rights");
+diff --git a/include/drm/vgem_drm.h b/include/drm/vgem_drm.h
+new file mode 100644
+index 0000000..df83503
+--- /dev/null
++++ b/include/drm/vgem_drm.h
+@@ -0,0 +1,62 @@
++/*
++ * Copyright 2011 Red Hat, Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software")
++ * to deal in the software without restriction, including without limitation
++ * on the rights to use, copy, modify, merge, publish, distribute, sub
++ * license, and/or sell copies of the Software, and to permit persons to whom
++ * them Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTIBILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER
++ * IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef VGEM_DRM_H
++#define VGEM_DRM_H
++
++/* Bare API largely ripped off from exynos driver */
++
++struct vgem_gem_create {
++	unsigned int size;
++	unsigned int flags;
++	unsigned int handle;
++};
++
++struct vgem_gem_mmap {
++	unsigned int handle;
++	unsigned int size;
++	uint64_t mapped;
++};
++
++struct vgem_gem_getparam {
++#define VGEM_PARAM_IS_VGEM 1
++	unsigned int param;
++	unsigned int *value;
++};
++
++#define DRM_VGEM_GEM_CREATE	0x00
++#define DRM_VGEM_GEM_MMAP	0x01
++#define DRM_VGEM_GEM_GETPARAM	0x02
++
++#define DRM_IOCTL_VGEM_GEM_CREATE \
++		DRM_IOWR(DRM_COMMAND_BASE + DRM_VGEM_GEM_CREATE, \
++			 struct vgem_gem_create)
++
++#define DRM_IOCTL_VGEM_GEM_MMAP \
++		DRM_IOWR(DRM_COMMAND_BASE + DRM_VGEM_GEM_MMAP, \
++			 struct vgem_gem_mmap)
++
++#define DRM_IOCTL_VGEM_GEM_GETPARAM \
++		DRM_IOWR(DRM_COMMAND_BASE + DRM_VGEM_GEM_GETPARAM, \
++			 struct vgem_gem_getparam)
++
++#endif
diff --git a/kernel.spec b/kernel.spec
index 87ca4f2..62afc75 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -698,6 +698,7 @@ Patch1556: linux-3.3-virtio-scsi.patch
 
 # DRM
 #atch1700: drm-edid-try-harder-to-fix-up-broken-headers.patch
+Patch1800: drm-vgem.patch
 
 # nouveau + drm fixes
 # intel drm is all merged upstream
@@ -1416,6 +1417,7 @@ ApplyPatch fix_xen_guest_on_old_EC2.patch
 
 # DRM core
 #ApplyPatch drm-edid-try-harder-to-fix-up-broken-headers.patch
+ApplyPatch drm-vgem.patch
 
 # Nouveau DRM
 
@@ -2347,6 +2349,9 @@ fi
 #                 ||----w |
 #                 ||     ||
 %changelog
+* Wed Feb 15 2012 Adam Jackson <ajax at redhat.com>
+- Add patch and config change for vgem.ko
+
 * Tue Feb 14 2012 Josh Boyer <jwboyer at redhat.com>
 - Add patch to fix RCU usage during cpu idle (rhbz 789641)
 - Add patch to fix mce rcu splat (rhbz 789644)


More information about the scm-commits mailing list