fpga-region.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /*
  2. * FPGA Region - Device Tree support for FPGA programming under Linux
  3. *
  4. * Copyright (C) 2013-2016 Altera Corporation
  5. * Copyright (C) 2017 Intel Corporation
  6. *
  7. * This program is free software; you can redistribute it and/or modify it
  8. * under the terms and conditions of the GNU General Public License,
  9. * version 2, as published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope it will be useful, but WITHOUT
  12. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  14. * more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along with
  17. * this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <linux/fpga/fpga-bridge.h>
  20. #include <linux/fpga/fpga-mgr.h>
  21. #include <linux/fpga/fpga-region.h>
  22. #include <linux/idr.h>
  23. #include <linux/kernel.h>
  24. #include <linux/list.h>
  25. #include <linux/module.h>
  26. #include <linux/slab.h>
  27. #include <linux/spinlock.h>
  28. static DEFINE_IDA(fpga_region_ida);
  29. static struct class *fpga_region_class;
  30. struct fpga_region *fpga_region_class_find(
  31. struct device *start, const void *data,
  32. int (*match)(struct device *, const void *))
  33. {
  34. struct device *dev;
  35. dev = class_find_device(fpga_region_class, start, data, match);
  36. if (!dev)
  37. return NULL;
  38. return to_fpga_region(dev);
  39. }
  40. EXPORT_SYMBOL_GPL(fpga_region_class_find);
  41. /**
  42. * fpga_region_get - get an exclusive reference to a fpga region
  43. * @region: FPGA Region struct
  44. *
  45. * Caller should call fpga_region_put() when done with region.
  46. *
  47. * Return fpga_region struct if successful.
  48. * Return -EBUSY if someone already has a reference to the region.
  49. * Return -ENODEV if @np is not a FPGA Region.
  50. */
  51. static struct fpga_region *fpga_region_get(struct fpga_region *region)
  52. {
  53. struct device *dev = &region->dev;
  54. if (!mutex_trylock(&region->mutex)) {
  55. dev_dbg(dev, "%s: FPGA Region already in use\n", __func__);
  56. return ERR_PTR(-EBUSY);
  57. }
  58. get_device(dev);
  59. if (!try_module_get(dev->parent->driver->owner)) {
  60. put_device(dev);
  61. mutex_unlock(&region->mutex);
  62. return ERR_PTR(-ENODEV);
  63. }
  64. dev_dbg(dev, "get\n");
  65. return region;
  66. }
  67. /**
  68. * fpga_region_put - release a reference to a region
  69. *
  70. * @region: FPGA region
  71. */
  72. static void fpga_region_put(struct fpga_region *region)
  73. {
  74. struct device *dev = &region->dev;
  75. dev_dbg(dev, "put\n");
  76. module_put(dev->parent->driver->owner);
  77. put_device(dev);
  78. mutex_unlock(&region->mutex);
  79. }
  80. /**
  81. * fpga_region_program_fpga - program FPGA
  82. * @region: FPGA region
  83. * Program an FPGA using fpga image info (region->info).
  84. * Return 0 for success or negative error code.
  85. */
  86. int fpga_region_program_fpga(struct fpga_region *region)
  87. {
  88. struct device *dev = &region->dev;
  89. struct fpga_image_info *info = region->info;
  90. int ret;
  91. region = fpga_region_get(region);
  92. if (IS_ERR(region)) {
  93. dev_err(dev, "failed to get FPGA region\n");
  94. return PTR_ERR(region);
  95. }
  96. ret = fpga_mgr_lock(region->mgr);
  97. if (ret) {
  98. dev_err(dev, "FPGA manager is busy\n");
  99. goto err_put_region;
  100. }
  101. /*
  102. * In some cases, we already have a list of bridges in the
  103. * fpga region struct. Or we don't have any bridges.
  104. */
  105. if (region->get_bridges) {
  106. ret = region->get_bridges(region);
  107. if (ret) {
  108. dev_err(dev, "failed to get fpga region bridges\n");
  109. goto err_unlock_mgr;
  110. }
  111. }
  112. ret = fpga_bridges_disable(&region->bridge_list);
  113. if (ret) {
  114. dev_err(dev, "failed to disable bridges\n");
  115. goto err_put_br;
  116. }
  117. ret = fpga_mgr_load(region->mgr, info);
  118. if (ret) {
  119. dev_err(dev, "failed to load FPGA image\n");
  120. goto err_put_br;
  121. }
  122. ret = fpga_bridges_enable(&region->bridge_list);
  123. if (ret) {
  124. dev_err(dev, "failed to enable region bridges\n");
  125. goto err_put_br;
  126. }
  127. fpga_mgr_unlock(region->mgr);
  128. fpga_region_put(region);
  129. return 0;
  130. err_put_br:
  131. if (region->get_bridges)
  132. fpga_bridges_put(&region->bridge_list);
  133. err_unlock_mgr:
  134. fpga_mgr_unlock(region->mgr);
  135. err_put_region:
  136. fpga_region_put(region);
  137. return ret;
  138. }
  139. EXPORT_SYMBOL_GPL(fpga_region_program_fpga);
  140. int fpga_region_register(struct device *dev, struct fpga_region *region)
  141. {
  142. int id, ret = 0;
  143. id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL);
  144. if (id < 0)
  145. return id;
  146. mutex_init(&region->mutex);
  147. INIT_LIST_HEAD(&region->bridge_list);
  148. device_initialize(&region->dev);
  149. region->dev.groups = region->groups;
  150. region->dev.class = fpga_region_class;
  151. region->dev.parent = dev;
  152. region->dev.of_node = dev->of_node;
  153. region->dev.id = id;
  154. dev_set_drvdata(dev, region);
  155. ret = dev_set_name(&region->dev, "region%d", id);
  156. if (ret)
  157. goto err_remove;
  158. ret = device_add(&region->dev);
  159. if (ret)
  160. goto err_remove;
  161. return 0;
  162. err_remove:
  163. ida_simple_remove(&fpga_region_ida, id);
  164. return ret;
  165. }
  166. EXPORT_SYMBOL_GPL(fpga_region_register);
  167. int fpga_region_unregister(struct fpga_region *region)
  168. {
  169. device_unregister(&region->dev);
  170. return 0;
  171. }
  172. EXPORT_SYMBOL_GPL(fpga_region_unregister);
  173. static void fpga_region_dev_release(struct device *dev)
  174. {
  175. struct fpga_region *region = to_fpga_region(dev);
  176. ida_simple_remove(&fpga_region_ida, region->dev.id);
  177. }
  178. /**
  179. * fpga_region_init - init function for fpga_region class
  180. * Creates the fpga_region class and registers a reconfig notifier.
  181. */
  182. static int __init fpga_region_init(void)
  183. {
  184. fpga_region_class = class_create(THIS_MODULE, "fpga_region");
  185. if (IS_ERR(fpga_region_class))
  186. return PTR_ERR(fpga_region_class);
  187. fpga_region_class->dev_release = fpga_region_dev_release;
  188. return 0;
  189. }
  190. static void __exit fpga_region_exit(void)
  191. {
  192. class_destroy(fpga_region_class);
  193. ida_destroy(&fpga_region_ida);
  194. }
  195. subsys_initcall(fpga_region_init);
  196. module_exit(fpga_region_exit);
  197. MODULE_DESCRIPTION("FPGA Region");
  198. MODULE_AUTHOR("Alan Tull <atull@kernel.org>");
  199. MODULE_LICENSE("GPL v2");