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(struct vfio_device * core_vdev)24 static int vfio_mdev_open(struct vfio_device *core_vdev)
25 {
26 struct mdev_device *mdev = to_mdev_device(core_vdev->dev);
27 struct mdev_parent *parent = mdev->type->parent;
28
29 int ret;
30
31 if (unlikely(!parent->ops->open))
32 return -EINVAL;
33
34 if (!try_module_get(THIS_MODULE))
35 return -ENODEV;
36
37 ret = parent->ops->open(mdev);
38 if (ret)
39 module_put(THIS_MODULE);
40
41 return ret;
42 }
43
vfio_mdev_release(struct vfio_device * core_vdev)44 static void vfio_mdev_release(struct vfio_device *core_vdev)
45 {
46 struct mdev_device *mdev = to_mdev_device(core_vdev->dev);
47 struct mdev_parent *parent = mdev->type->parent;
48
49 if (likely(parent->ops->release))
50 parent->ops->release(mdev);
51
52 module_put(THIS_MODULE);
53 }
54
vfio_mdev_unlocked_ioctl(struct vfio_device * core_vdev,unsigned int cmd,unsigned long arg)55 static long vfio_mdev_unlocked_ioctl(struct vfio_device *core_vdev,
56 unsigned int cmd, unsigned long arg)
57 {
58 struct mdev_device *mdev = to_mdev_device(core_vdev->dev);
59 struct mdev_parent *parent = mdev->type->parent;
60
61 if (unlikely(!parent->ops->ioctl))
62 return -EINVAL;
63
64 return parent->ops->ioctl(mdev, cmd, arg);
65 }
66
vfio_mdev_read(struct vfio_device * core_vdev,char __user * buf,size_t count,loff_t * ppos)67 static ssize_t vfio_mdev_read(struct vfio_device *core_vdev, char __user *buf,
68 size_t count, loff_t *ppos)
69 {
70 struct mdev_device *mdev = to_mdev_device(core_vdev->dev);
71 struct mdev_parent *parent = mdev->type->parent;
72
73 if (unlikely(!parent->ops->read))
74 return -EINVAL;
75
76 return parent->ops->read(mdev, buf, count, ppos);
77 }
78
vfio_mdev_write(struct vfio_device * core_vdev,const char __user * buf,size_t count,loff_t * ppos)79 static ssize_t vfio_mdev_write(struct vfio_device *core_vdev,
80 const char __user *buf, size_t count,
81 loff_t *ppos)
82 {
83 struct mdev_device *mdev = to_mdev_device(core_vdev->dev);
84 struct mdev_parent *parent = mdev->type->parent;
85
86 if (unlikely(!parent->ops->write))
87 return -EINVAL;
88
89 return parent->ops->write(mdev, buf, count, ppos);
90 }
91
vfio_mdev_mmap(struct vfio_device * core_vdev,struct vm_area_struct * vma)92 static int vfio_mdev_mmap(struct vfio_device *core_vdev,
93 struct vm_area_struct *vma)
94 {
95 struct mdev_device *mdev = to_mdev_device(core_vdev->dev);
96 struct mdev_parent *parent = mdev->type->parent;
97
98 if (unlikely(!parent->ops->mmap))
99 return -EINVAL;
100
101 return parent->ops->mmap(mdev, vma);
102 }
103
vfio_mdev_request(struct vfio_device * core_vdev,unsigned int count)104 static void vfio_mdev_request(struct vfio_device *core_vdev, unsigned int count)
105 {
106 struct mdev_device *mdev = to_mdev_device(core_vdev->dev);
107 struct mdev_parent *parent = mdev->type->parent;
108
109 if (parent->ops->request)
110 parent->ops->request(mdev, count);
111 else if (count == 0)
112 dev_notice(mdev_dev(mdev),
113 "No mdev vendor driver request callback support, blocked until released by user\n");
114 }
115
116 static const struct vfio_device_ops vfio_mdev_dev_ops = {
117 .name = "vfio-mdev",
118 .open = vfio_mdev_open,
119 .release = vfio_mdev_release,
120 .ioctl = vfio_mdev_unlocked_ioctl,
121 .read = vfio_mdev_read,
122 .write = vfio_mdev_write,
123 .mmap = vfio_mdev_mmap,
124 .request = vfio_mdev_request,
125 };
126
vfio_mdev_probe(struct mdev_device * mdev)127 static int vfio_mdev_probe(struct mdev_device *mdev)
128 {
129 struct vfio_device *vdev;
130 int ret;
131
132 vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
133 if (!vdev)
134 return -ENOMEM;
135
136 vfio_init_group_dev(vdev, &mdev->dev, &vfio_mdev_dev_ops);
137 ret = vfio_register_group_dev(vdev);
138 if (ret) {
139 kfree(vdev);
140 return ret;
141 }
142 dev_set_drvdata(&mdev->dev, vdev);
143 return 0;
144 }
145
vfio_mdev_remove(struct mdev_device * mdev)146 static void vfio_mdev_remove(struct mdev_device *mdev)
147 {
148 struct vfio_device *vdev = dev_get_drvdata(&mdev->dev);
149
150 vfio_unregister_group_dev(vdev);
151 kfree(vdev);
152 }
153
154 static struct mdev_driver vfio_mdev_driver = {
155 .driver = {
156 .name = "vfio_mdev",
157 .owner = THIS_MODULE,
158 .mod_name = KBUILD_MODNAME,
159 },
160 .probe = vfio_mdev_probe,
161 .remove = vfio_mdev_remove,
162 };
163
vfio_mdev_init(void)164 static int __init vfio_mdev_init(void)
165 {
166 return mdev_register_driver(&vfio_mdev_driver);
167 }
168
vfio_mdev_exit(void)169 static void __exit vfio_mdev_exit(void)
170 {
171 mdev_unregister_driver(&vfio_mdev_driver);
172 }
173
174 module_init(vfio_mdev_init)
175 module_exit(vfio_mdev_exit)
176
177 MODULE_VERSION(DRIVER_VERSION);
178 MODULE_LICENSE("GPL v2");
179 MODULE_AUTHOR(DRIVER_AUTHOR);
180 MODULE_DESCRIPTION(DRIVER_DESC);
181