xref: /linux/drivers/infiniband/hw/bng_re/bng_dev.c (revision 9270102a00aabbe4d1bbb6890d514b01f1c42989)
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_sp.h"
12 #include "bng_fw.h"
13 #include "bnge.h"
14 #include "bnge_auxr.h"
15 #include "bng_re.h"
16 #include "bnge_hwrm.h"
17 #include "bng_debugfs.h"
18 
19 MODULE_AUTHOR("Siva Reddy Kallam <siva.kallam@broadcom.com>");
20 MODULE_DESCRIPTION(BNG_RE_DESC);
21 MODULE_LICENSE("Dual BSD/GPL");
22 
23 static struct bng_re_dev *bng_re_dev_add(struct auxiliary_device *adev,
24 					 struct bnge_auxr_dev *aux_dev)
25 {
26 	struct bng_re_dev *rdev;
27 
28 	/* Allocate bng_re_dev instance */
29 	rdev = ib_alloc_device(bng_re_dev, ibdev);
30 	if (!rdev) {
31 		pr_err("%s: bng_re_dev allocation failure!", KBUILD_MODNAME);
32 		return NULL;
33 	}
34 
35 	/* Assign auxiliary device specific data */
36 	rdev->netdev = aux_dev->net;
37 	rdev->aux_dev = aux_dev;
38 	rdev->adev = adev;
39 	rdev->fn_id = rdev->aux_dev->pdev->devfn;
40 
41 	return rdev;
42 }
43 
44 
45 static int bng_re_register_netdev(struct bng_re_dev *rdev)
46 {
47 	struct bnge_auxr_dev *aux_dev;
48 
49 	aux_dev = rdev->aux_dev;
50 	return bnge_register_dev(aux_dev, rdev->adev);
51 }
52 
53 static void bng_re_destroy_chip_ctx(struct bng_re_dev *rdev)
54 {
55 	struct bng_re_chip_ctx *chip_ctx;
56 
57 	kfree(rdev->dev_attr);
58 	rdev->dev_attr = NULL;
59 
60 	chip_ctx = rdev->chip_ctx;
61 	rdev->chip_ctx = NULL;
62 	rdev->rcfw.res = NULL;
63 	rdev->bng_res.cctx = NULL;
64 	rdev->bng_res.pdev = NULL;
65 	kfree(chip_ctx);
66 }
67 
68 static int bng_re_setup_chip_ctx(struct bng_re_dev *rdev)
69 {
70 	struct bng_re_chip_ctx *chip_ctx;
71 	struct bnge_auxr_dev *aux_dev;
72 	int rc = -ENOMEM;
73 
74 	aux_dev = rdev->aux_dev;
75 	rdev->bng_res.pdev = aux_dev->pdev;
76 	rdev->rcfw.res = &rdev->bng_res;
77 	chip_ctx = kzalloc_obj(*chip_ctx);
78 	if (!chip_ctx)
79 		return -ENOMEM;
80 	chip_ctx->chip_num = aux_dev->chip_num;
81 	chip_ctx->hw_stats_size = aux_dev->hw_ring_stats_size;
82 
83 	rdev->chip_ctx = chip_ctx;
84 	rdev->bng_res.cctx = rdev->chip_ctx;
85 	rdev->dev_attr = kzalloc_obj(*rdev->dev_attr);
86 	if (!rdev->dev_attr)
87 		goto free_chip_ctx;
88 	rdev->bng_res.dattr = rdev->dev_attr;
89 
90 	return 0;
91 free_chip_ctx:
92 	kfree(rdev->chip_ctx);
93 	rdev->chip_ctx = NULL;
94 	return rc;
95 }
96 
97 static void bng_re_init_hwrm_hdr(struct input *hdr, u16 opcd)
98 {
99 	hdr->req_type = cpu_to_le16(opcd);
100 	hdr->cmpl_ring = cpu_to_le16(-1);
101 	hdr->target_id = cpu_to_le16(-1);
102 }
103 
104 static void bng_re_fill_fw_msg(struct bnge_fw_msg *fw_msg, void *msg,
105 			       int msg_len, void *resp, int resp_max_len,
106 			       int timeout)
107 {
108 	fw_msg->msg = msg;
109 	fw_msg->msg_len = msg_len;
110 	fw_msg->resp = resp;
111 	fw_msg->resp_max_len = resp_max_len;
112 	fw_msg->timeout = timeout;
113 }
114 
115 static int bng_re_net_ring_free(struct bng_re_dev *rdev,
116 				u16 fw_ring_id, int type)
117 {
118 	struct bnge_auxr_dev *aux_dev = rdev->aux_dev;
119 	struct hwrm_ring_free_input req = {};
120 	struct hwrm_ring_free_output resp;
121 	struct bnge_fw_msg fw_msg = {};
122 	int rc = -EINVAL;
123 
124 	bng_re_init_hwrm_hdr((void *)&req, HWRM_RING_FREE);
125 	req.ring_type = type;
126 	req.ring_id = cpu_to_le16(fw_ring_id);
127 	bng_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp,
128 			    sizeof(resp), BNGE_DFLT_HWRM_CMD_TIMEOUT);
129 	rc = bnge_send_msg(aux_dev, &fw_msg);
130 	if (rc)
131 		ibdev_err(&rdev->ibdev, "Failed to free HW ring:%d :%#x",
132 			  req.ring_id, rc);
133 	return rc;
134 }
135 
136 static int bng_re_net_ring_alloc(struct bng_re_dev *rdev,
137 				 struct bng_re_ring_attr *ring_attr,
138 				 u16 *fw_ring_id)
139 {
140 	struct bnge_auxr_dev *aux_dev = rdev->aux_dev;
141 	struct hwrm_ring_alloc_input req = {};
142 	struct hwrm_ring_alloc_output resp;
143 	struct bnge_fw_msg fw_msg = {};
144 	int rc;
145 
146 	bng_re_init_hwrm_hdr((void *)&req, HWRM_RING_ALLOC);
147 	req.enables = 0;
148 	req.page_tbl_addr =  cpu_to_le64(ring_attr->dma_arr[0]);
149 	if (ring_attr->pages > 1) {
150 		/* Page size is in log2 units */
151 		req.page_size = BNGE_PAGE_SHIFT;
152 		req.page_tbl_depth = 1;
153 	}
154 	req.fbo = 0;
155 	/* Association of ring index with doorbell index and MSIX number */
156 	req.logical_id = cpu_to_le16(ring_attr->lrid);
157 	req.length = cpu_to_le32(ring_attr->depth + 1);
158 	req.ring_type = ring_attr->type;
159 	req.int_mode = ring_attr->mode;
160 	bng_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp,
161 			   sizeof(resp), BNGE_DFLT_HWRM_CMD_TIMEOUT);
162 	rc = bnge_send_msg(aux_dev, &fw_msg);
163 	if (!rc)
164 		*fw_ring_id = le16_to_cpu(resp.ring_id);
165 
166 	return rc;
167 }
168 
169 static int bng_re_stats_ctx_free(struct bng_re_dev *rdev)
170 {
171 	struct bnge_auxr_dev *aux_dev = rdev->aux_dev;
172 	struct hwrm_stat_ctx_free_input req = {};
173 	struct hwrm_stat_ctx_free_output resp = {};
174 	struct bnge_fw_msg fw_msg = {};
175 	int rc;
176 
177 	bng_re_init_hwrm_hdr((void *)&req, HWRM_STAT_CTX_FREE);
178 	req.stat_ctx_id = cpu_to_le32(rdev->stats_ctx.fw_id);
179 	bng_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp,
180 			   sizeof(resp), BNGE_DFLT_HWRM_CMD_TIMEOUT);
181 	rc = bnge_send_msg(aux_dev, &fw_msg);
182 	if (rc)
183 		ibdev_err(&rdev->ibdev, "Failed to free HW stats context %#x",
184 			  rc);
185 
186 	return rc;
187 }
188 
189 static int bng_re_stats_ctx_alloc(struct bng_re_dev *rdev)
190 {
191 	struct bnge_auxr_dev *aux_dev = rdev->aux_dev;
192 	struct bng_re_stats *stats = &rdev->stats_ctx;
193 	struct hwrm_stat_ctx_alloc_output resp = {};
194 	struct hwrm_stat_ctx_alloc_input req = {};
195 	struct bnge_fw_msg fw_msg = {};
196 	int rc;
197 
198 	stats->fw_id = BNGE_INVALID_STATS_CTX_ID;
199 
200 	bng_re_init_hwrm_hdr((void *)&req, HWRM_STAT_CTX_ALLOC);
201 	req.update_period_ms = cpu_to_le32(1000);
202 	req.stats_dma_addr = cpu_to_le64(stats->dma_map);
203 	req.stats_dma_length = cpu_to_le16(rdev->chip_ctx->hw_stats_size);
204 	req.stat_ctx_flags = STAT_CTX_ALLOC_REQ_STAT_CTX_FLAGS_ROCE;
205 	bng_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp,
206 			   sizeof(resp), BNGE_DFLT_HWRM_CMD_TIMEOUT);
207 	rc = bnge_send_msg(aux_dev, &fw_msg);
208 	if (!rc)
209 		stats->fw_id = le32_to_cpu(resp.stat_ctx_id);
210 	return rc;
211 }
212 
213 static void bng_re_query_hwrm_version(struct bng_re_dev *rdev)
214 {
215 	struct bnge_auxr_dev *aux_dev = rdev->aux_dev;
216 	struct hwrm_ver_get_output ver_get_resp = {};
217 	struct hwrm_ver_get_input ver_get_req = {};
218 	struct bng_re_chip_ctx *cctx;
219 	struct bnge_fw_msg fw_msg = {};
220 	int rc;
221 
222 	bng_re_init_hwrm_hdr((void *)&ver_get_req, HWRM_VER_GET);
223 	ver_get_req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
224 	ver_get_req.hwrm_intf_min = HWRM_VERSION_MINOR;
225 	ver_get_req.hwrm_intf_upd = HWRM_VERSION_UPDATE;
226 	bng_re_fill_fw_msg(&fw_msg, (void *)&ver_get_req, sizeof(ver_get_req),
227 			    (void *)&ver_get_resp, sizeof(ver_get_resp),
228 			    BNGE_DFLT_HWRM_CMD_TIMEOUT);
229 	rc = bnge_send_msg(aux_dev, &fw_msg);
230 	if (rc) {
231 		ibdev_err(&rdev->ibdev, "Failed to query HW version, rc = 0x%x",
232 			  rc);
233 		return;
234 	}
235 
236 	cctx = rdev->chip_ctx;
237 	cctx->hwrm_intf_ver =
238 		(u64)le16_to_cpu(ver_get_resp.hwrm_intf_major) << 48 |
239 		(u64)le16_to_cpu(ver_get_resp.hwrm_intf_minor) << 32 |
240 		(u64)le16_to_cpu(ver_get_resp.hwrm_intf_build) << 16 |
241 		le16_to_cpu(ver_get_resp.hwrm_intf_patch);
242 
243 	cctx->hwrm_cmd_max_timeout = le16_to_cpu(ver_get_resp.max_req_timeout);
244 
245 	if (!cctx->hwrm_cmd_max_timeout)
246 		cctx->hwrm_cmd_max_timeout = BNG_ROCE_FW_MAX_TIMEOUT;
247 }
248 
249 static void bng_re_dev_uninit(struct bng_re_dev *rdev)
250 {
251 	int rc;
252 	bng_re_debugfs_rem_pdev(rdev);
253 
254 	if (test_and_clear_bit(BNG_RE_FLAG_RCFW_CHANNEL_EN, &rdev->flags)) {
255 		rc = bng_re_deinit_rcfw(&rdev->rcfw);
256 		if (rc)
257 			ibdev_warn(&rdev->ibdev,
258 				   "Failed to deinitialize RCFW: %#x", rc);
259 		bng_re_stats_ctx_free(rdev);
260 		bng_re_free_stats_ctx_mem(rdev->bng_res.pdev, &rdev->stats_ctx);
261 		bng_re_disable_rcfw_channel(&rdev->rcfw);
262 		bng_re_net_ring_free(rdev, rdev->rcfw.creq.ring_id,
263 			     RING_ALLOC_REQ_RING_TYPE_NQ);
264 		bng_re_free_rcfw_channel(&rdev->rcfw);
265 	}
266 
267 	kfree(rdev->nqr);
268 	rdev->nqr = NULL;
269 	bng_re_destroy_chip_ctx(rdev);
270 	if (test_and_clear_bit(BNG_RE_FLAG_NETDEV_REGISTERED, &rdev->flags))
271 		bnge_unregister_dev(rdev->aux_dev);
272 }
273 
274 static int bng_re_dev_init(struct bng_re_dev *rdev)
275 {
276 	struct bng_re_ring_attr rattr = {};
277 	struct bng_re_creq_ctx *creq;
278 	u32 db_offt;
279 	int vid;
280 	u8 type;
281 	int rc;
282 
283 	/* Registered a new RoCE device instance to netdev */
284 	rc = bng_re_register_netdev(rdev);
285 	if (rc) {
286 		ibdev_err(&rdev->ibdev,
287 				"Failed to register with netedev: %#x\n", rc);
288 		goto reg_netdev_fail;
289 	}
290 
291 	set_bit(BNG_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
292 
293 	if (rdev->aux_dev->auxr_info->msix_requested < BNG_RE_MIN_MSIX) {
294 		ibdev_err(&rdev->ibdev,
295 			  "RoCE requires minimum 2 MSI-X vectors, but only %d reserved\n",
296 			  rdev->aux_dev->auxr_info->msix_requested);
297 		rc = -EINVAL;
298 		goto msix_ctx_fail;
299 	}
300 	ibdev_dbg(&rdev->ibdev, "Got %d MSI-X vectors\n",
301 		  rdev->aux_dev->auxr_info->msix_requested);
302 
303 	rc = bng_re_setup_chip_ctx(rdev);
304 	if (rc) {
305 		ibdev_err(&rdev->ibdev, "Failed to get chip context\n");
306 		goto msix_ctx_fail;
307 	}
308 
309 	bng_re_query_hwrm_version(rdev);
310 
311 	rc = bng_re_alloc_fw_channel(&rdev->bng_res, &rdev->rcfw);
312 	if (rc) {
313 		ibdev_err(&rdev->ibdev,
314 			  "Failed to allocate RCFW Channel: %#x\n", rc);
315 		goto alloc_fw_chl_fail;
316 	}
317 
318 	/* Allocate nq record memory */
319 	rdev->nqr = kzalloc_obj(*rdev->nqr);
320 	if (!rdev->nqr) {
321 		rc = -ENOMEM;
322 		goto nq_alloc_fail;
323 	}
324 
325 	rdev->nqr->num_msix = rdev->aux_dev->auxr_info->msix_requested;
326 	memcpy(rdev->nqr->msix_entries, rdev->aux_dev->msix_info,
327 	       sizeof(struct bnge_msix_info) * rdev->nqr->num_msix);
328 
329 	type = RING_ALLOC_REQ_RING_TYPE_NQ;
330 	creq = &rdev->rcfw.creq;
331 	rattr.dma_arr = creq->hwq.pbl[BNG_PBL_LVL_0].pg_map_arr;
332 	rattr.pages = creq->hwq.pbl[creq->hwq.level].pg_count;
333 	rattr.type = type;
334 	rattr.mode = RING_ALLOC_REQ_INT_MODE_MSIX;
335 	rattr.depth = BNG_FW_CREQE_MAX_CNT - 1;
336 	rattr.lrid = rdev->nqr->msix_entries[BNG_RE_CREQ_NQ_IDX].ring_idx;
337 	rc = bng_re_net_ring_alloc(rdev, &rattr, &creq->ring_id);
338 	if (rc) {
339 		ibdev_err(&rdev->ibdev, "Failed to allocate CREQ: %#x\n", rc);
340 		goto free_rcfw;
341 	}
342 	db_offt = rdev->nqr->msix_entries[BNG_RE_CREQ_NQ_IDX].db_offset;
343 	vid = rdev->nqr->msix_entries[BNG_RE_CREQ_NQ_IDX].vector;
344 
345 	rc = bng_re_enable_fw_channel(&rdev->rcfw,
346 					vid, db_offt);
347 	if (rc) {
348 		ibdev_err(&rdev->ibdev, "Failed to enable RCFW channel: %#x\n",
349 			  rc);
350 		goto free_ring;
351 	}
352 
353 	rc = bng_re_get_dev_attr(&rdev->rcfw);
354 	if (rc)
355 		goto disable_rcfw;
356 
357 	bng_re_debugfs_add_pdev(rdev);
358 	rc = bng_re_alloc_stats_ctx_mem(rdev->bng_res.pdev, rdev->chip_ctx,
359 					&rdev->stats_ctx);
360 	if (rc) {
361 		ibdev_err(&rdev->ibdev,
362 			  "Failed to allocate stats context: %#x\n", rc);
363 		goto disable_rcfw;
364 	}
365 
366 	rc = bng_re_stats_ctx_alloc(rdev);
367 	if (rc) {
368 		ibdev_err(&rdev->ibdev,
369 			  "Failed to allocate QPLIB context: %#x\n", rc);
370 		goto free_stats_ctx;
371 	}
372 
373 	rc = bng_re_init_rcfw(&rdev->rcfw, &rdev->stats_ctx);
374 	if (rc) {
375 		ibdev_err(&rdev->ibdev,
376 			  "Failed to initialize RCFW: %#x\n", rc);
377 		goto free_sctx;
378 	}
379 	set_bit(BNG_RE_FLAG_RCFW_CHANNEL_EN, &rdev->flags);
380 
381 	return 0;
382 free_sctx:
383 	bng_re_stats_ctx_free(rdev);
384 free_stats_ctx:
385 	bng_re_free_stats_ctx_mem(rdev->bng_res.pdev, &rdev->stats_ctx);
386 disable_rcfw:
387 	bng_re_disable_rcfw_channel(&rdev->rcfw);
388 free_ring:
389 	bng_re_net_ring_free(rdev, rdev->rcfw.creq.ring_id, type);
390 free_rcfw:
391 	kfree(rdev->nqr);
392 nq_alloc_fail:
393 	bng_re_free_rcfw_channel(&rdev->rcfw);
394 alloc_fw_chl_fail:
395 	bng_re_destroy_chip_ctx(rdev);
396 msix_ctx_fail:
397 	bnge_unregister_dev(rdev->aux_dev);
398 	clear_bit(BNG_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
399 reg_netdev_fail:
400 	return rc;
401 }
402 
403 static int bng_re_add_device(struct auxiliary_device *adev)
404 {
405 	struct bnge_auxr_priv *auxr_priv =
406 		container_of(adev, struct bnge_auxr_priv, aux_dev);
407 	struct bng_re_en_dev_info *dev_info;
408 	struct bng_re_dev *rdev;
409 	int rc;
410 
411 	dev_info = auxiliary_get_drvdata(adev);
412 
413 	rdev = bng_re_dev_add(adev, auxr_priv->auxr_dev);
414 	if (!rdev) {
415 		rc = -ENOMEM;
416 		goto exit;
417 	}
418 
419 	dev_info->rdev = rdev;
420 
421 	rc = bng_re_dev_init(rdev);
422 	if (rc)
423 		goto re_dev_dealloc;
424 
425 	return 0;
426 
427 re_dev_dealloc:
428 	ib_dealloc_device(&rdev->ibdev);
429 exit:
430 	return rc;
431 }
432 
433 
434 static void bng_re_remove_device(struct bng_re_dev *rdev,
435 				 struct auxiliary_device *aux_dev)
436 {
437 	bng_re_dev_uninit(rdev);
438 	ib_dealloc_device(&rdev->ibdev);
439 }
440 
441 
442 static int bng_re_probe(struct auxiliary_device *adev,
443 			const struct auxiliary_device_id *id)
444 {
445 	struct bnge_auxr_priv *aux_priv =
446 		container_of(adev, struct bnge_auxr_priv, aux_dev);
447 	struct bng_re_en_dev_info *en_info;
448 	int rc;
449 
450 	en_info = kzalloc_obj(*en_info);
451 	if (!en_info)
452 		return -ENOMEM;
453 
454 	en_info->auxr_dev = aux_priv->auxr_dev;
455 
456 	auxiliary_set_drvdata(adev, en_info);
457 
458 	rc = bng_re_add_device(adev);
459 	if (rc)
460 		kfree(en_info);
461 
462 	return rc;
463 }
464 
465 static void bng_re_remove(struct auxiliary_device *adev)
466 {
467 	struct bng_re_en_dev_info *dev_info = auxiliary_get_drvdata(adev);
468 	struct bng_re_dev *rdev;
469 
470 	rdev = dev_info->rdev;
471 
472 	bng_re_remove_device(rdev, adev);
473 	kfree(dev_info);
474 }
475 
476 static const struct auxiliary_device_id bng_re_id_table[] = {
477 	{ .name = BNG_RE_ADEV_NAME ".rdma", },
478 	{},
479 };
480 
481 MODULE_DEVICE_TABLE(auxiliary, bng_re_id_table);
482 
483 static struct auxiliary_driver bng_re_driver = {
484 	.name = "rdma",
485 	.probe = bng_re_probe,
486 	.remove = bng_re_remove,
487 	.id_table = bng_re_id_table,
488 };
489 
490 static int __init bng_re_mod_init(void)
491 {
492 	int rc;
493 
494 
495 	bng_re_register_debugfs();
496 
497 	rc = auxiliary_driver_register(&bng_re_driver);
498 	if (rc) {
499 		pr_err("%s: Failed to register auxiliary driver\n",
500 		       KBUILD_MODNAME);
501 		goto unreg_debugfs;
502 	}
503 	return 0;
504 unreg_debugfs:
505 	bng_re_unregister_debugfs();
506 	return rc;
507 }
508 
509 static void __exit bng_re_mod_exit(void)
510 {
511 	auxiliary_driver_unregister(&bng_re_driver);
512 	bng_re_unregister_debugfs();
513 }
514 
515 module_init(bng_re_mod_init);
516 module_exit(bng_re_mod_exit);
517