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