xref: /openbmc/linux/drivers/net/ethernet/sfc/efx_devlink.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
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 
efx_devlink_port_addr_get(struct devlink_port * port,u8 * hw_addr,int * hw_addr_len,struct netlink_ext_ack * extack)2925414b2aSAlejandro Lucero static int efx_devlink_port_addr_get(struct devlink_port *port, u8 *hw_addr,
3025414b2aSAlejandro Lucero 				     int *hw_addr_len,
3125414b2aSAlejandro Lucero 				     struct netlink_ext_ack *extack)
3225414b2aSAlejandro Lucero {
3325414b2aSAlejandro Lucero 	struct efx_devlink *devlink = devlink_priv(port->devlink);
3425414b2aSAlejandro Lucero 	struct mae_mport_desc *mport_desc;
3525414b2aSAlejandro Lucero 	efx_qword_t pciefn;
3625414b2aSAlejandro Lucero 	u32 client_id;
3725414b2aSAlejandro Lucero 	int rc = 0;
3825414b2aSAlejandro Lucero 
3925414b2aSAlejandro Lucero 	mport_desc = container_of(port, struct mae_mport_desc, dl_port);
4025414b2aSAlejandro Lucero 
4125414b2aSAlejandro Lucero 	if (!ef100_mport_on_local_intf(devlink->efx, mport_desc)) {
4225414b2aSAlejandro Lucero 		rc = -EINVAL;
4325414b2aSAlejandro Lucero 		NL_SET_ERR_MSG_FMT(extack,
4425414b2aSAlejandro Lucero 				   "Port not on local interface (mport: %u)",
4525414b2aSAlejandro Lucero 				   mport_desc->mport_id);
4625414b2aSAlejandro Lucero 		goto out;
4725414b2aSAlejandro Lucero 	}
4825414b2aSAlejandro Lucero 
4925414b2aSAlejandro Lucero 	if (ef100_mport_is_vf(mport_desc))
5025414b2aSAlejandro Lucero 		EFX_POPULATE_QWORD_3(pciefn,
5125414b2aSAlejandro Lucero 				     PCIE_FUNCTION_PF, PCIE_FUNCTION_PF_NULL,
5225414b2aSAlejandro Lucero 				     PCIE_FUNCTION_VF, mport_desc->vf_idx,
5325414b2aSAlejandro Lucero 				     PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);
5425414b2aSAlejandro Lucero 	else
5525414b2aSAlejandro Lucero 		EFX_POPULATE_QWORD_3(pciefn,
5625414b2aSAlejandro Lucero 				     PCIE_FUNCTION_PF, mport_desc->pf_idx,
5725414b2aSAlejandro Lucero 				     PCIE_FUNCTION_VF, PCIE_FUNCTION_VF_NULL,
5825414b2aSAlejandro Lucero 				     PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);
5925414b2aSAlejandro Lucero 
6025414b2aSAlejandro Lucero 	rc = efx_ef100_lookup_client_id(devlink->efx, pciefn, &client_id);
6125414b2aSAlejandro Lucero 	if (rc) {
62fa78b017SAlejandro Lucero 		NL_SET_ERR_MSG_FMT(extack,
63fa78b017SAlejandro Lucero 				   "No internal client_ID for port (mport: %u)",
64fa78b017SAlejandro Lucero 				   mport_desc->mport_id);
65fa78b017SAlejandro Lucero 		goto out;
66fa78b017SAlejandro Lucero 	}
67fa78b017SAlejandro Lucero 
68fa78b017SAlejandro Lucero 	rc = ef100_get_mac_address(devlink->efx, hw_addr, client_id, true);
69fa78b017SAlejandro Lucero 	if (rc != 0)
70fa78b017SAlejandro Lucero 		NL_SET_ERR_MSG_FMT(extack,
71fa78b017SAlejandro Lucero 				   "No available MAC for port (mport: %u)",
72fa78b017SAlejandro Lucero 				   mport_desc->mport_id);
73fa78b017SAlejandro Lucero out:
74fa78b017SAlejandro Lucero 	*hw_addr_len = ETH_ALEN;
75fa78b017SAlejandro Lucero 	return rc;
76fa78b017SAlejandro Lucero }
77fa78b017SAlejandro Lucero 
efx_devlink_port_addr_set(struct devlink_port * port,const u8 * hw_addr,int hw_addr_len,struct netlink_ext_ack * extack)78fa78b017SAlejandro Lucero static int efx_devlink_port_addr_set(struct devlink_port *port,
79fa78b017SAlejandro Lucero 				     const u8 *hw_addr, int hw_addr_len,
80fa78b017SAlejandro Lucero 				     struct netlink_ext_ack *extack)
81fa78b017SAlejandro Lucero {
82fa78b017SAlejandro Lucero 	MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_CLIENT_MAC_ADDRESSES_IN_LEN(1));
83fa78b017SAlejandro Lucero 	struct efx_devlink *devlink = devlink_priv(port->devlink);
84fa78b017SAlejandro Lucero 	struct mae_mport_desc *mport_desc;
85fa78b017SAlejandro Lucero 	efx_qword_t pciefn;
86fa78b017SAlejandro Lucero 	u32 client_id;
87fa78b017SAlejandro Lucero 	int rc;
88fa78b017SAlejandro Lucero 
89fa78b017SAlejandro Lucero 	mport_desc = container_of(port, struct mae_mport_desc, dl_port);
90fa78b017SAlejandro Lucero 
91fa78b017SAlejandro Lucero 	if (!ef100_mport_is_vf(mport_desc)) {
92fa78b017SAlejandro Lucero 		NL_SET_ERR_MSG_FMT(extack,
93fa78b017SAlejandro Lucero 				   "port mac change not allowed (mport: %u)",
94fa78b017SAlejandro Lucero 				   mport_desc->mport_id);
95fa78b017SAlejandro Lucero 		return -EPERM;
96fa78b017SAlejandro Lucero 	}
97fa78b017SAlejandro Lucero 
98fa78b017SAlejandro Lucero 	EFX_POPULATE_QWORD_3(pciefn,
99fa78b017SAlejandro Lucero 			     PCIE_FUNCTION_PF, PCIE_FUNCTION_PF_NULL,
100fa78b017SAlejandro Lucero 			     PCIE_FUNCTION_VF, mport_desc->vf_idx,
101fa78b017SAlejandro Lucero 			     PCIE_FUNCTION_INTF, PCIE_INTERFACE_CALLER);
102fa78b017SAlejandro Lucero 
103fa78b017SAlejandro Lucero 	rc = efx_ef100_lookup_client_id(devlink->efx, pciefn, &client_id);
104fa78b017SAlejandro Lucero 	if (rc) {
105fa78b017SAlejandro Lucero 		NL_SET_ERR_MSG_FMT(extack,
106fa78b017SAlejandro Lucero 				   "No internal client_ID for port (mport: %u)",
107fa78b017SAlejandro Lucero 				   mport_desc->mport_id);
108fa78b017SAlejandro Lucero 		return rc;
109fa78b017SAlejandro Lucero 	}
110fa78b017SAlejandro Lucero 
111fa78b017SAlejandro Lucero 	MCDI_SET_DWORD(inbuf, SET_CLIENT_MAC_ADDRESSES_IN_CLIENT_HANDLE,
1123b6096c9SAlejandro Lucero 		       client_id);
1133b6096c9SAlejandro Lucero 
1143b6096c9SAlejandro Lucero 	ether_addr_copy(MCDI_PTR(inbuf, SET_CLIENT_MAC_ADDRESSES_IN_MAC_ADDRS),
1153b6096c9SAlejandro Lucero 			hw_addr);
1163b6096c9SAlejandro Lucero 
1173b6096c9SAlejandro Lucero 	rc = efx_mcdi_rpc(devlink->efx, MC_CMD_SET_CLIENT_MAC_ADDRESSES, inbuf,
1183b6096c9SAlejandro Lucero 			  sizeof(inbuf), NULL, 0, NULL);
1193b6096c9SAlejandro Lucero 	if (rc)
1203b6096c9SAlejandro Lucero 		NL_SET_ERR_MSG_FMT(extack,
1213b6096c9SAlejandro Lucero 				   "sfc MC_CMD_SET_CLIENT_MAC_ADDRESSES mcdi error (mport: %u)",
1223b6096c9SAlejandro Lucero 				   mport_desc->mport_id);
1233b6096c9SAlejandro Lucero 
1243b6096c9SAlejandro Lucero 	return rc;
1253b6096c9SAlejandro Lucero }
1263b6096c9SAlejandro Lucero 
1273b6096c9SAlejandro Lucero static const struct devlink_port_ops sfc_devlink_port_ops = {
1283b6096c9SAlejandro Lucero 	.port_fn_hw_addr_get = efx_devlink_port_addr_get,
1293b6096c9SAlejandro Lucero 	.port_fn_hw_addr_set = efx_devlink_port_addr_set,
1303b6096c9SAlejandro Lucero };
1313b6096c9SAlejandro Lucero 
efx_devlink_del_port(struct devlink_port * dl_port)1323b6096c9SAlejandro Lucero static void efx_devlink_del_port(struct devlink_port *dl_port)
1333b6096c9SAlejandro Lucero {
1343b6096c9SAlejandro Lucero 	if (!dl_port)
1353b6096c9SAlejandro Lucero 		return;
1363b6096c9SAlejandro Lucero 	devl_port_unregister(dl_port);
1373b6096c9SAlejandro Lucero }
1383b6096c9SAlejandro Lucero 
efx_devlink_add_port(struct efx_nic * efx,struct mae_mport_desc * mport)1393b6096c9SAlejandro Lucero static int efx_devlink_add_port(struct efx_nic *efx,
1403b6096c9SAlejandro Lucero 				struct mae_mport_desc *mport)
1413b6096c9SAlejandro Lucero {
1423b6096c9SAlejandro Lucero 	bool external = false;
1433b6096c9SAlejandro Lucero 
1443b6096c9SAlejandro Lucero 	if (!ef100_mport_on_local_intf(efx, mport))
1453b6096c9SAlejandro Lucero 		external = true;
1463b6096c9SAlejandro Lucero 
1473b6096c9SAlejandro Lucero 	switch (mport->mport_type) {
1483b6096c9SAlejandro Lucero 	case MAE_MPORT_DESC_MPORT_TYPE_VNIC:
1493b6096c9SAlejandro Lucero 		if (mport->vf_idx != MAE_MPORT_DESC_VF_IDX_NULL)
1503b6096c9SAlejandro Lucero 			devlink_port_attrs_pci_vf_set(&mport->dl_port, 0, mport->pf_idx,
1513b6096c9SAlejandro Lucero 						      mport->vf_idx,
1523b6096c9SAlejandro Lucero 						      external);
1533b6096c9SAlejandro Lucero 		else
1543b6096c9SAlejandro Lucero 			devlink_port_attrs_pci_pf_set(&mport->dl_port, 0, mport->pf_idx,
1553b6096c9SAlejandro Lucero 						      external);
1563b6096c9SAlejandro Lucero 		break;
1573b6096c9SAlejandro Lucero 	default:
1583b6096c9SAlejandro Lucero 		/* MAE_MPORT_DESC_MPORT_ALIAS and UNDEFINED */
1593b6096c9SAlejandro Lucero 		return 0;
1603b6096c9SAlejandro Lucero 	}
16125414b2aSAlejandro Lucero 
16225414b2aSAlejandro Lucero 	mport->dl_port.index = mport->mport_id;
16314743dddSAlejandro Lucero 
16414743dddSAlejandro Lucero 	return devl_port_register_with_ops(efx->devlink, &mport->dl_port,
16514743dddSAlejandro Lucero 					   mport->mport_id,
16614743dddSAlejandro Lucero 					   &sfc_devlink_port_ops);
16714743dddSAlejandro Lucero }
16814743dddSAlejandro Lucero 
16914743dddSAlejandro Lucero #endif
17014743dddSAlejandro Lucero 
efx_devlink_info_nvram_partition(struct efx_nic * efx,struct devlink_info_req * req,unsigned int partition_type,const char * version_name)17114743dddSAlejandro Lucero static int efx_devlink_info_nvram_partition(struct efx_nic *efx,
17214743dddSAlejandro Lucero 					    struct devlink_info_req *req,
17314743dddSAlejandro Lucero 					    unsigned int partition_type,
174*cfcb9428SAlejandro Lucero 					    const char *version_name)
175*cfcb9428SAlejandro Lucero {
176*cfcb9428SAlejandro Lucero 	char buf[EFX_MAX_VERSION_INFO_LEN];
177*cfcb9428SAlejandro Lucero 	u16 version[4];
178*cfcb9428SAlejandro Lucero 	int rc;
17914743dddSAlejandro Lucero 
180*cfcb9428SAlejandro Lucero 	rc = efx_mcdi_nvram_metadata(efx, partition_type, NULL, version, NULL,
181*cfcb9428SAlejandro Lucero 				     0);
18214743dddSAlejandro Lucero 
18314743dddSAlejandro Lucero 	/* If the partition does not exist, that is not an error. */
18414743dddSAlejandro Lucero 	if (rc == -ENOENT)
18514743dddSAlejandro Lucero 		return 0;
18614743dddSAlejandro Lucero 
18714743dddSAlejandro Lucero 	if (rc) {
18814743dddSAlejandro Lucero 		netif_err(efx, drv, efx->net_dev, "mcdi nvram %s: failed (rc=%d)\n",
18914743dddSAlejandro Lucero 			  version_name, rc);
19014743dddSAlejandro Lucero 		return rc;
19114743dddSAlejandro Lucero 	}
19214743dddSAlejandro Lucero 
19314743dddSAlejandro Lucero 	snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u", version[0],
19414743dddSAlejandro Lucero 		 version[1], version[2], version[3]);
195*cfcb9428SAlejandro Lucero 	devlink_info_version_stored_put(req, version_name, buf);
19614743dddSAlejandro Lucero 
197*cfcb9428SAlejandro Lucero 	return 0;
198*cfcb9428SAlejandro Lucero }
199*cfcb9428SAlejandro Lucero 
efx_devlink_info_stored_versions(struct efx_nic * efx,struct devlink_info_req * req)200*cfcb9428SAlejandro Lucero static int efx_devlink_info_stored_versions(struct efx_nic *efx,
201*cfcb9428SAlejandro Lucero 					    struct devlink_info_req *req)
202*cfcb9428SAlejandro Lucero {
20314743dddSAlejandro Lucero 	int err;
20414743dddSAlejandro Lucero 
20514743dddSAlejandro Lucero 	/* We do not care here about the specific error but just if an error
206*cfcb9428SAlejandro Lucero 	 * happened. The specific error will be reported inside the call
20714743dddSAlejandro Lucero 	 * through system messages, and if any error happened in any call
20814743dddSAlejandro Lucero 	 * below, we report it through extack.
20914743dddSAlejandro Lucero 	 */
210*cfcb9428SAlejandro Lucero 	err = efx_devlink_info_nvram_partition(efx, req,
21114743dddSAlejandro Lucero 					       NVRAM_PARTITION_TYPE_BUNDLE,
21214743dddSAlejandro Lucero 					       DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID);
21314743dddSAlejandro Lucero 
214*cfcb9428SAlejandro Lucero 	err |= efx_devlink_info_nvram_partition(efx, req,
21514743dddSAlejandro Lucero 						NVRAM_PARTITION_TYPE_MC_FIRMWARE,
21614743dddSAlejandro Lucero 						DEVLINK_INFO_VERSION_GENERIC_FW_MGMT);
21714743dddSAlejandro Lucero 
218*cfcb9428SAlejandro Lucero 	err |= efx_devlink_info_nvram_partition(efx, req,
21914743dddSAlejandro Lucero 						NVRAM_PARTITION_TYPE_SUC_FIRMWARE,
22014743dddSAlejandro Lucero 						EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC);
221*cfcb9428SAlejandro Lucero 
22214743dddSAlejandro Lucero 	err |= efx_devlink_info_nvram_partition(efx, req,
22314743dddSAlejandro Lucero 						NVRAM_PARTITION_TYPE_EXPANSION_ROM,
22414743dddSAlejandro Lucero 						EFX_DEVLINK_INFO_VERSION_FW_EXPROM);
22514743dddSAlejandro Lucero 
22614743dddSAlejandro Lucero 	err |= efx_devlink_info_nvram_partition(efx, req,
22714743dddSAlejandro Lucero 						NVRAM_PARTITION_TYPE_EXPANSION_UEFI,
22814743dddSAlejandro Lucero 						EFX_DEVLINK_INFO_VERSION_FW_UEFI);
22914743dddSAlejandro Lucero 	return err;
23014743dddSAlejandro Lucero }
23114743dddSAlejandro Lucero 
23214743dddSAlejandro Lucero #define EFX_VER_FLAG(_f)	\
23314743dddSAlejandro Lucero 	(MC_CMD_GET_VERSION_V5_OUT_ ## _f ## _PRESENT_LBN)
23414743dddSAlejandro Lucero 
efx_devlink_info_running_v2(struct efx_nic * efx,struct devlink_info_req * req,unsigned int flags,efx_dword_t * outbuf)23514743dddSAlejandro Lucero static void efx_devlink_info_running_v2(struct efx_nic *efx,
23614743dddSAlejandro Lucero 					struct devlink_info_req *req,
23714743dddSAlejandro Lucero 					unsigned int flags, efx_dword_t *outbuf)
23814743dddSAlejandro Lucero {
23914743dddSAlejandro Lucero 	char buf[EFX_MAX_VERSION_INFO_LEN];
24014743dddSAlejandro Lucero 	union {
24114743dddSAlejandro Lucero 		const __le32 *dwords;
24214743dddSAlejandro Lucero 		const __le16 *words;
24314743dddSAlejandro Lucero 		const char *str;
24414743dddSAlejandro Lucero 	} ver;
24514743dddSAlejandro Lucero 	struct rtc_time build_date;
24614743dddSAlejandro Lucero 	unsigned int build_id;
24714743dddSAlejandro Lucero 	size_t offset;
24814743dddSAlejandro Lucero 	__maybe_unused u64 tstamp;
24914743dddSAlejandro Lucero 
25014743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(BOARD_EXT_INFO))) {
25114743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%s",
25214743dddSAlejandro Lucero 			 MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_NAME));
25314743dddSAlejandro Lucero 		devlink_info_version_fixed_put(req,
25414743dddSAlejandro Lucero 					       DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
25514743dddSAlejandro Lucero 					       buf);
25614743dddSAlejandro Lucero 
25714743dddSAlejandro Lucero 		/* Favour full board version if present (in V5 or later) */
25814743dddSAlejandro Lucero 		if (~flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) {
25914743dddSAlejandro Lucero 			snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u",
26014743dddSAlejandro Lucero 				 MCDI_DWORD(outbuf,
26114743dddSAlejandro Lucero 					    GET_VERSION_V2_OUT_BOARD_REVISION));
26214743dddSAlejandro Lucero 			devlink_info_version_fixed_put(req,
26314743dddSAlejandro Lucero 						       DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,
26414743dddSAlejandro Lucero 						       buf);
26514743dddSAlejandro Lucero 		}
26614743dddSAlejandro Lucero 
26714743dddSAlejandro Lucero 		ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_SERIAL);
26814743dddSAlejandro Lucero 		if (ver.str[0])
26914743dddSAlejandro Lucero 			devlink_info_board_serial_number_put(req, ver.str);
27014743dddSAlejandro Lucero 	}
27114743dddSAlejandro Lucero 
27214743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(FPGA_EXT_INFO))) {
27314743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
27414743dddSAlejandro Lucero 						GET_VERSION_V2_OUT_FPGA_VERSION);
27514743dddSAlejandro Lucero 		offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u_%c%u",
27614743dddSAlejandro Lucero 				  le32_to_cpu(ver.dwords[0]),
27714743dddSAlejandro Lucero 				  'A' + le32_to_cpu(ver.dwords[1]),
27814743dddSAlejandro Lucero 				  le32_to_cpu(ver.dwords[2]));
27914743dddSAlejandro Lucero 
28014743dddSAlejandro Lucero 		ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_FPGA_EXTRA);
28114743dddSAlejandro Lucero 		if (ver.str[0])
28214743dddSAlejandro Lucero 			snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
28314743dddSAlejandro Lucero 				 " (%s)", ver.str);
28414743dddSAlejandro Lucero 
28514743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
28614743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_FPGA_REV,
28714743dddSAlejandro Lucero 						 buf);
28814743dddSAlejandro Lucero 	}
28914743dddSAlejandro Lucero 
29014743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(CMC_EXT_INFO))) {
29114743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
29214743dddSAlejandro Lucero 						GET_VERSION_V2_OUT_CMCFW_VERSION);
29314743dddSAlejandro Lucero 		offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
29414743dddSAlejandro Lucero 				  le32_to_cpu(ver.dwords[0]),
29514743dddSAlejandro Lucero 				  le32_to_cpu(ver.dwords[1]),
29614743dddSAlejandro Lucero 				  le32_to_cpu(ver.dwords[2]),
29714743dddSAlejandro Lucero 				  le32_to_cpu(ver.dwords[3]));
29814743dddSAlejandro Lucero 
29914743dddSAlejandro Lucero #ifdef CONFIG_RTC_LIB
30014743dddSAlejandro Lucero 		tstamp = MCDI_QWORD(outbuf,
30114743dddSAlejandro Lucero 				    GET_VERSION_V2_OUT_CMCFW_BUILD_DATE);
30214743dddSAlejandro Lucero 		if (tstamp) {
30314743dddSAlejandro Lucero 			rtc_time64_to_tm(tstamp, &build_date);
30414743dddSAlejandro Lucero 			snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
30514743dddSAlejandro Lucero 				 " (%ptRd)", &build_date);
30614743dddSAlejandro Lucero 		}
30714743dddSAlejandro Lucero #endif
30814743dddSAlejandro Lucero 
30914743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
31014743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_CMC,
31114743dddSAlejandro Lucero 						 buf);
31214743dddSAlejandro Lucero 	}
31314743dddSAlejandro Lucero 
31414743dddSAlejandro Lucero 	ver.words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_V2_OUT_VERSION);
31514743dddSAlejandro Lucero 	offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
31614743dddSAlejandro Lucero 			  le16_to_cpu(ver.words[0]), le16_to_cpu(ver.words[1]),
31714743dddSAlejandro Lucero 			  le16_to_cpu(ver.words[2]), le16_to_cpu(ver.words[3]));
31814743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(MCFW_EXT_INFO))) {
31914743dddSAlejandro Lucero 		build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_ID);
32014743dddSAlejandro Lucero 		snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset,
32114743dddSAlejandro Lucero 			 " (%x) %s", build_id,
32214743dddSAlejandro Lucero 			 MCDI_PTR(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_NAME));
32314743dddSAlejandro Lucero 	}
32414743dddSAlejandro Lucero 	devlink_info_version_running_put(req,
32514743dddSAlejandro Lucero 					 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT,
32614743dddSAlejandro Lucero 					 buf);
32714743dddSAlejandro Lucero 
3285f22c3b6SAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) {
32914743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
33014743dddSAlejandro Lucero 						GET_VERSION_V2_OUT_SUCFW_VERSION);
33114743dddSAlejandro Lucero #ifdef CONFIG_RTC_LIB
33214743dddSAlejandro Lucero 		tstamp = MCDI_QWORD(outbuf,
33314743dddSAlejandro Lucero 				    GET_VERSION_V2_OUT_SUCFW_BUILD_DATE);
33414743dddSAlejandro Lucero 		rtc_time64_to_tm(tstamp, &build_date);
33514743dddSAlejandro Lucero #else
33614743dddSAlejandro Lucero 		memset(&build_date, 0, sizeof(build_date));
33714743dddSAlejandro Lucero #endif
33814743dddSAlejandro Lucero 		build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_SUCFW_CHIP_ID);
33914743dddSAlejandro Lucero 
34014743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN,
34114743dddSAlejandro Lucero 			 "%u.%u.%u.%u type %x (%ptRd)",
34214743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
34314743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]), le32_to_cpu(ver.dwords[3]),
34414743dddSAlejandro Lucero 			 build_id, &build_date);
34514743dddSAlejandro Lucero 
34614743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
34714743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC,
34814743dddSAlejandro Lucero 						 buf);
34914743dddSAlejandro Lucero 	}
35014743dddSAlejandro Lucero }
35114743dddSAlejandro Lucero 
efx_devlink_info_running_v3(struct efx_nic * efx,struct devlink_info_req * req,unsigned int flags,efx_dword_t * outbuf)35214743dddSAlejandro Lucero static void efx_devlink_info_running_v3(struct efx_nic *efx,
35314743dddSAlejandro Lucero 					struct devlink_info_req *req,
35414743dddSAlejandro Lucero 					unsigned int flags, efx_dword_t *outbuf)
35514743dddSAlejandro Lucero {
35614743dddSAlejandro Lucero 	char buf[EFX_MAX_VERSION_INFO_LEN];
35714743dddSAlejandro Lucero 	union {
35814743dddSAlejandro Lucero 		const __le32 *dwords;
35914743dddSAlejandro Lucero 		const __le16 *words;
36014743dddSAlejandro Lucero 		const char *str;
36114743dddSAlejandro Lucero 	} ver;
36214743dddSAlejandro Lucero 
36314743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(DATAPATH_HW_VERSION))) {
36414743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
36514743dddSAlejandro Lucero 						GET_VERSION_V3_OUT_DATAPATH_HW_VERSION);
36614743dddSAlejandro Lucero 
36714743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u",
36814743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
36914743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]));
37014743dddSAlejandro Lucero 
37114743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
37214743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_DATAPATH_HW,
37314743dddSAlejandro Lucero 						 buf);
37414743dddSAlejandro Lucero 	}
37514743dddSAlejandro Lucero 
37614743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(DATAPATH_FW_VERSION))) {
37714743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
37814743dddSAlejandro Lucero 						GET_VERSION_V3_OUT_DATAPATH_FW_VERSION);
37914743dddSAlejandro Lucero 
38014743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u",
38114743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
38214743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]));
38314743dddSAlejandro Lucero 
38414743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
38514743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_DATAPATH_FW,
38614743dddSAlejandro Lucero 						 buf);
38714743dddSAlejandro Lucero 	}
38814743dddSAlejandro Lucero }
38914743dddSAlejandro Lucero 
efx_devlink_info_running_v4(struct efx_nic * efx,struct devlink_info_req * req,unsigned int flags,efx_dword_t * outbuf)39014743dddSAlejandro Lucero static void efx_devlink_info_running_v4(struct efx_nic *efx,
39114743dddSAlejandro Lucero 					struct devlink_info_req *req,
39214743dddSAlejandro Lucero 					unsigned int flags, efx_dword_t *outbuf)
39314743dddSAlejandro Lucero {
39414743dddSAlejandro Lucero 	char buf[EFX_MAX_VERSION_INFO_LEN];
39514743dddSAlejandro Lucero 	union {
39614743dddSAlejandro Lucero 		const __le32 *dwords;
39714743dddSAlejandro Lucero 		const __le16 *words;
39814743dddSAlejandro Lucero 		const char *str;
39914743dddSAlejandro Lucero 	} ver;
40014743dddSAlejandro Lucero 
40114743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(SOC_BOOT_VERSION))) {
40214743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
40314743dddSAlejandro Lucero 						GET_VERSION_V4_OUT_SOC_BOOT_VERSION);
40414743dddSAlejandro Lucero 
40514743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
40614743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
40714743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]),
40814743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[3]));
40914743dddSAlejandro Lucero 
41014743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
41114743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_SOC_BOOT,
41214743dddSAlejandro Lucero 						 buf);
41314743dddSAlejandro Lucero 	}
41414743dddSAlejandro Lucero 
41514743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(SOC_UBOOT_VERSION))) {
41614743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
41714743dddSAlejandro Lucero 						GET_VERSION_V4_OUT_SOC_UBOOT_VERSION);
41814743dddSAlejandro Lucero 
41914743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
42014743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
42114743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]),
42214743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[3]));
42314743dddSAlejandro Lucero 
42414743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
42514743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_SOC_UBOOT,
42614743dddSAlejandro Lucero 						 buf);
42714743dddSAlejandro Lucero 	}
42814743dddSAlejandro Lucero 
42914743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(SOC_MAIN_ROOTFS_VERSION))) {
43014743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
43114743dddSAlejandro Lucero 					GET_VERSION_V4_OUT_SOC_MAIN_ROOTFS_VERSION);
43214743dddSAlejandro Lucero 
43314743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
43414743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
43514743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]),
43614743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[3]));
43714743dddSAlejandro Lucero 
43814743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
43914743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_SOC_MAIN,
44014743dddSAlejandro Lucero 						 buf);
44114743dddSAlejandro Lucero 	}
44214743dddSAlejandro Lucero 
44314743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(SOC_RECOVERY_BUILDROOT_VERSION))) {
44414743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
44514743dddSAlejandro Lucero 						GET_VERSION_V4_OUT_SOC_RECOVERY_BUILDROOT_VERSION);
44614743dddSAlejandro Lucero 
44714743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
44814743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
44914743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]),
45014743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[3]));
45114743dddSAlejandro Lucero 
45214743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
45314743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_SOC_RECOVERY,
45414743dddSAlejandro Lucero 						 buf);
45514743dddSAlejandro Lucero 	}
45614743dddSAlejandro Lucero 
45714743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(SUCFW_VERSION)) &&
45814743dddSAlejandro Lucero 	    ~flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) {
45914743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
46014743dddSAlejandro Lucero 						GET_VERSION_V4_OUT_SUCFW_VERSION);
46114743dddSAlejandro Lucero 
46214743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
46314743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
46414743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]),
46514743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[3]));
46614743dddSAlejandro Lucero 
46714743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
46814743dddSAlejandro Lucero 						 EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC,
46914743dddSAlejandro Lucero 						 buf);
47014743dddSAlejandro Lucero 	}
47114743dddSAlejandro Lucero }
47214743dddSAlejandro Lucero 
efx_devlink_info_running_v5(struct efx_nic * efx,struct devlink_info_req * req,unsigned int flags,efx_dword_t * outbuf)47314743dddSAlejandro Lucero static void efx_devlink_info_running_v5(struct efx_nic *efx,
47414743dddSAlejandro Lucero 					struct devlink_info_req *req,
47514743dddSAlejandro Lucero 					unsigned int flags, efx_dword_t *outbuf)
47614743dddSAlejandro Lucero {
47714743dddSAlejandro Lucero 	char buf[EFX_MAX_VERSION_INFO_LEN];
47814743dddSAlejandro Lucero 	union {
47914743dddSAlejandro Lucero 		const __le32 *dwords;
48014743dddSAlejandro Lucero 		const __le16 *words;
48114743dddSAlejandro Lucero 		const char *str;
48214743dddSAlejandro Lucero 	} ver;
48314743dddSAlejandro Lucero 
48414743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) {
48514743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
48614743dddSAlejandro Lucero 						GET_VERSION_V5_OUT_BOARD_VERSION);
48714743dddSAlejandro Lucero 
48814743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
48914743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
49014743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]),
49114743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[3]));
49214743dddSAlejandro Lucero 
49314743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
49414743dddSAlejandro Lucero 						 DEVLINK_INFO_VERSION_GENERIC_BOARD_REV,
49514743dddSAlejandro Lucero 						 buf);
49614743dddSAlejandro Lucero 	}
49714743dddSAlejandro Lucero 
49814743dddSAlejandro Lucero 	if (flags & BIT(EFX_VER_FLAG(BUNDLE_VERSION))) {
49914743dddSAlejandro Lucero 		ver.dwords = (__le32 *)MCDI_PTR(outbuf,
50014743dddSAlejandro Lucero 						GET_VERSION_V5_OUT_BUNDLE_VERSION);
50114743dddSAlejandro Lucero 
50214743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
50314743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]),
50414743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[2]),
50514743dddSAlejandro Lucero 			 le32_to_cpu(ver.dwords[3]));
50614743dddSAlejandro Lucero 
50714743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
50814743dddSAlejandro Lucero 						 DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
50914743dddSAlejandro Lucero 						 buf);
51014743dddSAlejandro Lucero 	}
51114743dddSAlejandro Lucero }
51214743dddSAlejandro Lucero 
efx_devlink_info_running_versions(struct efx_nic * efx,struct devlink_info_req * req)51314743dddSAlejandro Lucero static int efx_devlink_info_running_versions(struct efx_nic *efx,
51414743dddSAlejandro Lucero 					     struct devlink_info_req *req)
51514743dddSAlejandro Lucero {
51614743dddSAlejandro Lucero 	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_VERSION_V5_OUT_LEN);
51714743dddSAlejandro Lucero 	MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_VERSION_EXT_IN_LEN);
51814743dddSAlejandro Lucero 	char buf[EFX_MAX_VERSION_INFO_LEN];
51914743dddSAlejandro Lucero 	union {
52014743dddSAlejandro Lucero 		const __le32 *dwords;
52114743dddSAlejandro Lucero 		const __le16 *words;
52214743dddSAlejandro Lucero 		const char *str;
52314743dddSAlejandro Lucero 	} ver;
52414743dddSAlejandro Lucero 	size_t outlength;
52514743dddSAlejandro Lucero 	unsigned int flags;
52614743dddSAlejandro Lucero 	int rc;
52714743dddSAlejandro Lucero 
52814743dddSAlejandro Lucero 	rc = efx_mcdi_rpc(efx, MC_CMD_GET_VERSION, inbuf, sizeof(inbuf),
52914743dddSAlejandro Lucero 			  outbuf, sizeof(outbuf), &outlength);
53014743dddSAlejandro Lucero 	if (rc || outlength < MC_CMD_GET_VERSION_OUT_LEN) {
53114743dddSAlejandro Lucero 		netif_err(efx, drv, efx->net_dev,
53214743dddSAlejandro Lucero 			  "mcdi MC_CMD_GET_VERSION failed\n");
53314743dddSAlejandro Lucero 		return rc;
53414743dddSAlejandro Lucero 	}
53514743dddSAlejandro Lucero 
53614743dddSAlejandro Lucero 	/* Handle previous output */
53714743dddSAlejandro Lucero 	if (outlength < MC_CMD_GET_VERSION_V2_OUT_LEN) {
53814743dddSAlejandro Lucero 		ver.words = (__le16 *)MCDI_PTR(outbuf,
53914743dddSAlejandro Lucero 					       GET_VERSION_EXT_OUT_VERSION);
54014743dddSAlejandro Lucero 		snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u",
54114743dddSAlejandro Lucero 			 le16_to_cpu(ver.words[0]),
54214743dddSAlejandro Lucero 			 le16_to_cpu(ver.words[1]),
54314743dddSAlejandro Lucero 			 le16_to_cpu(ver.words[2]),
54414743dddSAlejandro Lucero 			 le16_to_cpu(ver.words[3]));
54514743dddSAlejandro Lucero 
54614743dddSAlejandro Lucero 		devlink_info_version_running_put(req,
54714743dddSAlejandro Lucero 						 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT,
54814743dddSAlejandro Lucero 						 buf);
54914743dddSAlejandro Lucero 		return 0;
55014743dddSAlejandro Lucero 	}
55114743dddSAlejandro Lucero 
55214743dddSAlejandro Lucero 	/* Handle V2 additions */
55314743dddSAlejandro Lucero 	flags = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_FLAGS);
55414743dddSAlejandro Lucero 	efx_devlink_info_running_v2(efx, req, flags, outbuf);
55514743dddSAlejandro Lucero 
55614743dddSAlejandro Lucero 	if (outlength < MC_CMD_GET_VERSION_V3_OUT_LEN)
55714743dddSAlejandro Lucero 		return 0;
55814743dddSAlejandro Lucero 
55914743dddSAlejandro Lucero 	/* Handle V3 additions */
56014743dddSAlejandro Lucero 	efx_devlink_info_running_v3(efx, req, flags, outbuf);
56114743dddSAlejandro Lucero 
56214743dddSAlejandro Lucero 	if (outlength < MC_CMD_GET_VERSION_V4_OUT_LEN)
56314743dddSAlejandro Lucero 		return 0;
56414743dddSAlejandro Lucero 
56514743dddSAlejandro Lucero 	/* Handle V4 additions */
56614743dddSAlejandro Lucero 	efx_devlink_info_running_v4(efx, req, flags, outbuf);
56714743dddSAlejandro Lucero 
56814743dddSAlejandro Lucero 	if (outlength < MC_CMD_GET_VERSION_V5_OUT_LEN)
56914743dddSAlejandro Lucero 		return 0;
57014743dddSAlejandro Lucero 
57114743dddSAlejandro Lucero 	/* Handle V5 additions */
57214743dddSAlejandro Lucero 	efx_devlink_info_running_v5(efx, req, flags, outbuf);
57314743dddSAlejandro Lucero 
57414743dddSAlejandro Lucero 	return 0;
57514743dddSAlejandro Lucero }
57614743dddSAlejandro Lucero 
57714743dddSAlejandro Lucero #define EFX_MAX_SERIALNUM_LEN	(ETH_ALEN * 2 + 1)
57814743dddSAlejandro Lucero 
efx_devlink_info_board_cfg(struct efx_nic * efx,struct devlink_info_req * req)57914743dddSAlejandro Lucero static int efx_devlink_info_board_cfg(struct efx_nic *efx,
58014743dddSAlejandro Lucero 				      struct devlink_info_req *req)
58114743dddSAlejandro Lucero {
58214743dddSAlejandro Lucero 	char sn[EFX_MAX_SERIALNUM_LEN];
58314743dddSAlejandro Lucero 	u8 mac_address[ETH_ALEN];
58414743dddSAlejandro Lucero 	int rc;
58514743dddSAlejandro Lucero 
58614743dddSAlejandro Lucero 	rc = efx_mcdi_get_board_cfg(efx, (u8 *)mac_address, NULL, NULL);
58714743dddSAlejandro Lucero 	if (!rc) {
58814743dddSAlejandro Lucero 		snprintf(sn, EFX_MAX_SERIALNUM_LEN, "%pm", mac_address);
58914743dddSAlejandro Lucero 		devlink_info_serial_number_put(req, sn);
59014743dddSAlejandro Lucero 	}
59114743dddSAlejandro Lucero 	return rc;
592*cfcb9428SAlejandro Lucero }
59314743dddSAlejandro Lucero 
efx_devlink_info_get(struct devlink * devlink,struct devlink_info_req * req,struct netlink_ext_ack * extack)594*cfcb9428SAlejandro Lucero static int efx_devlink_info_get(struct devlink *devlink,
595*cfcb9428SAlejandro Lucero 				struct devlink_info_req *req,
596*cfcb9428SAlejandro Lucero 				struct netlink_ext_ack *extack)
59714743dddSAlejandro Lucero {
598*cfcb9428SAlejandro Lucero 	struct efx_devlink *devlink_private = devlink_priv(devlink);
599*cfcb9428SAlejandro Lucero 	struct efx_nic *efx = devlink_private->efx;
600*cfcb9428SAlejandro Lucero 	int err;
601*cfcb9428SAlejandro Lucero 
602*cfcb9428SAlejandro Lucero 	/* Several different MCDI commands are used. We report if errors
603*cfcb9428SAlejandro Lucero 	 * happened through extack. Specific error information via system
604*cfcb9428SAlejandro Lucero 	 * messages inside the calls.
605*cfcb9428SAlejandro Lucero 	 */
60614743dddSAlejandro Lucero 	err = efx_devlink_info_board_cfg(efx, req);
60714743dddSAlejandro Lucero 
60814743dddSAlejandro Lucero 	err |= efx_devlink_info_stored_versions(efx, req);
60914743dddSAlejandro Lucero 
610fa34a514SAlejandro Lucero 	err |= efx_devlink_info_running_versions(efx, req);
61114743dddSAlejandro Lucero 
612fa78b017SAlejandro Lucero 	if (err)
613fa78b017SAlejandro Lucero 		NL_SET_ERR_MSG_MOD(extack, "Errors when getting device info. Check system messages");
6143b6096c9SAlejandro Lucero 
615fa78b017SAlejandro Lucero 	return 0;
616fa34a514SAlejandro Lucero }
617fa34a514SAlejandro Lucero 
61825414b2aSAlejandro Lucero static const struct devlink_ops sfc_devlink_ops = {
61925414b2aSAlejandro Lucero 	.info_get			= efx_devlink_info_get,
62025414b2aSAlejandro Lucero };
62125414b2aSAlejandro Lucero 
62225414b2aSAlejandro Lucero #ifdef CONFIG_SFC_SRIOV
ef100_set_devlink_port(struct efx_nic * efx,u32 idx)62325414b2aSAlejandro Lucero static struct devlink_port *ef100_set_devlink_port(struct efx_nic *efx, u32 idx)
62425414b2aSAlejandro Lucero {
62525414b2aSAlejandro Lucero 	struct mae_mport_desc *mport;
62625414b2aSAlejandro Lucero 	u32 id;
62725414b2aSAlejandro Lucero 	int rc;
62825414b2aSAlejandro Lucero 
62925414b2aSAlejandro Lucero 	if (!efx->mae)
63025414b2aSAlejandro Lucero 		return NULL;
63125414b2aSAlejandro Lucero 
63225414b2aSAlejandro Lucero 	if (efx_mae_lookup_mport(efx, idx, &id)) {
63325414b2aSAlejandro Lucero 		/* This should not happen. */
63425414b2aSAlejandro Lucero 		if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
63525414b2aSAlejandro Lucero 			pci_warn_once(efx->pci_dev, "No mport ID found for PF.\n");
63625414b2aSAlejandro Lucero 		else
63725414b2aSAlejandro Lucero 			pci_warn_once(efx->pci_dev, "No mport ID found for VF %u.\n",
63825414b2aSAlejandro Lucero 				      idx);
63925414b2aSAlejandro Lucero 		return NULL;
64025414b2aSAlejandro Lucero 	}
64125414b2aSAlejandro Lucero 
64225414b2aSAlejandro Lucero 	mport = efx_mae_get_mport(efx, id);
64325414b2aSAlejandro Lucero 	if (!mport) {
64425414b2aSAlejandro Lucero 		/* This should not happen. */
64525414b2aSAlejandro Lucero 		if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
64625414b2aSAlejandro Lucero 			pci_warn_once(efx->pci_dev, "No mport found for PF.\n");
64725414b2aSAlejandro Lucero 		else
64825414b2aSAlejandro Lucero 			pci_warn_once(efx->pci_dev, "No mport found for VF %u.\n",
64925414b2aSAlejandro Lucero 				      idx);
65025414b2aSAlejandro Lucero 		return NULL;
65125414b2aSAlejandro Lucero 	}
65225414b2aSAlejandro Lucero 
6530d39ad3eSColin Ian King 	rc = efx_devlink_add_port(efx, mport);
65425414b2aSAlejandro Lucero 	if (rc) {
65525414b2aSAlejandro Lucero 		if (idx == MAE_MPORT_DESC_VF_IDX_NULL)
65625414b2aSAlejandro Lucero 			pci_warn(efx->pci_dev,
65725414b2aSAlejandro Lucero 				 "devlink port creation for PF failed.\n");
65825414b2aSAlejandro Lucero 		else
65925414b2aSAlejandro Lucero 			pci_warn(efx->pci_dev,
66025414b2aSAlejandro Lucero 				 "devlink_port creation for VF %u failed.\n",
66125414b2aSAlejandro Lucero 				 idx);
66225414b2aSAlejandro Lucero 		return NULL;
66325414b2aSAlejandro Lucero 	}
66425414b2aSAlejandro Lucero 
66525414b2aSAlejandro Lucero 	return &mport->dl_port;
66625414b2aSAlejandro Lucero }
66725414b2aSAlejandro Lucero 
ef100_rep_set_devlink_port(struct efx_rep * efv)66825414b2aSAlejandro Lucero void ef100_rep_set_devlink_port(struct efx_rep *efv)
66925414b2aSAlejandro Lucero {
67025414b2aSAlejandro Lucero 	efv->dl_port = ef100_set_devlink_port(efv->parent, efv->idx);
67125414b2aSAlejandro Lucero }
67225414b2aSAlejandro Lucero 
ef100_pf_set_devlink_port(struct efx_nic * efx)67325414b2aSAlejandro Lucero void ef100_pf_set_devlink_port(struct efx_nic *efx)
67425414b2aSAlejandro Lucero {
67525414b2aSAlejandro Lucero 	efx->dl_port = ef100_set_devlink_port(efx, MAE_MPORT_DESC_VF_IDX_NULL);
67625414b2aSAlejandro Lucero }
67725414b2aSAlejandro Lucero 
ef100_rep_unset_devlink_port(struct efx_rep * efv)67825414b2aSAlejandro Lucero void ef100_rep_unset_devlink_port(struct efx_rep *efv)
67925414b2aSAlejandro Lucero {
68025414b2aSAlejandro Lucero 	efx_devlink_del_port(efv->dl_port);
68125414b2aSAlejandro Lucero }
682fa34a514SAlejandro Lucero 
ef100_pf_unset_devlink_port(struct efx_nic * efx)683fa34a514SAlejandro Lucero void ef100_pf_unset_devlink_port(struct efx_nic *efx)
684fa34a514SAlejandro Lucero {
685fa34a514SAlejandro Lucero 	efx_devlink_del_port(efx->dl_port);
686fa34a514SAlejandro Lucero }
687fa34a514SAlejandro Lucero #endif
688fa34a514SAlejandro Lucero 
efx_fini_devlink_lock(struct efx_nic * efx)689fa34a514SAlejandro Lucero void efx_fini_devlink_lock(struct efx_nic *efx)
690fa34a514SAlejandro Lucero {
691fa34a514SAlejandro Lucero 	if (efx->devlink)
692fa34a514SAlejandro Lucero 		devl_lock(efx->devlink);
693fa34a514SAlejandro Lucero }
694fa34a514SAlejandro Lucero 
efx_fini_devlink_and_unlock(struct efx_nic * efx)695fa34a514SAlejandro Lucero void efx_fini_devlink_and_unlock(struct efx_nic *efx)
696fa34a514SAlejandro Lucero {
697fa34a514SAlejandro Lucero 	if (efx->devlink) {
698fa34a514SAlejandro Lucero 		devl_unregister(efx->devlink);
699fa34a514SAlejandro Lucero 		devl_unlock(efx->devlink);
700fa34a514SAlejandro Lucero 		devlink_free(efx->devlink);
701fa34a514SAlejandro Lucero 		efx->devlink = NULL;
702fa34a514SAlejandro Lucero 	}
703fa34a514SAlejandro Lucero }
704fa34a514SAlejandro Lucero 
efx_probe_devlink_and_lock(struct efx_nic * efx)705fa34a514SAlejandro Lucero int efx_probe_devlink_and_lock(struct efx_nic *efx)
706fa34a514SAlejandro Lucero {
707fa34a514SAlejandro Lucero 	struct efx_devlink *devlink_private;
708fa34a514SAlejandro Lucero 
709fa34a514SAlejandro Lucero 	if (efx->type->is_vf)
710fa34a514SAlejandro Lucero 		return 0;
711fa34a514SAlejandro Lucero 
712fa34a514SAlejandro Lucero 	efx->devlink = devlink_alloc(&sfc_devlink_ops,
713fa34a514SAlejandro Lucero 				     sizeof(struct efx_devlink),
714fa34a514SAlejandro Lucero 				     &efx->pci_dev->dev);
715fa34a514SAlejandro Lucero 	if (!efx->devlink)
716fa34a514SAlejandro Lucero 		return -ENOMEM;
717fa34a514SAlejandro Lucero 
718fa34a514SAlejandro Lucero 	devl_lock(efx->devlink);
719fa34a514SAlejandro Lucero 	devlink_private = devlink_priv(efx->devlink);
720fa34a514SAlejandro Lucero 	devlink_private->efx = efx;
721fa34a514SAlejandro Lucero 
722fa34a514SAlejandro Lucero 	devl_register(efx->devlink);
723fa34a514SAlejandro Lucero 
724fa34a514SAlejandro Lucero 	return 0;
725fa34a514SAlejandro Lucero }
726fa34a514SAlejandro Lucero 
efx_probe_devlink_unlock(struct efx_nic * efx)727 void efx_probe_devlink_unlock(struct efx_nic *efx)
728 {
729 	if (!efx->devlink)
730 		return;
731 
732 	devl_unlock(efx->devlink);
733 }
734