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 22*8210ff73SJedrzej 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 30*8210ff73SJedrzej Jagielski if (hw->mac.type == ixgbe_mac_e610) { 31*8210ff73SJedrzej Jagielski struct ixgbe_orom_info *orom = &adapter->hw.flash.orom; 32*8210ff73SJedrzej Jagielski 33*8210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 34*8210ff73SJedrzej Jagielski orom->major, orom->build, orom->patch); 35*8210ff73SJedrzej Jagielski return; 36*8210ff73SJedrzej Jagielski } 37*8210ff73SJedrzej 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 59*8210ff73SJedrzej Jagielski if (hw->mac.type == ixgbe_mac_e610) { 60*8210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", 61*8210ff73SJedrzej Jagielski hw->flash.nvm.eetrack); 62*8210ff73SJedrzej Jagielski return; 63*8210ff73SJedrzej Jagielski } 64*8210ff73SJedrzej 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 77*8210ff73SJedrzej Jagielski static void ixgbe_info_fw_api(struct ixgbe_adapter *adapter, 78*8210ff73SJedrzej Jagielski struct ixgbe_info_ctx *ctx) 79*8210ff73SJedrzej Jagielski { 80*8210ff73SJedrzej Jagielski struct ixgbe_hw *hw = &adapter->hw; 81*8210ff73SJedrzej Jagielski 82*8210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 83*8210ff73SJedrzej Jagielski hw->api_maj_ver, hw->api_min_ver, hw->api_patch); 84*8210ff73SJedrzej Jagielski } 85*8210ff73SJedrzej Jagielski 86*8210ff73SJedrzej Jagielski static void ixgbe_info_fw_build(struct ixgbe_adapter *adapter, 87*8210ff73SJedrzej Jagielski struct ixgbe_info_ctx *ctx) 88*8210ff73SJedrzej Jagielski { 89*8210ff73SJedrzej Jagielski struct ixgbe_hw *hw = &adapter->hw; 90*8210ff73SJedrzej Jagielski 91*8210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build); 92*8210ff73SJedrzej Jagielski } 93*8210ff73SJedrzej Jagielski 94*8210ff73SJedrzej Jagielski static void ixgbe_info_fw_srev(struct ixgbe_adapter *adapter, 95*8210ff73SJedrzej Jagielski struct ixgbe_info_ctx *ctx) 96*8210ff73SJedrzej Jagielski { 97*8210ff73SJedrzej Jagielski struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm; 98*8210ff73SJedrzej Jagielski 99*8210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%u", nvm->srev); 100*8210ff73SJedrzej Jagielski } 101*8210ff73SJedrzej Jagielski 102*8210ff73SJedrzej Jagielski static void ixgbe_info_orom_srev(struct ixgbe_adapter *adapter, 103*8210ff73SJedrzej Jagielski struct ixgbe_info_ctx *ctx) 104*8210ff73SJedrzej Jagielski { 105*8210ff73SJedrzej Jagielski struct ixgbe_orom_info *orom = &adapter->hw.flash.orom; 106*8210ff73SJedrzej Jagielski 107*8210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%u", orom->srev); 108*8210ff73SJedrzej Jagielski } 109*8210ff73SJedrzej Jagielski 110*8210ff73SJedrzej Jagielski static void ixgbe_info_nvm_ver(struct ixgbe_adapter *adapter, 111*8210ff73SJedrzej Jagielski struct ixgbe_info_ctx *ctx) 112*8210ff73SJedrzej Jagielski { 113*8210ff73SJedrzej Jagielski struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm; 114*8210ff73SJedrzej Jagielski 115*8210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor); 116*8210ff73SJedrzej Jagielski } 117*8210ff73SJedrzej Jagielski 118*8210ff73SJedrzej Jagielski static void ixgbe_info_netlist_ver(struct ixgbe_adapter *adapter, 119*8210ff73SJedrzej Jagielski struct ixgbe_info_ctx *ctx) 120*8210ff73SJedrzej Jagielski { 121*8210ff73SJedrzej Jagielski struct ixgbe_netlist_info *netlist = &adapter->hw.flash.netlist; 122*8210ff73SJedrzej Jagielski 123*8210ff73SJedrzej Jagielski /* The netlist version fields are BCD formatted */ 124*8210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x", 125*8210ff73SJedrzej Jagielski netlist->major, netlist->minor, 126*8210ff73SJedrzej Jagielski netlist->type >> 16, netlist->type & 0xFFFF, 127*8210ff73SJedrzej Jagielski netlist->rev, netlist->cust_ver); 128*8210ff73SJedrzej Jagielski } 129*8210ff73SJedrzej Jagielski 130*8210ff73SJedrzej Jagielski static void ixgbe_info_netlist_build(struct ixgbe_adapter *adapter, 131*8210ff73SJedrzej Jagielski struct ixgbe_info_ctx *ctx) 132*8210ff73SJedrzej Jagielski { 133*8210ff73SJedrzej Jagielski struct ixgbe_netlist_info *netlist = &adapter->hw.flash.netlist; 134*8210ff73SJedrzej Jagielski 135*8210ff73SJedrzej Jagielski snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash); 136*8210ff73SJedrzej Jagielski } 137*8210ff73SJedrzej Jagielski 138*8210ff73SJedrzej Jagielski static int ixgbe_devlink_info_get_e610(struct ixgbe_adapter *adapter, 139*8210ff73SJedrzej Jagielski struct devlink_info_req *req, 140*8210ff73SJedrzej Jagielski struct ixgbe_info_ctx *ctx) 141*8210ff73SJedrzej Jagielski { 142*8210ff73SJedrzej Jagielski int err; 143*8210ff73SJedrzej Jagielski 144*8210ff73SJedrzej Jagielski ixgbe_info_fw_api(adapter, ctx); 145*8210ff73SJedrzej Jagielski err = devlink_info_version_running_put(req, 146*8210ff73SJedrzej Jagielski DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API, 147*8210ff73SJedrzej Jagielski ctx->buf); 148*8210ff73SJedrzej Jagielski if (err) 149*8210ff73SJedrzej Jagielski return err; 150*8210ff73SJedrzej Jagielski 151*8210ff73SJedrzej Jagielski ixgbe_info_fw_build(adapter, ctx); 152*8210ff73SJedrzej Jagielski err = devlink_info_version_running_put(req, "fw.mgmt.build", ctx->buf); 153*8210ff73SJedrzej Jagielski if (err) 154*8210ff73SJedrzej Jagielski return err; 155*8210ff73SJedrzej Jagielski 156*8210ff73SJedrzej Jagielski ixgbe_info_fw_srev(adapter, ctx); 157*8210ff73SJedrzej Jagielski err = devlink_info_version_running_put(req, "fw.mgmt.srev", ctx->buf); 158*8210ff73SJedrzej Jagielski if (err) 159*8210ff73SJedrzej Jagielski return err; 160*8210ff73SJedrzej Jagielski 161*8210ff73SJedrzej Jagielski ixgbe_info_orom_srev(adapter, ctx); 162*8210ff73SJedrzej Jagielski err = devlink_info_version_running_put(req, "fw.undi.srev", ctx->buf); 163*8210ff73SJedrzej Jagielski if (err) 164*8210ff73SJedrzej Jagielski return err; 165*8210ff73SJedrzej Jagielski 166*8210ff73SJedrzej Jagielski ixgbe_info_nvm_ver(adapter, ctx); 167*8210ff73SJedrzej Jagielski err = devlink_info_version_running_put(req, "fw.psid.api", ctx->buf); 168*8210ff73SJedrzej Jagielski if (err) 169*8210ff73SJedrzej Jagielski return err; 170*8210ff73SJedrzej Jagielski 171*8210ff73SJedrzej Jagielski ixgbe_info_netlist_ver(adapter, ctx); 172*8210ff73SJedrzej Jagielski err = devlink_info_version_running_put(req, "fw.netlist", ctx->buf); 173*8210ff73SJedrzej Jagielski if (err) 174*8210ff73SJedrzej Jagielski return err; 175*8210ff73SJedrzej Jagielski 176*8210ff73SJedrzej Jagielski ixgbe_info_netlist_build(adapter, ctx); 177*8210ff73SJedrzej Jagielski return devlink_info_version_running_put(req, "fw.netlist.build", 178*8210ff73SJedrzej Jagielski ctx->buf); 179*8210ff73SJedrzej Jagielski } 180*8210ff73SJedrzej 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 199f6b588afSJedrzej Jagielski err = ixgbe_read_pba_string_generic(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 209*8210ff73SJedrzej 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); 220*8210ff73SJedrzej Jagielski if (err || hw->mac.type != ixgbe_mac_e610) 221*8210ff73SJedrzej Jagielski goto free_ctx; 222*8210ff73SJedrzej Jagielski 223*8210ff73SJedrzej 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