mdev_core.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. /*
  2. * Mediated device Core Driver
  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/module.h>
  13. #include <linux/device.h>
  14. #include <linux/slab.h>
  15. #include <linux/uuid.h>
  16. #include <linux/sysfs.h>
  17. #include <linux/mdev.h>
  18. #include "mdev_private.h"
  19. #define DRIVER_VERSION "0.1"
  20. #define DRIVER_AUTHOR "NVIDIA Corporation"
  21. #define DRIVER_DESC "Mediated device Core Driver"
  22. static LIST_HEAD(parent_list);
  23. static DEFINE_MUTEX(parent_list_lock);
  24. static struct class_compat *mdev_bus_compat_class;
  25. static LIST_HEAD(mdev_list);
  26. static DEFINE_MUTEX(mdev_list_lock);
  27. struct device *mdev_parent_dev(struct mdev_device *mdev)
  28. {
  29. return mdev->parent->dev;
  30. }
  31. EXPORT_SYMBOL(mdev_parent_dev);
  32. void *mdev_get_drvdata(struct mdev_device *mdev)
  33. {
  34. return mdev->driver_data;
  35. }
  36. EXPORT_SYMBOL(mdev_get_drvdata);
  37. void mdev_set_drvdata(struct mdev_device *mdev, void *data)
  38. {
  39. mdev->driver_data = data;
  40. }
  41. EXPORT_SYMBOL(mdev_set_drvdata);
  42. struct device *mdev_dev(struct mdev_device *mdev)
  43. {
  44. return &mdev->dev;
  45. }
  46. EXPORT_SYMBOL(mdev_dev);
  47. struct mdev_device *mdev_from_dev(struct device *dev)
  48. {
  49. return dev_is_mdev(dev) ? to_mdev_device(dev) : NULL;
  50. }
  51. EXPORT_SYMBOL(mdev_from_dev);
  52. uuid_le mdev_uuid(struct mdev_device *mdev)
  53. {
  54. return mdev->uuid;
  55. }
  56. EXPORT_SYMBOL(mdev_uuid);
  57. /* Should be called holding parent_list_lock */
  58. static struct mdev_parent *__find_parent_device(struct device *dev)
  59. {
  60. struct mdev_parent *parent;
  61. list_for_each_entry(parent, &parent_list, next) {
  62. if (parent->dev == dev)
  63. return parent;
  64. }
  65. return NULL;
  66. }
  67. static void mdev_release_parent(struct kref *kref)
  68. {
  69. struct mdev_parent *parent = container_of(kref, struct mdev_parent,
  70. ref);
  71. struct device *dev = parent->dev;
  72. kfree(parent);
  73. put_device(dev);
  74. }
  75. static
  76. inline struct mdev_parent *mdev_get_parent(struct mdev_parent *parent)
  77. {
  78. if (parent)
  79. kref_get(&parent->ref);
  80. return parent;
  81. }
  82. static inline void mdev_put_parent(struct mdev_parent *parent)
  83. {
  84. if (parent)
  85. kref_put(&parent->ref, mdev_release_parent);
  86. }
  87. static int mdev_device_create_ops(struct kobject *kobj,
  88. struct mdev_device *mdev)
  89. {
  90. struct mdev_parent *parent = mdev->parent;
  91. int ret;
  92. ret = parent->ops->create(kobj, mdev);
  93. if (ret)
  94. return ret;
  95. ret = sysfs_create_groups(&mdev->dev.kobj,
  96. parent->ops->mdev_attr_groups);
  97. if (ret)
  98. parent->ops->remove(mdev);
  99. return ret;
  100. }
  101. /*
  102. * mdev_device_remove_ops gets called from sysfs's 'remove' and when parent
  103. * device is being unregistered from mdev device framework.
  104. * - 'force_remove' is set to 'false' when called from sysfs's 'remove' which
  105. * indicates that if the mdev device is active, used by VMM or userspace
  106. * application, vendor driver could return error then don't remove the device.
  107. * - 'force_remove' is set to 'true' when called from mdev_unregister_device()
  108. * which indicate that parent device is being removed from mdev device
  109. * framework so remove mdev device forcefully.
  110. */
  111. static int mdev_device_remove_ops(struct mdev_device *mdev, bool force_remove)
  112. {
  113. struct mdev_parent *parent = mdev->parent;
  114. int ret;
  115. /*
  116. * Vendor driver can return error if VMM or userspace application is
  117. * using this mdev device.
  118. */
  119. ret = parent->ops->remove(mdev);
  120. if (ret && !force_remove)
  121. return -EBUSY;
  122. sysfs_remove_groups(&mdev->dev.kobj, parent->ops->mdev_attr_groups);
  123. return 0;
  124. }
  125. static int mdev_device_remove_cb(struct device *dev, void *data)
  126. {
  127. if (dev_is_mdev(dev))
  128. mdev_device_remove(dev, true);
  129. return 0;
  130. }
  131. /*
  132. * mdev_register_device : Register a device
  133. * @dev: device structure representing parent device.
  134. * @ops: Parent device operation structure to be registered.
  135. *
  136. * Add device to list of registered parent devices.
  137. * Returns a negative value on error, otherwise 0.
  138. */
  139. int mdev_register_device(struct device *dev, const struct mdev_parent_ops *ops)
  140. {
  141. int ret;
  142. struct mdev_parent *parent;
  143. /* check for mandatory ops */
  144. if (!ops || !ops->create || !ops->remove || !ops->supported_type_groups)
  145. return -EINVAL;
  146. dev = get_device(dev);
  147. if (!dev)
  148. return -EINVAL;
  149. mutex_lock(&parent_list_lock);
  150. /* Check for duplicate */
  151. parent = __find_parent_device(dev);
  152. if (parent) {
  153. parent = NULL;
  154. ret = -EEXIST;
  155. goto add_dev_err;
  156. }
  157. parent = kzalloc(sizeof(*parent), GFP_KERNEL);
  158. if (!parent) {
  159. ret = -ENOMEM;
  160. goto add_dev_err;
  161. }
  162. kref_init(&parent->ref);
  163. parent->dev = dev;
  164. parent->ops = ops;
  165. if (!mdev_bus_compat_class) {
  166. mdev_bus_compat_class = class_compat_register("mdev_bus");
  167. if (!mdev_bus_compat_class) {
  168. ret = -ENOMEM;
  169. goto add_dev_err;
  170. }
  171. }
  172. ret = parent_create_sysfs_files(parent);
  173. if (ret)
  174. goto add_dev_err;
  175. ret = class_compat_create_link(mdev_bus_compat_class, dev, NULL);
  176. if (ret)
  177. dev_warn(dev, "Failed to create compatibility class link\n");
  178. list_add(&parent->next, &parent_list);
  179. mutex_unlock(&parent_list_lock);
  180. dev_info(dev, "MDEV: Registered\n");
  181. return 0;
  182. add_dev_err:
  183. mutex_unlock(&parent_list_lock);
  184. if (parent)
  185. mdev_put_parent(parent);
  186. else
  187. put_device(dev);
  188. return ret;
  189. }
  190. EXPORT_SYMBOL(mdev_register_device);
  191. /*
  192. * mdev_unregister_device : Unregister a parent device
  193. * @dev: device structure representing parent device.
  194. *
  195. * Remove device from list of registered parent devices. Give a chance to free
  196. * existing mediated devices for given device.
  197. */
  198. void mdev_unregister_device(struct device *dev)
  199. {
  200. struct mdev_parent *parent;
  201. mutex_lock(&parent_list_lock);
  202. parent = __find_parent_device(dev);
  203. if (!parent) {
  204. mutex_unlock(&parent_list_lock);
  205. return;
  206. }
  207. dev_info(dev, "MDEV: Unregistering\n");
  208. list_del(&parent->next);
  209. class_compat_remove_link(mdev_bus_compat_class, dev, NULL);
  210. device_for_each_child(dev, NULL, mdev_device_remove_cb);
  211. parent_remove_sysfs_files(parent);
  212. mutex_unlock(&parent_list_lock);
  213. mdev_put_parent(parent);
  214. }
  215. EXPORT_SYMBOL(mdev_unregister_device);
  216. static void mdev_device_release(struct device *dev)
  217. {
  218. struct mdev_device *mdev = to_mdev_device(dev);
  219. mutex_lock(&mdev_list_lock);
  220. list_del(&mdev->next);
  221. mutex_unlock(&mdev_list_lock);
  222. dev_dbg(&mdev->dev, "MDEV: destroying\n");
  223. kfree(mdev);
  224. }
  225. int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid)
  226. {
  227. int ret;
  228. struct mdev_device *mdev, *tmp;
  229. struct mdev_parent *parent;
  230. struct mdev_type *type = to_mdev_type(kobj);
  231. parent = mdev_get_parent(type->parent);
  232. if (!parent)
  233. return -EINVAL;
  234. mutex_lock(&mdev_list_lock);
  235. /* Check for duplicate */
  236. list_for_each_entry(tmp, &mdev_list, next) {
  237. if (!uuid_le_cmp(tmp->uuid, uuid)) {
  238. mutex_unlock(&mdev_list_lock);
  239. ret = -EEXIST;
  240. goto mdev_fail;
  241. }
  242. }
  243. mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
  244. if (!mdev) {
  245. mutex_unlock(&mdev_list_lock);
  246. ret = -ENOMEM;
  247. goto mdev_fail;
  248. }
  249. memcpy(&mdev->uuid, &uuid, sizeof(uuid_le));
  250. list_add(&mdev->next, &mdev_list);
  251. mutex_unlock(&mdev_list_lock);
  252. mdev->parent = parent;
  253. kref_init(&mdev->ref);
  254. mdev->dev.parent = dev;
  255. mdev->dev.bus = &mdev_bus_type;
  256. mdev->dev.release = mdev_device_release;
  257. dev_set_name(&mdev->dev, "%pUl", uuid.b);
  258. ret = device_register(&mdev->dev);
  259. if (ret) {
  260. put_device(&mdev->dev);
  261. goto mdev_fail;
  262. }
  263. ret = mdev_device_create_ops(kobj, mdev);
  264. if (ret)
  265. goto create_fail;
  266. ret = mdev_create_sysfs_files(&mdev->dev, type);
  267. if (ret) {
  268. mdev_device_remove_ops(mdev, true);
  269. goto create_fail;
  270. }
  271. mdev->type_kobj = kobj;
  272. mdev->active = true;
  273. dev_dbg(&mdev->dev, "MDEV: created\n");
  274. return 0;
  275. create_fail:
  276. device_unregister(&mdev->dev);
  277. mdev_fail:
  278. mdev_put_parent(parent);
  279. return ret;
  280. }
  281. int mdev_device_remove(struct device *dev, bool force_remove)
  282. {
  283. struct mdev_device *mdev, *tmp;
  284. struct mdev_parent *parent;
  285. struct mdev_type *type;
  286. int ret;
  287. mdev = to_mdev_device(dev);
  288. mutex_lock(&mdev_list_lock);
  289. list_for_each_entry(tmp, &mdev_list, next) {
  290. if (tmp == mdev)
  291. break;
  292. }
  293. if (tmp != mdev) {
  294. mutex_unlock(&mdev_list_lock);
  295. return -ENODEV;
  296. }
  297. if (!mdev->active) {
  298. mutex_unlock(&mdev_list_lock);
  299. return -EAGAIN;
  300. }
  301. mdev->active = false;
  302. mutex_unlock(&mdev_list_lock);
  303. type = to_mdev_type(mdev->type_kobj);
  304. parent = mdev->parent;
  305. ret = mdev_device_remove_ops(mdev, force_remove);
  306. if (ret) {
  307. mdev->active = true;
  308. return ret;
  309. }
  310. mdev_remove_sysfs_files(dev, type);
  311. device_unregister(dev);
  312. mdev_put_parent(parent);
  313. return 0;
  314. }
  315. static int __init mdev_init(void)
  316. {
  317. return mdev_bus_register();
  318. }
  319. static void __exit mdev_exit(void)
  320. {
  321. if (mdev_bus_compat_class)
  322. class_compat_unregister(mdev_bus_compat_class);
  323. mdev_bus_unregister();
  324. }
  325. module_init(mdev_init)
  326. module_exit(mdev_exit)
  327. MODULE_VERSION(DRIVER_VERSION);
  328. MODULE_LICENSE("GPL v2");
  329. MODULE_AUTHOR(DRIVER_AUTHOR);
  330. MODULE_DESCRIPTION(DRIVER_DESC);
  331. MODULE_SOFTDEP("post: vfio_mdev");