cc9507ed85a1812514e3e7d2cdd32c3e801402da
[linux-2.6-microblaze.git] / drivers / vfio / mdev / vfio_mdev.c
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
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->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
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->parent;
48
49         if (likely(parent->ops->release))
50                 parent->ops->release(mdev);
51
52         module_put(THIS_MODULE);
53 }
54
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->parent;
60
61         if (unlikely(!parent->ops->ioctl))
62                 return -EINVAL;
63
64         return parent->ops->ioctl(mdev, cmd, arg);
65 }
66
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->parent;
72
73         if (unlikely(!parent->ops->read))
74                 return -EINVAL;
75
76         return parent->ops->read(mdev, buf, count, ppos);
77 }
78
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->parent;
85
86         if (unlikely(!parent->ops->write))
87                 return -EINVAL;
88
89         return parent->ops->write(mdev, buf, count, ppos);
90 }
91
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->parent;
97
98         if (unlikely(!parent->ops->mmap))
99                 return -EINVAL;
100
101         return parent->ops->mmap(mdev, vma);
102 }
103
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->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
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
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
164 static int __init vfio_mdev_init(void)
165 {
166         return mdev_register_driver(&vfio_mdev_driver);
167 }
168
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);