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