vfio_ap_drv.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * VFIO based AP device driver
  4. *
  5. * Copyright IBM Corp. 2018
  6. *
  7. * Author(s): Tony Krowiak <akrowiak@linux.ibm.com>
  8. * Pierre Morel <pmorel@linux.ibm.com>
  9. */
  10. #include <linux/module.h>
  11. #include <linux/mod_devicetable.h>
  12. #include <linux/slab.h>
  13. #include <linux/string.h>
  14. #include <asm/facility.h>
  15. #include "vfio_ap_private.h"
  16. #define VFIO_AP_ROOT_NAME "vfio_ap"
  17. #define VFIO_AP_DEV_NAME "matrix"
  18. MODULE_AUTHOR("IBM Corporation");
  19. MODULE_DESCRIPTION("VFIO AP device driver, Copyright IBM Corp. 2018");
  20. MODULE_LICENSE("GPL v2");
  21. static struct ap_driver vfio_ap_drv;
  22. struct ap_matrix_dev *matrix_dev;
  23. /* Only type 10 adapters (CEX4 and later) are supported
  24. * by the AP matrix device driver
  25. */
  26. static struct ap_device_id ap_queue_ids[] = {
  27. { .dev_type = AP_DEVICE_TYPE_CEX4,
  28. .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
  29. { .dev_type = AP_DEVICE_TYPE_CEX5,
  30. .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
  31. { .dev_type = AP_DEVICE_TYPE_CEX6,
  32. .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
  33. { .dev_type = AP_DEVICE_TYPE_CEX7,
  34. .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
  35. { /* end of sibling */ },
  36. };
  37. MODULE_DEVICE_TABLE(vfio_ap, ap_queue_ids);
  38. /**
  39. * vfio_ap_queue_dev_probe:
  40. *
  41. * Allocate a vfio_ap_queue structure and associate it
  42. * with the device as driver_data.
  43. */
  44. static int vfio_ap_queue_dev_probe(struct ap_device *apdev)
  45. {
  46. struct vfio_ap_queue *q;
  47. q = kzalloc(sizeof(*q), GFP_KERNEL);
  48. if (!q)
  49. return -ENOMEM;
  50. dev_set_drvdata(&apdev->device, q);
  51. q->apqn = to_ap_queue(&apdev->device)->qid;
  52. q->saved_isc = VFIO_AP_ISC_INVALID;
  53. return 0;
  54. }
  55. /**
  56. * vfio_ap_queue_dev_remove:
  57. *
  58. * Takes the matrix lock to avoid actions on this device while removing
  59. * Free the associated vfio_ap_queue structure
  60. */
  61. static void vfio_ap_queue_dev_remove(struct ap_device *apdev)
  62. {
  63. struct vfio_ap_queue *q;
  64. mutex_lock(&matrix_dev->lock);
  65. q = dev_get_drvdata(&apdev->device);
  66. vfio_ap_mdev_reset_queue(q, 1);
  67. dev_set_drvdata(&apdev->device, NULL);
  68. kfree(q);
  69. mutex_unlock(&matrix_dev->lock);
  70. }
  71. static void vfio_ap_matrix_dev_release(struct device *dev)
  72. {
  73. struct ap_matrix_dev *matrix_dev = dev_get_drvdata(dev);
  74. kfree(matrix_dev);
  75. }
  76. static int matrix_bus_match(struct device *dev, struct device_driver *drv)
  77. {
  78. return 1;
  79. }
  80. static struct bus_type matrix_bus = {
  81. .name = "matrix",
  82. .match = &matrix_bus_match,
  83. };
  84. static struct device_driver matrix_driver = {
  85. .name = "vfio_ap",
  86. .bus = &matrix_bus,
  87. .suppress_bind_attrs = true,
  88. };
  89. static int vfio_ap_matrix_dev_create(void)
  90. {
  91. int ret;
  92. struct device *root_device;
  93. root_device = root_device_register(VFIO_AP_ROOT_NAME);
  94. if (IS_ERR(root_device))
  95. return PTR_ERR(root_device);
  96. ret = bus_register(&matrix_bus);
  97. if (ret)
  98. goto bus_register_err;
  99. matrix_dev = kzalloc(sizeof(*matrix_dev), GFP_KERNEL);
  100. if (!matrix_dev) {
  101. ret = -ENOMEM;
  102. goto matrix_alloc_err;
  103. }
  104. /* Fill in config info via PQAP(QCI), if available */
  105. if (test_facility(12)) {
  106. ret = ap_qci(&matrix_dev->info);
  107. if (ret)
  108. goto matrix_alloc_err;
  109. }
  110. mutex_init(&matrix_dev->lock);
  111. INIT_LIST_HEAD(&matrix_dev->mdev_list);
  112. dev_set_name(&matrix_dev->device, "%s", VFIO_AP_DEV_NAME);
  113. matrix_dev->device.parent = root_device;
  114. matrix_dev->device.bus = &matrix_bus;
  115. matrix_dev->device.release = vfio_ap_matrix_dev_release;
  116. matrix_dev->vfio_ap_drv = &vfio_ap_drv;
  117. ret = device_register(&matrix_dev->device);
  118. if (ret)
  119. goto matrix_reg_err;
  120. ret = driver_register(&matrix_driver);
  121. if (ret)
  122. goto matrix_drv_err;
  123. return 0;
  124. matrix_drv_err:
  125. device_unregister(&matrix_dev->device);
  126. matrix_reg_err:
  127. put_device(&matrix_dev->device);
  128. matrix_alloc_err:
  129. bus_unregister(&matrix_bus);
  130. bus_register_err:
  131. root_device_unregister(root_device);
  132. return ret;
  133. }
  134. static void vfio_ap_matrix_dev_destroy(void)
  135. {
  136. struct device *root_device = matrix_dev->device.parent;
  137. driver_unregister(&matrix_driver);
  138. device_unregister(&matrix_dev->device);
  139. bus_unregister(&matrix_bus);
  140. root_device_unregister(root_device);
  141. }
  142. static int __init vfio_ap_init(void)
  143. {
  144. int ret;
  145. /* If there are no AP instructions, there is nothing to pass through. */
  146. if (!ap_instructions_available())
  147. return -ENODEV;
  148. ret = vfio_ap_matrix_dev_create();
  149. if (ret)
  150. return ret;
  151. memset(&vfio_ap_drv, 0, sizeof(vfio_ap_drv));
  152. vfio_ap_drv.probe = vfio_ap_queue_dev_probe;
  153. vfio_ap_drv.remove = vfio_ap_queue_dev_remove;
  154. vfio_ap_drv.ids = ap_queue_ids;
  155. ret = ap_driver_register(&vfio_ap_drv, THIS_MODULE, VFIO_AP_DRV_NAME);
  156. if (ret) {
  157. vfio_ap_matrix_dev_destroy();
  158. return ret;
  159. }
  160. ret = vfio_ap_mdev_register();
  161. if (ret) {
  162. ap_driver_unregister(&vfio_ap_drv);
  163. vfio_ap_matrix_dev_destroy();
  164. return ret;
  165. }
  166. return 0;
  167. }
  168. static void __exit vfio_ap_exit(void)
  169. {
  170. vfio_ap_mdev_unregister();
  171. ap_driver_unregister(&vfio_ap_drv);
  172. vfio_ap_matrix_dev_destroy();
  173. }
  174. module_init(vfio_ap_init);
  175. module_exit(vfio_ap_exit);