at v5.2-rc2 148 lines 3.5 kB view raw
1/* 2 * VFIO based driver for Mediated device 3 * 4 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 5 * Author: Neo Jia <cjia@nvidia.com> 6 * Kirti Wankhede <kwankhede@nvidia.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13#include <linux/init.h> 14#include <linux/module.h> 15#include <linux/device.h> 16#include <linux/kernel.h> 17#include <linux/slab.h> 18#include <linux/vfio.h> 19#include <linux/mdev.h> 20 21#include "mdev_private.h" 22 23#define DRIVER_VERSION "0.1" 24#define DRIVER_AUTHOR "NVIDIA Corporation" 25#define DRIVER_DESC "VFIO based driver for Mediated device" 26 27static int vfio_mdev_open(void *device_data) 28{ 29 struct mdev_device *mdev = device_data; 30 struct mdev_parent *parent = mdev->parent; 31 int ret; 32 33 if (unlikely(!parent->ops->open)) 34 return -EINVAL; 35 36 if (!try_module_get(THIS_MODULE)) 37 return -ENODEV; 38 39 ret = parent->ops->open(mdev); 40 if (ret) 41 module_put(THIS_MODULE); 42 43 return ret; 44} 45 46static void vfio_mdev_release(void *device_data) 47{ 48 struct mdev_device *mdev = device_data; 49 struct mdev_parent *parent = mdev->parent; 50 51 if (likely(parent->ops->release)) 52 parent->ops->release(mdev); 53 54 module_put(THIS_MODULE); 55} 56 57static long vfio_mdev_unlocked_ioctl(void *device_data, 58 unsigned int cmd, unsigned long arg) 59{ 60 struct mdev_device *mdev = device_data; 61 struct mdev_parent *parent = mdev->parent; 62 63 if (unlikely(!parent->ops->ioctl)) 64 return -EINVAL; 65 66 return parent->ops->ioctl(mdev, cmd, arg); 67} 68 69static ssize_t vfio_mdev_read(void *device_data, char __user *buf, 70 size_t count, loff_t *ppos) 71{ 72 struct mdev_device *mdev = device_data; 73 struct mdev_parent *parent = mdev->parent; 74 75 if (unlikely(!parent->ops->read)) 76 return -EINVAL; 77 78 return parent->ops->read(mdev, buf, count, ppos); 79} 80 81static ssize_t vfio_mdev_write(void *device_data, const char __user *buf, 82 size_t count, loff_t *ppos) 83{ 84 struct mdev_device *mdev = device_data; 85 struct mdev_parent *parent = mdev->parent; 86 87 if (unlikely(!parent->ops->write)) 88 return -EINVAL; 89 90 return parent->ops->write(mdev, buf, count, ppos); 91} 92 93static int vfio_mdev_mmap(void *device_data, struct vm_area_struct *vma) 94{ 95 struct mdev_device *mdev = device_data; 96 struct mdev_parent *parent = mdev->parent; 97 98 if (unlikely(!parent->ops->mmap)) 99 return -EINVAL; 100 101 return parent->ops->mmap(mdev, vma); 102} 103 104static const struct vfio_device_ops vfio_mdev_dev_ops = { 105 .name = "vfio-mdev", 106 .open = vfio_mdev_open, 107 .release = vfio_mdev_release, 108 .ioctl = vfio_mdev_unlocked_ioctl, 109 .read = vfio_mdev_read, 110 .write = vfio_mdev_write, 111 .mmap = vfio_mdev_mmap, 112}; 113 114static int vfio_mdev_probe(struct device *dev) 115{ 116 struct mdev_device *mdev = to_mdev_device(dev); 117 118 return vfio_add_group_dev(dev, &vfio_mdev_dev_ops, mdev); 119} 120 121static void vfio_mdev_remove(struct device *dev) 122{ 123 vfio_del_group_dev(dev); 124} 125 126static struct mdev_driver vfio_mdev_driver = { 127 .name = "vfio_mdev", 128 .probe = vfio_mdev_probe, 129 .remove = vfio_mdev_remove, 130}; 131 132static int __init vfio_mdev_init(void) 133{ 134 return mdev_register_driver(&vfio_mdev_driver, THIS_MODULE); 135} 136 137static void __exit vfio_mdev_exit(void) 138{ 139 mdev_unregister_driver(&vfio_mdev_driver); 140} 141 142module_init(vfio_mdev_init) 143module_exit(vfio_mdev_exit) 144 145MODULE_VERSION(DRIVER_VERSION); 146MODULE_LICENSE("GPL v2"); 147MODULE_AUTHOR(DRIVER_AUTHOR); 148MODULE_DESCRIPTION(DRIVER_DESC);