xref: /openbmc/linux/drivers/net/ethernet/sfc/efx_devlink.c (revision 3b6096c9b30b9d65d09f9f4ee5f473c8c28f45d0)
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"
12fa78b017SAlejandro Lucero #include "ef100_nic.h"
13fa34a514SAlejandro Lucero #include "efx_devlink.h"
1414743dddSAlejandro Lucero #include <linux/rtc.h>
1514743dddSAlejandro Lucero #include "mcdi.h"
1614743dddSAlejandro Lucero #include "mcdi_functions.h"
1714743dddSAlejandro Lucero #include "mcdi_pcol.h"
1825414b2aSAlejandro Lucero #ifdef CONFIG_SFC_SRIOV
1925414b2aSAlejandro Lucero #include "mae.h"
2025414b2aSAlejandro Lucero #include "ef100_rep.h"
2125414b2aSAlejandro Lucero #endif
22fa34a514SAlejandro Lucero 
23fa34a514SAlejandro Lucero struct efx_devlink {
24fa34a514SAlejandro Lucero 	struct efx_nic *efx;
25fa34a514SAlejandro Lucero };
26fa34a514SAlejandro Lucero 
2725414b2aSAlejandro Lucero #ifdef CONFIG_SFC_SRIOV
2825414b2aSAlejandro Lucero static void efx_devlink_del_port(struct devlink_port *dl_port)
2925414b2aSAlejandro Lucero {
3025414b2aSAlejandro Lucero 	if (!dl_port)
3125414b2aSAlejandro Lucero 		return;
3225414b2aSAlejandro Lucero 	devl_port_unregister(dl_port);
3325414b2aSAlejandro Lucero }
3425414b2aSAlejandro Lucero 
3525414b2aSAlejandro Lucero static int efx_devlink_add_port(struct efx_nic *efx,
3625414b2aSAlejandro Lucero 				struct mae_mport_desc *mport)
3725414b2aSAlejandro Lucero {
3825414b2aSAlejandro Lucero 	bool external = false;
3925414b2aSAlejandro Lucero 
4025414b2aSAlejandro Lucero 	if (!ef100_mport_on_local_intf(efx, mport))
4125414b2aSAlejandro Lucero 		external = true;
4225414b2aSAlejandro Lucero 
4325414b2aSAlejandro Lucero 	switch (mport->mport_type) {
4425414b2aSAlejandro Lucero 	case MAE_MPORT_DESC_MPORT_TYPE_VNIC:
4525414b2aSAlejandro Lucero 		if (mport->vf_idx != MAE_MPORT_DESC_VF_IDX_NULL)
4625414b2aSAlejandro Lucero 			devlink_port_attrs_pci_vf_set(&mport->dl_port, 0, mport->pf_idx,
4725414b2aSAlejandro Lucero 						      mport->vf_idx,
4825414b2aSAlejandro Lucero 						      external);
4925414b2aSAlejandro Lucero 		else
5025414b2aSAlejandro Lucero 			devlink_port_attrs_pci_pf_set(&mport->dl_port, 0, mport->pf_idx,
5125414b2aSAlejandro Lucero 						      external);
5225414b2aSAlejandro Lucero 		break;
5325414b2aSAlejandro Lucero 	default:
5425414b2aSAlejandro Lucero 		/* MAE_MPORT_DESC_MPORT_ALIAS and UNDEFINED */
5525414b2aSAlejandro Lucero 		return 0;
5625414b2aSAlejandro Lucero 	}
5725414b2aSAlejandro Lucero 
5825414b2aSAlejandro Lucero 	mport->dl_port.index = mport->mport_id;
5925414b2aSAlejandro Lucero 
6025414b2aSAlejandro Lucero 	return devl_port_register(efx->devlink, &mport->dl_port, mport->mport_id);
6125414b2aSAlejandro Lucero }
62fa78b017SAlejandro Lucero 
63fa78b017SAlejandro Lucero static int efx_devlink_port_addr_get(struct devlink_port *port, u8 *hw_addr,
64fa78b017SAlejandro Lucero 				     int *hw_addr_len,
65fa78b017SAlejandro Lucero 				     struct netlink_ext_ack *extack)
66fa78b017SAlejandro Lucero {
67fa78b017SAlejandro Lucero 	struct efx_devlink *devlink = devlink_priv(port->devlink);
68fa78b017SAlejandro Lucero 	struct mae_mport_desc *mport_desc;
69fa78b017SAlejandro Lucero 	efx_qword_t pciefn;
70fa78b017SAlejandro Lucero 	u32 client_id;
71fa78b017SAlejandro Lucero 	int rc = 0;
72fa78b017SAlejandro Lucero 
73fa78b017SAlejandro Lucero 	mport_desc = container_of(port, struct mae_mport_desc, dl_port);
74fa78b017SAlejandro Lucero 
75fa78b017SAlejandro Lucero 	if (!ef100_mport_on_local_intf(devlink->efx, mport_desc)) {
76fa78b017SAlejandro Lucero 		rc = -EINVAL;
77fa78b017SAlejandro Lucero 		NL_SET_ERR_MSG_FMT(extack,
78fa78b017SAlejandro Lucero 				   "Port not on local interface (mport: %u)",
79fa78b017SAlejandro Lucero 				   mport_desc->mport_id);
80fa78b017SAlejandro Lucero 		goto out;
81fa78b017SAlejandro Lucero 	}
82fa78b017SAlejandro Lucero 
83fa78b017SAlejandro Lucero 	if (ef100_mport_is_vf(mport_desc))
84fa78b017SAlejandro Lucero 		EFX_POPULATE_QWORD_3(pciefn,
85fa78b017SAlejandro Lucero 				     PCIE_FUNCTION_PF, PCIE_FUNCTION_PF_NULL,
86fa78b017SAlejandro Lucero 				     PCIE_FUNCTION_VF, mport_desc->vf_idx,
87fa78b017SAlejandro Lucero 				     PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);
88fa78b017SAlejandro Lucero 	else
89fa78b017SAlejandro Lucero 		EFX_POPULATE_QWORD_3(pciefn,
90fa78b017SAlejandro Lucero 				     PCIE_FUNCTION_PF, mport_desc->pf_idx,
91fa78b017SAlejandro Lucero 				     PCIE_FUNCTION_VF, PCIE_FUNCTION_VF_NULL,
92fa78b017SAlejandro Lucero 				     PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);
93fa78b017SAlejandro Lucero 
94fa78b017SAlejandro Lucero 	rc = efx_ef100_lookup_client_id(devlink->efx, pciefn, &client_id);
95fa78b017SAlejandro Lucero 	if (rc) {
96fa78b017SAlejandro Lucero 		NL_SET_ERR_MSG_FMT(extack,
97fa78b017SAlejandro Lucero 				   "No internal client_ID for port (mport: %u)",
98fa78b017SAlejandro Lucero 				   mport_desc->mport_id);
99fa78b017SAlejandro Lucero 		goto out;
100fa78b017SAlejandro Lucero 	}
101fa78b017SAlejandro Lucero 
102fa78b017SAlejandro Lucero 	rc = ef100_get_mac_address(devlink->efx, hw_addr, client_id, true);
103fa78b017SAlejandro Lucero 	if (rc != 0)
104fa78b017SAlejandro Lucero 		NL_SET_ERR_MSG_FMT(extack,
105fa78b017SAlejandro Lucero 				   "No available MAC for port (mport: %u)",
106fa78b017SAlejandro Lucero 				   mport_desc->mport_id);
107fa78b017SAlejandro Lucero out:
108fa78b017SAlejandro Lucero 	*hw_addr_len = ETH_ALEN;
109fa78b017SAlejandro Lucero 	return rc;
110fa78b017SAlejandro Lucero }
111fa78b017SAlejandro Lucero 
112*3b6096c9SAlejandro Lucero static int efx_devlink_port_addr_set(struct devlink_port *port,
113*3b6096c9SAlejandro Lucero 				     const u8 *hw_addr, int hw_addr_len,
114*3b6096c9SAlejandro Lucero 				     struct netlink_ext_ack *extack)
115*3b6096c9SAlejandro Lucero {
116*3b6096c9SAlejandro Lucero 	MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_CLIENT_MAC_ADDRESSES_IN_LEN(1));
117*3b6096c9SAlejandro Lucero 	struct efx_devlink *devlink = devlink_priv(port->devlink);
118*3b6096c9SAlejandro Lucero 	struct mae_mport_desc *mport_desc;
119*3b6096c9SAlejandro Lucero 	efx_qword_t pciefn;
120*3b6096c9SAlejandro Lucero 	u32 client_id;
121*3b6096c9SAlejandro Lucero 	int rc;
122*3b6096c9SAlejandro Lucero 
123*3b6096c9SAlejandro Lucero 	mport_desc = container_of(port, struct mae_mport_desc, dl_port);
124*3b6096c9SAlejandro Lucero 
125*3b6096c9SAlejandro Lucero 	if (!ef100_mport_is_vf(mport_desc)) {
126*3b6096c9SAlejandro Lucero 		NL_SET_ERR_MSG_FMT(extack,
127*3b6096c9SAlejandro Lucero 				   "port mac change not allowed (mport: %u)",
128*3b6096c9SAlejandro Lucero 				   mport_desc->mport_id);
129*3b6096c9SAlejandro Lucero 		return -EPERM;
130*3b6096c9SAlejandro Lucero 	}
131*3b6096c9SAlejandro Lucero 
132*3b6096c9SAlejandro Lucero 	EFX_POPULATE_QWORD_3(pciefn,
133*3b6096c9SAlejandro Lucero 			     PCIE_FUNCTION_PF, PCIE_FUNCTION_PF_NULL,
134*3b6096c9SAlejandro Lucero 			     PCIE_FUNCTION_VF, mport_desc->vf_idx,
135*3b6096c9SAlejandro Lucero 			     PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);
136*3b6096c9SAlejandro Lucero 
137*3b6096c9SAlejandro Lucero 	rc = efx_ef100_lookup_client_id(devlink->efx, pciefn, &client_id);
138*3b6096c9SAlejandro Lucero 	if (rc) {
139*3b6096c9SAlejandro Lucero 		NL_SET_ERR_MSG_FMT(extack,
140*3b6096c9SAlejandro Lucero 				   "No internal client_ID for port (mport: %u)",
141*3b6096c9SAlejandro Lucero 				   mport_desc->mport_id);
142*3b6096c9SAlejandro Lucero 		return rc;
143*3b6096c9SAlejandro Lucero 	}
144*3b6096c9SAlejandro Lucero 
145*3b6096c9SAlejandro Lucero 	MCDI_SET_DWORD(inbuf, SET_CLIENT_MAC_ADDRESSES_IN_CLIENT_HANDLE,
146*3b6096c9SAlejandro Lucero 		       client_id);
147*3b6096c9SAlejandro Lucero 
148*3b6096c9SAlejandro Lucero 	ether_addr_copy(MCDI_PTR(inbuf, SET_CLIENT_MAC_ADDRESSES_IN_MAC_ADDRS),
149*3b6096c9SAlejandro Lucero 			hw_addr);
150*3b6096c9SAlejandro Lucero 
151*3b6096c9SAlejandro Lucero 	rc = efx_mcdi_rpc(devlink->efx, MC_CMD_SET_CLIENT_MAC_ADDRESSES, inbuf,
152*3b6096c9SAlejandro Lucero 			  sizeof(inbuf), NULL, 0, NULL);
153*3b6096c9SAlejandro Lucero 	if (rc)
154*3b6096c9SAlejandro Lucero 		NL_SET_ERR_MSG_FMT(extack,
155*3b6096c9SAlejandro Lucero 				   "sfc MC_CMD_SET_CLIENT_MAC_ADDRESSES mcdi error (mport: %u)",
156*3b6096c9SAlejandro Lucero 				   mport_desc->mport_id);
157*3b6096c9SAlejandro Lucero 
158*3b6096c9SAlejandro Lucero 	return rc;
159*3b6096c9SAlejandro Lucero }
160*3b6096c9SAlejandro Lucero 
16125414b2aSAlejandro Lucero #endif
16225414b2aSAlejandro Lucero 
16314743dddSAlejandro Lucero static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
16414743dddSAlejandro Lucero 					    struct devlink_info_req *req,
16514743dddSAlejandro Lucero 					    unsigned int partition_type,
16614743dddSAlejandro Lucero 					    const char *version_name)
16714743dddSAlejandro Lucero {
16814743dddSAlejandro Lucero 	char buf[EFX_MAX_VERSION_INFO_LEN];
16914743dddSAlejandro Lucero 	u16 version[4];
17014743dddSAlejandro Lucero 	int rc;
17114743dddSAlejandro Lucero 
17214743dddSAlejandro Lucero 	rc = efx_mcdi_nvram_metadata(efx, partition_type, NULL, version, NULL,
17314743dddSAlejandro Lucero 				     0);
17414743dddSAlejandro Lucero 	if (rc) {
17514743dddSAlejandro Lucero 		netif_err(efx, drv, efx->net_dev, "mcdi nvram %s: failed\n",
17614743dddSAlejandro Lucero 			  version_name);
17714743dddSAlejandro Lucero 		return rc;
17814743dddSAlejandro Lucero 	}
17914743dddSAlejandro Lucero 
18014743dddSAlejandro Lucero 	snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u", version[0],
18114743dddSAlejandro Lucero 		 version[1], version[2], version[3]);
18214743dddSAlejandro Lucero 	devlink_info_version_stored_put(req, version_name, buf);
18314743dddSAlejandro Lucero 
18414743dddSAlejandro Lucero 	return 0;
18514743dddSAlejandro Lucero }
18614743dddSAlejandro Lucero 
18714743dddSAlejandro Lucero static int efx_devlink_info_stored_versions(struct efx_nic *efx,
18814743dddSAlejandro Lucero 					    struct devlink_info_req *req)
18914743dddSAlejandro Lucero {
19014743dddSAlejandro Lucero 	int rc;
19114743dddSAlejandro Lucero 
19214743dddSAlejandro Lucero 	rc = efx_devlink_info_nvram_partition(efx, req,
19314743dddSAlejandro Lucero 					      NVRAM_PARTITION_TYPE_BUNDLE,
19414743dddSAlejandro Lucero 					      DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID);
19514743dddSAlejandro Lucero 	if (rc)
19614743dddSAlejandro Lucero 		return rc;
19714743dddSAlejandro Lucero 
19814743dddSAlejandro Lucero 	rc = efx_devlink_info_nvram_partition(efx, req,
19914743dddSAlejandro Lucero 					      NVRAM_PARTITION_TYPE_MC_FIRMWARE,
20014743dddSAlejandro Lucero 					      DEVLINK_INFO_VERSION_GENERIC_FW_MGMT);
20114743dddSAlejandro Lucero 	if (rc)
20214743dddSAlejandro Lucero 		return rc;
20314743dddSAlejandro Lucero 
20414743dddSAlejandro Lucero 	rc = efx_devlink_info_nvram_partition(efx, req,
20514743dddSAlejandro Lucero 					      NVRAM_PARTITION_TYPE_SUC_FIRMWARE,
20614743dddSAlejandro Lucero 					      EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC);
20714743dddSAlejandro Lucero 	if (rc)
20814743dddSAlejandro Lucero 		return rc;
20914743dddSAlejandro Lucero 
21014743dddSAlejandro Lucero 	rc = efx_devlink_info_nvram_partition(efx, req,
21114743dddSAlejandro Lucero 					      NVRAM_PARTITION_TYPE_EXPANSION_ROM,
21214743dddSAlejandro Lucero 					      EFX_DEVLINK_INFO_VERSION_FW_EXPROM);
21314743dddSAlejandro Lucero 	if (rc)
21414743dddSAlejandro Lucero 		return rc;
21514743dddSAlejandro Lucero 
21614743dddSAlejandro Lucero 	rc = efx_devlink_info_nvram_partition(efx, req,
21714743dddSAlejandro Lucero 					      NVRAM_PARTITION_TYPE_EXPANSION_UEFI,
21814743dddSAlejandro Lucero 					      EFX_DEVLINK_INFO_VERSION_FW_UEFI);
21914743dddSAlejandro Lucero 	return rc;
22014743dddSAlejandro Lucero }
22114743dddSAlejandro Lucero 
22214743dddSAlejandro Lucero #define EFX_VER_FLAG(_f)	\
22314743dddSAlejandro Lucero 	(MC_CMD_GET_VERSION_V5_OUT_ ## _f ## _PRESENT_LBN)
22414743dddSAlejandro Lucero 
22514743dddSAlejandro Lucero static void efx_devlink_info_running_v2(struct efx_nic *efx,
22614743dddSAlejandro Lucero 					struct devlink_info_req *req,
22714743dddSAlejandro Lucero 					unsigned int flags, efx_dword_t *outbuf)
22814743dddSAlejandro Lucero {
22914743dddSAlejandro Lucero 	char buf[EFX_MAX_VERSION_INFO_LEN];
23014743dddSAlejandro Lucero 	union {
23114743dddSAlejandro Lucero 		const __le32 *dwords;
23214743dddSAlejandro Lucero 		const __le16 *words;
23314743dddSAlejandro Lucero 		const char *str;
23414743dddSAlejandro Lucero 	} ver;
23514743dddSAlejandro Lucero 	struct rtc_time build_date;
23614743dddSAlejandro Lucero 	unsigned int build_id;
23714743dddSAlejandro Lucero 	size_t offset;
23814743dddSAlejandro Lucero 	__maybe_unused u64 tstamp;
23914743dddSAlejandro Lucero 
24014743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(BOARD_EXT_INFO))) {
24114743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%s",
24214743dddSAlejandro Lucero 			 MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_NAME));
24314743dddSAlejandro Lucero 		devlink_info_version_fixed_put(req,
24414743dddSAlejandro Lucero 					       DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
24514743dddSAlejandro Lucero 					       buf);
24614743dddSAlejandro Lucero 
24714743dddSAlejandro Lucero 		/* Favour full board version if present (in V5 or later) */
24814743dddSAlejandro Lucero 		if (~flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) {
24914743dddSAlejandro Lucero 			snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u",
25014743dddSAlejandro Lucero 				 MCDI_DWORD(outbuf,
25114743dddSAlejandro Lucero 					    GET_VERSION_V2_OUT_BOARD_REVISION));
25214743dddSAlejandro Lucero 			devlink_info_version_fixed_put(req,
25314743dddSAlejandro Lucero 						       DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,
25414743dddSAlejandro Lucero 						       buf);
25514743dddSAlejandro Lucero 		}
25614743dddSAlejandro Lucero 
25714743dddSAlejandro Lucero 		ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_SERIAL);
25814743dddSAlejandro Lucero 		if (ver.str[0])
25914743dddSAlejandro Lucero 			devlink_info_board_serial_number_put(req, ver.str);
26014743dddSAlejandro Lucero 	}
26114743dddSAlejandro Lucero 
26214743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(FPGA_EXT_INFO))) {
26314743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
26414743dddSAlejandro Lucero 						GET_VERSION_V2_OUT_FPGA_VERSION);
26514743dddSAlejandro Lucero 		offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u_%c%u",
26614743dddSAlejandro Lucero 				  le32_to_cpu(ver.dwords[0]),
26714743dddSAlejandro Lucero 				  'A' + le32_to_cpu(ver.dwords[1]),
26814743dddSAlejandro Lucero 				  le32_to_cpu(ver.dwords[2]));
26914743dddSAlejandro Lucero 
27014743dddSAlejandro Lucero 		ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_FPGA_EXTRA);
27114743dddSAlejandro Lucero 		if (ver.str[0])
27214743dddSAlejandro Lucero 			snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
27314743dddSAlejandro Lucero 				 " (%s)", ver.str);
27414743dddSAlejandro Lucero 
27514743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
27614743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_FPGA_REV,
27714743dddSAlejandro Lucero 						 buf);
27814743dddSAlejandro Lucero 	}
27914743dddSAlejandro Lucero 
28014743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(CMC_EXT_INFO))) {
28114743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
28214743dddSAlejandro Lucero 						GET_VERSION_V2_OUT_CMCFW_VERSION);
28314743dddSAlejandro Lucero 		offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
28414743dddSAlejandro Lucero 				  le32_to_cpu(ver.dwords[0]),
28514743dddSAlejandro Lucero 				  le32_to_cpu(ver.dwords[1]),
28614743dddSAlejandro Lucero 				  le32_to_cpu(ver.dwords[2]),
28714743dddSAlejandro Lucero 				  le32_to_cpu(ver.dwords[3]));
28814743dddSAlejandro Lucero 
28914743dddSAlejandro Lucero #ifdef CONFIG_RTC_LIB
29014743dddSAlejandro Lucero 		tstamp = MCDI_QWORD(outbuf,
29114743dddSAlejandro Lucero 				    GET_VERSION_V2_OUT_CMCFW_BUILD_DATE);
29214743dddSAlejandro Lucero 		if (tstamp) {
29314743dddSAlejandro Lucero 			rtc_time64_to_tm(tstamp, &build_date);
29414743dddSAlejandro Lucero 			snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
29514743dddSAlejandro Lucero 				 " (%ptRd)", &build_date);
29614743dddSAlejandro Lucero 		}
29714743dddSAlejandro Lucero #endif
29814743dddSAlejandro Lucero 
29914743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
30014743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_CMC,
30114743dddSAlejandro Lucero 						 buf);
30214743dddSAlejandro Lucero 	}
30314743dddSAlejandro Lucero 
30414743dddSAlejandro Lucero 	ver.words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_V2_OUT_VERSION);
30514743dddSAlejandro Lucero 	offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
30614743dddSAlejandro Lucero 			  le16_to_cpu(ver.words[0]), le16_to_cpu(ver.words[1]),
30714743dddSAlejandro Lucero 			  le16_to_cpu(ver.words[2]), le16_to_cpu(ver.words[3]));
30814743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(MCFW_EXT_INFO))) {
30914743dddSAlejandro Lucero 		build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_ID);
31014743dddSAlejandro Lucero 		snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
31114743dddSAlejandro Lucero 			 " (%x) %s", build_id,
31214743dddSAlejandro Lucero 			 MCDI_PTR(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_NAME));
31314743dddSAlejandro Lucero 	}
31414743dddSAlejandro Lucero 	devlink_info_version_running_put(req,
31514743dddSAlejandro Lucero 					 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT,
31614743dddSAlejandro Lucero 					 buf);
31714743dddSAlejandro Lucero 
31814743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) {
31914743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
32014743dddSAlejandro Lucero 						GET_VERSION_V2_OUT_SUCFW_VERSION);
32114743dddSAlejandro Lucero #ifdef CONFIG_RTC_LIB
32214743dddSAlejandro Lucero 		tstamp = MCDI_QWORD(outbuf,
32314743dddSAlejandro Lucero 				    GET_VERSION_V2_OUT_SUCFW_BUILD_DATE);
32414743dddSAlejandro Lucero 		rtc_time64_to_tm(tstamp, &build_date);
32514743dddSAlejandro Lucero #else
32614743dddSAlejandro Lucero 		memset(&build_date, 0, sizeof(build_date)
32714743dddSAlejandro Lucero #endif
32814743dddSAlejandro Lucero 		build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_SUCFW_CHIP_ID);
32914743dddSAlejandro Lucero 
33014743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN,
33114743dddSAlejandro Lucero 			 "%u.%u.%u.%u type %x (%ptRd)",
33214743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
33314743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]), le32_to_cpu(ver.dwords[3]),
33414743dddSAlejandro Lucero 			 build_id, &build_date);
33514743dddSAlejandro Lucero 
33614743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
33714743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC,
33814743dddSAlejandro Lucero 						 buf);
33914743dddSAlejandro Lucero 	}
34014743dddSAlejandro Lucero }
34114743dddSAlejandro Lucero 
34214743dddSAlejandro Lucero static void efx_devlink_info_running_v3(struct efx_nic *efx,
34314743dddSAlejandro Lucero 					struct devlink_info_req *req,
34414743dddSAlejandro Lucero 					unsigned int flags, efx_dword_t *outbuf)
34514743dddSAlejandro Lucero {
34614743dddSAlejandro Lucero 	char buf[EFX_MAX_VERSION_INFO_LEN];
34714743dddSAlejandro Lucero 	union {
34814743dddSAlejandro Lucero 		const __le32 *dwords;
34914743dddSAlejandro Lucero 		const __le16 *words;
35014743dddSAlejandro Lucero 		const char *str;
35114743dddSAlejandro Lucero 	} ver;
35214743dddSAlejandro Lucero 
35314743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(DATAPATH_HW_VERSION))) {
35414743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
35514743dddSAlejandro Lucero 						GET_VERSION_V3_OUT_DATAPATH_HW_VERSION);
35614743dddSAlejandro Lucero 
35714743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u",
35814743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
35914743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]));
36014743dddSAlejandro Lucero 
36114743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
36214743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_DATAPATH_HW,
36314743dddSAlejandro Lucero 						 buf);
36414743dddSAlejandro Lucero 	}
36514743dddSAlejandro Lucero 
36614743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(DATAPATH_FW_VERSION))) {
36714743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
36814743dddSAlejandro Lucero 						GET_VERSION_V3_OUT_DATAPATH_FW_VERSION);
36914743dddSAlejandro Lucero 
37014743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u",
37114743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
37214743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]));
37314743dddSAlejandro Lucero 
37414743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
37514743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_DATAPATH_FW,
37614743dddSAlejandro Lucero 						 buf);
37714743dddSAlejandro Lucero 	}
37814743dddSAlejandro Lucero }
37914743dddSAlejandro Lucero 
38014743dddSAlejandro Lucero static void efx_devlink_info_running_v4(struct efx_nic *efx,
38114743dddSAlejandro Lucero 					struct devlink_info_req *req,
38214743dddSAlejandro Lucero 					unsigned int flags, efx_dword_t *outbuf)
38314743dddSAlejandro Lucero {
38414743dddSAlejandro Lucero 	char buf[EFX_MAX_VERSION_INFO_LEN];
38514743dddSAlejandro Lucero 	union {
38614743dddSAlejandro Lucero 		const __le32 *dwords;
38714743dddSAlejandro Lucero 		const __le16 *words;
38814743dddSAlejandro Lucero 		const char *str;
38914743dddSAlejandro Lucero 	} ver;
39014743dddSAlejandro Lucero 
39114743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(SOC_BOOT_VERSION))) {
39214743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
39314743dddSAlejandro Lucero 						GET_VERSION_V4_OUT_SOC_BOOT_VERSION);
39414743dddSAlejandro Lucero 
39514743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
39614743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
39714743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]),
39814743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[3]));
39914743dddSAlejandro Lucero 
40014743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
40114743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_SOC_BOOT,
40214743dddSAlejandro Lucero 						 buf);
40314743dddSAlejandro Lucero 	}
40414743dddSAlejandro Lucero 
40514743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(SOC_UBOOT_VERSION))) {
40614743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
40714743dddSAlejandro Lucero 						GET_VERSION_V4_OUT_SOC_UBOOT_VERSION);
40814743dddSAlejandro Lucero 
40914743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
41014743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
41114743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]),
41214743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[3]));
41314743dddSAlejandro Lucero 
41414743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
41514743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_SOC_UBOOT,
41614743dddSAlejandro Lucero 						 buf);
41714743dddSAlejandro Lucero 	}
41814743dddSAlejandro Lucero 
41914743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(SOC_MAIN_ROOTFS_VERSION))) {
42014743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
42114743dddSAlejandro Lucero 					GET_VERSION_V4_OUT_SOC_MAIN_ROOTFS_VERSION);
42214743dddSAlejandro Lucero 
42314743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
42414743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
42514743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]),
42614743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[3]));
42714743dddSAlejandro Lucero 
42814743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
42914743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_SOC_MAIN,
43014743dddSAlejandro Lucero 						 buf);
43114743dddSAlejandro Lucero 	}
43214743dddSAlejandro Lucero 
43314743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(SOC_RECOVERY_BUILDROOT_VERSION))) {
43414743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
43514743dddSAlejandro Lucero 						GET_VERSION_V4_OUT_SOC_RECOVERY_BUILDROOT_VERSION);
43614743dddSAlejandro Lucero 
43714743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
43814743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
43914743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]),
44014743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[3]));
44114743dddSAlejandro Lucero 
44214743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
44314743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_SOC_RECOVERY,
44414743dddSAlejandro Lucero 						 buf);
44514743dddSAlejandro Lucero 	}
44614743dddSAlejandro Lucero 
44714743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(SUCFW_VERSION)) &&
44814743dddSAlejandro Lucero 	    ~flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) {
44914743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
45014743dddSAlejandro Lucero 						GET_VERSION_V4_OUT_SUCFW_VERSION);
45114743dddSAlejandro Lucero 
45214743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
45314743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
45414743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]),
45514743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[3]));
45614743dddSAlejandro Lucero 
45714743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
45814743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC,
45914743dddSAlejandro Lucero 						 buf);
46014743dddSAlejandro Lucero 	}
46114743dddSAlejandro Lucero }
46214743dddSAlejandro Lucero 
46314743dddSAlejandro Lucero static void efx_devlink_info_running_v5(struct efx_nic *efx,
46414743dddSAlejandro Lucero 					struct devlink_info_req *req,
46514743dddSAlejandro Lucero 					unsigned int flags, efx_dword_t *outbuf)
46614743dddSAlejandro Lucero {
46714743dddSAlejandro Lucero 	char buf[EFX_MAX_VERSION_INFO_LEN];
46814743dddSAlejandro Lucero 	union {
46914743dddSAlejandro Lucero 		const __le32 *dwords;
47014743dddSAlejandro Lucero 		const __le16 *words;
47114743dddSAlejandro Lucero 		const char *str;
47214743dddSAlejandro Lucero 	} ver;
47314743dddSAlejandro Lucero 
47414743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) {
47514743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
47614743dddSAlejandro Lucero 						GET_VERSION_V5_OUT_BOARD_VERSION);
47714743dddSAlejandro Lucero 
47814743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
47914743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
48014743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]),
48114743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[3]));
48214743dddSAlejandro Lucero 
48314743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
48414743dddSAlejandro Lucero 						 DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,
48514743dddSAlejandro Lucero 						 buf);
48614743dddSAlejandro Lucero 	}
48714743dddSAlejandro Lucero 
48814743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(BUNDLE_VERSION))) {
48914743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
49014743dddSAlejandro Lucero 						GET_VERSION_V5_OUT_BUNDLE_VERSION);
49114743dddSAlejandro Lucero 
49214743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
49314743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
49414743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]),
49514743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[3]));
49614743dddSAlejandro Lucero 
49714743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
49814743dddSAlejandro Lucero 						 DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
49914743dddSAlejandro Lucero 						 buf);
50014743dddSAlejandro Lucero 	}
50114743dddSAlejandro Lucero }
50214743dddSAlejandro Lucero 
50314743dddSAlejandro Lucero static int efx_devlink_info_running_versions(struct efx_nic *efx,
50414743dddSAlejandro Lucero 					     struct devlink_info_req *req)
50514743dddSAlejandro Lucero {
50614743dddSAlejandro Lucero 	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_VERSION_V5_OUT_LEN);
50714743dddSAlejandro Lucero 	MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_VERSION_EXT_IN_LEN);
50814743dddSAlejandro Lucero 	char buf[EFX_MAX_VERSION_INFO_LEN];
50914743dddSAlejandro Lucero 	union {
51014743dddSAlejandro Lucero 		const __le32 *dwords;
51114743dddSAlejandro Lucero 		const __le16 *words;
51214743dddSAlejandro Lucero 		const char *str;
51314743dddSAlejandro Lucero 	} ver;
51414743dddSAlejandro Lucero 	size_t outlength;
51514743dddSAlejandro Lucero 	unsigned int flags;
51614743dddSAlejandro Lucero 	int rc;
51714743dddSAlejandro Lucero 
51814743dddSAlejandro Lucero 	rc = efx_mcdi_rpc(efx, MC_CMD_GET_VERSION, inbuf, sizeof(inbuf),
51914743dddSAlejandro Lucero 			  outbuf, sizeof(outbuf), &outlength);
52014743dddSAlejandro Lucero 	if (rc || outlength < MC_CMD_GET_VERSION_OUT_LEN) {
52114743dddSAlejandro Lucero 		netif_err(efx, drv, efx->net_dev,
52214743dddSAlejandro Lucero 			  "mcdi MC_CMD_GET_VERSION failed\n");
52314743dddSAlejandro Lucero 		return rc;
52414743dddSAlejandro Lucero 	}
52514743dddSAlejandro Lucero 
52614743dddSAlejandro Lucero 	/* Handle previous output */
52714743dddSAlejandro Lucero 	if (outlength < MC_CMD_GET_VERSION_V2_OUT_LEN) {
52814743dddSAlejandro Lucero 		ver.words = (__le16 *)MCDI_PTR(outbuf,
52914743dddSAlejandro Lucero 					       GET_VERSION_EXT_OUT_VERSION);
53014743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
53114743dddSAlejandro Lucero 			 le16_to_cpu(ver.words[0]),
53214743dddSAlejandro Lucero 			 le16_to_cpu(ver.words[1]),
53314743dddSAlejandro Lucero 			 le16_to_cpu(ver.words[2]),
53414743dddSAlejandro Lucero 			 le16_to_cpu(ver.words[3]));
53514743dddSAlejandro Lucero 
53614743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
53714743dddSAlejandro Lucero 						 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT,
53814743dddSAlejandro Lucero 						 buf);
53914743dddSAlejandro Lucero 		return 0;
54014743dddSAlejandro Lucero 	}
54114743dddSAlejandro Lucero 
54214743dddSAlejandro Lucero 	/* Handle V2 additions */
54314743dddSAlejandro Lucero 	flags = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_FLAGS);
54414743dddSAlejandro Lucero 	efx_devlink_info_running_v2(efx, req, flags, outbuf);
54514743dddSAlejandro Lucero 
54614743dddSAlejandro Lucero 	if (outlength < MC_CMD_GET_VERSION_V3_OUT_LEN)
54714743dddSAlejandro Lucero 		return 0;
54814743dddSAlejandro Lucero 
54914743dddSAlejandro Lucero 	/* Handle V3 additions */
55014743dddSAlejandro Lucero 	efx_devlink_info_running_v3(efx, req, flags, outbuf);
55114743dddSAlejandro Lucero 
55214743dddSAlejandro Lucero 	if (outlength < MC_CMD_GET_VERSION_V4_OUT_LEN)
55314743dddSAlejandro Lucero 		return 0;
55414743dddSAlejandro Lucero 
55514743dddSAlejandro Lucero 	/* Handle V4 additions */
55614743dddSAlejandro Lucero 	efx_devlink_info_running_v4(efx, req, flags, outbuf);
55714743dddSAlejandro Lucero 
55814743dddSAlejandro Lucero 	if (outlength < MC_CMD_GET_VERSION_V5_OUT_LEN)
55914743dddSAlejandro Lucero 		return 0;
56014743dddSAlejandro Lucero 
56114743dddSAlejandro Lucero 	/* Handle V5 additions */
56214743dddSAlejandro Lucero 	efx_devlink_info_running_v5(efx, req, flags, outbuf);
56314743dddSAlejandro Lucero 
56414743dddSAlejandro Lucero 	return 0;
56514743dddSAlejandro Lucero }
56614743dddSAlejandro Lucero 
56714743dddSAlejandro Lucero #define EFX_MAX_SERIALNUM_LEN	(ETH_ALEN * 2 + 1)
56814743dddSAlejandro Lucero 
56914743dddSAlejandro Lucero static int efx_devlink_info_board_cfg(struct efx_nic *efx,
57014743dddSAlejandro Lucero 				      struct devlink_info_req *req)
57114743dddSAlejandro Lucero {
57214743dddSAlejandro Lucero 	char sn[EFX_MAX_SERIALNUM_LEN];
57314743dddSAlejandro Lucero 	u8 mac_address[ETH_ALEN];
57414743dddSAlejandro Lucero 	int rc;
57514743dddSAlejandro Lucero 
57614743dddSAlejandro Lucero 	rc = efx_mcdi_get_board_cfg(efx, (u8 *)mac_address, NULL, NULL);
57714743dddSAlejandro Lucero 	if (!rc) {
57814743dddSAlejandro Lucero 		snprintf(sn, EFX_MAX_SERIALNUM_LEN, "%pm", mac_address);
57914743dddSAlejandro Lucero 		devlink_info_serial_number_put(req, sn);
58014743dddSAlejandro Lucero 	}
58114743dddSAlejandro Lucero 	return rc;
58214743dddSAlejandro Lucero }
58314743dddSAlejandro Lucero 
58414743dddSAlejandro Lucero static int efx_devlink_info_get(struct devlink *devlink,
58514743dddSAlejandro Lucero 				struct devlink_info_req *req,
58614743dddSAlejandro Lucero 				struct netlink_ext_ack *extack)
58714743dddSAlejandro Lucero {
58814743dddSAlejandro Lucero 	struct efx_devlink *devlink_private = devlink_priv(devlink);
58914743dddSAlejandro Lucero 	struct efx_nic *efx = devlink_private->efx;
59014743dddSAlejandro Lucero 	int rc;
59114743dddSAlejandro Lucero 
59214743dddSAlejandro Lucero 	/* Several different MCDI commands are used. We report first error
59314743dddSAlejandro Lucero 	 * through extack returning at that point. Specific error
59414743dddSAlejandro Lucero 	 * information via system messages.
59514743dddSAlejandro Lucero 	 */
59614743dddSAlejandro Lucero 	rc = efx_devlink_info_board_cfg(efx, req);
59714743dddSAlejandro Lucero 	if (rc) {
59814743dddSAlejandro Lucero 		NL_SET_ERR_MSG_MOD(extack, "Getting board info failed");
59914743dddSAlejandro Lucero 		return rc;
60014743dddSAlejandro Lucero 	}
60114743dddSAlejandro Lucero 	rc = efx_devlink_info_stored_versions(efx, req);
60214743dddSAlejandro Lucero 	if (rc) {
60314743dddSAlejandro Lucero 		NL_SET_ERR_MSG_MOD(extack, "Getting stored versions failed");
60414743dddSAlejandro Lucero 		return rc;
60514743dddSAlejandro Lucero 	}
60614743dddSAlejandro Lucero 	rc = efx_devlink_info_running_versions(efx, req);
60714743dddSAlejandro Lucero 	if (rc) {
60814743dddSAlejandro Lucero 		NL_SET_ERR_MSG_MOD(extack, "Getting running versions failed");
60914743dddSAlejandro Lucero 		return rc;
61014743dddSAlejandro Lucero 	}
61114743dddSAlejandro Lucero 
61214743dddSAlejandro Lucero 	return 0;
61314743dddSAlejandro Lucero }
61414743dddSAlejandro Lucero 
615fa34a514SAlejandro Lucero static const struct devlink_ops sfc_devlink_ops = {
61614743dddSAlejandro Lucero 	.info_get			= efx_devlink_info_get,
617fa78b017SAlejandro Lucero #ifdef CONFIG_SFC_SRIOV
618fa78b017SAlejandro Lucero 	.port_function_hw_addr_get	= efx_devlink_port_addr_get,
619*3b6096c9SAlejandro Lucero 	.port_function_hw_addr_set	= efx_devlink_port_addr_set,
620fa78b017SAlejandro Lucero #endif
621fa34a514SAlejandro Lucero };
622fa34a514SAlejandro Lucero 
62325414b2aSAlejandro Lucero #ifdef CONFIG_SFC_SRIOV
62425414b2aSAlejandro Lucero static struct devlink_port *ef100_set_devlink_port(struct efx_nic *efx, u32 idx)
62525414b2aSAlejandro Lucero {
62625414b2aSAlejandro Lucero 	struct mae_mport_desc *mport;
62725414b2aSAlejandro Lucero 	u32 id;
62825414b2aSAlejandro Lucero 	int rc;
62925414b2aSAlejandro Lucero 
63025414b2aSAlejandro Lucero 	if (efx_mae_lookup_mport(efx, idx, &id)) {
63125414b2aSAlejandro Lucero 		/* This should not happen. */
63225414b2aSAlejandro Lucero 		if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
63325414b2aSAlejandro Lucero 			pci_warn_once(efx->pci_dev, "No mport ID found for PF.\n");
63425414b2aSAlejandro Lucero 		else
63525414b2aSAlejandro Lucero 			pci_warn_once(efx->pci_dev, "No mport ID found for VF %u.\n",
63625414b2aSAlejandro Lucero 				      idx);
63725414b2aSAlejandro Lucero 		return NULL;
63825414b2aSAlejandro Lucero 	}
63925414b2aSAlejandro Lucero 
64025414b2aSAlejandro Lucero 	mport = efx_mae_get_mport(efx, id);
64125414b2aSAlejandro Lucero 	if (!mport) {
64225414b2aSAlejandro Lucero 		/* This should not happen. */
64325414b2aSAlejandro Lucero 		if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
64425414b2aSAlejandro Lucero 			pci_warn_once(efx->pci_dev, "No mport found for PF.\n");
64525414b2aSAlejandro Lucero 		else
64625414b2aSAlejandro Lucero 			pci_warn_once(efx->pci_dev, "No mport found for VF %u.\n",
64725414b2aSAlejandro Lucero 				      idx);
64825414b2aSAlejandro Lucero 		return NULL;
64925414b2aSAlejandro Lucero 	}
65025414b2aSAlejandro Lucero 
65125414b2aSAlejandro Lucero 	rc = efx_devlink_add_port(efx, mport);
65225414b2aSAlejandro Lucero 	if (rc) {
65325414b2aSAlejandro Lucero 		if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
65425414b2aSAlejandro Lucero 			pci_warn(efx->pci_dev,
65525414b2aSAlejandro Lucero 				 "devlink port creation for PF failed.\n");
65625414b2aSAlejandro Lucero 		else
65725414b2aSAlejandro Lucero 			pci_warn(efx->pci_dev,
65825414b2aSAlejandro Lucero 				 "devlink_port creationg for VF %u failed.\n",
65925414b2aSAlejandro Lucero 				 idx);
66025414b2aSAlejandro Lucero 		return NULL;
66125414b2aSAlejandro Lucero 	}
66225414b2aSAlejandro Lucero 
66325414b2aSAlejandro Lucero 	return &mport->dl_port;
66425414b2aSAlejandro Lucero }
66525414b2aSAlejandro Lucero 
66625414b2aSAlejandro Lucero void ef100_rep_set_devlink_port(struct efx_rep *efv)
66725414b2aSAlejandro Lucero {
66825414b2aSAlejandro Lucero 	efv->dl_port = ef100_set_devlink_port(efv->parent, efv->idx);
66925414b2aSAlejandro Lucero }
67025414b2aSAlejandro Lucero 
67125414b2aSAlejandro Lucero void ef100_pf_set_devlink_port(struct efx_nic *efx)
67225414b2aSAlejandro Lucero {
67325414b2aSAlejandro Lucero 	efx->dl_port = ef100_set_devlink_port(efx, MAE_MPORT_DESC_VF_IDX_NULL);
67425414b2aSAlejandro Lucero }
67525414b2aSAlejandro Lucero 
67625414b2aSAlejandro Lucero void ef100_rep_unset_devlink_port(struct efx_rep *efv)
67725414b2aSAlejandro Lucero {
67825414b2aSAlejandro Lucero 	efx_devlink_del_port(efv->dl_port);
67925414b2aSAlejandro Lucero }
68025414b2aSAlejandro Lucero 
68125414b2aSAlejandro Lucero void ef100_pf_unset_devlink_port(struct efx_nic *efx)
68225414b2aSAlejandro Lucero {
68325414b2aSAlejandro Lucero 	efx_devlink_del_port(efx->dl_port);
68425414b2aSAlejandro Lucero }
68525414b2aSAlejandro Lucero #endif
68625414b2aSAlejandro Lucero 
687fa34a514SAlejandro Lucero void efx_fini_devlink_lock(struct efx_nic *efx)
688fa34a514SAlejandro Lucero {
689fa34a514SAlejandro Lucero 	if (efx->devlink)
690fa34a514SAlejandro Lucero 		devl_lock(efx->devlink);
691fa34a514SAlejandro Lucero }
692fa34a514SAlejandro Lucero 
693fa34a514SAlejandro Lucero void efx_fini_devlink_and_unlock(struct efx_nic *efx)
694fa34a514SAlejandro Lucero {
695fa34a514SAlejandro Lucero 	if (efx->devlink) {
696fa34a514SAlejandro Lucero 		devl_unregister(efx->devlink);
697fa34a514SAlejandro Lucero 		devl_unlock(efx->devlink);
698fa34a514SAlejandro Lucero 		devlink_free(efx->devlink);
699fa34a514SAlejandro Lucero 		efx->devlink = NULL;
700fa34a514SAlejandro Lucero 	}
701fa34a514SAlejandro Lucero }
702fa34a514SAlejandro Lucero 
703fa34a514SAlejandro Lucero int efx_probe_devlink_and_lock(struct efx_nic *efx)
704fa34a514SAlejandro Lucero {
705fa34a514SAlejandro Lucero 	struct efx_devlink *devlink_private;
706fa34a514SAlejandro Lucero 
707fa34a514SAlejandro Lucero 	if (efx->type->is_vf)
708fa34a514SAlejandro Lucero 		return 0;
709fa34a514SAlejandro Lucero 
710fa34a514SAlejandro Lucero 	efx->devlink = devlink_alloc(&sfc_devlink_ops,
711fa34a514SAlejandro Lucero 				     sizeof(struct efx_devlink),
712fa34a514SAlejandro Lucero 				     &efx->pci_dev->dev);
713fa34a514SAlejandro Lucero 	if (!efx->devlink)
714fa34a514SAlejandro Lucero 		return -ENOMEM;
715fa34a514SAlejandro Lucero 
716fa34a514SAlejandro Lucero 	devl_lock(efx->devlink);
717fa34a514SAlejandro Lucero 	devlink_private = devlink_priv(efx->devlink);
718fa34a514SAlejandro Lucero 	devlink_private->efx = efx;
719fa34a514SAlejandro Lucero 
720fa34a514SAlejandro Lucero 	devl_register(efx->devlink);
721fa34a514SAlejandro Lucero 
722fa34a514SAlejandro Lucero 	return 0;
723fa34a514SAlejandro Lucero }
724fa34a514SAlejandro Lucero 
725fa34a514SAlejandro Lucero void efx_probe_devlink_unlock(struct efx_nic *efx)
726fa34a514SAlejandro Lucero {
727fa34a514SAlejandro Lucero 	if (!efx->devlink)
728fa34a514SAlejandro Lucero 		return;
729fa34a514SAlejandro Lucero 
730fa34a514SAlejandro Lucero 	devl_unlock(efx->devlink);
731fa34a514SAlejandro Lucero }
732