linux/drivers/gpu/drm/zocl/zocl_drv.c
<<
>>
Prefs
   1/*
   2 * A GEM style CMA backed memory manager for ZynQ based OpenCL accelerators.
   3 *
   4 * Copyright (C) 2016 Xilinx, Inc. All rights reserved.
   5 *
   6 * Authors:
   7 *    Sonal Santan <sonal.santan@xilinx.com>
   8 *    Umang Parekh <umang.parekh@xilinx.com>
   9 *
  10 * This software is licensed under the terms of the GNU General Public
  11 * License version 2, as published by the Free Software Foundation, and
  12 * may be copied, distributed, and modified under those terms.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 */
  19
  20#include <linux/dma-buf.h>
  21#include <linux/module.h>
  22#include <linux/ramfs.h>
  23#include <linux/shmem_fs.h>
  24#include "zocl_drv.h"
  25#include <drm/drmP.h>
  26#include <drm/drm_gem.h>
  27#include <linux/zocl_ioctl.h>
  28
  29#define ZOCL_DRIVER_NAME        "zocl"
  30#define ZOCL_DRIVER_DESC        "Zynq BO manager"
  31#define ZOCL_DRIVER_DATE        "20161024"
  32#define ZOCL_DRIVER_MAJOR       2016
  33#define ZOCL_DRIVER_MINOR       3
  34#define ZOCL_DRIVER_PATCHLEVEL  1
  35#define ZOCL_FILE_PAGE_OFFSET   0x00100000
  36
  37#ifndef VM_RESERVED
  38#define VM_RESERVED (VM_DONTEXPAND | VM_DONTDUMP)
  39#endif
  40
  41static const struct vm_operations_struct reg_physical_vm_ops = {
  42#ifdef CONFIG_HAVE_IOREMAP_PROT
  43        .access = generic_access_phys,
  44#endif
  45};
  46
  47static int zocl_drm_load(struct drm_device *drm, unsigned long flags)
  48{
  49        struct platform_device *pdev;
  50        struct resource *res;
  51        struct drm_zocl_dev *zdev;
  52        void __iomem *map;
  53
  54        pdev = to_platform_device(drm->dev);
  55        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  56        map = devm_ioremap_resource(&pdev->dev, res);
  57        if (IS_ERR(map)) {
  58                DRM_ERROR("Failed to map registers: %ld\n", PTR_ERR(map));
  59                return PTR_ERR(map);
  60        }
  61
  62        zdev = devm_kzalloc(drm->dev, sizeof(*zdev), GFP_KERNEL);
  63        if (!zdev)
  64                return -ENOMEM;
  65
  66        zdev->ddev = drm;
  67        drm->dev_private = zdev;
  68        zdev->regs = map;
  69        zdev->res_start = res->start;
  70        zdev->res_len = resource_size(res);
  71        platform_set_drvdata(pdev, zdev);
  72
  73        return 0;
  74}
  75
  76static int zocl_drm_unload(struct drm_device *drm)
  77{
  78        return 0;
  79}
  80
  81static void zocl_free_object(struct drm_gem_object *obj)
  82{
  83        struct drm_zocl_bo *zocl_obj = to_zocl_bo(obj);
  84
  85        DRM_INFO("Freeing BO\n");
  86        zocl_describe(zocl_obj);
  87        drm_gem_cma_free_object(obj);
  88}
  89
  90static int zocl_mmap(struct file *filp, struct vm_area_struct *vma)
  91{
  92        struct drm_file *priv = filp->private_data;
  93        struct drm_device *dev = priv->minor->dev;
  94        struct drm_zocl_dev *zdev = dev->dev_private;
  95        unsigned long vsize;
  96        int rc;
  97
  98        /* If the page offset is > than 4G, then let GEM handle that and do what
  99         * it thinks is best,we will only handle page offsets less than 4G.
 100         */
 101        if (likely(vma->vm_pgoff >= ZOCL_FILE_PAGE_OFFSET))
 102                return drm_gem_cma_mmap(filp, vma);
 103
 104        if (vma->vm_pgoff != 0)
 105                return -EINVAL;
 106
 107        vsize = vma->vm_end - vma->vm_start;
 108        if (vsize > zdev->res_len)
 109                return -EINVAL;
 110
 111        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 112        vma->vm_flags |= VM_IO;
 113        vma->vm_flags |= VM_RESERVED;
 114
 115        vma->vm_ops = &reg_physical_vm_ops;
 116        rc = io_remap_pfn_range(vma, vma->vm_start,
 117                                zdev->res_start >> PAGE_SHIFT,
 118                                vsize, vma->vm_page_prot);
 119
 120        return rc;
 121}
 122
 123static const struct drm_ioctl_desc zocl_ioctls[] = {
 124        DRM_IOCTL_DEF_DRV(ZOCL_CREATE_BO, zocl_create_bo_ioctl,
 125                          DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
 126        DRM_IOCTL_DEF_DRV(ZOCL_MAP_BO, zocl_map_bo_ioctl,
 127                          DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
 128        DRM_IOCTL_DEF_DRV(ZOCL_SYNC_BO, zocl_sync_bo_ioctl,
 129                          DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
 130        DRM_IOCTL_DEF_DRV(ZOCL_INFO_BO, zocl_info_bo_ioctl,
 131                          DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
 132        DRM_IOCTL_DEF_DRV(ZOCL_PWRITE_BO, zocl_pwrite_bo_ioctl,
 133                          DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
 134        DRM_IOCTL_DEF_DRV(ZOCL_PREAD_BO, zocl_pread_bo_ioctl,
 135                          DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
 136};
 137
 138static const struct file_operations zocl_driver_fops = {
 139        .owner          = THIS_MODULE,
 140        .open           = drm_open,
 141        .mmap           = zocl_mmap,
 142        .poll           = drm_poll,
 143        .read           = drm_read,
 144        .unlocked_ioctl = drm_ioctl,
 145        .release        = drm_release,
 146};
 147
 148static struct drm_driver zocl_driver = {
 149        .driver_features                = DRIVER_GEM | DRIVER_PRIME |
 150                                          DRIVER_RENDER,
 151        .load                           = zocl_drm_load,
 152        .unload                         = zocl_drm_unload,
 153        .gem_free_object                = zocl_free_object,
 154        .gem_vm_ops                     = &drm_gem_cma_vm_ops,
 155        .prime_handle_to_fd             = drm_gem_prime_handle_to_fd,
 156        .prime_fd_to_handle             = drm_gem_prime_fd_to_handle,
 157        .gem_prime_import               = drm_gem_prime_import,
 158        .gem_prime_export               = drm_gem_prime_export,
 159        .gem_prime_get_sg_table         = drm_gem_cma_prime_get_sg_table,
 160        .gem_prime_import_sg_table      = drm_gem_cma_prime_import_sg_table,
 161        .gem_prime_vmap                 = drm_gem_cma_prime_vmap,
 162        .gem_prime_vunmap               = drm_gem_cma_prime_vunmap,
 163        .gem_prime_mmap                 = drm_gem_cma_prime_mmap,
 164        .ioctls                         = zocl_ioctls,
 165        .num_ioctls                     = ARRAY_SIZE(zocl_ioctls),
 166        .fops                           = &zocl_driver_fops,
 167        .name                           = ZOCL_DRIVER_NAME,
 168        .desc                           = ZOCL_DRIVER_DESC,
 169        .date                           = ZOCL_DRIVER_DATE,
 170        .major                          = ZOCL_DRIVER_MAJOR,
 171        .minor                          = ZOCL_DRIVER_MINOR,
 172        .patchlevel                     = ZOCL_DRIVER_PATCHLEVEL,
 173};
 174
 175/* init xilinx opencl drm platform */
 176static int zocl_drm_platform_probe(struct platform_device *pdev)
 177{
 178        return drm_platform_init(&zocl_driver, pdev);
 179}
 180
 181/* exit xilinx opencl drm platform */
 182static int zocl_drm_platform_remove(struct platform_device *pdev)
 183{
 184        struct drm_zocl_dev *zdev = platform_get_drvdata(pdev);
 185
 186        if (zdev->ddev) {
 187                drm_dev_unregister(zdev->ddev);
 188                drm_dev_unref(zdev->ddev);
 189        }
 190
 191        return 0;
 192}
 193
 194static const struct of_device_id zocl_drm_of_match[] = {
 195        { .compatible = "xlnx,zocl", },
 196        { /* end of table */ },
 197};
 198MODULE_DEVICE_TABLE(of, zocl_drm_of_match);
 199
 200static struct platform_driver zocl_drm_private_driver = {
 201        .probe                  = zocl_drm_platform_probe,
 202        .remove                 = zocl_drm_platform_remove,
 203        .driver                 = {
 204                .name           = "zocl-drm",
 205                .of_match_table = zocl_drm_of_match,
 206        },
 207};
 208
 209module_platform_driver(zocl_drm_private_driver);
 210
 211MODULE_VERSION(__stringify(ZOCL_DRIVER_MAJOR) "."
 212                __stringify(ZOCL_DRIVER_MINOR) "."
 213                __stringify(ZOCL_DRIVER_PATCHLEVEL));
 214
 215MODULE_DESCRIPTION(ZOCL_DRIVER_DESC);
 216MODULE_AUTHOR("Sonal Santan <sonal.santan@xilinx.com>");
 217MODULE_LICENSE("GPL");
 218