brintos

brintos / linux-shallow public Read only

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