mdev_core.c 9.5 KB

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