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 struct ixgbe_orom_info pending_orom; 10 struct ixgbe_nvm_info pending_nvm; 11 struct ixgbe_netlist_info pending_netlist; 12 struct ixgbe_hw_dev_caps dev_caps; 13 }; 14 15 enum ixgbe_devlink_version_type { 16 IXGBE_DL_VERSION_RUNNING, 17 IXGBE_DL_VERSION_STORED 18 }; 19 20 static void ixgbe_info_get_dsn(struct ixgbe_adapter *adapter, 21 struct ixgbe_info_ctx *ctx) 22 { 23 u8 dsn[8]; 24 25 /* Copy the DSN into an array in Big Endian format */ 26 put_unaligned_be64(pci_get_dsn(adapter->pdev), dsn); 27 28 snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn); 29 } 30 31 static void ixgbe_info_orom_ver(struct ixgbe_adapter *adapter, 32 struct ixgbe_info_ctx *ctx, 33 enum ixgbe_devlink_version_type type) 34 { 35 struct ixgbe_hw *hw = &adapter->hw; 36 struct ixgbe_nvm_version nvm_ver; 37 38 ctx->buf[0] = '\0'; 39 40 if (hw->mac.type == ixgbe_mac_e610) { 41 struct ixgbe_orom_info *orom = &adapter->hw.flash.orom; 42 43 if (type == IXGBE_DL_VERSION_STORED && 44 ctx->dev_caps.common_cap.nvm_update_pending_orom) 45 orom = &ctx->pending_orom; 46 47 snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 48 orom->major, orom->build, orom->patch); 49 return; 50 } 51 52 ixgbe_get_oem_prod_version(hw, &nvm_ver); 53 if (nvm_ver.oem_valid) { 54 snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x", 55 nvm_ver.oem_major, nvm_ver.oem_minor, 56 nvm_ver.oem_release); 57 58 return; 59 } 60 61 ixgbe_get_orom_version(hw, &nvm_ver); 62 if (nvm_ver.or_valid) 63 snprintf(ctx->buf, sizeof(ctx->buf), "%d.%d.%d", 64 nvm_ver.or_major, nvm_ver.or_build, nvm_ver.or_patch); 65 } 66 67 static void ixgbe_info_eetrack(struct ixgbe_adapter *adapter, 68 struct ixgbe_info_ctx *ctx, 69 enum ixgbe_devlink_version_type type) 70 { 71 struct ixgbe_hw *hw = &adapter->hw; 72 struct ixgbe_nvm_version nvm_ver; 73 74 if (hw->mac.type == ixgbe_mac_e610) { 75 u32 eetrack = hw->flash.nvm.eetrack; 76 77 if (type == IXGBE_DL_VERSION_STORED && 78 ctx->dev_caps.common_cap.nvm_update_pending_nvm) 79 eetrack = ctx->pending_nvm.eetrack; 80 81 snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", eetrack); 82 return; 83 } 84 85 ixgbe_get_oem_prod_version(hw, &nvm_ver); 86 87 /* No ETRACK version for OEM */ 88 if (nvm_ver.oem_valid) { 89 ctx->buf[0] = '\0'; 90 return; 91 } 92 93 ixgbe_get_etk_id(hw, &nvm_ver); 94 snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm_ver.etk_id); 95 } 96 97 static void ixgbe_info_fw_api(struct ixgbe_adapter *adapter, 98 struct ixgbe_info_ctx *ctx) 99 { 100 struct ixgbe_hw *hw = &adapter->hw; 101 102 snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", 103 hw->api_maj_ver, hw->api_min_ver, hw->api_patch); 104 } 105 106 static void ixgbe_info_fw_build(struct ixgbe_adapter *adapter, 107 struct ixgbe_info_ctx *ctx) 108 { 109 struct ixgbe_hw *hw = &adapter->hw; 110 111 snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build); 112 } 113 114 static void ixgbe_info_fw_srev(struct ixgbe_adapter *adapter, 115 struct ixgbe_info_ctx *ctx, 116 enum ixgbe_devlink_version_type type) 117 { 118 struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm; 119 120 if (type == IXGBE_DL_VERSION_STORED && 121 ctx->dev_caps.common_cap.nvm_update_pending_nvm) 122 nvm = &ctx->pending_nvm; 123 124 snprintf(ctx->buf, sizeof(ctx->buf), "%u", nvm->srev); 125 } 126 127 static void ixgbe_info_orom_srev(struct ixgbe_adapter *adapter, 128 struct ixgbe_info_ctx *ctx, 129 enum ixgbe_devlink_version_type type) 130 { 131 struct ixgbe_orom_info *orom = &adapter->hw.flash.orom; 132 133 if (type == IXGBE_DL_VERSION_STORED && 134 ctx->dev_caps.common_cap.nvm_update_pending_orom) 135 orom = &ctx->pending_orom; 136 137 snprintf(ctx->buf, sizeof(ctx->buf), "%u", orom->srev); 138 } 139 140 static void ixgbe_info_nvm_ver(struct ixgbe_adapter *adapter, 141 struct ixgbe_info_ctx *ctx, 142 enum ixgbe_devlink_version_type type) 143 { 144 struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm; 145 146 if (type == IXGBE_DL_VERSION_STORED && 147 ctx->dev_caps.common_cap.nvm_update_pending_nvm) 148 nvm = &ctx->pending_nvm; 149 150 snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor); 151 } 152 153 static void ixgbe_info_netlist_ver(struct ixgbe_adapter *adapter, 154 struct ixgbe_info_ctx *ctx, 155 enum ixgbe_devlink_version_type type) 156 { 157 struct ixgbe_netlist_info *netlist = &adapter->hw.flash.netlist; 158 159 if (type == IXGBE_DL_VERSION_STORED && 160 ctx->dev_caps.common_cap.nvm_update_pending_netlist) 161 netlist = &ctx->pending_netlist; 162 163 /* The netlist version fields are BCD formatted */ 164 snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x", 165 netlist->major, netlist->minor, 166 netlist->type >> 16, netlist->type & 0xFFFF, 167 netlist->rev, netlist->cust_ver); 168 } 169 170 static void ixgbe_info_netlist_build(struct ixgbe_adapter *adapter, 171 struct ixgbe_info_ctx *ctx, 172 enum ixgbe_devlink_version_type type) 173 { 174 struct ixgbe_netlist_info *netlist = &adapter->hw.flash.netlist; 175 176 if (type == IXGBE_DL_VERSION_STORED && 177 ctx->dev_caps.common_cap.nvm_update_pending_netlist) 178 netlist = &ctx->pending_netlist; 179 180 snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash); 181 } 182 183 static int ixgbe_set_ctx_dev_caps(struct ixgbe_hw *hw, 184 struct ixgbe_info_ctx *ctx, 185 struct netlink_ext_ack *extack) 186 { 187 bool *pending_orom, *pending_nvm, *pending_netlist; 188 int err; 189 190 err = ixgbe_discover_dev_caps(hw, &ctx->dev_caps); 191 if (err) { 192 NL_SET_ERR_MSG_MOD(extack, 193 "Unable to discover device capabilities"); 194 return err; 195 } 196 197 pending_orom = &ctx->dev_caps.common_cap.nvm_update_pending_orom; 198 pending_nvm = &ctx->dev_caps.common_cap.nvm_update_pending_nvm; 199 pending_netlist = &ctx->dev_caps.common_cap.nvm_update_pending_netlist; 200 201 if (*pending_orom) { 202 err = ixgbe_get_inactive_orom_ver(hw, &ctx->pending_orom); 203 if (err) 204 *pending_orom = false; 205 } 206 207 if (*pending_nvm) { 208 err = ixgbe_get_inactive_nvm_ver(hw, &ctx->pending_nvm); 209 if (err) 210 *pending_nvm = false; 211 } 212 213 if (*pending_netlist) { 214 err = ixgbe_get_inactive_netlist_ver(hw, &ctx->pending_netlist); 215 if (err) 216 *pending_netlist = false; 217 } 218 219 return 0; 220 } 221 222 static int ixgbe_devlink_info_get_e610(struct ixgbe_adapter *adapter, 223 struct devlink_info_req *req, 224 struct ixgbe_info_ctx *ctx) 225 { 226 int err; 227 228 ixgbe_info_fw_api(adapter, ctx); 229 err = devlink_info_version_running_put(req, 230 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API, 231 ctx->buf); 232 if (err) 233 return err; 234 235 ixgbe_info_fw_build(adapter, ctx); 236 err = devlink_info_version_running_put(req, "fw.mgmt.build", ctx->buf); 237 if (err) 238 return err; 239 240 ixgbe_info_fw_srev(adapter, ctx, IXGBE_DL_VERSION_RUNNING); 241 err = devlink_info_version_running_put(req, "fw.mgmt.srev", ctx->buf); 242 if (err) 243 return err; 244 245 ixgbe_info_orom_srev(adapter, ctx, IXGBE_DL_VERSION_RUNNING); 246 err = devlink_info_version_running_put(req, "fw.undi.srev", ctx->buf); 247 if (err) 248 return err; 249 250 ixgbe_info_nvm_ver(adapter, ctx, IXGBE_DL_VERSION_RUNNING); 251 err = devlink_info_version_running_put(req, "fw.psid.api", ctx->buf); 252 if (err) 253 return err; 254 255 ixgbe_info_netlist_ver(adapter, ctx, IXGBE_DL_VERSION_RUNNING); 256 err = devlink_info_version_running_put(req, "fw.netlist", ctx->buf); 257 if (err) 258 return err; 259 260 ixgbe_info_netlist_build(adapter, ctx, IXGBE_DL_VERSION_RUNNING); 261 return devlink_info_version_running_put(req, "fw.netlist.build", 262 ctx->buf); 263 } 264 265 static int 266 ixgbe_devlink_pending_info_get_e610(struct ixgbe_adapter *adapter, 267 struct devlink_info_req *req, 268 struct ixgbe_info_ctx *ctx) 269 { 270 int err; 271 272 ixgbe_info_orom_ver(adapter, ctx, IXGBE_DL_VERSION_STORED); 273 err = devlink_info_version_stored_put(req, 274 DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, 275 ctx->buf); 276 if (err) 277 return err; 278 279 ixgbe_info_eetrack(adapter, ctx, IXGBE_DL_VERSION_STORED); 280 err = devlink_info_version_stored_put(req, 281 DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, 282 ctx->buf); 283 if (err) 284 return err; 285 286 ixgbe_info_fw_srev(adapter, ctx, IXGBE_DL_VERSION_STORED); 287 err = devlink_info_version_stored_put(req, "fw.mgmt.srev", ctx->buf); 288 if (err) 289 return err; 290 291 ixgbe_info_orom_srev(adapter, ctx, IXGBE_DL_VERSION_STORED); 292 err = devlink_info_version_stored_put(req, "fw.undi.srev", ctx->buf); 293 if (err) 294 return err; 295 296 ixgbe_info_nvm_ver(adapter, ctx, IXGBE_DL_VERSION_STORED); 297 err = devlink_info_version_stored_put(req, "fw.psid.api", ctx->buf); 298 if (err) 299 return err; 300 301 ixgbe_info_netlist_ver(adapter, ctx, IXGBE_DL_VERSION_STORED); 302 err = devlink_info_version_stored_put(req, "fw.netlist", ctx->buf); 303 if (err) 304 return err; 305 306 ixgbe_info_netlist_build(adapter, ctx, IXGBE_DL_VERSION_STORED); 307 return devlink_info_version_stored_put(req, "fw.netlist.build", 308 ctx->buf); 309 } 310 311 static int ixgbe_devlink_info_get(struct devlink *devlink, 312 struct devlink_info_req *req, 313 struct netlink_ext_ack *extack) 314 { 315 struct ixgbe_adapter *adapter = devlink_priv(devlink); 316 struct ixgbe_hw *hw = &adapter->hw; 317 struct ixgbe_info_ctx *ctx; 318 int err; 319 320 ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); 321 if (!ctx) 322 return -ENOMEM; 323 324 ixgbe_info_get_dsn(adapter, ctx); 325 err = devlink_info_serial_number_put(req, ctx->buf); 326 if (err) 327 goto free_ctx; 328 329 err = hw->eeprom.ops.read_pba_string(hw, ctx->buf, sizeof(ctx->buf)); 330 if (err) 331 goto free_ctx; 332 333 err = devlink_info_version_fixed_put(req, 334 DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, 335 ctx->buf); 336 if (err) 337 goto free_ctx; 338 339 ixgbe_info_orom_ver(adapter, ctx, IXGBE_DL_VERSION_RUNNING); 340 err = devlink_info_version_running_put(req, 341 DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, 342 ctx->buf); 343 if (err) 344 goto free_ctx; 345 346 ixgbe_info_eetrack(adapter, ctx, IXGBE_DL_VERSION_RUNNING); 347 err = devlink_info_version_running_put(req, 348 DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID, 349 ctx->buf); 350 if (err || hw->mac.type != ixgbe_mac_e610) 351 goto free_ctx; 352 353 err = ixgbe_set_ctx_dev_caps(hw, ctx, extack); 354 if (err) 355 goto free_ctx; 356 357 err = ixgbe_devlink_info_get_e610(adapter, req, ctx); 358 if (err) 359 goto free_ctx; 360 361 err = ixgbe_devlink_pending_info_get_e610(adapter, req, ctx); 362 free_ctx: 363 kfree(ctx); 364 return err; 365 } 366 367 static const struct devlink_ops ixgbe_devlink_ops = { 368 .info_get = ixgbe_devlink_info_get, 369 }; 370 371 /** 372 * ixgbe_allocate_devlink - Allocate devlink instance 373 * @dev: device to allocate devlink for 374 * 375 * Allocate a devlink instance for this physical function. 376 * 377 * Return: pointer to the device adapter structure on success, 378 * ERR_PTR(-ENOMEM) when allocation failed. 379 */ 380 struct ixgbe_adapter *ixgbe_allocate_devlink(struct device *dev) 381 { 382 struct ixgbe_adapter *adapter; 383 struct devlink *devlink; 384 385 devlink = devlink_alloc(&ixgbe_devlink_ops, sizeof(*adapter), dev); 386 if (!devlink) 387 return ERR_PTR(-ENOMEM); 388 389 adapter = devlink_priv(devlink); 390 adapter->devlink = devlink; 391 392 return adapter; 393 } 394 395 /** 396 * ixgbe_devlink_set_switch_id - Set unique switch ID based on PCI DSN 397 * @adapter: pointer to the device adapter structure 398 * @ppid: struct with switch id information 399 */ 400 static void ixgbe_devlink_set_switch_id(struct ixgbe_adapter *adapter, 401 struct netdev_phys_item_id *ppid) 402 { 403 u64 id = pci_get_dsn(adapter->pdev); 404 405 ppid->id_len = sizeof(id); 406 put_unaligned_be64(id, &ppid->id); 407 } 408 409 /** 410 * ixgbe_devlink_register_port - Register devlink port 411 * @adapter: pointer to the device adapter structure 412 * 413 * Create and register a devlink_port for this physical function. 414 * 415 * Return: 0 on success, error code on failure. 416 */ 417 int ixgbe_devlink_register_port(struct ixgbe_adapter *adapter) 418 { 419 struct devlink_port *devlink_port = &adapter->devlink_port; 420 struct devlink *devlink = adapter->devlink; 421 struct device *dev = &adapter->pdev->dev; 422 struct devlink_port_attrs attrs = {}; 423 int err; 424 425 attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; 426 attrs.phys.port_number = adapter->hw.bus.func; 427 ixgbe_devlink_set_switch_id(adapter, &attrs.switch_id); 428 429 devlink_port_attrs_set(devlink_port, &attrs); 430 431 err = devl_port_register(devlink, devlink_port, 0); 432 if (err) { 433 dev_err(dev, 434 "devlink port registration failed, err %d\n", err); 435 } 436 437 return err; 438 } 439