Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2011 Red Hat, Inc.
0003  * Copyright © 2014 The Chromium OS Authors
0004  *
0005  * Permission is hereby granted, free of charge, to any person obtaining a
0006  * copy of this software and associated documentation files (the "Software")
0007  * to deal in the software without restriction, including without limitation
0008  * on the rights to use, copy, modify, merge, publish, distribute, sub
0009  * license, and/or sell copies of the Software, and to permit persons to whom
0010  * them Software is furnished to do so, subject to the following conditions:
0011  *
0012  * The above copyright notice and this permission notice (including the next
0013  * paragraph) shall be included in all copies or substantial portions of the
0014  * Software.
0015  *
0016  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0017  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTIBILITY,
0018  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
0019  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER
0020  * IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN
0021  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0022  *
0023  * Authors:
0024  *  Adam Jackson <ajax@redhat.com>
0025  *  Ben Widawsky <ben@bwidawsk.net>
0026  */
0027 
0028 /*
0029  * This is vgem, a (non-hardware-backed) GEM service.  This is used by Mesa's
0030  * software renderer and the X server for efficient buffer sharing.
0031  */
0032 
0033 #include <linux/dma-buf.h>
0034 #include <linux/module.h>
0035 #include <linux/platform_device.h>
0036 #include <linux/shmem_fs.h>
0037 #include <linux/vmalloc.h>
0038 
0039 #include <drm/drm_drv.h>
0040 #include <drm/drm_file.h>
0041 #include <drm/drm_gem_shmem_helper.h>
0042 #include <drm/drm_ioctl.h>
0043 #include <drm/drm_managed.h>
0044 #include <drm/drm_prime.h>
0045 
0046 #include "vgem_drv.h"
0047 
0048 #define DRIVER_NAME "vgem"
0049 #define DRIVER_DESC "Virtual GEM provider"
0050 #define DRIVER_DATE "20120112"
0051 #define DRIVER_MAJOR    1
0052 #define DRIVER_MINOR    0
0053 
0054 static struct vgem_device {
0055     struct drm_device drm;
0056     struct platform_device *platform;
0057 } *vgem_device;
0058 
0059 static int vgem_open(struct drm_device *dev, struct drm_file *file)
0060 {
0061     struct vgem_file *vfile;
0062     int ret;
0063 
0064     vfile = kzalloc(sizeof(*vfile), GFP_KERNEL);
0065     if (!vfile)
0066         return -ENOMEM;
0067 
0068     file->driver_priv = vfile;
0069 
0070     ret = vgem_fence_open(vfile);
0071     if (ret) {
0072         kfree(vfile);
0073         return ret;
0074     }
0075 
0076     return 0;
0077 }
0078 
0079 static void vgem_postclose(struct drm_device *dev, struct drm_file *file)
0080 {
0081     struct vgem_file *vfile = file->driver_priv;
0082 
0083     vgem_fence_close(vfile);
0084     kfree(vfile);
0085 }
0086 
0087 static struct drm_ioctl_desc vgem_ioctls[] = {
0088     DRM_IOCTL_DEF_DRV(VGEM_FENCE_ATTACH, vgem_fence_attach_ioctl, DRM_RENDER_ALLOW),
0089     DRM_IOCTL_DEF_DRV(VGEM_FENCE_SIGNAL, vgem_fence_signal_ioctl, DRM_RENDER_ALLOW),
0090 };
0091 
0092 DEFINE_DRM_GEM_FOPS(vgem_driver_fops);
0093 
0094 static struct drm_gem_object *vgem_gem_create_object(struct drm_device *dev, size_t size)
0095 {
0096     struct drm_gem_shmem_object *obj;
0097 
0098     obj = kzalloc(sizeof(*obj), GFP_KERNEL);
0099     if (!obj)
0100         return ERR_PTR(-ENOMEM);
0101 
0102     /*
0103      * vgem doesn't have any begin/end cpu access ioctls, therefore must use
0104      * coherent memory or dma-buf sharing just wont work.
0105      */
0106     obj->map_wc = true;
0107 
0108     return &obj->base;
0109 }
0110 
0111 static const struct drm_driver vgem_driver = {
0112     .driver_features        = DRIVER_GEM | DRIVER_RENDER,
0113     .open               = vgem_open,
0114     .postclose          = vgem_postclose,
0115     .ioctls             = vgem_ioctls,
0116     .num_ioctls             = ARRAY_SIZE(vgem_ioctls),
0117     .fops               = &vgem_driver_fops,
0118 
0119     DRM_GEM_SHMEM_DRIVER_OPS,
0120     .gem_create_object      = vgem_gem_create_object,
0121 
0122     .name   = DRIVER_NAME,
0123     .desc   = DRIVER_DESC,
0124     .date   = DRIVER_DATE,
0125     .major  = DRIVER_MAJOR,
0126     .minor  = DRIVER_MINOR,
0127 };
0128 
0129 static int __init vgem_init(void)
0130 {
0131     int ret;
0132     struct platform_device *pdev;
0133 
0134     pdev = platform_device_register_simple("vgem", -1, NULL, 0);
0135     if (IS_ERR(pdev))
0136         return PTR_ERR(pdev);
0137 
0138     if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) {
0139         ret = -ENOMEM;
0140         goto out_unregister;
0141     }
0142 
0143     dma_coerce_mask_and_coherent(&pdev->dev,
0144                      DMA_BIT_MASK(64));
0145 
0146     vgem_device = devm_drm_dev_alloc(&pdev->dev, &vgem_driver,
0147                      struct vgem_device, drm);
0148     if (IS_ERR(vgem_device)) {
0149         ret = PTR_ERR(vgem_device);
0150         goto out_devres;
0151     }
0152     vgem_device->platform = pdev;
0153 
0154     /* Final step: expose the device/driver to userspace */
0155     ret = drm_dev_register(&vgem_device->drm, 0);
0156     if (ret)
0157         goto out_devres;
0158 
0159     return 0;
0160 
0161 out_devres:
0162     devres_release_group(&pdev->dev, NULL);
0163 out_unregister:
0164     platform_device_unregister(pdev);
0165     return ret;
0166 }
0167 
0168 static void __exit vgem_exit(void)
0169 {
0170     struct platform_device *pdev = vgem_device->platform;
0171 
0172     drm_dev_unregister(&vgem_device->drm);
0173     devres_release_group(&pdev->dev, NULL);
0174     platform_device_unregister(pdev);
0175 }
0176 
0177 module_init(vgem_init);
0178 module_exit(vgem_exit);
0179 
0180 MODULE_AUTHOR("Red Hat, Inc.");
0181 MODULE_AUTHOR("Intel Corporation");
0182 MODULE_DESCRIPTION(DRIVER_DESC);
0183 MODULE_LICENSE("GPL and additional rights");