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