1a0285236SJedrzej Jagielski // SPDX-License-Identifier: GPL-2.0 2a0285236SJedrzej Jagielski /* Copyright (c) 2025, Intel Corporation. */ 3a0285236SJedrzej Jagielski 4a0285236SJedrzej Jagielski #include "ixgbe.h" 5a0285236SJedrzej Jagielski #include "devlink.h" 6a0285236SJedrzej Jagielski 7f6b588afSJedrzej Jagielski struct ixgbe_info_ctx { 8f6b588afSJedrzej Jagielski char buf[128]; 9f6b588afSJedrzej Jagielski }; 10f6b588afSJedrzej Jagielski 11f6b588afSJedrzej Jagielski static void ixgbe_info_get_dsn(struct ixgbe_adapter *adapter, 12f6b588afSJedrzej Jagielski struct ixgbe_info_ctx *ctx) 13f6b588afSJedrzej Jagielski { 14f6b588afSJedrzej Jagielski u8 dsn[8]; 15f6b588afSJedrzej Jagielski 16f6b588afSJedrzej Jagielski /* Copy the DSN into an array in Big Endian format */ 17f6b588afSJedrzej Jagielski put_unaligned_be64(pci_get_dsn(adapter->pdev), dsn); 18f6b588afSJedrzej Jagielski 19f6b588afSJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn); 20f6b588afSJedrzej Jagielski } 21f6b588afSJedrzej Jagielski 228210ff73SJedrzej Jagielski static void ixgbe_info_orom_ver(struct ixgbe_adapter *adapter, 23f6b588afSJedrzej Jagielski struct ixgbe_info_ctx *ctx) 24f6b588afSJedrzej Jagielski { 25f6b588afSJedrzej Jagielski struct ixgbe_hw *hw = &adapter->hw; 26f6b588afSJedrzej Jagielski struct ixgbe_nvm_version nvm_ver; 27f6b588afSJedrzej Jagielski 28f6b588afSJedrzej Jagielski ctx->buf[0] = '\0'; 29f6b588afSJedrzej Jagielski 308210ff73SJedrzej Jagielski if (hw->mac.type == ixgbe_mac_e610) { 318210ff73SJedrzej Jagielski struct ixgbe_orom_info *orom = &adapter->hw.flash.orom; 328210ff73SJedrzej Jagielski 338210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 348210ff73SJedrzej Jagielski orom->major, orom->build, orom->patch); 358210ff73SJedrzej Jagielski return; 368210ff73SJedrzej Jagielski } 378210ff73SJedrzej Jagielski 38f6b588afSJedrzej Jagielski ixgbe_get_oem_prod_version(hw, &nvm_ver); 39f6b588afSJedrzej Jagielski if (nvm_ver.oem_valid) { 40f6b588afSJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x", 41f6b588afSJedrzej Jagielski nvm_ver.oem_major, nvm_ver.oem_minor, 42f6b588afSJedrzej Jagielski nvm_ver.oem_release); 43f6b588afSJedrzej Jagielski 44f6b588afSJedrzej Jagielski return; 45f6b588afSJedrzej Jagielski } 46f6b588afSJedrzej Jagielski 47f6b588afSJedrzej Jagielski ixgbe_get_orom_version(hw, &nvm_ver); 48f6b588afSJedrzej Jagielski if (nvm_ver.or_valid) 49f6b588afSJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%d.%d.%d", 50f6b588afSJedrzej Jagielski nvm_ver.or_major, nvm_ver.or_build, nvm_ver.or_patch); 51f6b588afSJedrzej Jagielski } 52f6b588afSJedrzej Jagielski 53f6b588afSJedrzej Jagielski static void ixgbe_info_eetrack(struct ixgbe_adapter *adapter, 54f6b588afSJedrzej Jagielski struct ixgbe_info_ctx *ctx) 55f6b588afSJedrzej Jagielski { 56f6b588afSJedrzej Jagielski struct ixgbe_hw *hw = &adapter->hw; 57f6b588afSJedrzej Jagielski struct ixgbe_nvm_version nvm_ver; 58f6b588afSJedrzej Jagielski 598210ff73SJedrzej Jagielski if (hw->mac.type == ixgbe_mac_e610) { 608210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", 618210ff73SJedrzej Jagielski hw->flash.nvm.eetrack); 628210ff73SJedrzej Jagielski return; 638210ff73SJedrzej Jagielski } 648210ff73SJedrzej Jagielski 65f6b588afSJedrzej Jagielski ixgbe_get_oem_prod_version(hw, &nvm_ver); 66f6b588afSJedrzej Jagielski 67f6b588afSJedrzej Jagielski /* No ETRACK version for OEM */ 68f6b588afSJedrzej Jagielski if (nvm_ver.oem_valid) { 69f6b588afSJedrzej Jagielski ctx->buf[0] = '\0'; 70f6b588afSJedrzej Jagielski return; 71f6b588afSJedrzej Jagielski } 72f6b588afSJedrzej Jagielski 73f6b588afSJedrzej Jagielski ixgbe_get_etk_id(hw, &nvm_ver); 74f6b588afSJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm_ver.etk_id); 75f6b588afSJedrzej Jagielski } 76f6b588afSJedrzej Jagielski 778210ff73SJedrzej Jagielski static void ixgbe_info_fw_api(struct ixgbe_adapter *adapter, 788210ff73SJedrzej Jagielski struct ixgbe_info_ctx *ctx) 798210ff73SJedrzej Jagielski { 808210ff73SJedrzej Jagielski struct ixgbe_hw *hw = &adapter->hw; 818210ff73SJedrzej Jagielski 828210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 838210ff73SJedrzej Jagielski hw->api_maj_ver, hw->api_min_ver, hw->api_patch); 848210ff73SJedrzej Jagielski } 858210ff73SJedrzej Jagielski 868210ff73SJedrzej Jagielski static void ixgbe_info_fw_build(struct ixgbe_adapter *adapter, 878210ff73SJedrzej Jagielski struct ixgbe_info_ctx *ctx) 888210ff73SJedrzej Jagielski { 898210ff73SJedrzej Jagielski struct ixgbe_hw *hw = &adapter->hw; 908210ff73SJedrzej Jagielski 918210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build); 928210ff73SJedrzej Jagielski } 938210ff73SJedrzej Jagielski 948210ff73SJedrzej Jagielski static void ixgbe_info_fw_srev(struct ixgbe_adapter *adapter, 958210ff73SJedrzej Jagielski struct ixgbe_info_ctx *ctx) 968210ff73SJedrzej Jagielski { 978210ff73SJedrzej Jagielski struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm; 988210ff73SJedrzej Jagielski 998210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%u", nvm->srev); 1008210ff73SJedrzej Jagielski } 1018210ff73SJedrzej Jagielski 1028210ff73SJedrzej Jagielski static void ixgbe_info_orom_srev(struct ixgbe_adapter *adapter, 1038210ff73SJedrzej Jagielski struct ixgbe_info_ctx *ctx) 1048210ff73SJedrzej Jagielski { 1058210ff73SJedrzej Jagielski struct ixgbe_orom_info *orom = &adapter->hw.flash.orom; 1068210ff73SJedrzej Jagielski 1078210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%u", orom->srev); 1088210ff73SJedrzej Jagielski } 1098210ff73SJedrzej Jagielski 1108210ff73SJedrzej Jagielski static void ixgbe_info_nvm_ver(struct ixgbe_adapter *adapter, 1118210ff73SJedrzej Jagielski struct ixgbe_info_ctx *ctx) 1128210ff73SJedrzej Jagielski { 1138210ff73SJedrzej Jagielski struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm; 1148210ff73SJedrzej Jagielski 1158210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor); 1168210ff73SJedrzej Jagielski } 1178210ff73SJedrzej Jagielski 1188210ff73SJedrzej Jagielski static void ixgbe_info_netlist_ver(struct ixgbe_adapter *adapter, 1198210ff73SJedrzej Jagielski struct ixgbe_info_ctx *ctx) 1208210ff73SJedrzej Jagielski { 1218210ff73SJedrzej Jagielski struct ixgbe_netlist_info *netlist = &adapter->hw.flash.netlist; 1228210ff73SJedrzej Jagielski 1238210ff73SJedrzej Jagielski /* The netlist version fields are BCD formatted */ 1248210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x", 1258210ff73SJedrzej Jagielski netlist->major, netlist->minor, 1268210ff73SJedrzej Jagielski netlist->type >> 16, netlist->type & 0xFFFF, 1278210ff73SJedrzej Jagielski netlist->rev, netlist->cust_ver); 1288210ff73SJedrzej Jagielski } 1298210ff73SJedrzej Jagielski 1308210ff73SJedrzej Jagielski static void ixgbe_info_netlist_build(struct ixgbe_adapter *adapter, 1318210ff73SJedrzej Jagielski struct ixgbe_info_ctx *ctx) 1328210ff73SJedrzej Jagielski { 1338210ff73SJedrzej Jagielski struct ixgbe_netlist_info *netlist = &adapter->hw.flash.netlist; 1348210ff73SJedrzej Jagielski 1358210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash); 1368210ff73SJedrzej Jagielski } 1378210ff73SJedrzej Jagielski 1388210ff73SJedrzej Jagielski static int ixgbe_devlink_info_get_e610(struct ixgbe_adapter *adapter, 1398210ff73SJedrzej Jagielski struct devlink_info_req *req, 1408210ff73SJedrzej Jagielski struct ixgbe_info_ctx *ctx) 1418210ff73SJedrzej Jagielski { 1428210ff73SJedrzej Jagielski int err; 1438210ff73SJedrzej Jagielski 1448210ff73SJedrzej Jagielski ixgbe_info_fw_api(adapter, ctx); 1458210ff73SJedrzej Jagielski err = devlink_info_version_running_put(req, 1468210ff73SJedrzej Jagielski DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API, 1478210ff73SJedrzej Jagielski ctx->buf); 1488210ff73SJedrzej Jagielski if (err) 1498210ff73SJedrzej Jagielski return err; 1508210ff73SJedrzej Jagielski 1518210ff73SJedrzej Jagielski ixgbe_info_fw_build(adapter, ctx); 1528210ff73SJedrzej Jagielski err = devlink_info_version_running_put(req, "fw.mgmt.build", ctx->buf); 1538210ff73SJedrzej Jagielski if (err) 1548210ff73SJedrzej Jagielski return err; 1558210ff73SJedrzej Jagielski 1568210ff73SJedrzej Jagielski ixgbe_info_fw_srev(adapter, ctx); 1578210ff73SJedrzej Jagielski err = devlink_info_version_running_put(req, "fw.mgmt.srev", ctx->buf); 1588210ff73SJedrzej Jagielski if (err) 1598210ff73SJedrzej Jagielski return err; 1608210ff73SJedrzej Jagielski 1618210ff73SJedrzej Jagielski ixgbe_info_orom_srev(adapter, ctx); 1628210ff73SJedrzej Jagielski err = devlink_info_version_running_put(req, "fw.undi.srev", ctx->buf); 1638210ff73SJedrzej Jagielski if (err) 1648210ff73SJedrzej Jagielski return err; 1658210ff73SJedrzej Jagielski 1668210ff73SJedrzej Jagielski ixgbe_info_nvm_ver(adapter, ctx); 1678210ff73SJedrzej Jagielski err = devlink_info_version_running_put(req, "fw.psid.api", ctx->buf); 1688210ff73SJedrzej Jagielski if (err) 1698210ff73SJedrzej Jagielski return err; 1708210ff73SJedrzej Jagielski 1718210ff73SJedrzej Jagielski ixgbe_info_netlist_ver(adapter, ctx); 1728210ff73SJedrzej Jagielski err = devlink_info_version_running_put(req, "fw.netlist", ctx->buf); 1738210ff73SJedrzej Jagielski if (err) 1748210ff73SJedrzej Jagielski return err; 1758210ff73SJedrzej Jagielski 1768210ff73SJedrzej Jagielski ixgbe_info_netlist_build(adapter, ctx); 1778210ff73SJedrzej Jagielski return devlink_info_version_running_put(req, "fw.netlist.build", 1788210ff73SJedrzej Jagielski ctx->buf); 1798210ff73SJedrzej Jagielski } 1808210ff73SJedrzej Jagielski 181f6b588afSJedrzej Jagielski static int ixgbe_devlink_info_get(struct devlink *devlink, 182f6b588afSJedrzej Jagielski struct devlink_info_req *req, 183f6b588afSJedrzej Jagielski struct netlink_ext_ack *extack) 184f6b588afSJedrzej Jagielski { 185f6b588afSJedrzej Jagielski struct ixgbe_adapter *adapter = devlink_priv(devlink); 186f6b588afSJedrzej Jagielski struct ixgbe_hw *hw = &adapter->hw; 187f6b588afSJedrzej Jagielski struct ixgbe_info_ctx *ctx; 188f6b588afSJedrzej Jagielski int err; 189f6b588afSJedrzej Jagielski 190f6b588afSJedrzej Jagielski ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); 191f6b588afSJedrzej Jagielski if (!ctx) 192f6b588afSJedrzej Jagielski return -ENOMEM; 193f6b588afSJedrzej Jagielski 194f6b588afSJedrzej Jagielski ixgbe_info_get_dsn(adapter, ctx); 195f6b588afSJedrzej Jagielski err = devlink_info_serial_number_put(req, ctx->buf); 196f6b588afSJedrzej Jagielski if (err) 197f6b588afSJedrzej Jagielski goto free_ctx; 198f6b588afSJedrzej Jagielski 199*4654ec61SJedrzej Jagielski err = hw->eeprom.ops.read_pba_string(hw, ctx->buf, sizeof(ctx->buf)); 200f6b588afSJedrzej Jagielski if (err) 201f6b588afSJedrzej Jagielski goto free_ctx; 202f6b588afSJedrzej Jagielski 203f6b588afSJedrzej Jagielski err = devlink_info_version_fixed_put(req, 204f6b588afSJedrzej Jagielski DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, 205f6b588afSJedrzej Jagielski ctx->buf); 206f6b588afSJedrzej Jagielski if (err) 207f6b588afSJedrzej Jagielski goto free_ctx; 208f6b588afSJedrzej Jagielski 2098210ff73SJedrzej Jagielski ixgbe_info_orom_ver(adapter, ctx); 210f6b588afSJedrzej Jagielski err = devlink_info_version_running_put(req, 211f6b588afSJedrzej Jagielski DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, 212f6b588afSJedrzej Jagielski ctx->buf); 213f6b588afSJedrzej Jagielski if (err) 214f6b588afSJedrzej Jagielski goto free_ctx; 215f6b588afSJedrzej Jagielski 216f6b588afSJedrzej Jagielski ixgbe_info_eetrack(adapter, ctx); 217f6b588afSJedrzej Jagielski err = devlink_info_version_running_put(req, 218f6b588afSJedrzej Jagielski DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, 219f6b588afSJedrzej Jagielski ctx->buf); 2208210ff73SJedrzej Jagielski if (err || hw->mac.type != ixgbe_mac_e610) 2218210ff73SJedrzej Jagielski goto free_ctx; 2228210ff73SJedrzej Jagielski 2238210ff73SJedrzej Jagielski err = ixgbe_devlink_info_get_e610(adapter, req, ctx); 224f6b588afSJedrzej Jagielski free_ctx: 225f6b588afSJedrzej Jagielski kfree(ctx); 226f6b588afSJedrzej Jagielski return err; 227f6b588afSJedrzej Jagielski } 228f6b588afSJedrzej Jagielski 229a0285236SJedrzej Jagielski static const struct devlink_ops ixgbe_devlink_ops = { 230f6b588afSJedrzej Jagielski .info_get = ixgbe_devlink_info_get, 231a0285236SJedrzej Jagielski }; 232a0285236SJedrzej Jagielski 233a0285236SJedrzej Jagielski /** 234a0285236SJedrzej Jagielski * ixgbe_allocate_devlink - Allocate devlink instance 235a0285236SJedrzej Jagielski * @dev: device to allocate devlink for 236a0285236SJedrzej Jagielski * 237a0285236SJedrzej Jagielski * Allocate a devlink instance for this physical function. 238a0285236SJedrzej Jagielski * 239a0285236SJedrzej Jagielski * Return: pointer to the device adapter structure on success, 240a0285236SJedrzej Jagielski * ERR_PTR(-ENOMEM) when allocation failed. 241a0285236SJedrzej Jagielski */ 242a0285236SJedrzej Jagielski struct ixgbe_adapter *ixgbe_allocate_devlink(struct device *dev) 243a0285236SJedrzej Jagielski { 244a0285236SJedrzej Jagielski struct ixgbe_adapter *adapter; 245a0285236SJedrzej Jagielski struct devlink *devlink; 246a0285236SJedrzej Jagielski 247a0285236SJedrzej Jagielski devlink = devlink_alloc(&ixgbe_devlink_ops, sizeof(*adapter), dev); 248a0285236SJedrzej Jagielski if (!devlink) 249a0285236SJedrzej Jagielski return ERR_PTR(-ENOMEM); 250a0285236SJedrzej Jagielski 251a0285236SJedrzej Jagielski adapter = devlink_priv(devlink); 252a0285236SJedrzej Jagielski adapter->devlink = devlink; 253a0285236SJedrzej Jagielski 254a0285236SJedrzej Jagielski return adapter; 255a0285236SJedrzej Jagielski } 256a0285236SJedrzej Jagielski 257a0285236SJedrzej Jagielski /** 258a0285236SJedrzej Jagielski * ixgbe_devlink_set_switch_id - Set unique switch ID based on PCI DSN 259a0285236SJedrzej Jagielski * @adapter: pointer to the device adapter structure 260a0285236SJedrzej Jagielski * @ppid: struct with switch id information 261a0285236SJedrzej Jagielski */ 262a0285236SJedrzej Jagielski static void ixgbe_devlink_set_switch_id(struct ixgbe_adapter *adapter, 263a0285236SJedrzej Jagielski struct netdev_phys_item_id *ppid) 264a0285236SJedrzej Jagielski { 265a0285236SJedrzej Jagielski u64 id = pci_get_dsn(adapter->pdev); 266a0285236SJedrzej Jagielski 267a0285236SJedrzej Jagielski ppid->id_len = sizeof(id); 268a0285236SJedrzej Jagielski put_unaligned_be64(id, &ppid->id); 269a0285236SJedrzej Jagielski } 270a0285236SJedrzej Jagielski 271a0285236SJedrzej Jagielski /** 272a0285236SJedrzej Jagielski * ixgbe_devlink_register_port - Register devlink port 273a0285236SJedrzej Jagielski * @adapter: pointer to the device adapter structure 274a0285236SJedrzej Jagielski * 275a0285236SJedrzej Jagielski * Create and register a devlink_port for this physical function. 276a0285236SJedrzej Jagielski * 277a0285236SJedrzej Jagielski * Return: 0 on success, error code on failure. 278a0285236SJedrzej Jagielski */ 279a0285236SJedrzej Jagielski int ixgbe_devlink_register_port(struct ixgbe_adapter *adapter) 280a0285236SJedrzej Jagielski { 281a0285236SJedrzej Jagielski struct devlink_port *devlink_port = &adapter->devlink_port; 282a0285236SJedrzej Jagielski struct devlink *devlink = adapter->devlink; 283a0285236SJedrzej Jagielski struct device *dev = &adapter->pdev->dev; 284a0285236SJedrzej Jagielski struct devlink_port_attrs attrs = {}; 285a0285236SJedrzej Jagielski int err; 286a0285236SJedrzej Jagielski 287a0285236SJedrzej Jagielski attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; 288a0285236SJedrzej Jagielski attrs.phys.port_number = adapter->hw.bus.func; 289a0285236SJedrzej Jagielski ixgbe_devlink_set_switch_id(adapter, &attrs.switch_id); 290a0285236SJedrzej Jagielski 291a0285236SJedrzej Jagielski devlink_port_attrs_set(devlink_port, &attrs); 292a0285236SJedrzej Jagielski 293a0285236SJedrzej Jagielski err = devl_port_register(devlink, devlink_port, 0); 294a0285236SJedrzej Jagielski if (err) { 295a0285236SJedrzej Jagielski dev_err(dev, 296a0285236SJedrzej Jagielski "devlink port registration failed, err %d\n", err); 297a0285236SJedrzej Jagielski } 298a0285236SJedrzej Jagielski 299a0285236SJedrzej Jagielski return err; 300a0285236SJedrzej Jagielski } 301