xref: /linux/drivers/infiniband/hw/ionic/ionic_ibdev.c (revision b83c62055b6faabb444b2f8f3355420927cc39fd)
18d765af5SAbhijit Gangurde // SPDX-License-Identifier: GPL-2.0
28d765af5SAbhijit Gangurde /* Copyright (C) 2018-2025, Advanced Micro Devices, Inc. */
38d765af5SAbhijit Gangurde 
48d765af5SAbhijit Gangurde #include <linux/module.h>
58d765af5SAbhijit Gangurde #include <linux/printk.h>
68d765af5SAbhijit Gangurde #include <net/addrconf.h>
78d765af5SAbhijit Gangurde 
88d765af5SAbhijit Gangurde #include "ionic_ibdev.h"
98d765af5SAbhijit Gangurde 
108d765af5SAbhijit Gangurde #define DRIVER_DESCRIPTION "AMD Pensando RoCE HCA driver"
118d765af5SAbhijit Gangurde #define DEVICE_DESCRIPTION "AMD Pensando RoCE HCA"
128d765af5SAbhijit Gangurde 
138d765af5SAbhijit Gangurde MODULE_AUTHOR("Allen Hubbe <allen.hubbe@amd.com>");
148d765af5SAbhijit Gangurde MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
158d765af5SAbhijit Gangurde MODULE_LICENSE("GPL");
168d765af5SAbhijit Gangurde MODULE_IMPORT_NS("NET_IONIC");
178d765af5SAbhijit Gangurde 
18e8521822SAbhijit Gangurde static const struct ib_device_ops ionic_dev_ops = {
19e8521822SAbhijit Gangurde 	.owner = THIS_MODULE,
20e8521822SAbhijit Gangurde 	.driver_id = RDMA_DRIVER_IONIC,
21e8521822SAbhijit Gangurde 	.uverbs_abi_ver = IONIC_ABI_VERSION,
22e8521822SAbhijit Gangurde 
23e8521822SAbhijit Gangurde 	.alloc_ucontext = ionic_alloc_ucontext,
24e8521822SAbhijit Gangurde 	.dealloc_ucontext = ionic_dealloc_ucontext,
25e8521822SAbhijit Gangurde 	.mmap = ionic_mmap,
26e8521822SAbhijit Gangurde 	.mmap_free = ionic_mmap_free,
27e8521822SAbhijit Gangurde 	.alloc_pd = ionic_alloc_pd,
28e8521822SAbhijit Gangurde 	.dealloc_pd = ionic_dealloc_pd,
29e8521822SAbhijit Gangurde 	.create_ah = ionic_create_ah,
30e8521822SAbhijit Gangurde 	.query_ah = ionic_query_ah,
31e8521822SAbhijit Gangurde 	.destroy_ah = ionic_destroy_ah,
32e8521822SAbhijit Gangurde 	.create_user_ah = ionic_create_ah,
33e8521822SAbhijit Gangurde 	.get_dma_mr = ionic_get_dma_mr,
34e8521822SAbhijit Gangurde 	.reg_user_mr = ionic_reg_user_mr,
35e8521822SAbhijit Gangurde 	.reg_user_mr_dmabuf = ionic_reg_user_mr_dmabuf,
36e8521822SAbhijit Gangurde 	.dereg_mr = ionic_dereg_mr,
37e8521822SAbhijit Gangurde 	.alloc_mr = ionic_alloc_mr,
38e8521822SAbhijit Gangurde 	.map_mr_sg = ionic_map_mr_sg,
39e8521822SAbhijit Gangurde 	.alloc_mw = ionic_alloc_mw,
40e8521822SAbhijit Gangurde 	.dealloc_mw = ionic_dealloc_mw,
41e8521822SAbhijit Gangurde 	.create_cq = ionic_create_cq,
42e8521822SAbhijit Gangurde 	.destroy_cq = ionic_destroy_cq,
43e8521822SAbhijit Gangurde 	.create_qp = ionic_create_qp,
44e8521822SAbhijit Gangurde 	.modify_qp = ionic_modify_qp,
45e8521822SAbhijit Gangurde 	.query_qp = ionic_query_qp,
46e8521822SAbhijit Gangurde 	.destroy_qp = ionic_destroy_qp,
47e8521822SAbhijit Gangurde 
48*b83c6205SAbhijit Gangurde 	.post_send = ionic_post_send,
49*b83c6205SAbhijit Gangurde 	.post_recv = ionic_post_recv,
50*b83c6205SAbhijit Gangurde 	.poll_cq = ionic_poll_cq,
51*b83c6205SAbhijit Gangurde 	.req_notify_cq = ionic_req_notify_cq,
52*b83c6205SAbhijit Gangurde 
53e8521822SAbhijit Gangurde 	INIT_RDMA_OBJ_SIZE(ib_ucontext, ionic_ctx, ibctx),
54e8521822SAbhijit Gangurde 	INIT_RDMA_OBJ_SIZE(ib_pd, ionic_pd, ibpd),
55e8521822SAbhijit Gangurde 	INIT_RDMA_OBJ_SIZE(ib_ah, ionic_ah, ibah),
56e8521822SAbhijit Gangurde 	INIT_RDMA_OBJ_SIZE(ib_cq, ionic_vcq, ibcq),
57e8521822SAbhijit Gangurde 	INIT_RDMA_OBJ_SIZE(ib_qp, ionic_qp, ibqp),
58e8521822SAbhijit Gangurde 	INIT_RDMA_OBJ_SIZE(ib_mw, ionic_mr, ibmw),
59e8521822SAbhijit Gangurde };
60e8521822SAbhijit Gangurde 
61f3bdbd42SAbhijit Gangurde static void ionic_init_resids(struct ionic_ibdev *dev)
62f3bdbd42SAbhijit Gangurde {
63f3bdbd42SAbhijit Gangurde 	ionic_resid_init(&dev->inuse_cqid, dev->lif_cfg.cq_count);
64f3bdbd42SAbhijit Gangurde 	dev->half_cqid_udma_shift =
65f3bdbd42SAbhijit Gangurde 		order_base_2(dev->lif_cfg.cq_count / dev->lif_cfg.udma_count);
66f3bdbd42SAbhijit Gangurde 	ionic_resid_init(&dev->inuse_pdid, IONIC_MAX_PD);
67f3bdbd42SAbhijit Gangurde 	ionic_resid_init(&dev->inuse_ahid, dev->lif_cfg.nahs_per_lif);
68f3bdbd42SAbhijit Gangurde 	ionic_resid_init(&dev->inuse_mrid, dev->lif_cfg.nmrs_per_lif);
69f3bdbd42SAbhijit Gangurde 	/* skip reserved lkey */
70f3bdbd42SAbhijit Gangurde 	dev->next_mrkey = 1;
71f3bdbd42SAbhijit Gangurde 	ionic_resid_init(&dev->inuse_qpid, dev->lif_cfg.qp_count);
72f3bdbd42SAbhijit Gangurde 	/* skip reserved SMI and GSI qpids */
73f3bdbd42SAbhijit Gangurde 	dev->half_qpid_udma_shift =
74f3bdbd42SAbhijit Gangurde 		order_base_2(dev->lif_cfg.qp_count / dev->lif_cfg.udma_count);
75f3bdbd42SAbhijit Gangurde 	ionic_resid_init(&dev->inuse_dbid, dev->lif_cfg.dbid_count);
76f3bdbd42SAbhijit Gangurde }
77f3bdbd42SAbhijit Gangurde 
78f3bdbd42SAbhijit Gangurde static void ionic_destroy_resids(struct ionic_ibdev *dev)
79f3bdbd42SAbhijit Gangurde {
80f3bdbd42SAbhijit Gangurde 	ionic_resid_destroy(&dev->inuse_cqid);
81f3bdbd42SAbhijit Gangurde 	ionic_resid_destroy(&dev->inuse_pdid);
82f3bdbd42SAbhijit Gangurde 	ionic_resid_destroy(&dev->inuse_ahid);
83f3bdbd42SAbhijit Gangurde 	ionic_resid_destroy(&dev->inuse_mrid);
84f3bdbd42SAbhijit Gangurde 	ionic_resid_destroy(&dev->inuse_qpid);
85f3bdbd42SAbhijit Gangurde 	ionic_resid_destroy(&dev->inuse_dbid);
86f3bdbd42SAbhijit Gangurde }
87f3bdbd42SAbhijit Gangurde 
888d765af5SAbhijit Gangurde static void ionic_destroy_ibdev(struct ionic_ibdev *dev)
898d765af5SAbhijit Gangurde {
90f3bdbd42SAbhijit Gangurde 	ionic_kill_rdma_admin(dev, false);
918d765af5SAbhijit Gangurde 	ib_unregister_device(&dev->ibdev);
92f3bdbd42SAbhijit Gangurde 	ionic_destroy_rdma_admin(dev);
93f3bdbd42SAbhijit Gangurde 	ionic_destroy_resids(dev);
94e8521822SAbhijit Gangurde 	WARN_ON(!xa_empty(&dev->qp_tbl));
95e8521822SAbhijit Gangurde 	xa_destroy(&dev->qp_tbl);
96f3bdbd42SAbhijit Gangurde 	WARN_ON(!xa_empty(&dev->cq_tbl));
97f3bdbd42SAbhijit Gangurde 	xa_destroy(&dev->cq_tbl);
988d765af5SAbhijit Gangurde 	ib_dealloc_device(&dev->ibdev);
998d765af5SAbhijit Gangurde }
1008d765af5SAbhijit Gangurde 
1018d765af5SAbhijit Gangurde static struct ionic_ibdev *ionic_create_ibdev(struct ionic_aux_dev *ionic_adev)
1028d765af5SAbhijit Gangurde {
1038d765af5SAbhijit Gangurde 	struct ib_device *ibdev;
1048d765af5SAbhijit Gangurde 	struct ionic_ibdev *dev;
1058d765af5SAbhijit Gangurde 	struct net_device *ndev;
1068d765af5SAbhijit Gangurde 	int rc;
1078d765af5SAbhijit Gangurde 
1088d765af5SAbhijit Gangurde 	dev = ib_alloc_device(ionic_ibdev, ibdev);
1098d765af5SAbhijit Gangurde 	if (!dev)
1108d765af5SAbhijit Gangurde 		return ERR_PTR(-EINVAL);
1118d765af5SAbhijit Gangurde 
1128d765af5SAbhijit Gangurde 	ionic_fill_lif_cfg(ionic_adev->lif, &dev->lif_cfg);
1138d765af5SAbhijit Gangurde 
114e8521822SAbhijit Gangurde 	xa_init_flags(&dev->qp_tbl, GFP_ATOMIC);
115f3bdbd42SAbhijit Gangurde 	xa_init_flags(&dev->cq_tbl, GFP_ATOMIC);
116f3bdbd42SAbhijit Gangurde 
117f3bdbd42SAbhijit Gangurde 	ionic_init_resids(dev);
118f3bdbd42SAbhijit Gangurde 
119f3bdbd42SAbhijit Gangurde 	rc = ionic_rdma_reset_devcmd(dev);
120f3bdbd42SAbhijit Gangurde 	if (rc)
121f3bdbd42SAbhijit Gangurde 		goto err_reset;
122f3bdbd42SAbhijit Gangurde 
123f3bdbd42SAbhijit Gangurde 	rc = ionic_create_rdma_admin(dev);
124f3bdbd42SAbhijit Gangurde 	if (rc)
125f3bdbd42SAbhijit Gangurde 		goto err_admin;
126f3bdbd42SAbhijit Gangurde 
1278d765af5SAbhijit Gangurde 	ibdev = &dev->ibdev;
1288d765af5SAbhijit Gangurde 	ibdev->dev.parent = dev->lif_cfg.hwdev;
1298d765af5SAbhijit Gangurde 
1308d765af5SAbhijit Gangurde 	strscpy(ibdev->name, "ionic_%d", IB_DEVICE_NAME_MAX);
1318d765af5SAbhijit Gangurde 	strscpy(ibdev->node_desc, DEVICE_DESCRIPTION, IB_DEVICE_NODE_DESC_MAX);
1328d765af5SAbhijit Gangurde 
1338d765af5SAbhijit Gangurde 	ibdev->node_type = RDMA_NODE_IB_CA;
1348d765af5SAbhijit Gangurde 	ibdev->phys_port_cnt = 1;
1358d765af5SAbhijit Gangurde 
1368d765af5SAbhijit Gangurde 	/* the first two eq are reserved for async events */
1378d765af5SAbhijit Gangurde 	ibdev->num_comp_vectors = dev->lif_cfg.eq_count - 2;
1388d765af5SAbhijit Gangurde 
1398d765af5SAbhijit Gangurde 	ndev = ionic_lif_netdev(ionic_adev->lif);
1408d765af5SAbhijit Gangurde 	addrconf_ifid_eui48((u8 *)&ibdev->node_guid, ndev);
1418d765af5SAbhijit Gangurde 	rc = ib_device_set_netdev(ibdev, ndev, 1);
1428d765af5SAbhijit Gangurde 	/* ionic_lif_netdev() returns ndev with refcount held */
1438d765af5SAbhijit Gangurde 	dev_put(ndev);
1448d765af5SAbhijit Gangurde 	if (rc)
1458d765af5SAbhijit Gangurde 		goto err_admin;
1468d765af5SAbhijit Gangurde 
147e8521822SAbhijit Gangurde 	ib_set_device_ops(&dev->ibdev, &ionic_dev_ops);
148e8521822SAbhijit Gangurde 
1498d765af5SAbhijit Gangurde 	rc = ib_register_device(ibdev, "ionic_%d", ibdev->dev.parent);
1508d765af5SAbhijit Gangurde 	if (rc)
1518d765af5SAbhijit Gangurde 		goto err_register;
1528d765af5SAbhijit Gangurde 
1538d765af5SAbhijit Gangurde 	return dev;
1548d765af5SAbhijit Gangurde 
1558d765af5SAbhijit Gangurde err_register:
1568d765af5SAbhijit Gangurde err_admin:
157f3bdbd42SAbhijit Gangurde 	ionic_kill_rdma_admin(dev, false);
158f3bdbd42SAbhijit Gangurde 	ionic_destroy_rdma_admin(dev);
159f3bdbd42SAbhijit Gangurde err_reset:
160f3bdbd42SAbhijit Gangurde 	ionic_destroy_resids(dev);
161e8521822SAbhijit Gangurde 	xa_destroy(&dev->qp_tbl);
162f3bdbd42SAbhijit Gangurde 	xa_destroy(&dev->cq_tbl);
1638d765af5SAbhijit Gangurde 	ib_dealloc_device(&dev->ibdev);
1648d765af5SAbhijit Gangurde 
1658d765af5SAbhijit Gangurde 	return ERR_PTR(rc);
1668d765af5SAbhijit Gangurde }
1678d765af5SAbhijit Gangurde 
1688d765af5SAbhijit Gangurde static int ionic_aux_probe(struct auxiliary_device *adev,
1698d765af5SAbhijit Gangurde 			   const struct auxiliary_device_id *id)
1708d765af5SAbhijit Gangurde {
1718d765af5SAbhijit Gangurde 	struct ionic_aux_dev *ionic_adev;
1728d765af5SAbhijit Gangurde 	struct ionic_ibdev *dev;
1738d765af5SAbhijit Gangurde 
1748d765af5SAbhijit Gangurde 	ionic_adev = container_of(adev, struct ionic_aux_dev, adev);
1758d765af5SAbhijit Gangurde 	dev = ionic_create_ibdev(ionic_adev);
1768d765af5SAbhijit Gangurde 	if (IS_ERR(dev))
1778d765af5SAbhijit Gangurde 		return dev_err_probe(&adev->dev, PTR_ERR(dev),
1788d765af5SAbhijit Gangurde 				     "Failed to register ibdev\n");
1798d765af5SAbhijit Gangurde 
1808d765af5SAbhijit Gangurde 	auxiliary_set_drvdata(adev, dev);
1818d765af5SAbhijit Gangurde 	ibdev_dbg(&dev->ibdev, "registered\n");
1828d765af5SAbhijit Gangurde 
1838d765af5SAbhijit Gangurde 	return 0;
1848d765af5SAbhijit Gangurde }
1858d765af5SAbhijit Gangurde 
1868d765af5SAbhijit Gangurde static void ionic_aux_remove(struct auxiliary_device *adev)
1878d765af5SAbhijit Gangurde {
1888d765af5SAbhijit Gangurde 	struct ionic_ibdev *dev = auxiliary_get_drvdata(adev);
1898d765af5SAbhijit Gangurde 
1908d765af5SAbhijit Gangurde 	dev_dbg(&adev->dev, "unregister ibdev\n");
1918d765af5SAbhijit Gangurde 	ionic_destroy_ibdev(dev);
1928d765af5SAbhijit Gangurde 	dev_dbg(&adev->dev, "unregistered\n");
1938d765af5SAbhijit Gangurde }
1948d765af5SAbhijit Gangurde 
1958d765af5SAbhijit Gangurde static const struct auxiliary_device_id ionic_aux_id_table[] = {
1968d765af5SAbhijit Gangurde 	{ .name = "ionic.rdma", },
1978d765af5SAbhijit Gangurde 	{},
1988d765af5SAbhijit Gangurde };
1998d765af5SAbhijit Gangurde 
2008d765af5SAbhijit Gangurde MODULE_DEVICE_TABLE(auxiliary, ionic_aux_id_table);
2018d765af5SAbhijit Gangurde 
2028d765af5SAbhijit Gangurde static struct auxiliary_driver ionic_aux_r_driver = {
2038d765af5SAbhijit Gangurde 	.name = "rdma",
2048d765af5SAbhijit Gangurde 	.probe = ionic_aux_probe,
2058d765af5SAbhijit Gangurde 	.remove = ionic_aux_remove,
2068d765af5SAbhijit Gangurde 	.id_table = ionic_aux_id_table,
2078d765af5SAbhijit Gangurde };
2088d765af5SAbhijit Gangurde 
2098d765af5SAbhijit Gangurde static int __init ionic_mod_init(void)
2108d765af5SAbhijit Gangurde {
2118d765af5SAbhijit Gangurde 	int rc;
2128d765af5SAbhijit Gangurde 
213e8521822SAbhijit Gangurde 	ionic_evt_workq = create_workqueue(KBUILD_MODNAME "-evt");
214f3bdbd42SAbhijit Gangurde 	if (!ionic_evt_workq)
215f3bdbd42SAbhijit Gangurde 		return -ENOMEM;
216f3bdbd42SAbhijit Gangurde 
2178d765af5SAbhijit Gangurde 	rc = auxiliary_driver_register(&ionic_aux_r_driver);
2188d765af5SAbhijit Gangurde 	if (rc)
2198d765af5SAbhijit Gangurde 		goto err_aux;
2208d765af5SAbhijit Gangurde 
2218d765af5SAbhijit Gangurde 	return 0;
2228d765af5SAbhijit Gangurde 
2238d765af5SAbhijit Gangurde err_aux:
224f3bdbd42SAbhijit Gangurde 	destroy_workqueue(ionic_evt_workq);
225f3bdbd42SAbhijit Gangurde 
2268d765af5SAbhijit Gangurde 	return rc;
2278d765af5SAbhijit Gangurde }
2288d765af5SAbhijit Gangurde 
2298d765af5SAbhijit Gangurde static void __exit ionic_mod_exit(void)
2308d765af5SAbhijit Gangurde {
2318d765af5SAbhijit Gangurde 	auxiliary_driver_unregister(&ionic_aux_r_driver);
232f3bdbd42SAbhijit Gangurde 	destroy_workqueue(ionic_evt_workq);
2338d765af5SAbhijit Gangurde }
2348d765af5SAbhijit Gangurde 
2358d765af5SAbhijit Gangurde module_init(ionic_mod_init);
2368d765af5SAbhijit Gangurde module_exit(ionic_mod_exit);
237