vfio_mdev.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  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. #include <linux/init.h>
  13. #include <linux/module.h>
  14. #include <linux/device.h>
  15. #include <linux/kernel.h>
  16. #include <linux/slab.h>
  17. #include <linux/vfio.h>
  18. #include <linux/mdev.h>
  19. #include "mdev_private.h"
  20. #define DRIVER_VERSION "0.1"
  21. #define DRIVER_AUTHOR "NVIDIA Corporation"
  22. #define DRIVER_DESC "VFIO based driver for Mediated device"
  23. static int vfio_mdev_open(void *device_data)
  24. {
  25. struct mdev_device *mdev = device_data;
  26. struct mdev_parent *parent = mdev->parent;
  27. int ret;
  28. if (unlikely(!parent->ops->open))
  29. return -EINVAL;
  30. if (!try_module_get(THIS_MODULE))
  31. return -ENODEV;
  32. ret = parent->ops->open(mdev);
  33. if (ret)
  34. module_put(THIS_MODULE);
  35. return ret;
  36. }
  37. static void vfio_mdev_release(void *device_data)
  38. {
  39. struct mdev_device *mdev = device_data;
  40. struct mdev_parent *parent = mdev->parent;
  41. if (likely(parent->ops->release))
  42. parent->ops->release(mdev);
  43. module_put(THIS_MODULE);
  44. }
  45. static long vfio_mdev_unlocked_ioctl(void *device_data,
  46. unsigned int cmd, unsigned long arg)
  47. {
  48. struct mdev_device *mdev = device_data;
  49. struct mdev_parent *parent = mdev->parent;
  50. if (unlikely(!parent->ops->ioctl))
  51. return -EINVAL;
  52. return parent->ops->ioctl(mdev, cmd, arg);
  53. }
  54. static ssize_t vfio_mdev_read(void *device_data, char __user *buf,
  55. size_t count, loff_t *ppos)
  56. {
  57. struct mdev_device *mdev = device_data;
  58. struct mdev_parent *parent = mdev->parent;
  59. if (unlikely(!parent->ops->read))
  60. return -EINVAL;
  61. return parent->ops->read(mdev, buf, count, ppos);
  62. }
  63. static ssize_t vfio_mdev_write(void *device_data, const char __user *buf,
  64. size_t count, loff_t *ppos)
  65. {
  66. struct mdev_device *mdev = device_data;
  67. struct mdev_parent *parent = mdev->parent;
  68. if (unlikely(!parent->ops->write))
  69. return -EINVAL;
  70. return parent->ops->write(mdev, buf, count, ppos);
  71. }
  72. static int vfio_mdev_mmap(void *device_data, struct vm_area_struct *vma)
  73. {
  74. struct mdev_device *mdev = device_data;
  75. struct mdev_parent *parent = mdev->parent;
  76. if (unlikely(!parent->ops->mmap))
  77. return -EINVAL;
  78. return parent->ops->mmap(mdev, vma);
  79. }
  80. static const struct vfio_device_ops vfio_mdev_dev_ops = {
  81. .name = "vfio-mdev",
  82. .open = vfio_mdev_open,
  83. .release = vfio_mdev_release,
  84. .ioctl = vfio_mdev_unlocked_ioctl,
  85. .read = vfio_mdev_read,
  86. .write = vfio_mdev_write,
  87. .mmap = vfio_mdev_mmap,
  88. };
  89. int vfio_mdev_probe(struct device *dev)
  90. {
  91. struct mdev_device *mdev = to_mdev_device(dev);
  92. return vfio_add_group_dev(dev, &vfio_mdev_dev_ops, mdev);
  93. }
  94. void vfio_mdev_remove(struct device *dev)
  95. {
  96. vfio_del_group_dev(dev);
  97. }
  98. struct mdev_driver vfio_mdev_driver = {
  99. .name = "vfio_mdev",
  100. .probe = vfio_mdev_probe,
  101. .remove = vfio_mdev_remove,
  102. };
  103. static int __init vfio_mdev_init(void)
  104. {
  105. return mdev_register_driver(&vfio_mdev_driver, THIS_MODULE);
  106. }
  107. static void __exit vfio_mdev_exit(void)
  108. {
  109. mdev_unregister_driver(&vfio_mdev_driver);
  110. }
  111. module_init(vfio_mdev_init)
  112. module_exit(vfio_mdev_exit)
  113. MODULE_VERSION(DRIVER_VERSION);
  114. MODULE_LICENSE("GPL v2");
  115. MODULE_AUTHOR(DRIVER_AUTHOR);
  116. MODULE_DESCRIPTION(DRIVER_DESC);