1fa34a514SAlejandro Lucero // SPDX-License-Identifier: GPL-2.0-only 2fa34a514SAlejandro Lucero /**************************************************************************** 3fa34a514SAlejandro Lucero * Driver for AMD network controllers and boards 4fa34a514SAlejandro Lucero * Copyright (C) 2023, Advanced Micro Devices, Inc. 5fa34a514SAlejandro Lucero * 6fa34a514SAlejandro Lucero * This program is free software; you can redistribute it and/or modify it 7fa34a514SAlejandro Lucero * under the terms of the GNU General Public License version 2 as published 8fa34a514SAlejandro Lucero * by the Free Software Foundation, incorporated herein by reference. 9fa34a514SAlejandro Lucero */ 10fa34a514SAlejandro Lucero 11fa34a514SAlejandro Lucero #include "net_driver.h" 12fa34a514SAlejandro Lucero #include "efx_devlink.h" 13*14743dddSAlejandro Lucero #include <linux/rtc.h> 14*14743dddSAlejandro Lucero #include "mcdi.h" 15*14743dddSAlejandro Lucero #include "mcdi_functions.h" 16*14743dddSAlejandro Lucero #include "mcdi_pcol.h" 17fa34a514SAlejandro Lucero 18fa34a514SAlejandro Lucero struct efx_devlink { 19fa34a514SAlejandro Lucero struct efx_nic *efx; 20fa34a514SAlejandro Lucero }; 21fa34a514SAlejandro Lucero 22*14743dddSAlejandro Lucero static int efx_devlink_info_nvram_partition(struct efx_nic *efx, 23*14743dddSAlejandro Lucero struct devlink_info_req *req, 24*14743dddSAlejandro Lucero unsigned int partition_type, 25*14743dddSAlejandro Lucero const char *version_name) 26*14743dddSAlejandro Lucero { 27*14743dddSAlejandro Lucero char buf[EFX_MAX_VERSION_INFO_LEN]; 28*14743dddSAlejandro Lucero u16 version[4]; 29*14743dddSAlejandro Lucero int rc; 30*14743dddSAlejandro Lucero 31*14743dddSAlejandro Lucero rc = efx_mcdi_nvram_metadata(efx, partition_type, NULL, version, NULL, 32*14743dddSAlejandro Lucero 0); 33*14743dddSAlejandro Lucero if (rc) { 34*14743dddSAlejandro Lucero netif_err(efx, drv, efx->net_dev, "mcdi nvram %s: failed\n", 35*14743dddSAlejandro Lucero version_name); 36*14743dddSAlejandro Lucero return rc; 37*14743dddSAlejandro Lucero } 38*14743dddSAlejandro Lucero 39*14743dddSAlejandro Lucero snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u", version[0], 40*14743dddSAlejandro Lucero version[1], version[2], version[3]); 41*14743dddSAlejandro Lucero devlink_info_version_stored_put(req, version_name, buf); 42*14743dddSAlejandro Lucero 43*14743dddSAlejandro Lucero return 0; 44*14743dddSAlejandro Lucero } 45*14743dddSAlejandro Lucero 46*14743dddSAlejandro Lucero static int efx_devlink_info_stored_versions(struct efx_nic *efx, 47*14743dddSAlejandro Lucero struct devlink_info_req *req) 48*14743dddSAlejandro Lucero { 49*14743dddSAlejandro Lucero int rc; 50*14743dddSAlejandro Lucero 51*14743dddSAlejandro Lucero rc = efx_devlink_info_nvram_partition(efx, req, 52*14743dddSAlejandro Lucero NVRAM_PARTITION_TYPE_BUNDLE, 53*14743dddSAlejandro Lucero DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID); 54*14743dddSAlejandro Lucero if (rc) 55*14743dddSAlejandro Lucero return rc; 56*14743dddSAlejandro Lucero 57*14743dddSAlejandro Lucero rc = efx_devlink_info_nvram_partition(efx, req, 58*14743dddSAlejandro Lucero NVRAM_PARTITION_TYPE_MC_FIRMWARE, 59*14743dddSAlejandro Lucero DEVLINK_INFO_VERSION_GENERIC_FW_MGMT); 60*14743dddSAlejandro Lucero if (rc) 61*14743dddSAlejandro Lucero return rc; 62*14743dddSAlejandro Lucero 63*14743dddSAlejandro Lucero rc = efx_devlink_info_nvram_partition(efx, req, 64*14743dddSAlejandro Lucero NVRAM_PARTITION_TYPE_SUC_FIRMWARE, 65*14743dddSAlejandro Lucero EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC); 66*14743dddSAlejandro Lucero if (rc) 67*14743dddSAlejandro Lucero return rc; 68*14743dddSAlejandro Lucero 69*14743dddSAlejandro Lucero rc = efx_devlink_info_nvram_partition(efx, req, 70*14743dddSAlejandro Lucero NVRAM_PARTITION_TYPE_EXPANSION_ROM, 71*14743dddSAlejandro Lucero EFX_DEVLINK_INFO_VERSION_FW_EXPROM); 72*14743dddSAlejandro Lucero if (rc) 73*14743dddSAlejandro Lucero return rc; 74*14743dddSAlejandro Lucero 75*14743dddSAlejandro Lucero rc = efx_devlink_info_nvram_partition(efx, req, 76*14743dddSAlejandro Lucero NVRAM_PARTITION_TYPE_EXPANSION_UEFI, 77*14743dddSAlejandro Lucero EFX_DEVLINK_INFO_VERSION_FW_UEFI); 78*14743dddSAlejandro Lucero return rc; 79*14743dddSAlejandro Lucero } 80*14743dddSAlejandro Lucero 81*14743dddSAlejandro Lucero #define EFX_VER_FLAG(_f) \ 82*14743dddSAlejandro Lucero (MC_CMD_GET_VERSION_V5_OUT_ ## _f ## _PRESENT_LBN) 83*14743dddSAlejandro Lucero 84*14743dddSAlejandro Lucero static void efx_devlink_info_running_v2(struct efx_nic *efx, 85*14743dddSAlejandro Lucero struct devlink_info_req *req, 86*14743dddSAlejandro Lucero unsigned int flags, efx_dword_t *outbuf) 87*14743dddSAlejandro Lucero { 88*14743dddSAlejandro Lucero char buf[EFX_MAX_VERSION_INFO_LEN]; 89*14743dddSAlejandro Lucero union { 90*14743dddSAlejandro Lucero const __le32 *dwords; 91*14743dddSAlejandro Lucero const __le16 *words; 92*14743dddSAlejandro Lucero const char *str; 93*14743dddSAlejandro Lucero } ver; 94*14743dddSAlejandro Lucero struct rtc_time build_date; 95*14743dddSAlejandro Lucero unsigned int build_id; 96*14743dddSAlejandro Lucero size_t offset; 97*14743dddSAlejandro Lucero __maybe_unused u64 tstamp; 98*14743dddSAlejandro Lucero 99*14743dddSAlejandro Lucero if (flags & BIT(EFX_VER_FLAG(BOARD_EXT_INFO))) { 100*14743dddSAlejandro Lucero snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%s", 101*14743dddSAlejandro Lucero MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_NAME)); 102*14743dddSAlejandro Lucero devlink_info_version_fixed_put(req, 103*14743dddSAlejandro Lucero DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, 104*14743dddSAlejandro Lucero buf); 105*14743dddSAlejandro Lucero 106*14743dddSAlejandro Lucero /* Favour full board version if present (in V5 or later) */ 107*14743dddSAlejandro Lucero if (~flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) { 108*14743dddSAlejandro Lucero snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u", 109*14743dddSAlejandro Lucero MCDI_DWORD(outbuf, 110*14743dddSAlejandro Lucero GET_VERSION_V2_OUT_BOARD_REVISION)); 111*14743dddSAlejandro Lucero devlink_info_version_fixed_put(req, 112*14743dddSAlejandro Lucero DEVLINK_INFO_VERSION_GENERIC_BOARD_REV, 113*14743dddSAlejandro Lucero buf); 114*14743dddSAlejandro Lucero } 115*14743dddSAlejandro Lucero 116*14743dddSAlejandro Lucero ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_BOARD_SERIAL); 117*14743dddSAlejandro Lucero if (ver.str[0]) 118*14743dddSAlejandro Lucero devlink_info_board_serial_number_put(req, ver.str); 119*14743dddSAlejandro Lucero } 120*14743dddSAlejandro Lucero 121*14743dddSAlejandro Lucero if (flags & BIT(EFX_VER_FLAG(FPGA_EXT_INFO))) { 122*14743dddSAlejandro Lucero ver.dwords = (__le32 *)MCDI_PTR(outbuf, 123*14743dddSAlejandro Lucero GET_VERSION_V2_OUT_FPGA_VERSION); 124*14743dddSAlejandro Lucero offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u_%c%u", 125*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[0]), 126*14743dddSAlejandro Lucero 'A' + le32_to_cpu(ver.dwords[1]), 127*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[2])); 128*14743dddSAlejandro Lucero 129*14743dddSAlejandro Lucero ver.str = MCDI_PTR(outbuf, GET_VERSION_V2_OUT_FPGA_EXTRA); 130*14743dddSAlejandro Lucero if (ver.str[0]) 131*14743dddSAlejandro Lucero snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset, 132*14743dddSAlejandro Lucero " (%s)", ver.str); 133*14743dddSAlejandro Lucero 134*14743dddSAlejandro Lucero devlink_info_version_running_put(req, 135*14743dddSAlejandro Lucero EFX_DEVLINK_INFO_VERSION_FPGA_REV, 136*14743dddSAlejandro Lucero buf); 137*14743dddSAlejandro Lucero } 138*14743dddSAlejandro Lucero 139*14743dddSAlejandro Lucero if (flags & BIT(EFX_VER_FLAG(CMC_EXT_INFO))) { 140*14743dddSAlejandro Lucero ver.dwords = (__le32 *)MCDI_PTR(outbuf, 141*14743dddSAlejandro Lucero GET_VERSION_V2_OUT_CMCFW_VERSION); 142*14743dddSAlejandro Lucero offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u", 143*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[0]), 144*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[1]), 145*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[2]), 146*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[3])); 147*14743dddSAlejandro Lucero 148*14743dddSAlejandro Lucero #ifdef CONFIG_RTC_LIB 149*14743dddSAlejandro Lucero tstamp = MCDI_QWORD(outbuf, 150*14743dddSAlejandro Lucero GET_VERSION_V2_OUT_CMCFW_BUILD_DATE); 151*14743dddSAlejandro Lucero if (tstamp) { 152*14743dddSAlejandro Lucero rtc_time64_to_tm(tstamp, &build_date); 153*14743dddSAlejandro Lucero snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset, 154*14743dddSAlejandro Lucero " (%ptRd)", &build_date); 155*14743dddSAlejandro Lucero } 156*14743dddSAlejandro Lucero #endif 157*14743dddSAlejandro Lucero 158*14743dddSAlejandro Lucero devlink_info_version_running_put(req, 159*14743dddSAlejandro Lucero EFX_DEVLINK_INFO_VERSION_FW_MGMT_CMC, 160*14743dddSAlejandro Lucero buf); 161*14743dddSAlejandro Lucero } 162*14743dddSAlejandro Lucero 163*14743dddSAlejandro Lucero ver.words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_V2_OUT_VERSION); 164*14743dddSAlejandro Lucero offset = snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u", 165*14743dddSAlejandro Lucero le16_to_cpu(ver.words[0]), le16_to_cpu(ver.words[1]), 166*14743dddSAlejandro Lucero le16_to_cpu(ver.words[2]), le16_to_cpu(ver.words[3])); 167*14743dddSAlejandro Lucero if (flags & BIT(EFX_VER_FLAG(MCFW_EXT_INFO))) { 168*14743dddSAlejandro Lucero build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_ID); 169*14743dddSAlejandro Lucero snprintf(&buf[offset], EFX_MAX_VERSION_INFO_LEN - offset, 170*14743dddSAlejandro Lucero " (%x) %s", build_id, 171*14743dddSAlejandro Lucero MCDI_PTR(outbuf, GET_VERSION_V2_OUT_MCFW_BUILD_NAME)); 172*14743dddSAlejandro Lucero } 173*14743dddSAlejandro Lucero devlink_info_version_running_put(req, 174*14743dddSAlejandro Lucero DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, 175*14743dddSAlejandro Lucero buf); 176*14743dddSAlejandro Lucero 177*14743dddSAlejandro Lucero if (flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) { 178*14743dddSAlejandro Lucero ver.dwords = (__le32 *)MCDI_PTR(outbuf, 179*14743dddSAlejandro Lucero GET_VERSION_V2_OUT_SUCFW_VERSION); 180*14743dddSAlejandro Lucero #ifdef CONFIG_RTC_LIB 181*14743dddSAlejandro Lucero tstamp = MCDI_QWORD(outbuf, 182*14743dddSAlejandro Lucero GET_VERSION_V2_OUT_SUCFW_BUILD_DATE); 183*14743dddSAlejandro Lucero rtc_time64_to_tm(tstamp, &build_date); 184*14743dddSAlejandro Lucero #else 185*14743dddSAlejandro Lucero memset(&build_date, 0, sizeof(build_date) 186*14743dddSAlejandro Lucero #endif 187*14743dddSAlejandro Lucero build_id = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_SUCFW_CHIP_ID); 188*14743dddSAlejandro Lucero 189*14743dddSAlejandro Lucero snprintf(buf, EFX_MAX_VERSION_INFO_LEN, 190*14743dddSAlejandro Lucero "%u.%u.%u.%u type %x (%ptRd)", 191*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]), 192*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[2]), le32_to_cpu(ver.dwords[3]), 193*14743dddSAlejandro Lucero build_id, &build_date); 194*14743dddSAlejandro Lucero 195*14743dddSAlejandro Lucero devlink_info_version_running_put(req, 196*14743dddSAlejandro Lucero EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC, 197*14743dddSAlejandro Lucero buf); 198*14743dddSAlejandro Lucero } 199*14743dddSAlejandro Lucero } 200*14743dddSAlejandro Lucero 201*14743dddSAlejandro Lucero static void efx_devlink_info_running_v3(struct efx_nic *efx, 202*14743dddSAlejandro Lucero struct devlink_info_req *req, 203*14743dddSAlejandro Lucero unsigned int flags, efx_dword_t *outbuf) 204*14743dddSAlejandro Lucero { 205*14743dddSAlejandro Lucero char buf[EFX_MAX_VERSION_INFO_LEN]; 206*14743dddSAlejandro Lucero union { 207*14743dddSAlejandro Lucero const __le32 *dwords; 208*14743dddSAlejandro Lucero const __le16 *words; 209*14743dddSAlejandro Lucero const char *str; 210*14743dddSAlejandro Lucero } ver; 211*14743dddSAlejandro Lucero 212*14743dddSAlejandro Lucero if (flags & BIT(EFX_VER_FLAG(DATAPATH_HW_VERSION))) { 213*14743dddSAlejandro Lucero ver.dwords = (__le32 *)MCDI_PTR(outbuf, 214*14743dddSAlejandro Lucero GET_VERSION_V3_OUT_DATAPATH_HW_VERSION); 215*14743dddSAlejandro Lucero 216*14743dddSAlejandro Lucero snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u", 217*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]), 218*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[2])); 219*14743dddSAlejandro Lucero 220*14743dddSAlejandro Lucero devlink_info_version_running_put(req, 221*14743dddSAlejandro Lucero EFX_DEVLINK_INFO_VERSION_DATAPATH_HW, 222*14743dddSAlejandro Lucero buf); 223*14743dddSAlejandro Lucero } 224*14743dddSAlejandro Lucero 225*14743dddSAlejandro Lucero if (flags & BIT(EFX_VER_FLAG(DATAPATH_FW_VERSION))) { 226*14743dddSAlejandro Lucero ver.dwords = (__le32 *)MCDI_PTR(outbuf, 227*14743dddSAlejandro Lucero GET_VERSION_V3_OUT_DATAPATH_FW_VERSION); 228*14743dddSAlejandro Lucero 229*14743dddSAlejandro Lucero snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u", 230*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]), 231*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[2])); 232*14743dddSAlejandro Lucero 233*14743dddSAlejandro Lucero devlink_info_version_running_put(req, 234*14743dddSAlejandro Lucero EFX_DEVLINK_INFO_VERSION_DATAPATH_FW, 235*14743dddSAlejandro Lucero buf); 236*14743dddSAlejandro Lucero } 237*14743dddSAlejandro Lucero } 238*14743dddSAlejandro Lucero 239*14743dddSAlejandro Lucero static void efx_devlink_info_running_v4(struct efx_nic *efx, 240*14743dddSAlejandro Lucero struct devlink_info_req *req, 241*14743dddSAlejandro Lucero unsigned int flags, efx_dword_t *outbuf) 242*14743dddSAlejandro Lucero { 243*14743dddSAlejandro Lucero char buf[EFX_MAX_VERSION_INFO_LEN]; 244*14743dddSAlejandro Lucero union { 245*14743dddSAlejandro Lucero const __le32 *dwords; 246*14743dddSAlejandro Lucero const __le16 *words; 247*14743dddSAlejandro Lucero const char *str; 248*14743dddSAlejandro Lucero } ver; 249*14743dddSAlejandro Lucero 250*14743dddSAlejandro Lucero if (flags & BIT(EFX_VER_FLAG(SOC_BOOT_VERSION))) { 251*14743dddSAlejandro Lucero ver.dwords = (__le32 *)MCDI_PTR(outbuf, 252*14743dddSAlejandro Lucero GET_VERSION_V4_OUT_SOC_BOOT_VERSION); 253*14743dddSAlejandro Lucero 254*14743dddSAlejandro Lucero snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u", 255*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]), 256*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[2]), 257*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[3])); 258*14743dddSAlejandro Lucero 259*14743dddSAlejandro Lucero devlink_info_version_running_put(req, 260*14743dddSAlejandro Lucero EFX_DEVLINK_INFO_VERSION_SOC_BOOT, 261*14743dddSAlejandro Lucero buf); 262*14743dddSAlejandro Lucero } 263*14743dddSAlejandro Lucero 264*14743dddSAlejandro Lucero if (flags & BIT(EFX_VER_FLAG(SOC_UBOOT_VERSION))) { 265*14743dddSAlejandro Lucero ver.dwords = (__le32 *)MCDI_PTR(outbuf, 266*14743dddSAlejandro Lucero GET_VERSION_V4_OUT_SOC_UBOOT_VERSION); 267*14743dddSAlejandro Lucero 268*14743dddSAlejandro Lucero snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u", 269*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]), 270*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[2]), 271*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[3])); 272*14743dddSAlejandro Lucero 273*14743dddSAlejandro Lucero devlink_info_version_running_put(req, 274*14743dddSAlejandro Lucero EFX_DEVLINK_INFO_VERSION_SOC_UBOOT, 275*14743dddSAlejandro Lucero buf); 276*14743dddSAlejandro Lucero } 277*14743dddSAlejandro Lucero 278*14743dddSAlejandro Lucero if (flags & BIT(EFX_VER_FLAG(SOC_MAIN_ROOTFS_VERSION))) { 279*14743dddSAlejandro Lucero ver.dwords = (__le32 *)MCDI_PTR(outbuf, 280*14743dddSAlejandro Lucero GET_VERSION_V4_OUT_SOC_MAIN_ROOTFS_VERSION); 281*14743dddSAlejandro Lucero 282*14743dddSAlejandro Lucero snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u", 283*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]), 284*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[2]), 285*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[3])); 286*14743dddSAlejandro Lucero 287*14743dddSAlejandro Lucero devlink_info_version_running_put(req, 288*14743dddSAlejandro Lucero EFX_DEVLINK_INFO_VERSION_SOC_MAIN, 289*14743dddSAlejandro Lucero buf); 290*14743dddSAlejandro Lucero } 291*14743dddSAlejandro Lucero 292*14743dddSAlejandro Lucero if (flags & BIT(EFX_VER_FLAG(SOC_RECOVERY_BUILDROOT_VERSION))) { 293*14743dddSAlejandro Lucero ver.dwords = (__le32 *)MCDI_PTR(outbuf, 294*14743dddSAlejandro Lucero GET_VERSION_V4_OUT_SOC_RECOVERY_BUILDROOT_VERSION); 295*14743dddSAlejandro Lucero 296*14743dddSAlejandro Lucero snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u", 297*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]), 298*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[2]), 299*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[3])); 300*14743dddSAlejandro Lucero 301*14743dddSAlejandro Lucero devlink_info_version_running_put(req, 302*14743dddSAlejandro Lucero EFX_DEVLINK_INFO_VERSION_SOC_RECOVERY, 303*14743dddSAlejandro Lucero buf); 304*14743dddSAlejandro Lucero } 305*14743dddSAlejandro Lucero 306*14743dddSAlejandro Lucero if (flags & BIT(EFX_VER_FLAG(SUCFW_VERSION)) && 307*14743dddSAlejandro Lucero ~flags & BIT(EFX_VER_FLAG(SUCFW_EXT_INFO))) { 308*14743dddSAlejandro Lucero ver.dwords = (__le32 *)MCDI_PTR(outbuf, 309*14743dddSAlejandro Lucero GET_VERSION_V4_OUT_SUCFW_VERSION); 310*14743dddSAlejandro Lucero 311*14743dddSAlejandro Lucero snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u", 312*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]), 313*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[2]), 314*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[3])); 315*14743dddSAlejandro Lucero 316*14743dddSAlejandro Lucero devlink_info_version_running_put(req, 317*14743dddSAlejandro Lucero EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC, 318*14743dddSAlejandro Lucero buf); 319*14743dddSAlejandro Lucero } 320*14743dddSAlejandro Lucero } 321*14743dddSAlejandro Lucero 322*14743dddSAlejandro Lucero static void efx_devlink_info_running_v5(struct efx_nic *efx, 323*14743dddSAlejandro Lucero struct devlink_info_req *req, 324*14743dddSAlejandro Lucero unsigned int flags, efx_dword_t *outbuf) 325*14743dddSAlejandro Lucero { 326*14743dddSAlejandro Lucero char buf[EFX_MAX_VERSION_INFO_LEN]; 327*14743dddSAlejandro Lucero union { 328*14743dddSAlejandro Lucero const __le32 *dwords; 329*14743dddSAlejandro Lucero const __le16 *words; 330*14743dddSAlejandro Lucero const char *str; 331*14743dddSAlejandro Lucero } ver; 332*14743dddSAlejandro Lucero 333*14743dddSAlejandro Lucero if (flags & BIT(EFX_VER_FLAG(BOARD_VERSION))) { 334*14743dddSAlejandro Lucero ver.dwords = (__le32 *)MCDI_PTR(outbuf, 335*14743dddSAlejandro Lucero GET_VERSION_V5_OUT_BOARD_VERSION); 336*14743dddSAlejandro Lucero 337*14743dddSAlejandro Lucero snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u", 338*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]), 339*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[2]), 340*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[3])); 341*14743dddSAlejandro Lucero 342*14743dddSAlejandro Lucero devlink_info_version_running_put(req, 343*14743dddSAlejandro Lucero DEVLINK_INFO_VERSION_GENERIC_BOARD_REV, 344*14743dddSAlejandro Lucero buf); 345*14743dddSAlejandro Lucero } 346*14743dddSAlejandro Lucero 347*14743dddSAlejandro Lucero if (flags & BIT(EFX_VER_FLAG(BUNDLE_VERSION))) { 348*14743dddSAlejandro Lucero ver.dwords = (__le32 *)MCDI_PTR(outbuf, 349*14743dddSAlejandro Lucero GET_VERSION_V5_OUT_BUNDLE_VERSION); 350*14743dddSAlejandro Lucero 351*14743dddSAlejandro Lucero snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u", 352*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[0]), le32_to_cpu(ver.dwords[1]), 353*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[2]), 354*14743dddSAlejandro Lucero le32_to_cpu(ver.dwords[3])); 355*14743dddSAlejandro Lucero 356*14743dddSAlejandro Lucero devlink_info_version_running_put(req, 357*14743dddSAlejandro Lucero DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, 358*14743dddSAlejandro Lucero buf); 359*14743dddSAlejandro Lucero } 360*14743dddSAlejandro Lucero } 361*14743dddSAlejandro Lucero 362*14743dddSAlejandro Lucero static int efx_devlink_info_running_versions(struct efx_nic *efx, 363*14743dddSAlejandro Lucero struct devlink_info_req *req) 364*14743dddSAlejandro Lucero { 365*14743dddSAlejandro Lucero MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_VERSION_V5_OUT_LEN); 366*14743dddSAlejandro Lucero MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_VERSION_EXT_IN_LEN); 367*14743dddSAlejandro Lucero char buf[EFX_MAX_VERSION_INFO_LEN]; 368*14743dddSAlejandro Lucero union { 369*14743dddSAlejandro Lucero const __le32 *dwords; 370*14743dddSAlejandro Lucero const __le16 *words; 371*14743dddSAlejandro Lucero const char *str; 372*14743dddSAlejandro Lucero } ver; 373*14743dddSAlejandro Lucero size_t outlength; 374*14743dddSAlejandro Lucero unsigned int flags; 375*14743dddSAlejandro Lucero int rc; 376*14743dddSAlejandro Lucero 377*14743dddSAlejandro Lucero rc = efx_mcdi_rpc(efx, MC_CMD_GET_VERSION, inbuf, sizeof(inbuf), 378*14743dddSAlejandro Lucero outbuf, sizeof(outbuf), &outlength); 379*14743dddSAlejandro Lucero if (rc || outlength < MC_CMD_GET_VERSION_OUT_LEN) { 380*14743dddSAlejandro Lucero netif_err(efx, drv, efx->net_dev, 381*14743dddSAlejandro Lucero "mcdi MC_CMD_GET_VERSION failed\n"); 382*14743dddSAlejandro Lucero return rc; 383*14743dddSAlejandro Lucero } 384*14743dddSAlejandro Lucero 385*14743dddSAlejandro Lucero /* Handle previous output */ 386*14743dddSAlejandro Lucero if (outlength < MC_CMD_GET_VERSION_V2_OUT_LEN) { 387*14743dddSAlejandro Lucero ver.words = (__le16 *)MCDI_PTR(outbuf, 388*14743dddSAlejandro Lucero GET_VERSION_EXT_OUT_VERSION); 389*14743dddSAlejandro Lucero snprintf(buf, EFX_MAX_VERSION_INFO_LEN, "%u.%u.%u.%u", 390*14743dddSAlejandro Lucero le16_to_cpu(ver.words[0]), 391*14743dddSAlejandro Lucero le16_to_cpu(ver.words[1]), 392*14743dddSAlejandro Lucero le16_to_cpu(ver.words[2]), 393*14743dddSAlejandro Lucero le16_to_cpu(ver.words[3])); 394*14743dddSAlejandro Lucero 395*14743dddSAlejandro Lucero devlink_info_version_running_put(req, 396*14743dddSAlejandro Lucero DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, 397*14743dddSAlejandro Lucero buf); 398*14743dddSAlejandro Lucero return 0; 399*14743dddSAlejandro Lucero } 400*14743dddSAlejandro Lucero 401*14743dddSAlejandro Lucero /* Handle V2 additions */ 402*14743dddSAlejandro Lucero flags = MCDI_DWORD(outbuf, GET_VERSION_V2_OUT_FLAGS); 403*14743dddSAlejandro Lucero efx_devlink_info_running_v2(efx, req, flags, outbuf); 404*14743dddSAlejandro Lucero 405*14743dddSAlejandro Lucero if (outlength < MC_CMD_GET_VERSION_V3_OUT_LEN) 406*14743dddSAlejandro Lucero return 0; 407*14743dddSAlejandro Lucero 408*14743dddSAlejandro Lucero /* Handle V3 additions */ 409*14743dddSAlejandro Lucero efx_devlink_info_running_v3(efx, req, flags, outbuf); 410*14743dddSAlejandro Lucero 411*14743dddSAlejandro Lucero if (outlength < MC_CMD_GET_VERSION_V4_OUT_LEN) 412*14743dddSAlejandro Lucero return 0; 413*14743dddSAlejandro Lucero 414*14743dddSAlejandro Lucero /* Handle V4 additions */ 415*14743dddSAlejandro Lucero efx_devlink_info_running_v4(efx, req, flags, outbuf); 416*14743dddSAlejandro Lucero 417*14743dddSAlejandro Lucero if (outlength < MC_CMD_GET_VERSION_V5_OUT_LEN) 418*14743dddSAlejandro Lucero return 0; 419*14743dddSAlejandro Lucero 420*14743dddSAlejandro Lucero /* Handle V5 additions */ 421*14743dddSAlejandro Lucero efx_devlink_info_running_v5(efx, req, flags, outbuf); 422*14743dddSAlejandro Lucero 423*14743dddSAlejandro Lucero return 0; 424*14743dddSAlejandro Lucero } 425*14743dddSAlejandro Lucero 426*14743dddSAlejandro Lucero #define EFX_MAX_SERIALNUM_LEN (ETH_ALEN * 2 + 1) 427*14743dddSAlejandro Lucero 428*14743dddSAlejandro Lucero static int efx_devlink_info_board_cfg(struct efx_nic *efx, 429*14743dddSAlejandro Lucero struct devlink_info_req *req) 430*14743dddSAlejandro Lucero { 431*14743dddSAlejandro Lucero char sn[EFX_MAX_SERIALNUM_LEN]; 432*14743dddSAlejandro Lucero u8 mac_address[ETH_ALEN]; 433*14743dddSAlejandro Lucero int rc; 434*14743dddSAlejandro Lucero 435*14743dddSAlejandro Lucero rc = efx_mcdi_get_board_cfg(efx, (u8 *)mac_address, NULL, NULL); 436*14743dddSAlejandro Lucero if (!rc) { 437*14743dddSAlejandro Lucero snprintf(sn, EFX_MAX_SERIALNUM_LEN, "%pm", mac_address); 438*14743dddSAlejandro Lucero devlink_info_serial_number_put(req, sn); 439*14743dddSAlejandro Lucero } 440*14743dddSAlejandro Lucero return rc; 441*14743dddSAlejandro Lucero } 442*14743dddSAlejandro Lucero 443*14743dddSAlejandro Lucero static int efx_devlink_info_get(struct devlink *devlink, 444*14743dddSAlejandro Lucero struct devlink_info_req *req, 445*14743dddSAlejandro Lucero struct netlink_ext_ack *extack) 446*14743dddSAlejandro Lucero { 447*14743dddSAlejandro Lucero struct efx_devlink *devlink_private = devlink_priv(devlink); 448*14743dddSAlejandro Lucero struct efx_nic *efx = devlink_private->efx; 449*14743dddSAlejandro Lucero int rc; 450*14743dddSAlejandro Lucero 451*14743dddSAlejandro Lucero /* Several different MCDI commands are used. We report first error 452*14743dddSAlejandro Lucero * through extack returning at that point. Specific error 453*14743dddSAlejandro Lucero * information via system messages. 454*14743dddSAlejandro Lucero */ 455*14743dddSAlejandro Lucero rc = efx_devlink_info_board_cfg(efx, req); 456*14743dddSAlejandro Lucero if (rc) { 457*14743dddSAlejandro Lucero NL_SET_ERR_MSG_MOD(extack, "Getting board info failed"); 458*14743dddSAlejandro Lucero return rc; 459*14743dddSAlejandro Lucero } 460*14743dddSAlejandro Lucero rc = efx_devlink_info_stored_versions(efx, req); 461*14743dddSAlejandro Lucero if (rc) { 462*14743dddSAlejandro Lucero NL_SET_ERR_MSG_MOD(extack, "Getting stored versions failed"); 463*14743dddSAlejandro Lucero return rc; 464*14743dddSAlejandro Lucero } 465*14743dddSAlejandro Lucero rc = efx_devlink_info_running_versions(efx, req); 466*14743dddSAlejandro Lucero if (rc) { 467*14743dddSAlejandro Lucero NL_SET_ERR_MSG_MOD(extack, "Getting running versions failed"); 468*14743dddSAlejandro Lucero return rc; 469*14743dddSAlejandro Lucero } 470*14743dddSAlejandro Lucero 471*14743dddSAlejandro Lucero return 0; 472*14743dddSAlejandro Lucero } 473*14743dddSAlejandro Lucero 474fa34a514SAlejandro Lucero static const struct devlink_ops sfc_devlink_ops = { 475*14743dddSAlejandro Lucero .info_get = efx_devlink_info_get, 476fa34a514SAlejandro Lucero }; 477fa34a514SAlejandro Lucero 478fa34a514SAlejandro Lucero void efx_fini_devlink_lock(struct efx_nic *efx) 479fa34a514SAlejandro Lucero { 480fa34a514SAlejandro Lucero if (efx->devlink) 481fa34a514SAlejandro Lucero devl_lock(efx->devlink); 482fa34a514SAlejandro Lucero } 483fa34a514SAlejandro Lucero 484fa34a514SAlejandro Lucero void efx_fini_devlink_and_unlock(struct efx_nic *efx) 485fa34a514SAlejandro Lucero { 486fa34a514SAlejandro Lucero if (efx->devlink) { 487fa34a514SAlejandro Lucero devl_unregister(efx->devlink); 488fa34a514SAlejandro Lucero devl_unlock(efx->devlink); 489fa34a514SAlejandro Lucero devlink_free(efx->devlink); 490fa34a514SAlejandro Lucero efx->devlink = NULL; 491fa34a514SAlejandro Lucero } 492fa34a514SAlejandro Lucero } 493fa34a514SAlejandro Lucero 494fa34a514SAlejandro Lucero int efx_probe_devlink_and_lock(struct efx_nic *efx) 495fa34a514SAlejandro Lucero { 496fa34a514SAlejandro Lucero struct efx_devlink *devlink_private; 497fa34a514SAlejandro Lucero 498fa34a514SAlejandro Lucero if (efx->type->is_vf) 499fa34a514SAlejandro Lucero return 0; 500fa34a514SAlejandro Lucero 501fa34a514SAlejandro Lucero efx->devlink = devlink_alloc(&sfc_devlink_ops, 502fa34a514SAlejandro Lucero sizeof(struct efx_devlink), 503fa34a514SAlejandro Lucero &efx->pci_dev->dev); 504fa34a514SAlejandro Lucero if (!efx->devlink) 505fa34a514SAlejandro Lucero return -ENOMEM; 506fa34a514SAlejandro Lucero 507fa34a514SAlejandro Lucero devl_lock(efx->devlink); 508fa34a514SAlejandro Lucero devlink_private = devlink_priv(efx->devlink); 509fa34a514SAlejandro Lucero devlink_private->efx = efx; 510fa34a514SAlejandro Lucero 511fa34a514SAlejandro Lucero devl_register(efx->devlink); 512fa34a514SAlejandro Lucero 513fa34a514SAlejandro Lucero return 0; 514fa34a514SAlejandro Lucero } 515fa34a514SAlejandro Lucero 516fa34a514SAlejandro Lucero void efx_probe_devlink_unlock(struct efx_nic *efx) 517fa34a514SAlejandro Lucero { 518fa34a514SAlejandro Lucero if (!efx->devlink) 519fa34a514SAlejandro Lucero return; 520fa34a514SAlejandro Lucero 521fa34a514SAlejandro Lucero devl_unlock(efx->devlink); 522fa34a514SAlejandro Lucero } 523