0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
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
0104
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
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");