xref: /linux/drivers/infiniband/hw/ionic/ionic_ibdev.c (revision b83c62055b6faabb444b2f8f3355420927cc39fd)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2018-2025, Advanced Micro Devices, Inc. */
3 
4 #include <linux/module.h>
5 #include <linux/printk.h>
6 #include <net/addrconf.h>
7 
8 #include "ionic_ibdev.h"
9 
10 #define DRIVER_DESCRIPTION "AMD Pensando RoCE HCA driver"
11 #define DEVICE_DESCRIPTION "AMD Pensando RoCE HCA"
12 
13 MODULE_AUTHOR("Allen Hubbe <allen.hubbe@amd.com>");
14 MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
15 MODULE_LICENSE("GPL");
16 MODULE_IMPORT_NS("NET_IONIC");
17 
18 static const struct ib_device_ops ionic_dev_ops = {
19 	.owner = THIS_MODULE,
20 	.driver_id = RDMA_DRIVER_IONIC,
21 	.uverbs_abi_ver = IONIC_ABI_VERSION,
22 
23 	.alloc_ucontext = ionic_alloc_ucontext,
24 	.dealloc_ucontext = ionic_dealloc_ucontext,
25 	.mmap = ionic_mmap,
26 	.mmap_free = ionic_mmap_free,
27 	.alloc_pd = ionic_alloc_pd,
28 	.dealloc_pd = ionic_dealloc_pd,
29 	.create_ah = ionic_create_ah,
30 	.query_ah = ionic_query_ah,
31 	.destroy_ah = ionic_destroy_ah,
32 	.create_user_ah = ionic_create_ah,
33 	.get_dma_mr = ionic_get_dma_mr,
34 	.reg_user_mr = ionic_reg_user_mr,
35 	.reg_user_mr_dmabuf = ionic_reg_user_mr_dmabuf,
36 	.dereg_mr = ionic_dereg_mr,
37 	.alloc_mr = ionic_alloc_mr,
38 	.map_mr_sg = ionic_map_mr_sg,
39 	.alloc_mw = ionic_alloc_mw,
40 	.dealloc_mw = ionic_dealloc_mw,
41 	.create_cq = ionic_create_cq,
42 	.destroy_cq = ionic_destroy_cq,
43 	.create_qp = ionic_create_qp,
44 	.modify_qp = ionic_modify_qp,
45 	.query_qp = ionic_query_qp,
46 	.destroy_qp = ionic_destroy_qp,
47 
48 	.post_send = ionic_post_send,
49 	.post_recv = ionic_post_recv,
50 	.poll_cq = ionic_poll_cq,
51 	.req_notify_cq = ionic_req_notify_cq,
52 
53 	INIT_RDMA_OBJ_SIZE(ib_ucontext, ionic_ctx, ibctx),
54 	INIT_RDMA_OBJ_SIZE(ib_pd, ionic_pd, ibpd),
55 	INIT_RDMA_OBJ_SIZE(ib_ah, ionic_ah, ibah),
56 	INIT_RDMA_OBJ_SIZE(ib_cq, ionic_vcq, ibcq),
57 	INIT_RDMA_OBJ_SIZE(ib_qp, ionic_qp, ibqp),
58 	INIT_RDMA_OBJ_SIZE(ib_mw, ionic_mr, ibmw),
59 };
60 
61 static void ionic_init_resids(struct ionic_ibdev *dev)
62 {
63 	ionic_resid_init(&dev->inuse_cqid, dev->lif_cfg.cq_count);
64 	dev->half_cqid_udma_shift =
65 		order_base_2(dev->lif_cfg.cq_count / dev->lif_cfg.udma_count);
66 	ionic_resid_init(&dev->inuse_pdid, IONIC_MAX_PD);
67 	ionic_resid_init(&dev->inuse_ahid, dev->lif_cfg.nahs_per_lif);
68 	ionic_resid_init(&dev->inuse_mrid, dev->lif_cfg.nmrs_per_lif);
69 	/* skip reserved lkey */
70 	dev->next_mrkey = 1;
71 	ionic_resid_init(&dev->inuse_qpid, dev->lif_cfg.qp_count);
72 	/* skip reserved SMI and GSI qpids */
73 	dev->half_qpid_udma_shift =
74 		order_base_2(dev->lif_cfg.qp_count / dev->lif_cfg.udma_count);
75 	ionic_resid_init(&dev->inuse_dbid, dev->lif_cfg.dbid_count);
76 }
77 
78 static void ionic_destroy_resids(struct ionic_ibdev *dev)
79 {
80 	ionic_resid_destroy(&dev->inuse_cqid);
81 	ionic_resid_destroy(&dev->inuse_pdid);
82 	ionic_resid_destroy(&dev->inuse_ahid);
83 	ionic_resid_destroy(&dev->inuse_mrid);
84 	ionic_resid_destroy(&dev->inuse_qpid);
85 	ionic_resid_destroy(&dev->inuse_dbid);
86 }
87 
88 static void ionic_destroy_ibdev(struct ionic_ibdev *dev)
89 {
90 	ionic_kill_rdma_admin(dev, false);
91 	ib_unregister_device(&dev->ibdev);
92 	ionic_destroy_rdma_admin(dev);
93 	ionic_destroy_resids(dev);
94 	WARN_ON(!xa_empty(&dev->qp_tbl));
95 	xa_destroy(&dev->qp_tbl);
96 	WARN_ON(!xa_empty(&dev->cq_tbl));
97 	xa_destroy(&dev->cq_tbl);
98 	ib_dealloc_device(&dev->ibdev);
99 }
100 
101 static struct ionic_ibdev *ionic_create_ibdev(struct ionic_aux_dev *ionic_adev)
102 {
103 	struct ib_device *ibdev;
104 	struct ionic_ibdev *dev;
105 	struct net_device *ndev;
106 	int rc;
107 
108 	dev = ib_alloc_device(ionic_ibdev, ibdev);
109 	if (!dev)
110 		return ERR_PTR(-EINVAL);
111 
112 	ionic_fill_lif_cfg(ionic_adev->lif, &dev->lif_cfg);
113 
114 	xa_init_flags(&dev->qp_tbl, GFP_ATOMIC);
115 	xa_init_flags(&dev->cq_tbl, GFP_ATOMIC);
116 
117 	ionic_init_resids(dev);
118 
119 	rc = ionic_rdma_reset_devcmd(dev);
120 	if (rc)
121 		goto err_reset;
122 
123 	rc = ionic_create_rdma_admin(dev);
124 	if (rc)
125 		goto err_admin;
126 
127 	ibdev = &dev->ibdev;
128 	ibdev->dev.parent = dev->lif_cfg.hwdev;
129 
130 	strscpy(ibdev->name, "ionic_%d", IB_DEVICE_NAME_MAX);
131 	strscpy(ibdev->node_desc, DEVICE_DESCRIPTION, IB_DEVICE_NODE_DESC_MAX);
132 
133 	ibdev->node_type = RDMA_NODE_IB_CA;
134 	ibdev->phys_port_cnt = 1;
135 
136 	/* the first two eq are reserved for async events */
137 	ibdev->num_comp_vectors = dev->lif_cfg.eq_count - 2;
138 
139 	ndev = ionic_lif_netdev(ionic_adev->lif);
140 	addrconf_ifid_eui48((u8 *)&ibdev->node_guid, ndev);
141 	rc = ib_device_set_netdev(ibdev, ndev, 1);
142 	/* ionic_lif_netdev() returns ndev with refcount held */
143 	dev_put(ndev);
144 	if (rc)
145 		goto err_admin;
146 
147 	ib_set_device_ops(&dev->ibdev, &ionic_dev_ops);
148 
149 	rc = ib_register_device(ibdev, "ionic_%d", ibdev->dev.parent);
150 	if (rc)
151 		goto err_register;
152 
153 	return dev;
154 
155 err_register:
156 err_admin:
157 	ionic_kill_rdma_admin(dev, false);
158 	ionic_destroy_rdma_admin(dev);
159 err_reset:
160 	ionic_destroy_resids(dev);
161 	xa_destroy(&dev->qp_tbl);
162 	xa_destroy(&dev->cq_tbl);
163 	ib_dealloc_device(&dev->ibdev);
164 
165 	return ERR_PTR(rc);
166 }
167 
168 static int ionic_aux_probe(struct auxiliary_device *adev,
169 			   const struct auxiliary_device_id *id)
170 {
171 	struct ionic_aux_dev *ionic_adev;
172 	struct ionic_ibdev *dev;
173 
174 	ionic_adev = container_of(adev, struct ionic_aux_dev, adev);
175 	dev = ionic_create_ibdev(ionic_adev);
176 	if (IS_ERR(dev))
177 		return dev_err_probe(&adev->dev, PTR_ERR(dev),
178 				     "Failed to register ibdev\n");
179 
180 	auxiliary_set_drvdata(adev, dev);
181 	ibdev_dbg(&dev->ibdev, "registered\n");
182 
183 	return 0;
184 }
185 
186 static void ionic_aux_remove(struct auxiliary_device *adev)
187 {
188 	struct ionic_ibdev *dev = auxiliary_get_drvdata(adev);
189 
190 	dev_dbg(&adev->dev, "unregister ibdev\n");
191 	ionic_destroy_ibdev(dev);
192 	dev_dbg(&adev->dev, "unregistered\n");
193 }
194 
195 static const struct auxiliary_device_id ionic_aux_id_table[] = {
196 	{ .name = "ionic.rdma", },
197 	{},
198 };
199 
200 MODULE_DEVICE_TABLE(auxiliary, ionic_aux_id_table);
201 
202 static struct auxiliary_driver ionic_aux_r_driver = {
203 	.name = "rdma",
204 	.probe = ionic_aux_probe,
205 	.remove = ionic_aux_remove,
206 	.id_table = ionic_aux_id_table,
207 };
208 
209 static int __init ionic_mod_init(void)
210 {
211 	int rc;
212 
213 	ionic_evt_workq = create_workqueue(KBUILD_MODNAME "-evt");
214 	if (!ionic_evt_workq)
215 		return -ENOMEM;
216 
217 	rc = auxiliary_driver_register(&ionic_aux_r_driver);
218 	if (rc)
219 		goto err_aux;
220 
221 	return 0;
222 
223 err_aux:
224 	destroy_workqueue(ionic_evt_workq);
225 
226 	return rc;
227 }
228 
229 static void __exit ionic_mod_exit(void)
230 {
231 	auxiliary_driver_unregister(&ionic_aux_r_driver);
232 	destroy_workqueue(ionic_evt_workq);
233 }
234 
235 module_init(ionic_mod_init);
236 module_exit(ionic_mod_exit);
237