smc_loopback.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Shared Memory Communications Direct over loopback-ism device.
  4. *
  5. * Functions for loopback-ism device.
  6. *
  7. * Copyright (c) 2024, Alibaba Inc.
  8. *
  9. * Author: Wen Gu <guwen@linux.alibaba.com>
  10. * Tony Lu <tonylu@linux.alibaba.com>
  11. *
  12. */
  13. #include <linux/device.h>
  14. #include <linux/types.h>
  15. #include <net/smc.h>
  16. #include "smc_cdc.h"
  17. #include "smc_ism.h"
  18. #include "smc_loopback.h"
  19. #define SMC_LO_V2_CAPABLE 0x1 /* loopback-ism acts as ISMv2 */
  20. #define SMC_LO_SUPPORT_NOCOPY 0x1
  21. #define SMC_DMA_ADDR_INVALID (~(dma_addr_t)0)
  22. static const char smc_lo_dev_name[] = "loopback-ism";
  23. static struct smc_lo_dev *lo_dev;
  24. static void smc_lo_generate_ids(struct smc_lo_dev *ldev)
  25. {
  26. struct smcd_gid *lgid = &ldev->local_gid;
  27. uuid_t uuid;
  28. uuid_gen(&uuid);
  29. memcpy(&lgid->gid, &uuid, sizeof(lgid->gid));
  30. memcpy(&lgid->gid_ext, (u8 *)&uuid + sizeof(lgid->gid),
  31. sizeof(lgid->gid_ext));
  32. ldev->chid = SMC_LO_RESERVED_CHID;
  33. }
  34. static int smc_lo_query_rgid(struct smcd_dev *smcd, struct smcd_gid *rgid,
  35. u32 vid_valid, u32 vid)
  36. {
  37. struct smc_lo_dev *ldev = smcd->priv;
  38. /* rgid should be the same as lgid */
  39. if (!ldev || rgid->gid != ldev->local_gid.gid ||
  40. rgid->gid_ext != ldev->local_gid.gid_ext)
  41. return -ENETUNREACH;
  42. return 0;
  43. }
  44. static int smc_lo_register_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb,
  45. void *client_priv)
  46. {
  47. struct smc_lo_dmb_node *dmb_node, *tmp_node;
  48. struct smc_lo_dev *ldev = smcd->priv;
  49. int sba_idx, rc;
  50. /* check space for new dmb */
  51. for_each_clear_bit(sba_idx, ldev->sba_idx_mask, SMC_LO_MAX_DMBS) {
  52. if (!test_and_set_bit(sba_idx, ldev->sba_idx_mask))
  53. break;
  54. }
  55. if (sba_idx == SMC_LO_MAX_DMBS)
  56. return -ENOSPC;
  57. dmb_node = kzalloc(sizeof(*dmb_node), GFP_KERNEL);
  58. if (!dmb_node) {
  59. rc = -ENOMEM;
  60. goto err_bit;
  61. }
  62. dmb_node->sba_idx = sba_idx;
  63. dmb_node->len = dmb->dmb_len;
  64. dmb_node->cpu_addr = kzalloc(dmb_node->len, GFP_KERNEL |
  65. __GFP_NOWARN | __GFP_NORETRY |
  66. __GFP_NOMEMALLOC);
  67. if (!dmb_node->cpu_addr) {
  68. rc = -ENOMEM;
  69. goto err_node;
  70. }
  71. dmb_node->dma_addr = SMC_DMA_ADDR_INVALID;
  72. refcount_set(&dmb_node->refcnt, 1);
  73. again:
  74. /* add new dmb into hash table */
  75. get_random_bytes(&dmb_node->token, sizeof(dmb_node->token));
  76. write_lock_bh(&ldev->dmb_ht_lock);
  77. hash_for_each_possible(ldev->dmb_ht, tmp_node, list, dmb_node->token) {
  78. if (tmp_node->token == dmb_node->token) {
  79. write_unlock_bh(&ldev->dmb_ht_lock);
  80. goto again;
  81. }
  82. }
  83. hash_add(ldev->dmb_ht, &dmb_node->list, dmb_node->token);
  84. write_unlock_bh(&ldev->dmb_ht_lock);
  85. atomic_inc(&ldev->dmb_cnt);
  86. dmb->sba_idx = dmb_node->sba_idx;
  87. dmb->dmb_tok = dmb_node->token;
  88. dmb->cpu_addr = dmb_node->cpu_addr;
  89. dmb->dma_addr = dmb_node->dma_addr;
  90. dmb->dmb_len = dmb_node->len;
  91. return 0;
  92. err_node:
  93. kfree(dmb_node);
  94. err_bit:
  95. clear_bit(sba_idx, ldev->sba_idx_mask);
  96. return rc;
  97. }
  98. static void __smc_lo_unregister_dmb(struct smc_lo_dev *ldev,
  99. struct smc_lo_dmb_node *dmb_node)
  100. {
  101. /* remove dmb from hash table */
  102. write_lock_bh(&ldev->dmb_ht_lock);
  103. hash_del(&dmb_node->list);
  104. write_unlock_bh(&ldev->dmb_ht_lock);
  105. clear_bit(dmb_node->sba_idx, ldev->sba_idx_mask);
  106. kvfree(dmb_node->cpu_addr);
  107. kfree(dmb_node);
  108. if (atomic_dec_and_test(&ldev->dmb_cnt))
  109. wake_up(&ldev->ldev_release);
  110. }
  111. static int smc_lo_unregister_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb)
  112. {
  113. struct smc_lo_dmb_node *dmb_node = NULL, *tmp_node;
  114. struct smc_lo_dev *ldev = smcd->priv;
  115. /* find dmb from hash table */
  116. read_lock_bh(&ldev->dmb_ht_lock);
  117. hash_for_each_possible(ldev->dmb_ht, tmp_node, list, dmb->dmb_tok) {
  118. if (tmp_node->token == dmb->dmb_tok) {
  119. dmb_node = tmp_node;
  120. break;
  121. }
  122. }
  123. if (!dmb_node) {
  124. read_unlock_bh(&ldev->dmb_ht_lock);
  125. return -EINVAL;
  126. }
  127. read_unlock_bh(&ldev->dmb_ht_lock);
  128. if (refcount_dec_and_test(&dmb_node->refcnt))
  129. __smc_lo_unregister_dmb(ldev, dmb_node);
  130. return 0;
  131. }
  132. static int smc_lo_support_dmb_nocopy(struct smcd_dev *smcd)
  133. {
  134. return SMC_LO_SUPPORT_NOCOPY;
  135. }
  136. static int smc_lo_attach_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb)
  137. {
  138. struct smc_lo_dmb_node *dmb_node = NULL, *tmp_node;
  139. struct smc_lo_dev *ldev = smcd->priv;
  140. /* find dmb_node according to dmb->dmb_tok */
  141. read_lock_bh(&ldev->dmb_ht_lock);
  142. hash_for_each_possible(ldev->dmb_ht, tmp_node, list, dmb->dmb_tok) {
  143. if (tmp_node->token == dmb->dmb_tok) {
  144. dmb_node = tmp_node;
  145. break;
  146. }
  147. }
  148. if (!dmb_node) {
  149. read_unlock_bh(&ldev->dmb_ht_lock);
  150. return -EINVAL;
  151. }
  152. read_unlock_bh(&ldev->dmb_ht_lock);
  153. if (!refcount_inc_not_zero(&dmb_node->refcnt))
  154. /* the dmb is being unregistered, but has
  155. * not been removed from the hash table.
  156. */
  157. return -EINVAL;
  158. /* provide dmb information */
  159. dmb->sba_idx = dmb_node->sba_idx;
  160. dmb->dmb_tok = dmb_node->token;
  161. dmb->cpu_addr = dmb_node->cpu_addr;
  162. dmb->dma_addr = dmb_node->dma_addr;
  163. dmb->dmb_len = dmb_node->len;
  164. return 0;
  165. }
  166. static int smc_lo_detach_dmb(struct smcd_dev *smcd, u64 token)
  167. {
  168. struct smc_lo_dmb_node *dmb_node = NULL, *tmp_node;
  169. struct smc_lo_dev *ldev = smcd->priv;
  170. /* find dmb_node according to dmb->dmb_tok */
  171. read_lock_bh(&ldev->dmb_ht_lock);
  172. hash_for_each_possible(ldev->dmb_ht, tmp_node, list, token) {
  173. if (tmp_node->token == token) {
  174. dmb_node = tmp_node;
  175. break;
  176. }
  177. }
  178. if (!dmb_node) {
  179. read_unlock_bh(&ldev->dmb_ht_lock);
  180. return -EINVAL;
  181. }
  182. read_unlock_bh(&ldev->dmb_ht_lock);
  183. if (refcount_dec_and_test(&dmb_node->refcnt))
  184. __smc_lo_unregister_dmb(ldev, dmb_node);
  185. return 0;
  186. }
  187. static int smc_lo_move_data(struct smcd_dev *smcd, u64 dmb_tok,
  188. unsigned int idx, bool sf, unsigned int offset,
  189. void *data, unsigned int size)
  190. {
  191. struct smc_lo_dmb_node *rmb_node = NULL, *tmp_node;
  192. struct smc_lo_dev *ldev = smcd->priv;
  193. struct smc_connection *conn;
  194. if (!sf)
  195. /* since sndbuf is merged with peer DMB, there is
  196. * no need to copy data from sndbuf to peer DMB.
  197. */
  198. return 0;
  199. read_lock_bh(&ldev->dmb_ht_lock);
  200. hash_for_each_possible(ldev->dmb_ht, tmp_node, list, dmb_tok) {
  201. if (tmp_node->token == dmb_tok) {
  202. rmb_node = tmp_node;
  203. break;
  204. }
  205. }
  206. if (!rmb_node) {
  207. read_unlock_bh(&ldev->dmb_ht_lock);
  208. return -EINVAL;
  209. }
  210. memcpy((char *)rmb_node->cpu_addr + offset, data, size);
  211. read_unlock_bh(&ldev->dmb_ht_lock);
  212. conn = smcd->conn[rmb_node->sba_idx];
  213. if (!conn || conn->killed)
  214. return -EPIPE;
  215. tasklet_schedule(&conn->rx_tsklet);
  216. return 0;
  217. }
  218. static int smc_lo_supports_v2(void)
  219. {
  220. return SMC_LO_V2_CAPABLE;
  221. }
  222. static void smc_lo_get_local_gid(struct smcd_dev *smcd,
  223. struct smcd_gid *smcd_gid)
  224. {
  225. struct smc_lo_dev *ldev = smcd->priv;
  226. smcd_gid->gid = ldev->local_gid.gid;
  227. smcd_gid->gid_ext = ldev->local_gid.gid_ext;
  228. }
  229. static u16 smc_lo_get_chid(struct smcd_dev *smcd)
  230. {
  231. return ((struct smc_lo_dev *)smcd->priv)->chid;
  232. }
  233. static struct device *smc_lo_get_dev(struct smcd_dev *smcd)
  234. {
  235. return &((struct smc_lo_dev *)smcd->priv)->dev;
  236. }
  237. static const struct smcd_ops lo_ops = {
  238. .query_remote_gid = smc_lo_query_rgid,
  239. .register_dmb = smc_lo_register_dmb,
  240. .unregister_dmb = smc_lo_unregister_dmb,
  241. .support_dmb_nocopy = smc_lo_support_dmb_nocopy,
  242. .attach_dmb = smc_lo_attach_dmb,
  243. .detach_dmb = smc_lo_detach_dmb,
  244. .add_vlan_id = NULL,
  245. .del_vlan_id = NULL,
  246. .set_vlan_required = NULL,
  247. .reset_vlan_required = NULL,
  248. .signal_event = NULL,
  249. .move_data = smc_lo_move_data,
  250. .supports_v2 = smc_lo_supports_v2,
  251. .get_local_gid = smc_lo_get_local_gid,
  252. .get_chid = smc_lo_get_chid,
  253. .get_dev = smc_lo_get_dev,
  254. };
  255. static struct smcd_dev *smcd_lo_alloc_dev(const struct smcd_ops *ops,
  256. int max_dmbs)
  257. {
  258. struct smcd_dev *smcd;
  259. smcd = kzalloc(sizeof(*smcd), GFP_KERNEL);
  260. if (!smcd)
  261. return NULL;
  262. smcd->conn = kcalloc(max_dmbs, sizeof(struct smc_connection *),
  263. GFP_KERNEL);
  264. if (!smcd->conn)
  265. goto out_smcd;
  266. smcd->ops = ops;
  267. spin_lock_init(&smcd->lock);
  268. spin_lock_init(&smcd->lgr_lock);
  269. INIT_LIST_HEAD(&smcd->vlan);
  270. INIT_LIST_HEAD(&smcd->lgr_list);
  271. init_waitqueue_head(&smcd->lgrs_deleted);
  272. return smcd;
  273. out_smcd:
  274. kfree(smcd);
  275. return NULL;
  276. }
  277. static int smcd_lo_register_dev(struct smc_lo_dev *ldev)
  278. {
  279. struct smcd_dev *smcd;
  280. smcd = smcd_lo_alloc_dev(&lo_ops, SMC_LO_MAX_DMBS);
  281. if (!smcd)
  282. return -ENOMEM;
  283. ldev->smcd = smcd;
  284. smcd->priv = ldev;
  285. smc_ism_set_v2_capable();
  286. mutex_lock(&smcd_dev_list.mutex);
  287. list_add(&smcd->list, &smcd_dev_list.list);
  288. mutex_unlock(&smcd_dev_list.mutex);
  289. pr_warn_ratelimited("smc: adding smcd device %s\n",
  290. dev_name(&ldev->dev));
  291. return 0;
  292. }
  293. static void smcd_lo_unregister_dev(struct smc_lo_dev *ldev)
  294. {
  295. struct smcd_dev *smcd = ldev->smcd;
  296. pr_warn_ratelimited("smc: removing smcd device %s\n",
  297. dev_name(&ldev->dev));
  298. smcd->going_away = 1;
  299. smc_smcd_terminate_all(smcd);
  300. mutex_lock(&smcd_dev_list.mutex);
  301. list_del_init(&smcd->list);
  302. mutex_unlock(&smcd_dev_list.mutex);
  303. kfree(smcd->conn);
  304. kfree(smcd);
  305. }
  306. static int smc_lo_dev_init(struct smc_lo_dev *ldev)
  307. {
  308. smc_lo_generate_ids(ldev);
  309. rwlock_init(&ldev->dmb_ht_lock);
  310. hash_init(ldev->dmb_ht);
  311. atomic_set(&ldev->dmb_cnt, 0);
  312. init_waitqueue_head(&ldev->ldev_release);
  313. return smcd_lo_register_dev(ldev);
  314. }
  315. static void smc_lo_dev_exit(struct smc_lo_dev *ldev)
  316. {
  317. smcd_lo_unregister_dev(ldev);
  318. if (atomic_read(&ldev->dmb_cnt))
  319. wait_event(ldev->ldev_release, !atomic_read(&ldev->dmb_cnt));
  320. }
  321. static void smc_lo_dev_release(struct device *dev)
  322. {
  323. struct smc_lo_dev *ldev =
  324. container_of(dev, struct smc_lo_dev, dev);
  325. kfree(ldev);
  326. }
  327. static int smc_lo_dev_probe(void)
  328. {
  329. struct smc_lo_dev *ldev;
  330. int ret;
  331. ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
  332. if (!ldev)
  333. return -ENOMEM;
  334. ldev->dev.parent = NULL;
  335. ldev->dev.release = smc_lo_dev_release;
  336. device_initialize(&ldev->dev);
  337. dev_set_name(&ldev->dev, smc_lo_dev_name);
  338. ret = smc_lo_dev_init(ldev);
  339. if (ret)
  340. goto free_dev;
  341. lo_dev = ldev; /* global loopback device */
  342. return 0;
  343. free_dev:
  344. put_device(&ldev->dev);
  345. return ret;
  346. }
  347. static void smc_lo_dev_remove(void)
  348. {
  349. if (!lo_dev)
  350. return;
  351. smc_lo_dev_exit(lo_dev);
  352. put_device(&lo_dev->dev); /* device_initialize in smc_lo_dev_probe */
  353. }
  354. int smc_loopback_init(void)
  355. {
  356. return smc_lo_dev_probe();
  357. }
  358. void smc_loopback_exit(void)
  359. {
  360. smc_lo_dev_remove();
  361. }