linux/drivers/vfio/mdev/vfio_mdev.c
<<
>>
Prefs
   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 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
 111static 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
 118static void vfio_mdev_remove(struct device *dev)
 119{
 120        vfio_del_group_dev(dev);
 121}
 122
 123static struct mdev_driver vfio_mdev_driver = {
 124        .name   = "vfio_mdev",
 125        .probe  = vfio_mdev_probe,
 126        .remove = vfio_mdev_remove,
 127};
 128
 129static int __init vfio_mdev_init(void)
 130{
 131        return mdev_register_driver(&vfio_mdev_driver, THIS_MODULE);
 132}
 133
 134static void __exit vfio_mdev_exit(void)
 135{
 136        mdev_unregister_driver(&vfio_mdev_driver);
 137}
 138
 139module_init(vfio_mdev_init)
 140module_exit(vfio_mdev_exit)
 141
 142MODULE_VERSION(DRIVER_VERSION);
 143MODULE_LICENSE("GPL v2");
 144MODULE_AUTHOR(DRIVER_AUTHOR);
 145MODULE_DESCRIPTION(DRIVER_DESC);
 146