1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2025, Intel Corporation. */ 3 4 #include "ixgbe.h" 5 #include "devlink.h" 6 7 struct ixgbe_info_ctx { 8 char buf[128]; 9 }; 10 11 static void ixgbe_info_get_dsn(struct ixgbe_adapter *adapter, 12 struct ixgbe_info_ctx *ctx) 13 { 14 u8 dsn[8]; 15 16 /* Copy the DSN into an array in Big Endian format */ 17 put_unaligned_be64(pci_get_dsn(adapter->pdev), dsn); 18 19 snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn); 20 } 21 22 static void ixgbe_info_nvm_ver(struct ixgbe_adapter *adapter, 23 struct ixgbe_info_ctx *ctx) 24 { 25 struct ixgbe_hw *hw = &adapter->hw; 26 struct ixgbe_nvm_version nvm_ver; 27 28 ctx->buf[0] = '\0'; 29 30 ixgbe_get_oem_prod_version(hw, &nvm_ver); 31 if (nvm_ver.oem_valid) { 32 snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x", 33 nvm_ver.oem_major, nvm_ver.oem_minor, 34 nvm_ver.oem_release); 35 36 return; 37 } 38 39 ixgbe_get_orom_version(hw, &nvm_ver); 40 if (nvm_ver.or_valid) 41 snprintf(ctx->buf, sizeof(ctx->buf), "%d.%d.%d", 42 nvm_ver.or_major, nvm_ver.or_build, nvm_ver.or_patch); 43 } 44 45 static void ixgbe_info_eetrack(struct ixgbe_adapter *adapter, 46 struct ixgbe_info_ctx *ctx) 47 { 48 struct ixgbe_hw *hw = &adapter->hw; 49 struct ixgbe_nvm_version nvm_ver; 50 51 ixgbe_get_oem_prod_version(hw, &nvm_ver); 52 53 /* No ETRACK version for OEM */ 54 if (nvm_ver.oem_valid) { 55 ctx->buf[0] = '\0'; 56 return; 57 } 58 59 ixgbe_get_etk_id(hw, &nvm_ver); 60 snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm_ver.etk_id); 61 } 62 63 static int ixgbe_devlink_info_get(struct devlink *devlink, 64 struct devlink_info_req *req, 65 struct netlink_ext_ack *extack) 66 { 67 struct ixgbe_adapter *adapter = devlink_priv(devlink); 68 struct ixgbe_hw *hw = &adapter->hw; 69 struct ixgbe_info_ctx *ctx; 70 int err; 71 72 ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); 73 if (!ctx) 74 return -ENOMEM; 75 76 ixgbe_info_get_dsn(adapter, ctx); 77 err = devlink_info_serial_number_put(req, ctx->buf); 78 if (err) 79 goto free_ctx; 80 81 err = ixgbe_read_pba_string_generic(hw, ctx->buf, sizeof(ctx->buf)); 82 if (err) 83 goto free_ctx; 84 85 err = devlink_info_version_fixed_put(req, 86 DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, 87 ctx->buf); 88 if (err) 89 goto free_ctx; 90 91 ixgbe_info_nvm_ver(adapter, ctx); 92 err = devlink_info_version_running_put(req, 93 DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, 94 ctx->buf); 95 if (err) 96 goto free_ctx; 97 98 ixgbe_info_eetrack(adapter, ctx); 99 err = devlink_info_version_running_put(req, 100 DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, 101 ctx->buf); 102 free_ctx: 103 kfree(ctx); 104 return err; 105 } 106 107 static const struct devlink_ops ixgbe_devlink_ops = { 108 .info_get = ixgbe_devlink_info_get, 109 }; 110 111 /** 112 * ixgbe_allocate_devlink - Allocate devlink instance 113 * @dev: device to allocate devlink for 114 * 115 * Allocate a devlink instance for this physical function. 116 * 117 * Return: pointer to the device adapter structure on success, 118 * ERR_PTR(-ENOMEM) when allocation failed. 119 */ 120 struct ixgbe_adapter *ixgbe_allocate_devlink(struct device *dev) 121 { 122 struct ixgbe_adapter *adapter; 123 struct devlink *devlink; 124 125 devlink = devlink_alloc(&ixgbe_devlink_ops, sizeof(*adapter), dev); 126 if (!devlink) 127 return ERR_PTR(-ENOMEM); 128 129 adapter = devlink_priv(devlink); 130 adapter->devlink = devlink; 131 132 return adapter; 133 } 134 135 /** 136 * ixgbe_devlink_set_switch_id - Set unique switch ID based on PCI DSN 137 * @adapter: pointer to the device adapter structure 138 * @ppid: struct with switch id information 139 */ 140 static void ixgbe_devlink_set_switch_id(struct ixgbe_adapter *adapter, 141 struct netdev_phys_item_id *ppid) 142 { 143 u64 id = pci_get_dsn(adapter->pdev); 144 145 ppid->id_len = sizeof(id); 146 put_unaligned_be64(id, &ppid->id); 147 } 148 149 /** 150 * ixgbe_devlink_register_port - Register devlink port 151 * @adapter: pointer to the device adapter structure 152 * 153 * Create and register a devlink_port for this physical function. 154 * 155 * Return: 0 on success, error code on failure. 156 */ 157 int ixgbe_devlink_register_port(struct ixgbe_adapter *adapter) 158 { 159 struct devlink_port *devlink_port = &adapter->devlink_port; 160 struct devlink *devlink = adapter->devlink; 161 struct device *dev = &adapter->pdev->dev; 162 struct devlink_port_attrs attrs = {}; 163 int err; 164 165 attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; 166 attrs.phys.port_number = adapter->hw.bus.func; 167 ixgbe_devlink_set_switch_id(adapter, &attrs.switch_id); 168 169 devlink_port_attrs_set(devlink_port, &attrs); 170 171 err = devl_port_register(devlink, devlink_port, 0); 172 if (err) { 173 dev_err(dev, 174 "devlink port registration failed, err %d\n", err); 175 } 176 177 return err; 178 } 179