xref: /linux/drivers/infiniband/hw/bng_re/bng_dev.c (revision 53310b698f3cf601dfdc6c3b2b60c7cb275b1199)
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2025 Broadcom.
3 
4 #include <linux/module.h>
5 #include <linux/pci.h>
6 #include <linux/auxiliary_bus.h>
7 
8 #include <rdma/ib_verbs.h>
9 
10 #include "bng_res.h"
11 #include "bng_fw.h"
12 #include "bng_re.h"
13 #include "bnge.h"
14 #include "bnge_hwrm.h"
15 #include "bnge_auxr.h"
16 
17 MODULE_AUTHOR("Siva Reddy Kallam <siva.kallam@broadcom.com>");
18 MODULE_DESCRIPTION(BNG_RE_DESC);
19 MODULE_LICENSE("Dual BSD/GPL");
20 
21 static struct bng_re_dev *bng_re_dev_add(struct auxiliary_device *adev,
22 					 struct bnge_auxr_dev *aux_dev)
23 {
24 	struct bng_re_dev *rdev;
25 
26 	/* Allocate bng_re_dev instance */
27 	rdev = ib_alloc_device(bng_re_dev, ibdev);
28 	if (!rdev) {
29 		pr_err("%s: bng_re_dev allocation failure!", KBUILD_MODNAME);
30 		return NULL;
31 	}
32 
33 	/* Assign auxiliary device specific data */
34 	rdev->netdev = aux_dev->net;
35 	rdev->aux_dev = aux_dev;
36 	rdev->adev = adev;
37 	rdev->fn_id = rdev->aux_dev->pdev->devfn;
38 
39 	return rdev;
40 }
41 
42 
43 static int bng_re_register_netdev(struct bng_re_dev *rdev)
44 {
45 	struct bnge_auxr_dev *aux_dev;
46 
47 	aux_dev = rdev->aux_dev;
48 	return bnge_register_dev(aux_dev, rdev->adev);
49 }
50 
51 static void bng_re_destroy_chip_ctx(struct bng_re_dev *rdev)
52 {
53 	struct bng_re_chip_ctx *chip_ctx;
54 
55 	if (!rdev->chip_ctx)
56 		return;
57 
58 	chip_ctx = rdev->chip_ctx;
59 	rdev->chip_ctx = NULL;
60 	rdev->rcfw.res = NULL;
61 	rdev->bng_res.cctx = NULL;
62 	rdev->bng_res.pdev = NULL;
63 	kfree(chip_ctx);
64 }
65 
66 static int bng_re_setup_chip_ctx(struct bng_re_dev *rdev)
67 {
68 	struct bng_re_chip_ctx *chip_ctx;
69 	struct bnge_auxr_dev *aux_dev;
70 
71 	aux_dev = rdev->aux_dev;
72 	rdev->bng_res.pdev = aux_dev->pdev;
73 	rdev->rcfw.res = &rdev->bng_res;
74 	chip_ctx = kzalloc(sizeof(*chip_ctx), GFP_KERNEL);
75 	if (!chip_ctx)
76 		return -ENOMEM;
77 	chip_ctx->chip_num = aux_dev->chip_num;
78 	chip_ctx->hw_stats_size = aux_dev->hw_ring_stats_size;
79 
80 	rdev->chip_ctx = chip_ctx;
81 	rdev->bng_res.cctx = rdev->chip_ctx;
82 
83 	return 0;
84 }
85 
86 static void bng_re_init_hwrm_hdr(struct input *hdr, u16 opcd)
87 {
88 	hdr->req_type = cpu_to_le16(opcd);
89 	hdr->cmpl_ring = cpu_to_le16(-1);
90 	hdr->target_id = cpu_to_le16(-1);
91 }
92 
93 static void bng_re_fill_fw_msg(struct bnge_fw_msg *fw_msg, void *msg,
94 			       int msg_len, void *resp, int resp_max_len,
95 			       int timeout)
96 {
97 	fw_msg->msg = msg;
98 	fw_msg->msg_len = msg_len;
99 	fw_msg->resp = resp;
100 	fw_msg->resp_max_len = resp_max_len;
101 	fw_msg->timeout = timeout;
102 }
103 
104 static void bng_re_query_hwrm_version(struct bng_re_dev *rdev)
105 {
106 	struct bnge_auxr_dev *aux_dev = rdev->aux_dev;
107 	struct hwrm_ver_get_output ver_get_resp = {};
108 	struct hwrm_ver_get_input ver_get_req = {};
109 	struct bng_re_chip_ctx *cctx;
110 	struct bnge_fw_msg fw_msg = {};
111 	int rc;
112 
113 	bng_re_init_hwrm_hdr((void *)&ver_get_req, HWRM_VER_GET);
114 	ver_get_req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
115 	ver_get_req.hwrm_intf_min = HWRM_VERSION_MINOR;
116 	ver_get_req.hwrm_intf_upd = HWRM_VERSION_UPDATE;
117 	bng_re_fill_fw_msg(&fw_msg, (void *)&ver_get_req, sizeof(ver_get_req),
118 			    (void *)&ver_get_resp, sizeof(ver_get_resp),
119 			    BNGE_DFLT_HWRM_CMD_TIMEOUT);
120 	rc = bnge_send_msg(aux_dev, &fw_msg);
121 	if (rc) {
122 		ibdev_err(&rdev->ibdev, "Failed to query HW version, rc = 0x%x",
123 			  rc);
124 		return;
125 	}
126 
127 	cctx = rdev->chip_ctx;
128 	cctx->hwrm_intf_ver =
129 		(u64)le16_to_cpu(ver_get_resp.hwrm_intf_major) << 48 |
130 		(u64)le16_to_cpu(ver_get_resp.hwrm_intf_minor) << 32 |
131 		(u64)le16_to_cpu(ver_get_resp.hwrm_intf_build) << 16 |
132 		le16_to_cpu(ver_get_resp.hwrm_intf_patch);
133 
134 	cctx->hwrm_cmd_max_timeout = le16_to_cpu(ver_get_resp.max_req_timeout);
135 
136 	if (!cctx->hwrm_cmd_max_timeout)
137 		cctx->hwrm_cmd_max_timeout = BNG_ROCE_FW_MAX_TIMEOUT;
138 }
139 
140 static void bng_re_dev_uninit(struct bng_re_dev *rdev)
141 {
142 	bng_re_free_rcfw_channel(&rdev->rcfw);
143 	bng_re_destroy_chip_ctx(rdev);
144 	if (test_and_clear_bit(BNG_RE_FLAG_NETDEV_REGISTERED, &rdev->flags))
145 		bnge_unregister_dev(rdev->aux_dev);
146 }
147 
148 static int bng_re_dev_init(struct bng_re_dev *rdev)
149 {
150 	int rc;
151 
152 	/* Registered a new RoCE device instance to netdev */
153 	rc = bng_re_register_netdev(rdev);
154 	if (rc) {
155 		ibdev_err(&rdev->ibdev,
156 				"Failed to register with netedev: %#x\n", rc);
157 		return -EINVAL;
158 	}
159 
160 	set_bit(BNG_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
161 
162 	if (rdev->aux_dev->auxr_info->msix_requested < BNG_RE_MIN_MSIX) {
163 		ibdev_err(&rdev->ibdev,
164 			  "RoCE requires minimum 2 MSI-X vectors, but only %d reserved\n",
165 			  rdev->aux_dev->auxr_info->msix_requested);
166 		bnge_unregister_dev(rdev->aux_dev);
167 		clear_bit(BNG_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
168 		return -EINVAL;
169 	}
170 	ibdev_dbg(&rdev->ibdev, "Got %d MSI-X vectors\n",
171 		  rdev->aux_dev->auxr_info->msix_requested);
172 
173 	rc = bng_re_setup_chip_ctx(rdev);
174 	if (rc) {
175 		bnge_unregister_dev(rdev->aux_dev);
176 		clear_bit(BNG_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
177 		ibdev_err(&rdev->ibdev, "Failed to get chip context\n");
178 		return -EINVAL;
179 	}
180 
181 	bng_re_query_hwrm_version(rdev);
182 
183 	rc = bng_re_alloc_fw_channel(&rdev->bng_res, &rdev->rcfw);
184 	if (rc) {
185 		ibdev_err(&rdev->ibdev,
186 			  "Failed to allocate RCFW Channel: %#x\n", rc);
187 		goto fail;
188 	}
189 
190 	return 0;
191 
192 fail:
193 	bng_re_dev_uninit(rdev);
194 	return rc;
195 }
196 
197 static int bng_re_add_device(struct auxiliary_device *adev)
198 {
199 	struct bnge_auxr_priv *auxr_priv =
200 		container_of(adev, struct bnge_auxr_priv, aux_dev);
201 	struct bng_re_en_dev_info *dev_info;
202 	struct bng_re_dev *rdev;
203 	int rc;
204 
205 	dev_info = auxiliary_get_drvdata(adev);
206 
207 	rdev = bng_re_dev_add(adev, auxr_priv->auxr_dev);
208 	if (!rdev) {
209 		rc = -ENOMEM;
210 		goto exit;
211 	}
212 
213 	dev_info->rdev = rdev;
214 
215 	rc = bng_re_dev_init(rdev);
216 	if (rc)
217 		goto re_dev_dealloc;
218 
219 	return 0;
220 
221 re_dev_dealloc:
222 	ib_dealloc_device(&rdev->ibdev);
223 exit:
224 	return rc;
225 }
226 
227 
228 static void bng_re_remove_device(struct bng_re_dev *rdev,
229 				 struct auxiliary_device *aux_dev)
230 {
231 	bng_re_dev_uninit(rdev);
232 	ib_dealloc_device(&rdev->ibdev);
233 }
234 
235 
236 static int bng_re_probe(struct auxiliary_device *adev,
237 			const struct auxiliary_device_id *id)
238 {
239 	struct bnge_auxr_priv *aux_priv =
240 		container_of(adev, struct bnge_auxr_priv, aux_dev);
241 	struct bng_re_en_dev_info *en_info;
242 	int rc;
243 
244 	en_info = kzalloc(sizeof(*en_info), GFP_KERNEL);
245 	if (!en_info)
246 		return -ENOMEM;
247 
248 	en_info->auxr_dev = aux_priv->auxr_dev;
249 
250 	auxiliary_set_drvdata(adev, en_info);
251 
252 	rc = bng_re_add_device(adev);
253 	if (rc)
254 		kfree(en_info);
255 
256 	return rc;
257 }
258 
259 static void bng_re_remove(struct auxiliary_device *adev)
260 {
261 	struct bng_re_en_dev_info *dev_info = auxiliary_get_drvdata(adev);
262 	struct bng_re_dev *rdev;
263 
264 	rdev = dev_info->rdev;
265 
266 	if (rdev)
267 		bng_re_remove_device(rdev, adev);
268 	kfree(dev_info);
269 }
270 
271 static const struct auxiliary_device_id bng_re_id_table[] = {
272 	{ .name = BNG_RE_ADEV_NAME ".rdma", },
273 	{},
274 };
275 
276 MODULE_DEVICE_TABLE(auxiliary, bng_re_id_table);
277 
278 static struct auxiliary_driver bng_re_driver = {
279 	.name = "rdma",
280 	.probe = bng_re_probe,
281 	.remove = bng_re_remove,
282 	.id_table = bng_re_id_table,
283 };
284 
285 static int __init bng_re_mod_init(void)
286 {
287 	int rc;
288 
289 
290 	rc = auxiliary_driver_register(&bng_re_driver);
291 	if (rc) {
292 		pr_err("%s: Failed to register auxiliary driver\n",
293 		       KBUILD_MODNAME);
294 	}
295 	return rc;
296 }
297 
298 static void __exit bng_re_mod_exit(void)
299 {
300 	auxiliary_driver_unregister(&bng_re_driver);
301 }
302 
303 module_init(bng_re_mod_init);
304 module_exit(bng_re_mod_exit);
305