1 // SPDX-License-Identifier: GPL-2.0-only
2 /****************************************************************************
3  * Driver for AMD network controllers and boards
4  * Copyright (C) 2023, Advanced Micro Devices, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 as published
8  * by the Free Software Foundation, incorporated herein by reference.
9  */
10 
11 #include "net_driver.h"
12 #include "ef100_nic.h"
13 #include "efx_devlink.h"
14 #include <linux/rtc.h>
15 #include "mcdi.h"
16 #include "mcdi_functions.h"
17 #include "mcdi_pcol.h"
18 #ifdef CONFIG_SFC_SRIOV
19 #include "mae.h"
20 #include "ef100_rep.h"
21 #endif
22 
23 struct efx_devlink {
24 	struct efx_nic *efx;
25 };
26 
27 #ifdef CONFIG_SFC_SRIOV
28 
29 static int efx_devlink_port_addr_get(struct devlink_port *port, u8 *hw_addr,
30 				     int *hw_addr_len,
31 				     struct netlink_ext_ack *extack)
32 {
33 	struct efx_devlink *devlink = devlink_priv(port->devlink);
34 	struct mae_mport_desc *mport_desc;
35 	efx_qword_t pciefn;
36 	u32 client_id;
37 	int rc = 0;
38 
39 	mport_desc = container_of(port, struct mae_mport_desc, dl_port);
40 
41 	if (!ef100_mport_on_local_intf(devlink->efx, mport_desc)) {
42 		rc = -EINVAL;
43 		NL_SET_ERR_MSG_FMT(extack,
44 				   "Port not on local interface (mport: %u)",
45 				   mport_desc->mport_id);
46 		goto out;
47 	}
48 
49 	if (ef100_mport_is_vf(mport_desc))
50 		EFX_POPULATE_QWORD_3(pciefn,
51 				     PCIE_FUNCTION_PF, PCIE_FUNCTION_PF_NULL,
52 				     PCIE_FUNCTION_VF, mport_desc->vf_idx,
53 				     PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);
54 	else
55 		EFX_POPULATE_QWORD_3(pciefn,
56 				     PCIE_FUNCTION_PF, mport_desc->pf_idx,
57 				     PCIE_FUNCTION_VF, PCIE_FUNCTION_VF_NULL,
58 				     PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);
59 
60 	rc = efx_ef100_lookup_client_id(devlink->efx, pciefn, &client_id);
61 	if (rc) {
62 		NL_SET_ERR_MSG_FMT(extack,
63 				   "No internal client_ID for port (mport: %u)",
64 				   mport_desc->mport_id);
65 		goto out;
66 	}
67 
68 	rc = ef100_get_mac_address(devlink->efx, hw_addr, client_id, true);
69 	if (rc != 0)
70 		NL_SET_ERR_MSG_FMT(extack,
71 				   "No available MAC for port (mport: %u)",
72 				   mport_desc->mport_id);
73 out:
74 	*hw_addr_len = ETH_ALEN;
75 	return rc;
76 }
77 
78 static int efx_devlink_port_addr_set(struct devlink_port *port,
79 				     const u8 *hw_addr, int hw_addr_len,
80 				     struct netlink_ext_ack *extack)
81 {
82 	MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_CLIENT_MAC_ADDRESSES_IN_LEN(1));
83 	struct efx_devlink *devlink = devlink_priv(port->devlink);
84 	struct mae_mport_desc *mport_desc;
85 	efx_qword_t pciefn;
86 	u32 client_id;
87 	int rc;
88 
89 	mport_desc = container_of(port, struct mae_mport_desc, dl_port);
90 
91 	if (!ef100_mport_is_vf(mport_desc)) {
92 		NL_SET_ERR_MSG_FMT(extack,
93 				   "port mac change not allowed (mport: %u)",
94 				   mport_desc->mport_id);
95 		return -EPERM;
96 	}
97 
98 	EFX_POPULATE_QWORD_3(pciefn,
99 			     PCIE_FUNCTION_PF, PCIE_FUNCTION_PF_NULL,
100 			     PCIE_FUNCTION_VF, mport_desc->vf_idx,
101 			     PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);
102 
103 	rc = efx_ef100_lookup_client_id(devlink->efx, pciefn, &client_id);
104 	if (rc) {
105 		NL_SET_ERR_MSG_FMT(extack,
106 				   "No internal client_ID for port (mport: %u)",
107 				   mport_desc->mport_id);
108 		return rc;
109 	}
110 
111 	MCDI_SET_DWORD(inbuf, SET_CLIENT_MAC_ADDRESSES_IN_CLIENT_HANDLE,
112 		       client_id);
113 
114 	ether_addr_copy(MCDI_PTR(inbuf, SET_CLIENT_MAC_ADDRESSES_IN_MAC_ADDRS),
115 			hw_addr);
116 
117 	rc = efx_mcdi_rpc(devlink->efx, MC_CMD_SET_CLIENT_MAC_ADDRESSES, inbuf,
118 			  sizeof(inbuf), NULL, 0, NULL);
119 	if (rc)
120 		NL_SET_ERR_MSG_FMT(extack,
121 				   "sfc MC_CMD_SET_CLIENT_MAC_ADDRESSES mcdi error (mport: %u)",
122 				   mport_desc->mport_id);
123 
124 	return rc;
125 }
126 
127 static const struct devlink_port_ops sfc_devlink_port_ops = {
128 	.port_fn_hw_addr_get = efx_devlink_port_addr_get,
129 	.port_fn_hw_addr_set = efx_devlink_port_addr_set,
130 };
131 
132 static void efx_devlink_del_port(struct devlink_port *dl_port)
133 {
134 	if (!dl_port)
135 		return;
136 	devl_port_unregister(dl_port);
137 }
138 
139 static int efx_devlink_add_port(struct efx_nic *efx,
140 				struct mae_mport_desc *mport)
141 {
142 	bool external = false;
143 
144 	if (!ef100_mport_on_local_intf(efx, mport))
145 		external = true;
146 
147 	switch (mport->mport_type) {
148 	case MAE_MPORT_DESC_MPORT_TYPE_VNIC:
149 		if (mport->vf_idx != MAE_MPORT_DESC_VF_IDX_NULL)
150 			devlink_port_attrs_pci_vf_set(&mport->dl_port, 0, mport->pf_idx,
151 						      mport->vf_idx,
152 						      external);
153 		else
154 			devlink_port_attrs_pci_pf_set(&mport->dl_port, 0, mport->pf_idx,
155 						      external);
156 		break;
157 	default:
158 		/* MAE_MPORT_DESC_MPORT_ALIAS and UNDEFINED */
159 		return 0;
160 	}
161 
162 	mport->dl_port.index = mport->mport_id;
163 
164 	return devl_port_register_with_ops(efx->devlink, &mport->dl_port,
165 					   mport->mport_id,
166 					   &sfc_devlink_port_ops);
167 }
168 
169 #endif
170 
171 static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
172 					    struct devlink_info_req *req,
173 					    unsigned int partition_type,
174 					    const char *version_name)
175 {
176 	char buf[EFX_MAX_VERSION_INFO_LEN];
177 	u16 version[4];
178 	int rc;
179 
180 	rc = efx_mcdi_nvram_metadata(efx, partition_type, NULL, version, NULL,
181 				     0);
182 
183 	/* If the partition does not exist, that is not an error. */
184 	if (rc == -ENOENT)
185 		return 0;
186 
187 	if (rc) {
188 		netif_err(efx, drv, efx->net_dev, "mcdi nvram %s: failed (rc=%d)\n",
189 			  version_name, rc);
190 		return rc;
191 	}
192 
193 	snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u", version[0],
194 		 version[1], version[2], version[3]);
195 	devlink_info_version_stored_put(req, version_name, buf);
196 
197 	return 0;
198 }
199 
200 static int efx_devlink_info_stored_versions(struct efx_nic *efx,
201 					    struct devlink_info_req *req)
202 {
203 	int err;
204 
205 	/* We do not care here about the specific error but just if an error
206 	 * happened. The specific error will be reported inside the call
207 	 * through system messages, and if any error happened in any call
208 	 * below, we report it through extack.
209 	 */
210 	err = efx_devlink_info_nvram_partition(efx, req,
211 					       NVRAM_PARTITION_TYPE_BUNDLE,
212 					       DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID);
213 
214 	err |= efx_devlink_info_nvram_partition(efx, req,
215 						NVRAM_PARTITION_TYPE_MC_FIRMWARE,
216 						DEVLINK_INFO_VERSION_GENERIC_FW_MGMT);
217 
218 	err |= efx_devlink_info_nvram_partition(efx, req,
219 						NVRAM_PARTITION_TYPE_SUC_FIRMWARE,
220 						EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC);
221 
222 	err |= efx_devlink_info_nvram_partition(efx, req,
223 						NVRAM_PARTITION_TYPE_EXPANSION_ROM,
224 						EFX_DEVLINK_INFO_VERSION_FW_EXPROM);
225 
226 	err |= efx_devlink_info_nvram_partition(efx, req,
227 						NVRAM_PARTITION_TYPE_EXPANSION_UEFI,
228 						EFX_DEVLINK_INFO_VERSION_FW_UEFI);
229 	return err;
230 }
231 
232 #define EFX_VER_FLAG(_f)	\
233 	(MC_CMD_GET_VERSION_V5_OUT_ ## _f ## _PRESENT_LBN)
234 
235 static void efx_devlink_info_running_v2(struct efx_nic *efx,
236 					struct devlink_info_req *req,
237 					unsigned int flags, efx_dword_t *outbuf)
238 {
239 	char buf[EFX_MAX_VERSION_INFO_LEN];
240 	union {
241 		const __le32 *dwords;
242 		const __le16 *words;
243 		const char *str;
244 	} ver;
245 	struct rtc_time build_date;
246 	unsigned int build_id;
247 	size_t offset;
248 	__maybe_unused u64 tstamp;
249 
250 	if (flags & BIT(EFX_VER_FLAG(BOARD_EXT_INFO))) {
251 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%s",
252 			 MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_NAME));
253 		devlink_info_version_fixed_put(req,
254 					       DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
255 					       buf);
256 
257 		/* Favour full board version if present (in V5 or later) */
258 		if (~flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) {
259 			snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u",
260 				 MCDI_DWORD(outbuf,
261 					    GET_VERSION_V2_OUT_BOARD_REVISION));
262 			devlink_info_version_fixed_put(req,
263 						       DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,
264 						       buf);
265 		}
266 
267 		ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_SERIAL);
268 		if (ver.str[0])
269 			devlink_info_board_serial_number_put(req, ver.str);
270 	}
271 
272 	if (flags & BIT(EFX_VER_FLAG(FPGA_EXT_INFO))) {
273 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
274 						GET_VERSION_V2_OUT_FPGA_VERSION);
275 		offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u_%c%u",
276 				  le32_to_cpu(ver.dwords[0]),
277 				  'A' + le32_to_cpu(ver.dwords[1]),
278 				  le32_to_cpu(ver.dwords[2]));
279 
280 		ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_FPGA_EXTRA);
281 		if (ver.str[0])
282 			snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
283 				 " (%s)", ver.str);
284 
285 		devlink_info_version_running_put(req,
286 						 EFX_DEVLINK_INFO_VERSION_FPGA_REV,
287 						 buf);
288 	}
289 
290 	if (flags & BIT(EFX_VER_FLAG(CMC_EXT_INFO))) {
291 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
292 						GET_VERSION_V2_OUT_CMCFW_VERSION);
293 		offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
294 				  le32_to_cpu(ver.dwords[0]),
295 				  le32_to_cpu(ver.dwords[1]),
296 				  le32_to_cpu(ver.dwords[2]),
297 				  le32_to_cpu(ver.dwords[3]));
298 
299 #ifdef CONFIG_RTC_LIB
300 		tstamp = MCDI_QWORD(outbuf,
301 				    GET_VERSION_V2_OUT_CMCFW_BUILD_DATE);
302 		if (tstamp) {
303 			rtc_time64_to_tm(tstamp, &build_date);
304 			snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
305 				 " (%ptRd)", &build_date);
306 		}
307 #endif
308 
309 		devlink_info_version_running_put(req,
310 						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_CMC,
311 						 buf);
312 	}
313 
314 	ver.words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_V2_OUT_VERSION);
315 	offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
316 			  le16_to_cpu(ver.words[0]), le16_to_cpu(ver.words[1]),
317 			  le16_to_cpu(ver.words[2]), le16_to_cpu(ver.words[3]));
318 	if (flags & BIT(EFX_VER_FLAG(MCFW_EXT_INFO))) {
319 		build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_ID);
320 		snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
321 			 " (%x) %s", build_id,
322 			 MCDI_PTR(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_NAME));
323 	}
324 	devlink_info_version_running_put(req,
325 					 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT,
326 					 buf);
327 
328 	if (flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) {
329 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
330 						GET_VERSION_V2_OUT_SUCFW_VERSION);
331 #ifdef CONFIG_RTC_LIB
332 		tstamp = MCDI_QWORD(outbuf,
333 				    GET_VERSION_V2_OUT_SUCFW_BUILD_DATE);
334 		rtc_time64_to_tm(tstamp, &build_date);
335 #else
336 		memset(&build_date, 0, sizeof(build_date));
337 #endif
338 		build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_SUCFW_CHIP_ID);
339 
340 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN,
341 			 "%u.%u.%u.%u type %x (%ptRd)",
342 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
343 			 le32_to_cpu(ver.dwords[2]), le32_to_cpu(ver.dwords[3]),
344 			 build_id, &build_date);
345 
346 		devlink_info_version_running_put(req,
347 						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC,
348 						 buf);
349 	}
350 }
351 
352 static void efx_devlink_info_running_v3(struct efx_nic *efx,
353 					struct devlink_info_req *req,
354 					unsigned int flags, efx_dword_t *outbuf)
355 {
356 	char buf[EFX_MAX_VERSION_INFO_LEN];
357 	union {
358 		const __le32 *dwords;
359 		const __le16 *words;
360 		const char *str;
361 	} ver;
362 
363 	if (flags & BIT(EFX_VER_FLAG(DATAPATH_HW_VERSION))) {
364 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
365 						GET_VERSION_V3_OUT_DATAPATH_HW_VERSION);
366 
367 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u",
368 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
369 			 le32_to_cpu(ver.dwords[2]));
370 
371 		devlink_info_version_running_put(req,
372 						 EFX_DEVLINK_INFO_VERSION_DATAPATH_HW,
373 						 buf);
374 	}
375 
376 	if (flags & BIT(EFX_VER_FLAG(DATAPATH_FW_VERSION))) {
377 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
378 						GET_VERSION_V3_OUT_DATAPATH_FW_VERSION);
379 
380 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u",
381 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
382 			 le32_to_cpu(ver.dwords[2]));
383 
384 		devlink_info_version_running_put(req,
385 						 EFX_DEVLINK_INFO_VERSION_DATAPATH_FW,
386 						 buf);
387 	}
388 }
389 
390 static void efx_devlink_info_running_v4(struct efx_nic *efx,
391 					struct devlink_info_req *req,
392 					unsigned int flags, efx_dword_t *outbuf)
393 {
394 	char buf[EFX_MAX_VERSION_INFO_LEN];
395 	union {
396 		const __le32 *dwords;
397 		const __le16 *words;
398 		const char *str;
399 	} ver;
400 
401 	if (flags & BIT(EFX_VER_FLAG(SOC_BOOT_VERSION))) {
402 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
403 						GET_VERSION_V4_OUT_SOC_BOOT_VERSION);
404 
405 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
406 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
407 			 le32_to_cpu(ver.dwords[2]),
408 			 le32_to_cpu(ver.dwords[3]));
409 
410 		devlink_info_version_running_put(req,
411 						 EFX_DEVLINK_INFO_VERSION_SOC_BOOT,
412 						 buf);
413 	}
414 
415 	if (flags & BIT(EFX_VER_FLAG(SOC_UBOOT_VERSION))) {
416 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
417 						GET_VERSION_V4_OUT_SOC_UBOOT_VERSION);
418 
419 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
420 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
421 			 le32_to_cpu(ver.dwords[2]),
422 			 le32_to_cpu(ver.dwords[3]));
423 
424 		devlink_info_version_running_put(req,
425 						 EFX_DEVLINK_INFO_VERSION_SOC_UBOOT,
426 						 buf);
427 	}
428 
429 	if (flags & BIT(EFX_VER_FLAG(SOC_MAIN_ROOTFS_VERSION))) {
430 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
431 					GET_VERSION_V4_OUT_SOC_MAIN_ROOTFS_VERSION);
432 
433 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
434 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
435 			 le32_to_cpu(ver.dwords[2]),
436 			 le32_to_cpu(ver.dwords[3]));
437 
438 		devlink_info_version_running_put(req,
439 						 EFX_DEVLINK_INFO_VERSION_SOC_MAIN,
440 						 buf);
441 	}
442 
443 	if (flags & BIT(EFX_VER_FLAG(SOC_RECOVERY_BUILDROOT_VERSION))) {
444 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
445 						GET_VERSION_V4_OUT_SOC_RECOVERY_BUILDROOT_VERSION);
446 
447 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
448 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
449 			 le32_to_cpu(ver.dwords[2]),
450 			 le32_to_cpu(ver.dwords[3]));
451 
452 		devlink_info_version_running_put(req,
453 						 EFX_DEVLINK_INFO_VERSION_SOC_RECOVERY,
454 						 buf);
455 	}
456 
457 	if (flags & BIT(EFX_VER_FLAG(SUCFW_VERSION)) &&
458 	    ~flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) {
459 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
460 						GET_VERSION_V4_OUT_SUCFW_VERSION);
461 
462 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
463 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
464 			 le32_to_cpu(ver.dwords[2]),
465 			 le32_to_cpu(ver.dwords[3]));
466 
467 		devlink_info_version_running_put(req,
468 						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC,
469 						 buf);
470 	}
471 }
472 
473 static void efx_devlink_info_running_v5(struct efx_nic *efx,
474 					struct devlink_info_req *req,
475 					unsigned int flags, efx_dword_t *outbuf)
476 {
477 	char buf[EFX_MAX_VERSION_INFO_LEN];
478 	union {
479 		const __le32 *dwords;
480 		const __le16 *words;
481 		const char *str;
482 	} ver;
483 
484 	if (flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) {
485 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
486 						GET_VERSION_V5_OUT_BOARD_VERSION);
487 
488 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
489 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
490 			 le32_to_cpu(ver.dwords[2]),
491 			 le32_to_cpu(ver.dwords[3]));
492 
493 		devlink_info_version_running_put(req,
494 						 DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,
495 						 buf);
496 	}
497 
498 	if (flags & BIT(EFX_VER_FLAG(BUNDLE_VERSION))) {
499 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
500 						GET_VERSION_V5_OUT_BUNDLE_VERSION);
501 
502 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
503 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
504 			 le32_to_cpu(ver.dwords[2]),
505 			 le32_to_cpu(ver.dwords[3]));
506 
507 		devlink_info_version_running_put(req,
508 						 DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
509 						 buf);
510 	}
511 }
512 
513 static int efx_devlink_info_running_versions(struct efx_nic *efx,
514 					     struct devlink_info_req *req)
515 {
516 	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_VERSION_V5_OUT_LEN);
517 	MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_VERSION_EXT_IN_LEN);
518 	char buf[EFX_MAX_VERSION_INFO_LEN];
519 	union {
520 		const __le32 *dwords;
521 		const __le16 *words;
522 		const char *str;
523 	} ver;
524 	size_t outlength;
525 	unsigned int flags;
526 	int rc;
527 
528 	rc = efx_mcdi_rpc(efx, MC_CMD_GET_VERSION, inbuf, sizeof(inbuf),
529 			  outbuf, sizeof(outbuf), &outlength);
530 	if (rc || outlength < MC_CMD_GET_VERSION_OUT_LEN) {
531 		netif_err(efx, drv, efx->net_dev,
532 			  "mcdi MC_CMD_GET_VERSION failed\n");
533 		return rc;
534 	}
535 
536 	/* Handle previous output */
537 	if (outlength < MC_CMD_GET_VERSION_V2_OUT_LEN) {
538 		ver.words = (__le16 *)MCDI_PTR(outbuf,
539 					       GET_VERSION_EXT_OUT_VERSION);
540 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
541 			 le16_to_cpu(ver.words[0]),
542 			 le16_to_cpu(ver.words[1]),
543 			 le16_to_cpu(ver.words[2]),
544 			 le16_to_cpu(ver.words[3]));
545 
546 		devlink_info_version_running_put(req,
547 						 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT,
548 						 buf);
549 		return 0;
550 	}
551 
552 	/* Handle V2 additions */
553 	flags = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_FLAGS);
554 	efx_devlink_info_running_v2(efx, req, flags, outbuf);
555 
556 	if (outlength < MC_CMD_GET_VERSION_V3_OUT_LEN)
557 		return 0;
558 
559 	/* Handle V3 additions */
560 	efx_devlink_info_running_v3(efx, req, flags, outbuf);
561 
562 	if (outlength < MC_CMD_GET_VERSION_V4_OUT_LEN)
563 		return 0;
564 
565 	/* Handle V4 additions */
566 	efx_devlink_info_running_v4(efx, req, flags, outbuf);
567 
568 	if (outlength < MC_CMD_GET_VERSION_V5_OUT_LEN)
569 		return 0;
570 
571 	/* Handle V5 additions */
572 	efx_devlink_info_running_v5(efx, req, flags, outbuf);
573 
574 	return 0;
575 }
576 
577 #define EFX_MAX_SERIALNUM_LEN	(ETH_ALEN * 2 + 1)
578 
579 static int efx_devlink_info_board_cfg(struct efx_nic *efx,
580 				      struct devlink_info_req *req)
581 {
582 	char sn[EFX_MAX_SERIALNUM_LEN];
583 	u8 mac_address[ETH_ALEN];
584 	int rc;
585 
586 	rc = efx_mcdi_get_board_cfg(efx, (u8 *)mac_address, NULL, NULL);
587 	if (!rc) {
588 		snprintf(sn, EFX_MAX_SERIALNUM_LEN, "%pm", mac_address);
589 		devlink_info_serial_number_put(req, sn);
590 	}
591 	return rc;
592 }
593 
594 static int efx_devlink_info_get(struct devlink *devlink,
595 				struct devlink_info_req *req,
596 				struct netlink_ext_ack *extack)
597 {
598 	struct efx_devlink *devlink_private = devlink_priv(devlink);
599 	struct efx_nic *efx = devlink_private->efx;
600 	int err;
601 
602 	/* Several different MCDI commands are used. We report if errors
603 	 * happened through extack. Specific error information via system
604 	 * messages inside the calls.
605 	 */
606 	err = efx_devlink_info_board_cfg(efx, req);
607 
608 	err |= efx_devlink_info_stored_versions(efx, req);
609 
610 	err |= efx_devlink_info_running_versions(efx, req);
611 
612 	if (err)
613 		NL_SET_ERR_MSG_MOD(extack, "Errors when getting device info. Check system messages");
614 
615 	return 0;
616 }
617 
618 static const struct devlink_ops sfc_devlink_ops = {
619 	.info_get			= efx_devlink_info_get,
620 };
621 
622 #ifdef CONFIG_SFC_SRIOV
623 static struct devlink_port *ef100_set_devlink_port(struct efx_nic *efx, u32 idx)
624 {
625 	struct mae_mport_desc *mport;
626 	u32 id;
627 	int rc;
628 
629 	if (efx_mae_lookup_mport(efx, idx, &id)) {
630 		/* This should not happen. */
631 		if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
632 			pci_warn_once(efx->pci_dev, "No mport ID found for PF.\n");
633 		else
634 			pci_warn_once(efx->pci_dev, "No mport ID found for VF %u.\n",
635 				      idx);
636 		return NULL;
637 	}
638 
639 	mport = efx_mae_get_mport(efx, id);
640 	if (!mport) {
641 		/* This should not happen. */
642 		if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
643 			pci_warn_once(efx->pci_dev, "No mport found for PF.\n");
644 		else
645 			pci_warn_once(efx->pci_dev, "No mport found for VF %u.\n",
646 				      idx);
647 		return NULL;
648 	}
649 
650 	rc = efx_devlink_add_port(efx, mport);
651 	if (rc) {
652 		if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
653 			pci_warn(efx->pci_dev,
654 				 "devlink port creation for PF failed.\n");
655 		else
656 			pci_warn(efx->pci_dev,
657 				 "devlink_port creation for VF %u failed.\n",
658 				 idx);
659 		return NULL;
660 	}
661 
662 	return &mport->dl_port;
663 }
664 
665 void ef100_rep_set_devlink_port(struct efx_rep *efv)
666 {
667 	efv->dl_port = ef100_set_devlink_port(efv->parent, efv->idx);
668 }
669 
670 void ef100_pf_set_devlink_port(struct efx_nic *efx)
671 {
672 	efx->dl_port = ef100_set_devlink_port(efx, MAE_MPORT_DESC_VF_IDX_NULL);
673 }
674 
675 void ef100_rep_unset_devlink_port(struct efx_rep *efv)
676 {
677 	efx_devlink_del_port(efv->dl_port);
678 }
679 
680 void ef100_pf_unset_devlink_port(struct efx_nic *efx)
681 {
682 	efx_devlink_del_port(efx->dl_port);
683 }
684 #endif
685 
686 void efx_fini_devlink_lock(struct efx_nic *efx)
687 {
688 	if (efx->devlink)
689 		devl_lock(efx->devlink);
690 }
691 
692 void efx_fini_devlink_and_unlock(struct efx_nic *efx)
693 {
694 	if (efx->devlink) {
695 		devl_unregister(efx->devlink);
696 		devl_unlock(efx->devlink);
697 		devlink_free(efx->devlink);
698 		efx->devlink = NULL;
699 	}
700 }
701 
702 int efx_probe_devlink_and_lock(struct efx_nic *efx)
703 {
704 	struct efx_devlink *devlink_private;
705 
706 	if (efx->type->is_vf)
707 		return 0;
708 
709 	efx->devlink = devlink_alloc(&sfc_devlink_ops,
710 				     sizeof(struct efx_devlink),
711 				     &efx->pci_dev->dev);
712 	if (!efx->devlink)
713 		return -ENOMEM;
714 
715 	devl_lock(efx->devlink);
716 	devlink_private = devlink_priv(efx->devlink);
717 	devlink_private->efx = efx;
718 
719 	devl_register(efx->devlink);
720 
721 	return 0;
722 }
723 
724 void efx_probe_devlink_unlock(struct efx_nic *efx)
725 {
726 	if (!efx->devlink)
727 		return;
728 
729 	devl_unlock(efx->devlink);
730 }
731