xref: /openbmc/linux/drivers/net/ethernet/sfc/efx_devlink.c (revision 25414b2a64ae7ea8742933bd7b1d056e069b15a7)
1fa34a514SAlejandro Lucero // SPDX-License-Identifier: GPL-2.0-only
2fa34a514SAlejandro Lucero /****************************************************************************
3fa34a514SAlejandro Lucero  * Driver for AMD network controllers and boards
4fa34a514SAlejandro Lucero  * Copyright (C) 2023, Advanced Micro Devices, Inc.
5fa34a514SAlejandro Lucero  *
6fa34a514SAlejandro Lucero  * This program is free software; you can redistribute it and/or modify it
7fa34a514SAlejandro Lucero  * under the terms of the GNU General Public License version 2 as published
8fa34a514SAlejandro Lucero  * by the Free Software Foundation, incorporated herein by reference.
9fa34a514SAlejandro Lucero  */
10fa34a514SAlejandro Lucero 
11fa34a514SAlejandro Lucero #include "net_driver.h"
12fa34a514SAlejandro Lucero #include "efx_devlink.h"
1314743dddSAlejandro Lucero #include <linux/rtc.h>
1414743dddSAlejandro Lucero #include "mcdi.h"
1514743dddSAlejandro Lucero #include "mcdi_functions.h"
1614743dddSAlejandro Lucero #include "mcdi_pcol.h"
17*25414b2aSAlejandro Lucero #ifdef CONFIG_SFC_SRIOV
18*25414b2aSAlejandro Lucero #include "mae.h"
19*25414b2aSAlejandro Lucero #include "ef100_rep.h"
20*25414b2aSAlejandro Lucero #endif
21fa34a514SAlejandro Lucero 
22fa34a514SAlejandro Lucero struct efx_devlink {
23fa34a514SAlejandro Lucero 	struct efx_nic *efx;
24fa34a514SAlejandro Lucero };
25fa34a514SAlejandro Lucero 
26*25414b2aSAlejandro Lucero #ifdef CONFIG_SFC_SRIOV
27*25414b2aSAlejandro Lucero static void efx_devlink_del_port(struct devlink_port *dl_port)
28*25414b2aSAlejandro Lucero {
29*25414b2aSAlejandro Lucero 	if (!dl_port)
30*25414b2aSAlejandro Lucero 		return;
31*25414b2aSAlejandro Lucero 	devl_port_unregister(dl_port);
32*25414b2aSAlejandro Lucero }
33*25414b2aSAlejandro Lucero 
34*25414b2aSAlejandro Lucero static int efx_devlink_add_port(struct efx_nic *efx,
35*25414b2aSAlejandro Lucero 				struct mae_mport_desc *mport)
36*25414b2aSAlejandro Lucero {
37*25414b2aSAlejandro Lucero 	bool external = false;
38*25414b2aSAlejandro Lucero 
39*25414b2aSAlejandro Lucero 	if (!ef100_mport_on_local_intf(efx, mport))
40*25414b2aSAlejandro Lucero 		external = true;
41*25414b2aSAlejandro Lucero 
42*25414b2aSAlejandro Lucero 	switch (mport->mport_type) {
43*25414b2aSAlejandro Lucero 	case MAE_MPORT_DESC_MPORT_TYPE_VNIC:
44*25414b2aSAlejandro Lucero 		if (mport->vf_idx != MAE_MPORT_DESC_VF_IDX_NULL)
45*25414b2aSAlejandro Lucero 			devlink_port_attrs_pci_vf_set(&mport->dl_port, 0, mport->pf_idx,
46*25414b2aSAlejandro Lucero 						      mport->vf_idx,
47*25414b2aSAlejandro Lucero 						      external);
48*25414b2aSAlejandro Lucero 		else
49*25414b2aSAlejandro Lucero 			devlink_port_attrs_pci_pf_set(&mport->dl_port, 0, mport->pf_idx,
50*25414b2aSAlejandro Lucero 						      external);
51*25414b2aSAlejandro Lucero 		break;
52*25414b2aSAlejandro Lucero 	default:
53*25414b2aSAlejandro Lucero 		/* MAE_MPORT_DESC_MPORT_ALIAS and UNDEFINED */
54*25414b2aSAlejandro Lucero 		return 0;
55*25414b2aSAlejandro Lucero 	}
56*25414b2aSAlejandro Lucero 
57*25414b2aSAlejandro Lucero 	mport->dl_port.index = mport->mport_id;
58*25414b2aSAlejandro Lucero 
59*25414b2aSAlejandro Lucero 	return devl_port_register(efx->devlink, &mport->dl_port, mport->mport_id);
60*25414b2aSAlejandro Lucero }
61*25414b2aSAlejandro Lucero #endif
62*25414b2aSAlejandro Lucero 
6314743dddSAlejandro Lucero static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
6414743dddSAlejandro Lucero 					    struct devlink_info_req *req,
6514743dddSAlejandro Lucero 					    unsigned int partition_type,
6614743dddSAlejandro Lucero 					    const char *version_name)
6714743dddSAlejandro Lucero {
6814743dddSAlejandro Lucero 	char buf[EFX_MAX_VERSION_INFO_LEN];
6914743dddSAlejandro Lucero 	u16 version[4];
7014743dddSAlejandro Lucero 	int rc;
7114743dddSAlejandro Lucero 
7214743dddSAlejandro Lucero 	rc = efx_mcdi_nvram_metadata(efx, partition_type, NULL, version, NULL,
7314743dddSAlejandro Lucero 				     0);
7414743dddSAlejandro Lucero 	if (rc) {
7514743dddSAlejandro Lucero 		netif_err(efx, drv, efx->net_dev, "mcdi nvram %s: failed\n",
7614743dddSAlejandro Lucero 			  version_name);
7714743dddSAlejandro Lucero 		return rc;
7814743dddSAlejandro Lucero 	}
7914743dddSAlejandro Lucero 
8014743dddSAlejandro Lucero 	snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u", version[0],
8114743dddSAlejandro Lucero 		 version[1], version[2], version[3]);
8214743dddSAlejandro Lucero 	devlink_info_version_stored_put(req, version_name, buf);
8314743dddSAlejandro Lucero 
8414743dddSAlejandro Lucero 	return 0;
8514743dddSAlejandro Lucero }
8614743dddSAlejandro Lucero 
8714743dddSAlejandro Lucero static int efx_devlink_info_stored_versions(struct efx_nic *efx,
8814743dddSAlejandro Lucero 					    struct devlink_info_req *req)
8914743dddSAlejandro Lucero {
9014743dddSAlejandro Lucero 	int rc;
9114743dddSAlejandro Lucero 
9214743dddSAlejandro Lucero 	rc = efx_devlink_info_nvram_partition(efx, req,
9314743dddSAlejandro Lucero 					      NVRAM_PARTITION_TYPE_BUNDLE,
9414743dddSAlejandro Lucero 					      DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID);
9514743dddSAlejandro Lucero 	if (rc)
9614743dddSAlejandro Lucero 		return rc;
9714743dddSAlejandro Lucero 
9814743dddSAlejandro Lucero 	rc = efx_devlink_info_nvram_partition(efx, req,
9914743dddSAlejandro Lucero 					      NVRAM_PARTITION_TYPE_MC_FIRMWARE,
10014743dddSAlejandro Lucero 					      DEVLINK_INFO_VERSION_GENERIC_FW_MGMT);
10114743dddSAlejandro Lucero 	if (rc)
10214743dddSAlejandro Lucero 		return rc;
10314743dddSAlejandro Lucero 
10414743dddSAlejandro Lucero 	rc = efx_devlink_info_nvram_partition(efx, req,
10514743dddSAlejandro Lucero 					      NVRAM_PARTITION_TYPE_SUC_FIRMWARE,
10614743dddSAlejandro Lucero 					      EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC);
10714743dddSAlejandro Lucero 	if (rc)
10814743dddSAlejandro Lucero 		return rc;
10914743dddSAlejandro Lucero 
11014743dddSAlejandro Lucero 	rc = efx_devlink_info_nvram_partition(efx, req,
11114743dddSAlejandro Lucero 					      NVRAM_PARTITION_TYPE_EXPANSION_ROM,
11214743dddSAlejandro Lucero 					      EFX_DEVLINK_INFO_VERSION_FW_EXPROM);
11314743dddSAlejandro Lucero 	if (rc)
11414743dddSAlejandro Lucero 		return rc;
11514743dddSAlejandro Lucero 
11614743dddSAlejandro Lucero 	rc = efx_devlink_info_nvram_partition(efx, req,
11714743dddSAlejandro Lucero 					      NVRAM_PARTITION_TYPE_EXPANSION_UEFI,
11814743dddSAlejandro Lucero 					      EFX_DEVLINK_INFO_VERSION_FW_UEFI);
11914743dddSAlejandro Lucero 	return rc;
12014743dddSAlejandro Lucero }
12114743dddSAlejandro Lucero 
12214743dddSAlejandro Lucero #define EFX_VER_FLAG(_f)	\
12314743dddSAlejandro Lucero 	(MC_CMD_GET_VERSION_V5_OUT_ ## _f ## _PRESENT_LBN)
12414743dddSAlejandro Lucero 
12514743dddSAlejandro Lucero static void efx_devlink_info_running_v2(struct efx_nic *efx,
12614743dddSAlejandro Lucero 					struct devlink_info_req *req,
12714743dddSAlejandro Lucero 					unsigned int flags, efx_dword_t *outbuf)
12814743dddSAlejandro Lucero {
12914743dddSAlejandro Lucero 	char buf[EFX_MAX_VERSION_INFO_LEN];
13014743dddSAlejandro Lucero 	union {
13114743dddSAlejandro Lucero 		const __le32 *dwords;
13214743dddSAlejandro Lucero 		const __le16 *words;
13314743dddSAlejandro Lucero 		const char *str;
13414743dddSAlejandro Lucero 	} ver;
13514743dddSAlejandro Lucero 	struct rtc_time build_date;
13614743dddSAlejandro Lucero 	unsigned int build_id;
13714743dddSAlejandro Lucero 	size_t offset;
13814743dddSAlejandro Lucero 	__maybe_unused u64 tstamp;
13914743dddSAlejandro Lucero 
14014743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(BOARD_EXT_INFO))) {
14114743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%s",
14214743dddSAlejandro Lucero 			 MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_NAME));
14314743dddSAlejandro Lucero 		devlink_info_version_fixed_put(req,
14414743dddSAlejandro Lucero 					       DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
14514743dddSAlejandro Lucero 					       buf);
14614743dddSAlejandro Lucero 
14714743dddSAlejandro Lucero 		/* Favour full board version if present (in V5 or later) */
14814743dddSAlejandro Lucero 		if (~flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) {
14914743dddSAlejandro Lucero 			snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u",
15014743dddSAlejandro Lucero 				 MCDI_DWORD(outbuf,
15114743dddSAlejandro Lucero 					    GET_VERSION_V2_OUT_BOARD_REVISION));
15214743dddSAlejandro Lucero 			devlink_info_version_fixed_put(req,
15314743dddSAlejandro Lucero 						       DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,
15414743dddSAlejandro Lucero 						       buf);
15514743dddSAlejandro Lucero 		}
15614743dddSAlejandro Lucero 
15714743dddSAlejandro Lucero 		ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_SERIAL);
15814743dddSAlejandro Lucero 		if (ver.str[0])
15914743dddSAlejandro Lucero 			devlink_info_board_serial_number_put(req, ver.str);
16014743dddSAlejandro Lucero 	}
16114743dddSAlejandro Lucero 
16214743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(FPGA_EXT_INFO))) {
16314743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
16414743dddSAlejandro Lucero 						GET_VERSION_V2_OUT_FPGA_VERSION);
16514743dddSAlejandro Lucero 		offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u_%c%u",
16614743dddSAlejandro Lucero 				  le32_to_cpu(ver.dwords[0]),
16714743dddSAlejandro Lucero 				  'A' + le32_to_cpu(ver.dwords[1]),
16814743dddSAlejandro Lucero 				  le32_to_cpu(ver.dwords[2]));
16914743dddSAlejandro Lucero 
17014743dddSAlejandro Lucero 		ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_FPGA_EXTRA);
17114743dddSAlejandro Lucero 		if (ver.str[0])
17214743dddSAlejandro Lucero 			snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
17314743dddSAlejandro Lucero 				 " (%s)", ver.str);
17414743dddSAlejandro Lucero 
17514743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
17614743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_FPGA_REV,
17714743dddSAlejandro Lucero 						 buf);
17814743dddSAlejandro Lucero 	}
17914743dddSAlejandro Lucero 
18014743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(CMC_EXT_INFO))) {
18114743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
18214743dddSAlejandro Lucero 						GET_VERSION_V2_OUT_CMCFW_VERSION);
18314743dddSAlejandro Lucero 		offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
18414743dddSAlejandro Lucero 				  le32_to_cpu(ver.dwords[0]),
18514743dddSAlejandro Lucero 				  le32_to_cpu(ver.dwords[1]),
18614743dddSAlejandro Lucero 				  le32_to_cpu(ver.dwords[2]),
18714743dddSAlejandro Lucero 				  le32_to_cpu(ver.dwords[3]));
18814743dddSAlejandro Lucero 
18914743dddSAlejandro Lucero #ifdef CONFIG_RTC_LIB
19014743dddSAlejandro Lucero 		tstamp = MCDI_QWORD(outbuf,
19114743dddSAlejandro Lucero 				    GET_VERSION_V2_OUT_CMCFW_BUILD_DATE);
19214743dddSAlejandro Lucero 		if (tstamp) {
19314743dddSAlejandro Lucero 			rtc_time64_to_tm(tstamp, &build_date);
19414743dddSAlejandro Lucero 			snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
19514743dddSAlejandro Lucero 				 " (%ptRd)", &build_date);
19614743dddSAlejandro Lucero 		}
19714743dddSAlejandro Lucero #endif
19814743dddSAlejandro Lucero 
19914743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
20014743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_CMC,
20114743dddSAlejandro Lucero 						 buf);
20214743dddSAlejandro Lucero 	}
20314743dddSAlejandro Lucero 
20414743dddSAlejandro Lucero 	ver.words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_V2_OUT_VERSION);
20514743dddSAlejandro Lucero 	offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
20614743dddSAlejandro Lucero 			  le16_to_cpu(ver.words[0]), le16_to_cpu(ver.words[1]),
20714743dddSAlejandro Lucero 			  le16_to_cpu(ver.words[2]), le16_to_cpu(ver.words[3]));
20814743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(MCFW_EXT_INFO))) {
20914743dddSAlejandro Lucero 		build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_ID);
21014743dddSAlejandro Lucero 		snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
21114743dddSAlejandro Lucero 			 " (%x) %s", build_id,
21214743dddSAlejandro Lucero 			 MCDI_PTR(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_NAME));
21314743dddSAlejandro Lucero 	}
21414743dddSAlejandro Lucero 	devlink_info_version_running_put(req,
21514743dddSAlejandro Lucero 					 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT,
21614743dddSAlejandro Lucero 					 buf);
21714743dddSAlejandro Lucero 
21814743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) {
21914743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
22014743dddSAlejandro Lucero 						GET_VERSION_V2_OUT_SUCFW_VERSION);
22114743dddSAlejandro Lucero #ifdef CONFIG_RTC_LIB
22214743dddSAlejandro Lucero 		tstamp = MCDI_QWORD(outbuf,
22314743dddSAlejandro Lucero 				    GET_VERSION_V2_OUT_SUCFW_BUILD_DATE);
22414743dddSAlejandro Lucero 		rtc_time64_to_tm(tstamp, &build_date);
22514743dddSAlejandro Lucero #else
22614743dddSAlejandro Lucero 		memset(&build_date, 0, sizeof(build_date)
22714743dddSAlejandro Lucero #endif
22814743dddSAlejandro Lucero 		build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_SUCFW_CHIP_ID);
22914743dddSAlejandro Lucero 
23014743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN,
23114743dddSAlejandro Lucero 			 "%u.%u.%u.%u type %x (%ptRd)",
23214743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
23314743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]), le32_to_cpu(ver.dwords[3]),
23414743dddSAlejandro Lucero 			 build_id, &build_date);
23514743dddSAlejandro Lucero 
23614743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
23714743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC,
23814743dddSAlejandro Lucero 						 buf);
23914743dddSAlejandro Lucero 	}
24014743dddSAlejandro Lucero }
24114743dddSAlejandro Lucero 
24214743dddSAlejandro Lucero static void efx_devlink_info_running_v3(struct efx_nic *efx,
24314743dddSAlejandro Lucero 					struct devlink_info_req *req,
24414743dddSAlejandro Lucero 					unsigned int flags, efx_dword_t *outbuf)
24514743dddSAlejandro Lucero {
24614743dddSAlejandro Lucero 	char buf[EFX_MAX_VERSION_INFO_LEN];
24714743dddSAlejandro Lucero 	union {
24814743dddSAlejandro Lucero 		const __le32 *dwords;
24914743dddSAlejandro Lucero 		const __le16 *words;
25014743dddSAlejandro Lucero 		const char *str;
25114743dddSAlejandro Lucero 	} ver;
25214743dddSAlejandro Lucero 
25314743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(DATAPATH_HW_VERSION))) {
25414743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
25514743dddSAlejandro Lucero 						GET_VERSION_V3_OUT_DATAPATH_HW_VERSION);
25614743dddSAlejandro Lucero 
25714743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u",
25814743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
25914743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]));
26014743dddSAlejandro Lucero 
26114743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
26214743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_DATAPATH_HW,
26314743dddSAlejandro Lucero 						 buf);
26414743dddSAlejandro Lucero 	}
26514743dddSAlejandro Lucero 
26614743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(DATAPATH_FW_VERSION))) {
26714743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
26814743dddSAlejandro Lucero 						GET_VERSION_V3_OUT_DATAPATH_FW_VERSION);
26914743dddSAlejandro Lucero 
27014743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u",
27114743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
27214743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]));
27314743dddSAlejandro Lucero 
27414743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
27514743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_DATAPATH_FW,
27614743dddSAlejandro Lucero 						 buf);
27714743dddSAlejandro Lucero 	}
27814743dddSAlejandro Lucero }
27914743dddSAlejandro Lucero 
28014743dddSAlejandro Lucero static void efx_devlink_info_running_v4(struct efx_nic *efx,
28114743dddSAlejandro Lucero 					struct devlink_info_req *req,
28214743dddSAlejandro Lucero 					unsigned int flags, efx_dword_t *outbuf)
28314743dddSAlejandro Lucero {
28414743dddSAlejandro Lucero 	char buf[EFX_MAX_VERSION_INFO_LEN];
28514743dddSAlejandro Lucero 	union {
28614743dddSAlejandro Lucero 		const __le32 *dwords;
28714743dddSAlejandro Lucero 		const __le16 *words;
28814743dddSAlejandro Lucero 		const char *str;
28914743dddSAlejandro Lucero 	} ver;
29014743dddSAlejandro Lucero 
29114743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(SOC_BOOT_VERSION))) {
29214743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
29314743dddSAlejandro Lucero 						GET_VERSION_V4_OUT_SOC_BOOT_VERSION);
29414743dddSAlejandro Lucero 
29514743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
29614743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
29714743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]),
29814743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[3]));
29914743dddSAlejandro Lucero 
30014743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
30114743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_SOC_BOOT,
30214743dddSAlejandro Lucero 						 buf);
30314743dddSAlejandro Lucero 	}
30414743dddSAlejandro Lucero 
30514743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(SOC_UBOOT_VERSION))) {
30614743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
30714743dddSAlejandro Lucero 						GET_VERSION_V4_OUT_SOC_UBOOT_VERSION);
30814743dddSAlejandro Lucero 
30914743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
31014743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
31114743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]),
31214743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[3]));
31314743dddSAlejandro Lucero 
31414743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
31514743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_SOC_UBOOT,
31614743dddSAlejandro Lucero 						 buf);
31714743dddSAlejandro Lucero 	}
31814743dddSAlejandro Lucero 
31914743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(SOC_MAIN_ROOTFS_VERSION))) {
32014743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
32114743dddSAlejandro Lucero 					GET_VERSION_V4_OUT_SOC_MAIN_ROOTFS_VERSION);
32214743dddSAlejandro Lucero 
32314743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
32414743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
32514743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]),
32614743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[3]));
32714743dddSAlejandro Lucero 
32814743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
32914743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_SOC_MAIN,
33014743dddSAlejandro Lucero 						 buf);
33114743dddSAlejandro Lucero 	}
33214743dddSAlejandro Lucero 
33314743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(SOC_RECOVERY_BUILDROOT_VERSION))) {
33414743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
33514743dddSAlejandro Lucero 						GET_VERSION_V4_OUT_SOC_RECOVERY_BUILDROOT_VERSION);
33614743dddSAlejandro Lucero 
33714743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
33814743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
33914743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]),
34014743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[3]));
34114743dddSAlejandro Lucero 
34214743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
34314743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_SOC_RECOVERY,
34414743dddSAlejandro Lucero 						 buf);
34514743dddSAlejandro Lucero 	}
34614743dddSAlejandro Lucero 
34714743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(SUCFW_VERSION)) &&
34814743dddSAlejandro Lucero 	    ~flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) {
34914743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
35014743dddSAlejandro Lucero 						GET_VERSION_V4_OUT_SUCFW_VERSION);
35114743dddSAlejandro Lucero 
35214743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
35314743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
35414743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]),
35514743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[3]));
35614743dddSAlejandro Lucero 
35714743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
35814743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC,
35914743dddSAlejandro Lucero 						 buf);
36014743dddSAlejandro Lucero 	}
36114743dddSAlejandro Lucero }
36214743dddSAlejandro Lucero 
36314743dddSAlejandro Lucero static void efx_devlink_info_running_v5(struct efx_nic *efx,
36414743dddSAlejandro Lucero 					struct devlink_info_req *req,
36514743dddSAlejandro Lucero 					unsigned int flags, efx_dword_t *outbuf)
36614743dddSAlejandro Lucero {
36714743dddSAlejandro Lucero 	char buf[EFX_MAX_VERSION_INFO_LEN];
36814743dddSAlejandro Lucero 	union {
36914743dddSAlejandro Lucero 		const __le32 *dwords;
37014743dddSAlejandro Lucero 		const __le16 *words;
37114743dddSAlejandro Lucero 		const char *str;
37214743dddSAlejandro Lucero 	} ver;
37314743dddSAlejandro Lucero 
37414743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) {
37514743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
37614743dddSAlejandro Lucero 						GET_VERSION_V5_OUT_BOARD_VERSION);
37714743dddSAlejandro Lucero 
37814743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
37914743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
38014743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]),
38114743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[3]));
38214743dddSAlejandro Lucero 
38314743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
38414743dddSAlejandro Lucero 						 DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,
38514743dddSAlejandro Lucero 						 buf);
38614743dddSAlejandro Lucero 	}
38714743dddSAlejandro Lucero 
38814743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(BUNDLE_VERSION))) {
38914743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
39014743dddSAlejandro Lucero 						GET_VERSION_V5_OUT_BUNDLE_VERSION);
39114743dddSAlejandro Lucero 
39214743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
39314743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
39414743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]),
39514743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[3]));
39614743dddSAlejandro Lucero 
39714743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
39814743dddSAlejandro Lucero 						 DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
39914743dddSAlejandro Lucero 						 buf);
40014743dddSAlejandro Lucero 	}
40114743dddSAlejandro Lucero }
40214743dddSAlejandro Lucero 
40314743dddSAlejandro Lucero static int efx_devlink_info_running_versions(struct efx_nic *efx,
40414743dddSAlejandro Lucero 					     struct devlink_info_req *req)
40514743dddSAlejandro Lucero {
40614743dddSAlejandro Lucero 	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_VERSION_V5_OUT_LEN);
40714743dddSAlejandro Lucero 	MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_VERSION_EXT_IN_LEN);
40814743dddSAlejandro Lucero 	char buf[EFX_MAX_VERSION_INFO_LEN];
40914743dddSAlejandro Lucero 	union {
41014743dddSAlejandro Lucero 		const __le32 *dwords;
41114743dddSAlejandro Lucero 		const __le16 *words;
41214743dddSAlejandro Lucero 		const char *str;
41314743dddSAlejandro Lucero 	} ver;
41414743dddSAlejandro Lucero 	size_t outlength;
41514743dddSAlejandro Lucero 	unsigned int flags;
41614743dddSAlejandro Lucero 	int rc;
41714743dddSAlejandro Lucero 
41814743dddSAlejandro Lucero 	rc = efx_mcdi_rpc(efx, MC_CMD_GET_VERSION, inbuf, sizeof(inbuf),
41914743dddSAlejandro Lucero 			  outbuf, sizeof(outbuf), &outlength);
42014743dddSAlejandro Lucero 	if (rc || outlength < MC_CMD_GET_VERSION_OUT_LEN) {
42114743dddSAlejandro Lucero 		netif_err(efx, drv, efx->net_dev,
42214743dddSAlejandro Lucero 			  "mcdi MC_CMD_GET_VERSION failed\n");
42314743dddSAlejandro Lucero 		return rc;
42414743dddSAlejandro Lucero 	}
42514743dddSAlejandro Lucero 
42614743dddSAlejandro Lucero 	/* Handle previous output */
42714743dddSAlejandro Lucero 	if (outlength < MC_CMD_GET_VERSION_V2_OUT_LEN) {
42814743dddSAlejandro Lucero 		ver.words = (__le16 *)MCDI_PTR(outbuf,
42914743dddSAlejandro Lucero 					       GET_VERSION_EXT_OUT_VERSION);
43014743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
43114743dddSAlejandro Lucero 			 le16_to_cpu(ver.words[0]),
43214743dddSAlejandro Lucero 			 le16_to_cpu(ver.words[1]),
43314743dddSAlejandro Lucero 			 le16_to_cpu(ver.words[2]),
43414743dddSAlejandro Lucero 			 le16_to_cpu(ver.words[3]));
43514743dddSAlejandro Lucero 
43614743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
43714743dddSAlejandro Lucero 						 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT,
43814743dddSAlejandro Lucero 						 buf);
43914743dddSAlejandro Lucero 		return 0;
44014743dddSAlejandro Lucero 	}
44114743dddSAlejandro Lucero 
44214743dddSAlejandro Lucero 	/* Handle V2 additions */
44314743dddSAlejandro Lucero 	flags = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_FLAGS);
44414743dddSAlejandro Lucero 	efx_devlink_info_running_v2(efx, req, flags, outbuf);
44514743dddSAlejandro Lucero 
44614743dddSAlejandro Lucero 	if (outlength < MC_CMD_GET_VERSION_V3_OUT_LEN)
44714743dddSAlejandro Lucero 		return 0;
44814743dddSAlejandro Lucero 
44914743dddSAlejandro Lucero 	/* Handle V3 additions */
45014743dddSAlejandro Lucero 	efx_devlink_info_running_v3(efx, req, flags, outbuf);
45114743dddSAlejandro Lucero 
45214743dddSAlejandro Lucero 	if (outlength < MC_CMD_GET_VERSION_V4_OUT_LEN)
45314743dddSAlejandro Lucero 		return 0;
45414743dddSAlejandro Lucero 
45514743dddSAlejandro Lucero 	/* Handle V4 additions */
45614743dddSAlejandro Lucero 	efx_devlink_info_running_v4(efx, req, flags, outbuf);
45714743dddSAlejandro Lucero 
45814743dddSAlejandro Lucero 	if (outlength < MC_CMD_GET_VERSION_V5_OUT_LEN)
45914743dddSAlejandro Lucero 		return 0;
46014743dddSAlejandro Lucero 
46114743dddSAlejandro Lucero 	/* Handle V5 additions */
46214743dddSAlejandro Lucero 	efx_devlink_info_running_v5(efx, req, flags, outbuf);
46314743dddSAlejandro Lucero 
46414743dddSAlejandro Lucero 	return 0;
46514743dddSAlejandro Lucero }
46614743dddSAlejandro Lucero 
46714743dddSAlejandro Lucero #define EFX_MAX_SERIALNUM_LEN	(ETH_ALEN * 2 + 1)
46814743dddSAlejandro Lucero 
46914743dddSAlejandro Lucero static int efx_devlink_info_board_cfg(struct efx_nic *efx,
47014743dddSAlejandro Lucero 				      struct devlink_info_req *req)
47114743dddSAlejandro Lucero {
47214743dddSAlejandro Lucero 	char sn[EFX_MAX_SERIALNUM_LEN];
47314743dddSAlejandro Lucero 	u8 mac_address[ETH_ALEN];
47414743dddSAlejandro Lucero 	int rc;
47514743dddSAlejandro Lucero 
47614743dddSAlejandro Lucero 	rc = efx_mcdi_get_board_cfg(efx, (u8 *)mac_address, NULL, NULL);
47714743dddSAlejandro Lucero 	if (!rc) {
47814743dddSAlejandro Lucero 		snprintf(sn, EFX_MAX_SERIALNUM_LEN, "%pm", mac_address);
47914743dddSAlejandro Lucero 		devlink_info_serial_number_put(req, sn);
48014743dddSAlejandro Lucero 	}
48114743dddSAlejandro Lucero 	return rc;
48214743dddSAlejandro Lucero }
48314743dddSAlejandro Lucero 
48414743dddSAlejandro Lucero static int efx_devlink_info_get(struct devlink *devlink,
48514743dddSAlejandro Lucero 				struct devlink_info_req *req,
48614743dddSAlejandro Lucero 				struct netlink_ext_ack *extack)
48714743dddSAlejandro Lucero {
48814743dddSAlejandro Lucero 	struct efx_devlink *devlink_private = devlink_priv(devlink);
48914743dddSAlejandro Lucero 	struct efx_nic *efx = devlink_private->efx;
49014743dddSAlejandro Lucero 	int rc;
49114743dddSAlejandro Lucero 
49214743dddSAlejandro Lucero 	/* Several different MCDI commands are used. We report first error
49314743dddSAlejandro Lucero 	 * through extack returning at that point. Specific error
49414743dddSAlejandro Lucero 	 * information via system messages.
49514743dddSAlejandro Lucero 	 */
49614743dddSAlejandro Lucero 	rc = efx_devlink_info_board_cfg(efx, req);
49714743dddSAlejandro Lucero 	if (rc) {
49814743dddSAlejandro Lucero 		NL_SET_ERR_MSG_MOD(extack, "Getting board info failed");
49914743dddSAlejandro Lucero 		return rc;
50014743dddSAlejandro Lucero 	}
50114743dddSAlejandro Lucero 	rc = efx_devlink_info_stored_versions(efx, req);
50214743dddSAlejandro Lucero 	if (rc) {
50314743dddSAlejandro Lucero 		NL_SET_ERR_MSG_MOD(extack, "Getting stored versions failed");
50414743dddSAlejandro Lucero 		return rc;
50514743dddSAlejandro Lucero 	}
50614743dddSAlejandro Lucero 	rc = efx_devlink_info_running_versions(efx, req);
50714743dddSAlejandro Lucero 	if (rc) {
50814743dddSAlejandro Lucero 		NL_SET_ERR_MSG_MOD(extack, "Getting running versions failed");
50914743dddSAlejandro Lucero 		return rc;
51014743dddSAlejandro Lucero 	}
51114743dddSAlejandro Lucero 
51214743dddSAlejandro Lucero 	return 0;
51314743dddSAlejandro Lucero }
51414743dddSAlejandro Lucero 
515fa34a514SAlejandro Lucero static const struct devlink_ops sfc_devlink_ops = {
51614743dddSAlejandro Lucero 	.info_get			= efx_devlink_info_get,
517fa34a514SAlejandro Lucero };
518fa34a514SAlejandro Lucero 
519*25414b2aSAlejandro Lucero #ifdef CONFIG_SFC_SRIOV
520*25414b2aSAlejandro Lucero static struct devlink_port *ef100_set_devlink_port(struct efx_nic *efx, u32 idx)
521*25414b2aSAlejandro Lucero {
522*25414b2aSAlejandro Lucero 	struct mae_mport_desc *mport;
523*25414b2aSAlejandro Lucero 	u32 id;
524*25414b2aSAlejandro Lucero 	int rc;
525*25414b2aSAlejandro Lucero 
526*25414b2aSAlejandro Lucero 	if (efx_mae_lookup_mport(efx, idx, &id)) {
527*25414b2aSAlejandro Lucero 		/* This should not happen. */
528*25414b2aSAlejandro Lucero 		if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
529*25414b2aSAlejandro Lucero 			pci_warn_once(efx->pci_dev, "No mport ID found for PF.\n");
530*25414b2aSAlejandro Lucero 		else
531*25414b2aSAlejandro Lucero 			pci_warn_once(efx->pci_dev, "No mport ID found for VF %u.\n",
532*25414b2aSAlejandro Lucero 				      idx);
533*25414b2aSAlejandro Lucero 		return NULL;
534*25414b2aSAlejandro Lucero 	}
535*25414b2aSAlejandro Lucero 
536*25414b2aSAlejandro Lucero 	mport = efx_mae_get_mport(efx, id);
537*25414b2aSAlejandro Lucero 	if (!mport) {
538*25414b2aSAlejandro Lucero 		/* This should not happen. */
539*25414b2aSAlejandro Lucero 		if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
540*25414b2aSAlejandro Lucero 			pci_warn_once(efx->pci_dev, "No mport found for PF.\n");
541*25414b2aSAlejandro Lucero 		else
542*25414b2aSAlejandro Lucero 			pci_warn_once(efx->pci_dev, "No mport found for VF %u.\n",
543*25414b2aSAlejandro Lucero 				      idx);
544*25414b2aSAlejandro Lucero 		return NULL;
545*25414b2aSAlejandro Lucero 	}
546*25414b2aSAlejandro Lucero 
547*25414b2aSAlejandro Lucero 	rc = efx_devlink_add_port(efx, mport);
548*25414b2aSAlejandro Lucero 	if (rc) {
549*25414b2aSAlejandro Lucero 		if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
550*25414b2aSAlejandro Lucero 			pci_warn(efx->pci_dev,
551*25414b2aSAlejandro Lucero 				 "devlink port creation for PF failed.\n");
552*25414b2aSAlejandro Lucero 		else
553*25414b2aSAlejandro Lucero 			pci_warn(efx->pci_dev,
554*25414b2aSAlejandro Lucero 				 "devlink_port creationg for VF %u failed.\n",
555*25414b2aSAlejandro Lucero 				 idx);
556*25414b2aSAlejandro Lucero 		return NULL;
557*25414b2aSAlejandro Lucero 	}
558*25414b2aSAlejandro Lucero 
559*25414b2aSAlejandro Lucero 	return &mport->dl_port;
560*25414b2aSAlejandro Lucero }
561*25414b2aSAlejandro Lucero 
562*25414b2aSAlejandro Lucero void ef100_rep_set_devlink_port(struct efx_rep *efv)
563*25414b2aSAlejandro Lucero {
564*25414b2aSAlejandro Lucero 	efv->dl_port = ef100_set_devlink_port(efv->parent, efv->idx);
565*25414b2aSAlejandro Lucero }
566*25414b2aSAlejandro Lucero 
567*25414b2aSAlejandro Lucero void ef100_pf_set_devlink_port(struct efx_nic *efx)
568*25414b2aSAlejandro Lucero {
569*25414b2aSAlejandro Lucero 	efx->dl_port = ef100_set_devlink_port(efx, MAE_MPORT_DESC_VF_IDX_NULL);
570*25414b2aSAlejandro Lucero }
571*25414b2aSAlejandro Lucero 
572*25414b2aSAlejandro Lucero void ef100_rep_unset_devlink_port(struct efx_rep *efv)
573*25414b2aSAlejandro Lucero {
574*25414b2aSAlejandro Lucero 	efx_devlink_del_port(efv->dl_port);
575*25414b2aSAlejandro Lucero }
576*25414b2aSAlejandro Lucero 
577*25414b2aSAlejandro Lucero void ef100_pf_unset_devlink_port(struct efx_nic *efx)
578*25414b2aSAlejandro Lucero {
579*25414b2aSAlejandro Lucero 	efx_devlink_del_port(efx->dl_port);
580*25414b2aSAlejandro Lucero }
581*25414b2aSAlejandro Lucero #endif
582*25414b2aSAlejandro Lucero 
583fa34a514SAlejandro Lucero void efx_fini_devlink_lock(struct efx_nic *efx)
584fa34a514SAlejandro Lucero {
585fa34a514SAlejandro Lucero 	if (efx->devlink)
586fa34a514SAlejandro Lucero 		devl_lock(efx->devlink);
587fa34a514SAlejandro Lucero }
588fa34a514SAlejandro Lucero 
589fa34a514SAlejandro Lucero void efx_fini_devlink_and_unlock(struct efx_nic *efx)
590fa34a514SAlejandro Lucero {
591fa34a514SAlejandro Lucero 	if (efx->devlink) {
592fa34a514SAlejandro Lucero 		devl_unregister(efx->devlink);
593fa34a514SAlejandro Lucero 		devl_unlock(efx->devlink);
594fa34a514SAlejandro Lucero 		devlink_free(efx->devlink);
595fa34a514SAlejandro Lucero 		efx->devlink = NULL;
596fa34a514SAlejandro Lucero 	}
597fa34a514SAlejandro Lucero }
598fa34a514SAlejandro Lucero 
599fa34a514SAlejandro Lucero int efx_probe_devlink_and_lock(struct efx_nic *efx)
600fa34a514SAlejandro Lucero {
601fa34a514SAlejandro Lucero 	struct efx_devlink *devlink_private;
602fa34a514SAlejandro Lucero 
603fa34a514SAlejandro Lucero 	if (efx->type->is_vf)
604fa34a514SAlejandro Lucero 		return 0;
605fa34a514SAlejandro Lucero 
606fa34a514SAlejandro Lucero 	efx->devlink = devlink_alloc(&sfc_devlink_ops,
607fa34a514SAlejandro Lucero 				     sizeof(struct efx_devlink),
608fa34a514SAlejandro Lucero 				     &efx->pci_dev->dev);
609fa34a514SAlejandro Lucero 	if (!efx->devlink)
610fa34a514SAlejandro Lucero 		return -ENOMEM;
611fa34a514SAlejandro Lucero 
612fa34a514SAlejandro Lucero 	devl_lock(efx->devlink);
613fa34a514SAlejandro Lucero 	devlink_private = devlink_priv(efx->devlink);
614fa34a514SAlejandro Lucero 	devlink_private->efx = efx;
615fa34a514SAlejandro Lucero 
616fa34a514SAlejandro Lucero 	devl_register(efx->devlink);
617fa34a514SAlejandro Lucero 
618fa34a514SAlejandro Lucero 	return 0;
619fa34a514SAlejandro Lucero }
620fa34a514SAlejandro Lucero 
621fa34a514SAlejandro Lucero void efx_probe_devlink_unlock(struct efx_nic *efx)
622fa34a514SAlejandro Lucero {
623fa34a514SAlejandro Lucero 	if (!efx->devlink)
624fa34a514SAlejandro Lucero 		return;
625fa34a514SAlejandro Lucero 
626fa34a514SAlejandro Lucero 	devl_unlock(efx->devlink);
627fa34a514SAlejandro Lucero }
628