1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright(c) 2025 Intel Corporation. */ 3 4 #include <linux/crc32.h> 5 #include <linux/pldmfw.h> 6 #include <linux/uuid.h> 7 8 #include "ixgbe.h" 9 #include "ixgbe_fw_update.h" 10 11 struct ixgbe_fwu_priv { 12 struct pldmfw context; 13 14 struct ixgbe_adapter *adapter; 15 struct netlink_ext_ack *extack; 16 17 /* Track which NVM banks to activate at the end of the update */ 18 u8 activate_flags; 19 bool emp_reset_available; 20 }; 21 22 /** 23 * ixgbe_send_package_data - Send record package data to firmware 24 * @context: PLDM fw update structure 25 * @data: pointer to the package data 26 * @length: length of the package data 27 * 28 * Send a copy of the package data associated with the PLDM record matching 29 * this device to the firmware. 30 * 31 * Note that this function sends an AdminQ command that will fail unless the 32 * NVM resource has been acquired. 33 * 34 * Return: zero on success, or a negative error code on failure. 35 */ 36 static int ixgbe_send_package_data(struct pldmfw *context, 37 const u8 *data, u16 length) 38 { 39 struct ixgbe_fwu_priv *priv = container_of(context, 40 struct ixgbe_fwu_priv, 41 context); 42 struct ixgbe_adapter *adapter = priv->adapter; 43 struct ixgbe_hw *hw = &adapter->hw; 44 u8 *package_data; 45 int err; 46 47 package_data = kmemdup(data, length, GFP_KERNEL); 48 if (!package_data) 49 return -ENOMEM; 50 51 err = ixgbe_nvm_set_pkg_data(hw, false, package_data, length); 52 53 kfree(package_data); 54 55 return err; 56 } 57 58 /** 59 * ixgbe_check_component_response - Report firmware response to a component 60 * @adapter: device private data structure 61 * @response: indicates whether this component can be updated 62 * @code: code indicating reason for response 63 * @extack: netlink extended ACK structure 64 * 65 * Check whether firmware indicates if this component can be updated. Report 66 * a suitable error message over the netlink extended ACK if the component 67 * cannot be updated. 68 * 69 * Return: 0 if the component can be updated, or -ECANCELED if the 70 * firmware indicates the component cannot be updated. 71 */ 72 static int ixgbe_check_component_response(struct ixgbe_adapter *adapter, 73 u8 response, u8 code, 74 struct netlink_ext_ack *extack) 75 { 76 struct ixgbe_hw *hw = &adapter->hw; 77 78 switch (response) { 79 case IXGBE_ACI_NVM_PASS_COMP_CAN_BE_UPDATED: 80 /* Firmware indicated this update is good to proceed. */ 81 return 0; 82 case IXGBE_ACI_NVM_PASS_COMP_CAN_MAY_BE_UPDATEABLE: 83 NL_SET_ERR_MSG_MOD(extack, 84 "Firmware recommends not updating, as it may result in a downgrade. Continuing anyways"); 85 return 0; 86 case IXGBE_ACI_NVM_PASS_COMP_CAN_NOT_BE_UPDATED: 87 NL_SET_ERR_MSG_MOD(extack, "Firmware has rejected updating."); 88 break; 89 case IXGBE_ACI_NVM_PASS_COMP_PARTIAL_CHECK: 90 if (hw->mac.ops.fw_recovery_mode && 91 hw->mac.ops.fw_recovery_mode(hw)) 92 return 0; 93 break; 94 } 95 96 switch (code) { 97 case IXGBE_ACI_NVM_PASS_COMP_STAMP_IDENTICAL_CODE: 98 NL_SET_ERR_MSG_MOD(extack, 99 "Component comparison stamp is identical to running image"); 100 break; 101 case IXGBE_ACI_NVM_PASS_COMP_STAMP_LOWER: 102 NL_SET_ERR_MSG_MOD(extack, 103 "Component comparison stamp is lower than running image"); 104 break; 105 case IXGBE_ACI_NVM_PASS_COMP_INVALID_STAMP_CODE: 106 NL_SET_ERR_MSG_MOD(extack, 107 "Component comparison stamp is invalid"); 108 break; 109 case IXGBE_ACI_NVM_PASS_COMP_CONFLICT_CODE: 110 NL_SET_ERR_MSG_MOD(extack, 111 "Component table conflict occurred"); 112 break; 113 case IXGBE_ACI_NVM_PASS_COMP_PRE_REQ_NOT_MET_CODE: 114 NL_SET_ERR_MSG_MOD(extack, "Component pre-requisites not met"); 115 break; 116 case IXGBE_ACI_NVM_PASS_COMP_NOT_SUPPORTED_CODE: 117 NL_SET_ERR_MSG_MOD(extack, "Component not supported"); 118 break; 119 case IXGBE_ACI_NVM_PASS_COMP_CANNOT_DOWNGRADE_CODE: 120 NL_SET_ERR_MSG_MOD(extack, "Component cannot be downgraded"); 121 break; 122 case IXGBE_ACI_NVM_PASS_COMP_INCOMPLETE_IMAGE_CODE: 123 NL_SET_ERR_MSG_MOD(extack, "Incomplete component image"); 124 break; 125 case IXGBE_ACI_NVM_PASS_COMP_VER_STR_IDENTICAL_CODE: 126 NL_SET_ERR_MSG_MOD(extack, 127 "Component version is identical to running image"); 128 break; 129 case IXGBE_ACI_NVM_PASS_COMP_VER_STR_LOWER_CODE: 130 NL_SET_ERR_MSG_MOD(extack, 131 "Component version is lower than the running image"); 132 break; 133 default: 134 NL_SET_ERR_MSG_MOD(extack, 135 "Received unexpected response code from firmware"); 136 break; 137 } 138 139 return -ECANCELED; 140 } 141 142 /** 143 * ixgbe_send_component_table - Send PLDM component table to firmware 144 * @context: PLDM fw update structure 145 * @component: the component to process 146 * @transfer_flag: relative transfer order of this component 147 * 148 * Read relevant data from the component and forward it to the device 149 * firmware. Check the response to determine if the firmware indicates that 150 * the update can proceed. 151 * 152 * This function sends ACI commands related to the NVM, and assumes that 153 * the NVM resource has been acquired. 154 * 155 * Return: 0 on success, or a negative error code on failure. 156 */ 157 static int ixgbe_send_component_table(struct pldmfw *context, 158 struct pldmfw_component *component, 159 u8 transfer_flag) 160 { 161 struct ixgbe_fwu_priv *priv = container_of(context, 162 struct ixgbe_fwu_priv, 163 context); 164 struct ixgbe_adapter *adapter = priv->adapter; 165 struct netlink_ext_ack *extack = priv->extack; 166 struct ixgbe_aci_cmd_nvm_comp_tbl *comp_tbl; 167 u8 comp_response, comp_response_code; 168 struct ixgbe_hw *hw = &adapter->hw; 169 size_t length; 170 int err; 171 172 switch (component->identifier) { 173 case NVM_COMP_ID_OROM: 174 case NVM_COMP_ID_NVM: 175 case NVM_COMP_ID_NETLIST: 176 break; 177 default: 178 NL_SET_ERR_MSG_MOD(extack, 179 "Unable to update due to unknown firmware component"); 180 return -EOPNOTSUPP; 181 } 182 183 length = struct_size(comp_tbl, cvs, component->version_len); 184 comp_tbl = kzalloc(length, GFP_KERNEL); 185 if (!comp_tbl) 186 return -ENOMEM; 187 188 comp_tbl->comp_class = cpu_to_le16(component->classification); 189 comp_tbl->comp_id = cpu_to_le16(component->identifier); 190 comp_tbl->comp_class_idx = FWU_COMP_CLASS_IDX_NOT_USE; 191 comp_tbl->comp_cmp_stamp = cpu_to_le32(component->comparison_stamp); 192 comp_tbl->cvs_type = component->version_type; 193 comp_tbl->cvs_len = component->version_len; 194 195 memcpy(comp_tbl->cvs, component->version_string, 196 component->version_len); 197 198 err = ixgbe_nvm_pass_component_tbl(hw, (u8 *)comp_tbl, length, 199 transfer_flag, &comp_response, 200 &comp_response_code); 201 202 kfree(comp_tbl); 203 204 if (err) { 205 NL_SET_ERR_MSG_MOD(extack, 206 "Failed to transfer component table to firmware"); 207 return -EIO; 208 } 209 210 return ixgbe_check_component_response(adapter, 211 comp_response, 212 comp_response_code, extack); 213 } 214 215 /** 216 * ixgbe_write_one_nvm_block - Write an NVM block and await completion response 217 * @adapter: the PF data structure 218 * @module: the module to write to 219 * @offset: offset in bytes 220 * @block_size: size of the block to write, up to 4k 221 * @block: pointer to block of data to write 222 * @last_cmd: whether this is the last command 223 * @extack: netlink extended ACK structure 224 * 225 * Write a block of data to a flash module, and await for the completion 226 * response message from firmware. 227 * 228 * Note this function assumes the caller has acquired the NVM resource. 229 * 230 * On successful return, reset level indicates the device reset required to 231 * complete the update. 232 * 233 * 0 - IXGBE_ACI_NVM_POR_FLAG - A full power on is required 234 * 1 - IXGBE_ACI_NVM_PERST_FLAG - A cold PCIe reset is required 235 * 2 - IXGBE_ACI_NVM_EMPR_FLAG - An EMP reset is required 236 * 237 * Return: 0 on success, or a negative error code on failure. 238 */ 239 static int ixgbe_write_one_nvm_block(struct ixgbe_adapter *adapter, 240 u16 module, u32 offset, 241 u16 block_size, u8 *block, bool last_cmd, 242 struct netlink_ext_ack *extack) 243 { 244 struct ixgbe_hw *hw = &adapter->hw; 245 246 return ixgbe_aci_update_nvm(hw, module, offset, block_size, block, 247 last_cmd, 0); 248 } 249 250 /** 251 * ixgbe_write_nvm_module - Write data to an NVM module 252 * @adapter: the PF driver structure 253 * @module: the module id to program 254 * @component: the name of the component being updated 255 * @image: buffer of image data to write to the NVM 256 * @length: length of the buffer 257 * @extack: netlink extended ACK structure 258 * 259 * Loop over the data for a given NVM module and program it in 4 Kb 260 * blocks. Notify devlink core of progress after each block is programmed. 261 * Loops over a block of data and programs the NVM in 4k block chunks. 262 * 263 * Note this function assumes the caller has acquired the NVM resource. 264 * 265 * Return: 0 on success, or a negative error code on failure. 266 */ 267 static int ixgbe_write_nvm_module(struct ixgbe_adapter *adapter, u16 module, 268 const char *component, const u8 *image, 269 u32 length, 270 struct netlink_ext_ack *extack) 271 { 272 struct devlink *devlink = adapter->devlink; 273 u32 offset = 0; 274 bool last_cmd; 275 u8 *block; 276 int err; 277 278 devlink_flash_update_status_notify(devlink, "Flashing", 279 component, 0, length); 280 281 block = kzalloc(IXGBE_ACI_MAX_BUFFER_SIZE, GFP_KERNEL); 282 if (!block) 283 return -ENOMEM; 284 285 do { 286 u32 block_size; 287 288 block_size = min_t(u32, IXGBE_ACI_MAX_BUFFER_SIZE, 289 length - offset); 290 last_cmd = !(offset + block_size < length); 291 292 memcpy(block, image + offset, block_size); 293 294 err = ixgbe_write_one_nvm_block(adapter, module, offset, 295 block_size, block, last_cmd, 296 extack); 297 if (err) 298 break; 299 300 offset += block_size; 301 302 devlink_flash_update_status_notify(devlink, "Flashing", 303 component, offset, length); 304 } while (!last_cmd); 305 306 if (err) 307 devlink_flash_update_status_notify(devlink, "Flashing failed", 308 component, length, length); 309 else 310 devlink_flash_update_status_notify(devlink, "Flashing done", 311 component, length, length); 312 313 kfree(block); 314 315 return err; 316 } 317 318 /* Length in seconds to wait before timing out when erasing a flash module. 319 * Yes, erasing really can take minutes to complete. 320 */ 321 #define IXGBE_FW_ERASE_TIMEOUT 300 322 323 /** 324 * ixgbe_erase_nvm_module - Erase an NVM module and await firmware completion 325 * @adapter: the PF data structure 326 * @module: the module to erase 327 * @component: name of the component being updated 328 * @extack: netlink extended ACK structure 329 * 330 * Erase the inactive NVM bank associated with this module, and await for 331 * a completion response message from firmware. 332 * 333 * Note this function assumes the caller has acquired the NVM resource. 334 * 335 * Return: 0 on success, or a negative error code on failure. 336 */ 337 static int ixgbe_erase_nvm_module(struct ixgbe_adapter *adapter, u16 module, 338 const char *component, 339 struct netlink_ext_ack *extack) 340 { 341 struct devlink *devlink = adapter->devlink; 342 struct ixgbe_hw *hw = &adapter->hw; 343 int err; 344 345 devlink_flash_update_timeout_notify(devlink, "Erasing", component, 346 IXGBE_FW_ERASE_TIMEOUT); 347 348 err = ixgbe_aci_erase_nvm(hw, module); 349 if (err) 350 devlink_flash_update_status_notify(devlink, "Erasing failed", 351 component, 0, 0); 352 else 353 devlink_flash_update_status_notify(devlink, "Erasing done", 354 component, 0, 0); 355 356 return err; 357 } 358 359 /** 360 * ixgbe_switch_flash_banks - Tell firmware to switch NVM banks 361 * @adapter: Pointer to the PF data structure 362 * @activate_flags: flags used for the activation command 363 * @emp_reset_available: on return, indicates if EMP reset is available 364 * @extack: netlink extended ACK structure 365 * 366 * Notify firmware to activate the newly written flash banks, and wait for the 367 * firmware response. 368 * 369 * Return: 0 on success or an error code on failure. 370 */ 371 static int ixgbe_switch_flash_banks(struct ixgbe_adapter *adapter, 372 u8 activate_flags, 373 bool *emp_reset_available, 374 struct netlink_ext_ack *extack) 375 { 376 struct ixgbe_hw *hw = &adapter->hw; 377 u8 response_flags; 378 int err; 379 380 err = ixgbe_nvm_write_activate(hw, activate_flags, &response_flags); 381 if (err) { 382 NL_SET_ERR_MSG_MOD(extack, 383 "Failed to switch active flash banks"); 384 return err; 385 } 386 387 if (emp_reset_available) { 388 if (hw->dev_caps.common_cap.reset_restrict_support) 389 *emp_reset_available = 390 response_flags & IXGBE_ACI_NVM_EMPR_ENA; 391 else 392 *emp_reset_available = true; 393 } 394 395 return 0; 396 } 397 398 /** 399 * ixgbe_flash_component - Flash a component of the NVM 400 * @context: PLDM fw update structure 401 * @component: the component table to program 402 * 403 * Program the flash contents for a given component. First, determine the 404 * module id. Then, erase the secondary bank for this module. Finally, write 405 * the contents of the component to the NVM. 406 * 407 * Note this function assumes the caller has acquired the NVM resource. 408 * 409 * Return: 0 on success, or a negative error code on failure. 410 */ 411 static int ixgbe_flash_component(struct pldmfw *context, 412 struct pldmfw_component *component) 413 { 414 struct ixgbe_fwu_priv *priv = container_of(context, 415 struct ixgbe_fwu_priv, 416 context); 417 struct netlink_ext_ack *extack = priv->extack; 418 struct ixgbe_adapter *adapter = priv->adapter; 419 const char *name; 420 u16 module; 421 int err; 422 u8 flag; 423 424 switch (component->identifier) { 425 case NVM_COMP_ID_OROM: 426 module = IXGBE_E610_SR_1ST_OROM_BANK_PTR; 427 flag = IXGBE_ACI_NVM_ACTIV_SEL_OROM; 428 name = "fw.undi"; 429 break; 430 case NVM_COMP_ID_NVM: 431 module = IXGBE_E610_SR_1ST_NVM_BANK_PTR; 432 flag = IXGBE_ACI_NVM_ACTIV_SEL_NVM; 433 name = "fw.mgmt"; 434 break; 435 case NVM_COMP_ID_NETLIST: 436 module = IXGBE_E610_SR_NETLIST_BANK_PTR; 437 flag = IXGBE_ACI_NVM_ACTIV_SEL_NETLIST; 438 name = "fw.netlist"; 439 break; 440 441 default: 442 return -EOPNOTSUPP; 443 } 444 445 /* Mark this component for activating at the end. */ 446 priv->activate_flags |= flag; 447 448 err = ixgbe_erase_nvm_module(adapter, module, name, extack); 449 if (err) 450 return err; 451 452 return ixgbe_write_nvm_module(adapter, module, name, 453 component->component_data, 454 component->component_size, extack); 455 } 456 457 /** 458 * ixgbe_finalize_update - Perform last steps to complete device update 459 * @context: PLDM fw update structure 460 * 461 * Called as the last step of the update process. Complete the update by 462 * telling the firmware to switch active banks, and perform a reset of 463 * configured. 464 * 465 * Return: 0 on success, or an error code on failure. 466 */ 467 static int ixgbe_finalize_update(struct pldmfw *context) 468 { 469 struct ixgbe_fwu_priv *priv = container_of(context, 470 struct ixgbe_fwu_priv, 471 context); 472 struct ixgbe_adapter *adapter = priv->adapter; 473 struct netlink_ext_ack *extack = priv->extack; 474 struct devlink *devlink = adapter->devlink; 475 int err; 476 477 /* Finally, notify firmware to activate the written NVM banks */ 478 err = ixgbe_switch_flash_banks(adapter, priv->activate_flags, 479 &priv->emp_reset_available, extack); 480 if (err) 481 return err; 482 483 adapter->fw_emp_reset_disabled = !priv->emp_reset_available; 484 485 if (!adapter->fw_emp_reset_disabled) 486 devlink_flash_update_status_notify(devlink, 487 "Suggested is to activate new firmware by devlink reload, if it doesn't work then a power cycle is required", 488 NULL, 0, 0); 489 490 return 0; 491 } 492 493 static const struct pldmfw_ops ixgbe_fwu_ops_e610 = { 494 .match_record = &pldmfw_op_pci_match_record, 495 .send_package_data = &ixgbe_send_package_data, 496 .send_component_table = &ixgbe_send_component_table, 497 .flash_component = &ixgbe_flash_component, 498 .finalize_update = &ixgbe_finalize_update, 499 }; 500 501 /** 502 * ixgbe_get_pending_updates - Check if the component has a pending update 503 * @adapter: the PF driver structure 504 * @pending: on return, bitmap of updates pending 505 * @extack: Netlink extended ACK 506 * 507 * Check if the device has any pending updates on any flash components. 508 * 509 * Return: 0 on success, or a negative error code on failure. Update 510 * pending with the bitmap of pending updates. 511 */ 512 int ixgbe_get_pending_updates(struct ixgbe_adapter *adapter, u8 *pending, 513 struct netlink_ext_ack *extack) 514 { 515 struct ixgbe_hw_dev_caps *dev_caps; 516 struct ixgbe_hw *hw = &adapter->hw; 517 int err; 518 519 dev_caps = kzalloc(sizeof(*dev_caps), GFP_KERNEL); 520 if (!dev_caps) 521 return -ENOMEM; 522 523 err = ixgbe_discover_dev_caps(hw, dev_caps); 524 if (err) { 525 NL_SET_ERR_MSG_MOD(extack, 526 "Unable to read device capabilities"); 527 kfree(dev_caps); 528 return -EIO; 529 } 530 531 *pending = 0; 532 533 if (dev_caps->common_cap.nvm_update_pending_nvm) 534 *pending |= IXGBE_ACI_NVM_ACTIV_SEL_NVM; 535 536 if (dev_caps->common_cap.nvm_update_pending_orom) 537 *pending |= IXGBE_ACI_NVM_ACTIV_SEL_OROM; 538 539 if (dev_caps->common_cap.nvm_update_pending_netlist) 540 *pending |= IXGBE_ACI_NVM_ACTIV_SEL_NETLIST; 541 542 kfree(dev_caps); 543 544 return 0; 545 } 546 547 /** 548 * ixgbe_cancel_pending_update - Cancel any pending update for a component 549 * @adapter: the PF driver structure 550 * @component: if not NULL, the name of the component being updated 551 * @extack: Netlink extended ACK structure 552 * 553 * Cancel any pending update for the specified component. If component is 554 * NULL, all device updates will be canceled. 555 * 556 * Return: 0 on success, or a negative error code on failure. 557 */ 558 static int ixgbe_cancel_pending_update(struct ixgbe_adapter *adapter, 559 const char *component, 560 struct netlink_ext_ack *extack) 561 { 562 struct devlink *devlink = adapter->devlink; 563 struct ixgbe_hw *hw = &adapter->hw; 564 u8 pending; 565 int err; 566 567 err = ixgbe_get_pending_updates(adapter, &pending, extack); 568 if (err) 569 return err; 570 571 /* If the flash_update request is for a specific component, ignore all 572 * of the other components. 573 */ 574 if (component) { 575 if (strcmp(component, "fw.mgmt") == 0) 576 pending &= IXGBE_ACI_NVM_ACTIV_SEL_NVM; 577 else if (strcmp(component, "fw.undi") == 0) 578 pending &= IXGBE_ACI_NVM_ACTIV_SEL_OROM; 579 else if (strcmp(component, "fw.netlist") == 0) 580 pending &= IXGBE_ACI_NVM_ACTIV_SEL_NETLIST; 581 else 582 return -EINVAL; 583 } 584 585 /* There is no previous pending update, so this request may continue */ 586 if (!pending) 587 return 0; 588 589 /* In order to allow overwriting a previous pending update, notify 590 * firmware to cancel that update by issuing the appropriate command. 591 */ 592 devlink_flash_update_status_notify(devlink, 593 "Canceling previous pending update", 594 component, 0, 0); 595 596 err = ixgbe_acquire_nvm(hw, IXGBE_RES_WRITE); 597 if (err) { 598 NL_SET_ERR_MSG_MOD(extack, 599 "Failed to acquire device flash lock"); 600 return -EIO; 601 } 602 603 pending |= IXGBE_ACI_NVM_REVERT_LAST_ACTIV; 604 err = ixgbe_switch_flash_banks(adapter, pending, NULL, extack); 605 606 ixgbe_release_nvm(hw); 607 608 return err; 609 } 610 611 /** 612 * ixgbe_flash_pldm_image - Write a PLDM-formatted firmware image to the device 613 * @devlink: pointer to devlink associated with the device to update 614 * @params: devlink flash update parameters 615 * @extack: netlink extended ACK structure 616 * 617 * Parse the data for a given firmware file, verifying that it is a valid PLDM 618 * formatted image that matches this device. 619 * 620 * Extract the device record Package Data and Component Tables and send them 621 * to the firmware. Extract and write the flash data for each of the three 622 * main flash components, "fw.mgmt", "fw.undi", and "fw.netlist". Notify 623 * firmware once the data is written to the inactive banks. 624 * 625 * Return: 0 on success or a negative error code on failure. 626 */ 627 int ixgbe_flash_pldm_image(struct devlink *devlink, 628 struct devlink_flash_update_params *params, 629 struct netlink_ext_ack *extack) 630 { 631 struct ixgbe_adapter *adapter = devlink_priv(devlink); 632 struct device *dev = &adapter->pdev->dev; 633 struct ixgbe_hw *hw = &adapter->hw; 634 struct ixgbe_fwu_priv priv; 635 u8 preservation; 636 int err; 637 638 if (hw->mac.type != ixgbe_mac_e610) 639 return -EOPNOTSUPP; 640 641 switch (params->overwrite_mask) { 642 case 0: 643 /* preserve all settings and identifiers */ 644 preservation = IXGBE_ACI_NVM_PRESERVE_ALL; 645 break; 646 case DEVLINK_FLASH_OVERWRITE_SETTINGS: 647 /* Overwrite settings, but preserve vital information such as 648 * device identifiers. 649 */ 650 preservation = IXGBE_ACI_NVM_PRESERVE_SELECTED; 651 break; 652 case (DEVLINK_FLASH_OVERWRITE_SETTINGS | 653 DEVLINK_FLASH_OVERWRITE_IDENTIFIERS): 654 /* overwrite both settings and identifiers, preserve nothing */ 655 preservation = IXGBE_ACI_NVM_NO_PRESERVATION; 656 break; 657 default: 658 NL_SET_ERR_MSG_MOD(extack, 659 "Requested overwrite mask is not supported"); 660 return -EOPNOTSUPP; 661 } 662 663 /* Cannot get caps in recovery mode, so lack of nvm_unified_update bit 664 * cannot lead to error 665 */ 666 if (!hw->dev_caps.common_cap.nvm_unified_update && 667 (hw->mac.ops.fw_recovery_mode && 668 !hw->mac.ops.fw_recovery_mode(hw))) { 669 NL_SET_ERR_MSG_MOD(extack, 670 "Current firmware does not support unified update"); 671 return -EOPNOTSUPP; 672 } 673 674 memset(&priv, 0, sizeof(priv)); 675 676 priv.context.ops = &ixgbe_fwu_ops_e610; 677 priv.context.dev = dev; 678 priv.extack = extack; 679 priv.adapter = adapter; 680 priv.activate_flags = preservation; 681 682 devlink_flash_update_status_notify(devlink, 683 "Preparing to flash", NULL, 0, 0); 684 685 err = ixgbe_cancel_pending_update(adapter, NULL, extack); 686 if (err) 687 return err; 688 689 err = ixgbe_acquire_nvm(hw, IXGBE_RES_WRITE); 690 if (err) { 691 NL_SET_ERR_MSG_MOD(extack, 692 "Failed to acquire device flash lock"); 693 return -EIO; 694 } 695 696 err = pldmfw_flash_image(&priv.context, params->fw); 697 if (err == -ENOENT) { 698 NL_SET_ERR_MSG_MOD(extack, 699 "Firmware image has no record matching this device"); 700 } else if (err) { 701 NL_SET_ERR_MSG_MOD(extack, "Failed to flash PLDM image"); 702 } 703 704 ixgbe_release_nvm(hw); 705 706 return err; 707 } 708