• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
vfio_mdev_open(void * device_data)24 static 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 
vfio_mdev_release(void * device_data)43 static 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 
vfio_mdev_unlocked_ioctl(void * device_data,unsigned int cmd,unsigned long arg)54 static 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 
vfio_mdev_read(void * device_data,char __user * buf,size_t count,loff_t * ppos)66 static 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 
vfio_mdev_write(void * device_data,const char __user * buf,size_t count,loff_t * ppos)78 static 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 
vfio_mdev_mmap(void * device_data,struct vm_area_struct * vma)90 static 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 
101 static const struct vfio_device_ops vfio_mdev_dev_ops = {
102 	.name		= "vfio-mdev",
103 	.open		= vfio_mdev_open,
104 	.release	= vfio_mdev_release,
105 	.ioctl		= vfio_mdev_unlocked_ioctl,
106 	.read		= vfio_mdev_read,
107 	.write		= vfio_mdev_write,
108 	.mmap		= vfio_mdev_mmap,
109 };
110 
vfio_mdev_probe(struct device * dev)111 static int vfio_mdev_probe(struct device *dev)
112 {
113 	struct mdev_device *mdev = to_mdev_device(dev);
114 
115 	return vfio_add_group_dev(dev, &vfio_mdev_dev_ops, mdev);
116 }
117 
vfio_mdev_remove(struct device * dev)118 static void vfio_mdev_remove(struct device *dev)
119 {
120 	vfio_del_group_dev(dev);
121 }
122 
123 static struct mdev_driver vfio_mdev_driver = {
124 	.name	= "vfio_mdev",
125 	.probe	= vfio_mdev_probe,
126 	.remove	= vfio_mdev_remove,
127 };
128 
vfio_mdev_init(void)129 static int __init vfio_mdev_init(void)
130 {
131 	return mdev_register_driver(&vfio_mdev_driver, THIS_MODULE);
132 }
133 
vfio_mdev_exit(void)134 static void __exit vfio_mdev_exit(void)
135 {
136 	mdev_unregister_driver(&vfio_mdev_driver);
137 }
138 
139 module_init(vfio_mdev_init)
140 module_exit(vfio_mdev_exit)
141 
142 MODULE_VERSION(DRIVER_VERSION);
143 MODULE_LICENSE("GPL v2");
144 MODULE_AUTHOR(DRIVER_AUTHOR);
145 MODULE_DESCRIPTION(DRIVER_DESC);
146