diff options
author | Kirti Wankhede <kwankhede@nvidia.com> | 2016-11-16 15:46:14 -0500 |
---|---|---|
committer | Alex Williamson <alex.williamson@redhat.com> | 2016-11-17 10:24:50 -0500 |
commit | fa3da00cb8c0d403030f4805ae615b444f0d2f3c (patch) | |
tree | b4235ea4d0bb2f48a3742d06727facda15cf4ca3 | |
parent | 7b96953bc640b6b25665fe17ffca4b668b371f14 (diff) |
vfio: VFIO based driver for Mediated devices
vfio_mdev driver registers with mdev core driver.
mdev core driver creates mediated device and calls probe routine of
vfio_mdev driver for each device.
Probe routine of vfio_mdev driver adds mediated device to VFIO core module
This driver forms a shim layer that pass through VFIO devices operations
to vendor driver for mediated devices.
Signed-off-by: Kirti Wankhede <kwankhede@nvidia.com>
Signed-off-by: Neo Jia <cjia@nvidia.com>
Reviewed-by: Jike Song <jike.song@intel.com>
Reviewed-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
-rw-r--r-- | drivers/vfio/mdev/Kconfig | 7 | ||||
-rw-r--r-- | drivers/vfio/mdev/Makefile | 1 | ||||
-rw-r--r-- | drivers/vfio/mdev/mdev_core.c | 13 | ||||
-rw-r--r-- | drivers/vfio/mdev/vfio_mdev.c | 148 |
4 files changed, 168 insertions, 1 deletions
diff --git a/drivers/vfio/mdev/Kconfig b/drivers/vfio/mdev/Kconfig index 258481d65ebd..424ddebee55d 100644 --- a/drivers/vfio/mdev/Kconfig +++ b/drivers/vfio/mdev/Kconfig | |||
@@ -7,3 +7,10 @@ config VFIO_MDEV | |||
7 | Provides a framework to virtualize devices. | 7 | Provides a framework to virtualize devices. |
8 | 8 | ||
9 | If you don't know what do here, say N. | 9 | If you don't know what do here, say N. |
10 | |||
11 | config VFIO_MDEV_DEVICE | ||
12 | tristate "VFIO driver for Mediated devices" | ||
13 | depends on VFIO && VFIO_MDEV | ||
14 | default n | ||
15 | help | ||
16 | VFIO based driver for Mediated devices. | ||
diff --git a/drivers/vfio/mdev/Makefile b/drivers/vfio/mdev/Makefile index 31bc04801d94..fa2d5ea466ee 100644 --- a/drivers/vfio/mdev/Makefile +++ b/drivers/vfio/mdev/Makefile | |||
@@ -2,3 +2,4 @@ | |||
2 | mdev-y := mdev_core.o mdev_sysfs.o mdev_driver.o | 2 | mdev-y := mdev_core.o mdev_sysfs.o mdev_driver.o |
3 | 3 | ||
4 | obj-$(CONFIG_VFIO_MDEV) += mdev.o | 4 | obj-$(CONFIG_VFIO_MDEV) += mdev.o |
5 | obj-$(CONFIG_VFIO_MDEV_DEVICE) += vfio_mdev.o | ||
diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c index 613e8a8a3b2a..be1ee89ee917 100644 --- a/drivers/vfio/mdev/mdev_core.c +++ b/drivers/vfio/mdev/mdev_core.c | |||
@@ -354,7 +354,18 @@ int mdev_device_remove(struct device *dev, bool force_remove) | |||
354 | 354 | ||
355 | static int __init mdev_init(void) | 355 | static int __init mdev_init(void) |
356 | { | 356 | { |
357 | return mdev_bus_register(); | 357 | int ret; |
358 | |||
359 | ret = mdev_bus_register(); | ||
360 | |||
361 | /* | ||
362 | * Attempt to load known vfio_mdev. This gives us a working environment | ||
363 | * without the user needing to explicitly load vfio_mdev driver. | ||
364 | */ | ||
365 | if (!ret) | ||
366 | request_module_nowait("vfio_mdev"); | ||
367 | |||
368 | return ret; | ||
358 | } | 369 | } |
359 | 370 | ||
360 | static void __exit mdev_exit(void) | 371 | static void __exit mdev_exit(void) |
diff --git a/drivers/vfio/mdev/vfio_mdev.c b/drivers/vfio/mdev/vfio_mdev.c new file mode 100644 index 000000000000..ffc36758cb84 --- /dev/null +++ b/drivers/vfio/mdev/vfio_mdev.c | |||
@@ -0,0 +1,148 @@ | |||
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 | |||
27 | static int vfio_mdev_open(void *device_data) | ||
28 | { | ||
29 | struct mdev_device *mdev = device_data; | ||
30 | struct parent_device *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 | |||
46 | static void vfio_mdev_release(void *device_data) | ||
47 | { | ||
48 | struct mdev_device *mdev = device_data; | ||
49 | struct parent_device *parent = mdev->parent; | ||
50 | |||
51 | if (likely(parent->ops->release)) | ||
52 | parent->ops->release(mdev); | ||
53 | |||
54 | module_put(THIS_MODULE); | ||
55 | } | ||
56 | |||
57 | static 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 parent_device *parent = mdev->parent; | ||
62 | |||
63 | if (unlikely(!parent->ops->ioctl)) | ||
64 | return -EINVAL; | ||
65 | |||
66 | return parent->ops->ioctl(mdev, cmd, arg); | ||
67 | } | ||
68 | |||
69 | static 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 parent_device *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 | |||
81 | static 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 parent_device *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 | |||
93 | static int vfio_mdev_mmap(void *device_data, struct vm_area_struct *vma) | ||
94 | { | ||
95 | struct mdev_device *mdev = device_data; | ||
96 | struct parent_device *parent = mdev->parent; | ||
97 | |||
98 | if (unlikely(!parent->ops->mmap)) | ||
99 | return -EINVAL; | ||
100 | |||
101 | return parent->ops->mmap(mdev, vma); | ||
102 | } | ||
103 | |||
104 | static 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 | |||
114 | 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 | |||
121 | void vfio_mdev_remove(struct device *dev) | ||
122 | { | ||
123 | vfio_del_group_dev(dev); | ||
124 | } | ||
125 | |||
126 | struct mdev_driver vfio_mdev_driver = { | ||
127 | .name = "vfio_mdev", | ||
128 | .probe = vfio_mdev_probe, | ||
129 | .remove = vfio_mdev_remove, | ||
130 | }; | ||
131 | |||
132 | static int __init vfio_mdev_init(void) | ||
133 | { | ||
134 | return mdev_register_driver(&vfio_mdev_driver, THIS_MODULE); | ||
135 | } | ||
136 | |||
137 | static void __exit vfio_mdev_exit(void) | ||
138 | { | ||
139 | mdev_unregister_driver(&vfio_mdev_driver); | ||
140 | } | ||
141 | |||
142 | module_init(vfio_mdev_init) | ||
143 | module_exit(vfio_mdev_exit) | ||
144 | |||
145 | MODULE_VERSION(DRIVER_VERSION); | ||
146 | MODULE_LICENSE("GPL v2"); | ||
147 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
148 | MODULE_DESCRIPTION(DRIVER_DESC); | ||