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