mdev_core.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  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. return 0;
  129. return mdev_device_remove(dev, data ? *(bool *)data : true);
  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. ret = -EEXIST;
  154. goto add_dev_err;
  155. }
  156. parent = kzalloc(sizeof(*parent), GFP_KERNEL);
  157. if (!parent) {
  158. ret = -ENOMEM;
  159. goto add_dev_err;
  160. }
  161. kref_init(&parent->ref);
  162. parent->dev = dev;
  163. parent->ops = ops;
  164. if (!mdev_bus_compat_class) {
  165. mdev_bus_compat_class = class_compat_register("mdev_bus");
  166. if (!mdev_bus_compat_class) {
  167. ret = -ENOMEM;
  168. goto add_dev_err;
  169. }
  170. }
  171. ret = parent_create_sysfs_files(parent);
  172. if (ret)
  173. goto add_dev_err;
  174. ret = class_compat_create_link(mdev_bus_compat_class, dev, NULL);
  175. if (ret)
  176. dev_warn(dev, "Failed to create compatibility class link\n");
  177. list_add(&parent->next, &parent_list);
  178. mutex_unlock(&parent_list_lock);
  179. dev_info(dev, "MDEV: Registered\n");
  180. return 0;
  181. add_dev_err:
  182. mutex_unlock(&parent_list_lock);
  183. if (parent)
  184. mdev_put_parent(parent);
  185. else
  186. put_device(dev);
  187. return ret;
  188. }
  189. EXPORT_SYMBOL(mdev_register_device);
  190. /*
  191. * mdev_unregister_device : Unregister a parent device
  192. * @dev: device structure representing parent device.
  193. *
  194. * Remove device from list of registered parent devices. Give a chance to free
  195. * existing mediated devices for given device.
  196. */
  197. void mdev_unregister_device(struct device *dev)
  198. {
  199. struct mdev_parent *parent;
  200. bool force_remove = true;
  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, (void *)&force_remove,
  211. mdev_device_remove_cb);
  212. parent_remove_sysfs_files(parent);
  213. mutex_unlock(&parent_list_lock);
  214. mdev_put_parent(parent);
  215. }
  216. EXPORT_SYMBOL(mdev_unregister_device);
  217. static void mdev_device_release(struct device *dev)
  218. {
  219. struct mdev_device *mdev = to_mdev_device(dev);
  220. mutex_lock(&mdev_list_lock);
  221. list_del(&mdev->next);
  222. mutex_unlock(&mdev_list_lock);
  223. dev_dbg(&mdev->dev, "MDEV: destroying\n");
  224. kfree(mdev);
  225. }
  226. int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid)
  227. {
  228. int ret;
  229. struct mdev_device *mdev, *tmp;
  230. struct mdev_parent *parent;
  231. struct mdev_type *type = to_mdev_type(kobj);
  232. parent = mdev_get_parent(type->parent);
  233. if (!parent)
  234. return -EINVAL;
  235. mutex_lock(&mdev_list_lock);
  236. /* Check for duplicate */
  237. list_for_each_entry(tmp, &mdev_list, next) {
  238. if (!uuid_le_cmp(tmp->uuid, uuid)) {
  239. mutex_unlock(&mdev_list_lock);
  240. ret = -EEXIST;
  241. goto mdev_fail;
  242. }
  243. }
  244. mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
  245. if (!mdev) {
  246. mutex_unlock(&mdev_list_lock);
  247. ret = -ENOMEM;
  248. goto mdev_fail;
  249. }
  250. memcpy(&mdev->uuid, &uuid, sizeof(uuid_le));
  251. list_add(&mdev->next, &mdev_list);
  252. mutex_unlock(&mdev_list_lock);
  253. mdev->parent = parent;
  254. kref_init(&mdev->ref);
  255. mdev->dev.parent = dev;
  256. mdev->dev.bus = &mdev_bus_type;
  257. mdev->dev.release = mdev_device_release;
  258. dev_set_name(&mdev->dev, "%pUl", uuid.b);
  259. ret = device_register(&mdev->dev);
  260. if (ret) {
  261. put_device(&mdev->dev);
  262. goto mdev_fail;
  263. }
  264. ret = mdev_device_create_ops(kobj, mdev);
  265. if (ret)
  266. goto create_fail;
  267. ret = mdev_create_sysfs_files(&mdev->dev, type);
  268. if (ret) {
  269. mdev_device_remove_ops(mdev, true);
  270. goto create_fail;
  271. }
  272. mdev->type_kobj = kobj;
  273. mdev->active = true;
  274. dev_dbg(&mdev->dev, "MDEV: created\n");
  275. return 0;
  276. create_fail:
  277. device_unregister(&mdev->dev);
  278. mdev_fail:
  279. mdev_put_parent(parent);
  280. return ret;
  281. }
  282. int mdev_device_remove(struct device *dev, bool force_remove)
  283. {
  284. struct mdev_device *mdev, *tmp;
  285. struct mdev_parent *parent;
  286. struct mdev_type *type;
  287. int ret;
  288. mdev = to_mdev_device(dev);
  289. mutex_lock(&mdev_list_lock);
  290. list_for_each_entry(tmp, &mdev_list, next) {
  291. if (tmp == mdev)
  292. break;
  293. }
  294. if (tmp != mdev) {
  295. mutex_unlock(&mdev_list_lock);
  296. return -ENODEV;
  297. }
  298. if (!mdev->active) {
  299. mutex_unlock(&mdev_list_lock);
  300. return -EAGAIN;
  301. }
  302. mdev->active = false;
  303. mutex_unlock(&mdev_list_lock);
  304. type = to_mdev_type(mdev->type_kobj);
  305. parent = mdev->parent;
  306. ret = mdev_device_remove_ops(mdev, force_remove);
  307. if (ret) {
  308. mdev->active = true;
  309. return ret;
  310. }
  311. mdev_remove_sysfs_files(dev, type);
  312. device_unregister(dev);
  313. mdev_put_parent(parent);
  314. return 0;
  315. }
  316. static int __init mdev_init(void)
  317. {
  318. return mdev_bus_register();
  319. }
  320. static void __exit mdev_exit(void)
  321. {
  322. if (mdev_bus_compat_class)
  323. class_compat_unregister(mdev_bus_compat_class);
  324. mdev_bus_unregister();
  325. }
  326. module_init(mdev_init)
  327. module_exit(mdev_exit)
  328. MODULE_VERSION(DRIVER_VERSION);
  329. MODULE_LICENSE("GPL v2");
  330. MODULE_AUTHOR(DRIVER_AUTHOR);
  331. MODULE_DESCRIPTION(DRIVER_DESC);
  332. MODULE_SOFTDEP("post: vfio_mdev");