xref: /linux/drivers/infiniband/hw/ionic/ionic_ibdev.c (revision f3bdbd42702c6b10ebe627828c76ef51c68e4355)
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 void ionic_init_resids(struct ionic_ibdev *dev)
19 {
20 	ionic_resid_init(&dev->inuse_cqid, dev->lif_cfg.cq_count);
21 	dev->half_cqid_udma_shift =
22 		order_base_2(dev->lif_cfg.cq_count / dev->lif_cfg.udma_count);
23 	ionic_resid_init(&dev->inuse_pdid, IONIC_MAX_PD);
24 	ionic_resid_init(&dev->inuse_ahid, dev->lif_cfg.nahs_per_lif);
25 	ionic_resid_init(&dev->inuse_mrid, dev->lif_cfg.nmrs_per_lif);
26 	/* skip reserved lkey */
27 	dev->next_mrkey = 1;
28 	ionic_resid_init(&dev->inuse_qpid, dev->lif_cfg.qp_count);
29 	/* skip reserved SMI and GSI qpids */
30 	dev->half_qpid_udma_shift =
31 		order_base_2(dev->lif_cfg.qp_count / dev->lif_cfg.udma_count);
32 	ionic_resid_init(&dev->inuse_dbid, dev->lif_cfg.dbid_count);
33 }
34 
35 static void ionic_destroy_resids(struct ionic_ibdev *dev)
36 {
37 	ionic_resid_destroy(&dev->inuse_cqid);
38 	ionic_resid_destroy(&dev->inuse_pdid);
39 	ionic_resid_destroy(&dev->inuse_ahid);
40 	ionic_resid_destroy(&dev->inuse_mrid);
41 	ionic_resid_destroy(&dev->inuse_qpid);
42 	ionic_resid_destroy(&dev->inuse_dbid);
43 }
44 
45 static void ionic_destroy_ibdev(struct ionic_ibdev *dev)
46 {
47 	ionic_kill_rdma_admin(dev, false);
48 	ib_unregister_device(&dev->ibdev);
49 	ionic_destroy_rdma_admin(dev);
50 	ionic_destroy_resids(dev);
51 	WARN_ON(!xa_empty(&dev->cq_tbl));
52 	xa_destroy(&dev->cq_tbl);
53 	ib_dealloc_device(&dev->ibdev);
54 }
55 
56 static struct ionic_ibdev *ionic_create_ibdev(struct ionic_aux_dev *ionic_adev)
57 {
58 	struct ib_device *ibdev;
59 	struct ionic_ibdev *dev;
60 	struct net_device *ndev;
61 	int rc;
62 
63 	dev = ib_alloc_device(ionic_ibdev, ibdev);
64 	if (!dev)
65 		return ERR_PTR(-EINVAL);
66 
67 	ionic_fill_lif_cfg(ionic_adev->lif, &dev->lif_cfg);
68 
69 	xa_init_flags(&dev->cq_tbl, GFP_ATOMIC);
70 
71 	ionic_init_resids(dev);
72 
73 	rc = ionic_rdma_reset_devcmd(dev);
74 	if (rc)
75 		goto err_reset;
76 
77 	rc = ionic_create_rdma_admin(dev);
78 	if (rc)
79 		goto err_admin;
80 
81 	ibdev = &dev->ibdev;
82 	ibdev->dev.parent = dev->lif_cfg.hwdev;
83 
84 	strscpy(ibdev->name, "ionic_%d", IB_DEVICE_NAME_MAX);
85 	strscpy(ibdev->node_desc, DEVICE_DESCRIPTION, IB_DEVICE_NODE_DESC_MAX);
86 
87 	ibdev->node_type = RDMA_NODE_IB_CA;
88 	ibdev->phys_port_cnt = 1;
89 
90 	/* the first two eq are reserved for async events */
91 	ibdev->num_comp_vectors = dev->lif_cfg.eq_count - 2;
92 
93 	ndev = ionic_lif_netdev(ionic_adev->lif);
94 	addrconf_ifid_eui48((u8 *)&ibdev->node_guid, ndev);
95 	rc = ib_device_set_netdev(ibdev, ndev, 1);
96 	/* ionic_lif_netdev() returns ndev with refcount held */
97 	dev_put(ndev);
98 	if (rc)
99 		goto err_admin;
100 
101 	rc = ib_register_device(ibdev, "ionic_%d", ibdev->dev.parent);
102 	if (rc)
103 		goto err_register;
104 
105 	return dev;
106 
107 err_register:
108 err_admin:
109 	ionic_kill_rdma_admin(dev, false);
110 	ionic_destroy_rdma_admin(dev);
111 err_reset:
112 	ionic_destroy_resids(dev);
113 	xa_destroy(&dev->cq_tbl);
114 	ib_dealloc_device(&dev->ibdev);
115 
116 	return ERR_PTR(rc);
117 }
118 
119 static int ionic_aux_probe(struct auxiliary_device *adev,
120 			   const struct auxiliary_device_id *id)
121 {
122 	struct ionic_aux_dev *ionic_adev;
123 	struct ionic_ibdev *dev;
124 
125 	ionic_adev = container_of(adev, struct ionic_aux_dev, adev);
126 	dev = ionic_create_ibdev(ionic_adev);
127 	if (IS_ERR(dev))
128 		return dev_err_probe(&adev->dev, PTR_ERR(dev),
129 				     "Failed to register ibdev\n");
130 
131 	auxiliary_set_drvdata(adev, dev);
132 	ibdev_dbg(&dev->ibdev, "registered\n");
133 
134 	return 0;
135 }
136 
137 static void ionic_aux_remove(struct auxiliary_device *adev)
138 {
139 	struct ionic_ibdev *dev = auxiliary_get_drvdata(adev);
140 
141 	dev_dbg(&adev->dev, "unregister ibdev\n");
142 	ionic_destroy_ibdev(dev);
143 	dev_dbg(&adev->dev, "unregistered\n");
144 }
145 
146 static const struct auxiliary_device_id ionic_aux_id_table[] = {
147 	{ .name = "ionic.rdma", },
148 	{},
149 };
150 
151 MODULE_DEVICE_TABLE(auxiliary, ionic_aux_id_table);
152 
153 static struct auxiliary_driver ionic_aux_r_driver = {
154 	.name = "rdma",
155 	.probe = ionic_aux_probe,
156 	.remove = ionic_aux_remove,
157 	.id_table = ionic_aux_id_table,
158 };
159 
160 static int __init ionic_mod_init(void)
161 {
162 	int rc;
163 
164 	ionic_evt_workq = create_workqueue(DRIVER_NAME "-evt");
165 	if (!ionic_evt_workq)
166 		return -ENOMEM;
167 
168 	rc = auxiliary_driver_register(&ionic_aux_r_driver);
169 	if (rc)
170 		goto err_aux;
171 
172 	return 0;
173 
174 err_aux:
175 	destroy_workqueue(ionic_evt_workq);
176 
177 	return rc;
178 }
179 
180 static void __exit ionic_mod_exit(void)
181 {
182 	auxiliary_driver_unregister(&ionic_aux_r_driver);
183 	destroy_workqueue(ionic_evt_workq);
184 }
185 
186 module_init(ionic_mod_init);
187 module_exit(ionic_mod_exit);
188