smc_loopback.c 10 KB

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