/drivers/net/ethernet/hisilicon/hns3/hnae3.c

https://github.com/tekkamanninja/linux · C · 371 lines · 258 code · 69 blank · 44 comment · 35 complexity · f88cf8d232294e0f0c2e06b683314554 MD5 · raw file

  1. // SPDX-License-Identifier: GPL-2.0+
  2. // Copyright (c) 2016-2017 Hisilicon Limited.
  3. #include <linux/list.h>
  4. #include <linux/spinlock.h>
  5. #include "hnae3.h"
  6. static LIST_HEAD(hnae3_ae_algo_list);
  7. static LIST_HEAD(hnae3_client_list);
  8. static LIST_HEAD(hnae3_ae_dev_list);
  9. /* we are keeping things simple and using single lock for all the
  10. * list. This is a non-critical code so other updations, if happen
  11. * in parallel, can wait.
  12. */
  13. static DEFINE_MUTEX(hnae3_common_lock);
  14. static bool hnae3_client_match(enum hnae3_client_type client_type)
  15. {
  16. if (client_type == HNAE3_CLIENT_KNIC ||
  17. client_type == HNAE3_CLIENT_ROCE)
  18. return true;
  19. return false;
  20. }
  21. void hnae3_set_client_init_flag(struct hnae3_client *client,
  22. struct hnae3_ae_dev *ae_dev,
  23. unsigned int inited)
  24. {
  25. if (!client || !ae_dev)
  26. return;
  27. switch (client->type) {
  28. case HNAE3_CLIENT_KNIC:
  29. hnae3_set_bit(ae_dev->flag, HNAE3_KNIC_CLIENT_INITED_B, inited);
  30. break;
  31. case HNAE3_CLIENT_ROCE:
  32. hnae3_set_bit(ae_dev->flag, HNAE3_ROCE_CLIENT_INITED_B, inited);
  33. break;
  34. default:
  35. break;
  36. }
  37. }
  38. EXPORT_SYMBOL(hnae3_set_client_init_flag);
  39. static int hnae3_get_client_init_flag(struct hnae3_client *client,
  40. struct hnae3_ae_dev *ae_dev)
  41. {
  42. int inited = 0;
  43. switch (client->type) {
  44. case HNAE3_CLIENT_KNIC:
  45. inited = hnae3_get_bit(ae_dev->flag,
  46. HNAE3_KNIC_CLIENT_INITED_B);
  47. break;
  48. case HNAE3_CLIENT_ROCE:
  49. inited = hnae3_get_bit(ae_dev->flag,
  50. HNAE3_ROCE_CLIENT_INITED_B);
  51. break;
  52. default:
  53. break;
  54. }
  55. return inited;
  56. }
  57. static int hnae3_init_client_instance(struct hnae3_client *client,
  58. struct hnae3_ae_dev *ae_dev)
  59. {
  60. int ret;
  61. /* check if this client matches the type of ae_dev */
  62. if (!(hnae3_client_match(client->type) &&
  63. hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))) {
  64. return 0;
  65. }
  66. ret = ae_dev->ops->init_client_instance(client, ae_dev);
  67. if (ret)
  68. dev_err(&ae_dev->pdev->dev,
  69. "fail to instantiate client, ret = %d\n", ret);
  70. return ret;
  71. }
  72. static void hnae3_uninit_client_instance(struct hnae3_client *client,
  73. struct hnae3_ae_dev *ae_dev)
  74. {
  75. /* check if this client matches the type of ae_dev */
  76. if (!(hnae3_client_match(client->type) &&
  77. hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B)))
  78. return;
  79. if (hnae3_get_client_init_flag(client, ae_dev)) {
  80. ae_dev->ops->uninit_client_instance(client, ae_dev);
  81. hnae3_set_client_init_flag(client, ae_dev, 0);
  82. }
  83. }
  84. int hnae3_register_client(struct hnae3_client *client)
  85. {
  86. struct hnae3_client *client_tmp;
  87. struct hnae3_ae_dev *ae_dev;
  88. if (!client)
  89. return -ENODEV;
  90. mutex_lock(&hnae3_common_lock);
  91. /* one system should only have one client for every type */
  92. list_for_each_entry(client_tmp, &hnae3_client_list, node) {
  93. if (client_tmp->type == client->type)
  94. goto exit;
  95. }
  96. list_add_tail(&client->node, &hnae3_client_list);
  97. /* initialize the client on every matched port */
  98. list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
  99. /* if the client could not be initialized on current port, for
  100. * any error reasons, move on to next available port
  101. */
  102. int ret = hnae3_init_client_instance(client, ae_dev);
  103. if (ret)
  104. dev_err(&ae_dev->pdev->dev,
  105. "match and instantiation failed for port, ret = %d\n",
  106. ret);
  107. }
  108. exit:
  109. mutex_unlock(&hnae3_common_lock);
  110. return 0;
  111. }
  112. EXPORT_SYMBOL(hnae3_register_client);
  113. void hnae3_unregister_client(struct hnae3_client *client)
  114. {
  115. struct hnae3_client *client_tmp;
  116. struct hnae3_ae_dev *ae_dev;
  117. bool existed = false;
  118. if (!client)
  119. return;
  120. mutex_lock(&hnae3_common_lock);
  121. /* one system should only have one client for every type */
  122. list_for_each_entry(client_tmp, &hnae3_client_list, node) {
  123. if (client_tmp->type == client->type) {
  124. existed = true;
  125. break;
  126. }
  127. }
  128. if (!existed) {
  129. mutex_unlock(&hnae3_common_lock);
  130. pr_err("client %s does not exist!\n", client->name);
  131. return;
  132. }
  133. /* un-initialize the client on every matched port */
  134. list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
  135. hnae3_uninit_client_instance(client, ae_dev);
  136. }
  137. list_del(&client->node);
  138. mutex_unlock(&hnae3_common_lock);
  139. }
  140. EXPORT_SYMBOL(hnae3_unregister_client);
  141. /* hnae3_register_ae_algo - register a AE algorithm to hnae3 framework
  142. * @ae_algo: AE algorithm
  143. * NOTE: the duplicated name will not be checked
  144. */
  145. void hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo)
  146. {
  147. const struct pci_device_id *id;
  148. struct hnae3_ae_dev *ae_dev;
  149. struct hnae3_client *client;
  150. int ret;
  151. if (!ae_algo)
  152. return;
  153. mutex_lock(&hnae3_common_lock);
  154. list_add_tail(&ae_algo->node, &hnae3_ae_algo_list);
  155. /* Check if this algo/ops matches the list of ae_devs */
  156. list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
  157. id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
  158. if (!id)
  159. continue;
  160. if (!ae_algo->ops) {
  161. dev_err(&ae_dev->pdev->dev, "ae_algo ops are null\n");
  162. continue;
  163. }
  164. ae_dev->ops = ae_algo->ops;
  165. ret = ae_algo->ops->init_ae_dev(ae_dev);
  166. if (ret) {
  167. dev_err(&ae_dev->pdev->dev,
  168. "init ae_dev error, ret = %d\n", ret);
  169. continue;
  170. }
  171. /* ae_dev init should set flag */
  172. hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
  173. /* check the client list for the match with this ae_dev type and
  174. * initialize the figure out client instance
  175. */
  176. list_for_each_entry(client, &hnae3_client_list, node) {
  177. ret = hnae3_init_client_instance(client, ae_dev);
  178. if (ret)
  179. dev_err(&ae_dev->pdev->dev,
  180. "match and instantiation failed, ret = %d\n",
  181. ret);
  182. }
  183. }
  184. mutex_unlock(&hnae3_common_lock);
  185. }
  186. EXPORT_SYMBOL(hnae3_register_ae_algo);
  187. /* hnae3_unregister_ae_algo - unregisters a AE algorithm
  188. * @ae_algo: the AE algorithm to unregister
  189. */
  190. void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo)
  191. {
  192. const struct pci_device_id *id;
  193. struct hnae3_ae_dev *ae_dev;
  194. struct hnae3_client *client;
  195. if (!ae_algo)
  196. return;
  197. mutex_lock(&hnae3_common_lock);
  198. /* Check if there are matched ae_dev */
  199. list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
  200. if (!hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))
  201. continue;
  202. id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
  203. if (!id)
  204. continue;
  205. /* check the client list for the match with this ae_dev type and
  206. * un-initialize the figure out client instance
  207. */
  208. list_for_each_entry(client, &hnae3_client_list, node)
  209. hnae3_uninit_client_instance(client, ae_dev);
  210. ae_algo->ops->uninit_ae_dev(ae_dev);
  211. hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
  212. ae_dev->ops = NULL;
  213. }
  214. list_del(&ae_algo->node);
  215. mutex_unlock(&hnae3_common_lock);
  216. }
  217. EXPORT_SYMBOL(hnae3_unregister_ae_algo);
  218. /* hnae3_register_ae_dev - registers a AE device to hnae3 framework
  219. * @ae_dev: the AE device
  220. * NOTE: the duplicated name will not be checked
  221. */
  222. int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
  223. {
  224. const struct pci_device_id *id;
  225. struct hnae3_ae_algo *ae_algo;
  226. struct hnae3_client *client;
  227. int ret;
  228. if (!ae_dev)
  229. return -ENODEV;
  230. mutex_lock(&hnae3_common_lock);
  231. list_add_tail(&ae_dev->node, &hnae3_ae_dev_list);
  232. /* Check if there are matched ae_algo */
  233. list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
  234. id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
  235. if (!id)
  236. continue;
  237. if (!ae_algo->ops) {
  238. dev_err(&ae_dev->pdev->dev, "ae_algo ops are null\n");
  239. ret = -EOPNOTSUPP;
  240. goto out_err;
  241. }
  242. ae_dev->ops = ae_algo->ops;
  243. ret = ae_dev->ops->init_ae_dev(ae_dev);
  244. if (ret) {
  245. dev_err(&ae_dev->pdev->dev,
  246. "init ae_dev error, ret = %d\n", ret);
  247. goto out_err;
  248. }
  249. /* ae_dev init should set flag */
  250. hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
  251. break;
  252. }
  253. /* check the client list for the match with this ae_dev type and
  254. * initialize the figure out client instance
  255. */
  256. list_for_each_entry(client, &hnae3_client_list, node) {
  257. ret = hnae3_init_client_instance(client, ae_dev);
  258. if (ret)
  259. dev_err(&ae_dev->pdev->dev,
  260. "match and instantiation failed, ret = %d\n",
  261. ret);
  262. }
  263. mutex_unlock(&hnae3_common_lock);
  264. return 0;
  265. out_err:
  266. list_del(&ae_dev->node);
  267. mutex_unlock(&hnae3_common_lock);
  268. return ret;
  269. }
  270. EXPORT_SYMBOL(hnae3_register_ae_dev);
  271. /* hnae3_unregister_ae_dev - unregisters a AE device
  272. * @ae_dev: the AE device to unregister
  273. */
  274. void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev)
  275. {
  276. const struct pci_device_id *id;
  277. struct hnae3_ae_algo *ae_algo;
  278. struct hnae3_client *client;
  279. if (!ae_dev)
  280. return;
  281. mutex_lock(&hnae3_common_lock);
  282. /* Check if there are matched ae_algo */
  283. list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
  284. if (!hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))
  285. continue;
  286. id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
  287. if (!id)
  288. continue;
  289. list_for_each_entry(client, &hnae3_client_list, node)
  290. hnae3_uninit_client_instance(client, ae_dev);
  291. ae_algo->ops->uninit_ae_dev(ae_dev);
  292. hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
  293. ae_dev->ops = NULL;
  294. }
  295. list_del(&ae_dev->node);
  296. mutex_unlock(&hnae3_common_lock);
  297. }
  298. EXPORT_SYMBOL(hnae3_unregister_ae_dev);
  299. MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
  300. MODULE_LICENSE("GPL");
  301. MODULE_DESCRIPTION("HNAE3(Hisilicon Network Acceleration Engine) Framework");
  302. MODULE_VERSION(HNAE3_MOD_VERSION);