bnxt_en: Restructure bnxt_flash_package_from_fw_obj() to execute in a loop.
On NICs with a smaller NVRAM, FW installation may fail after multiple updates due to fragmentation. The driver can retry when FW returns a special error code. To faciliate the retry, we restructure the logic that performs the flashing in a loop. The actual retry logic will be added in the next patch. Signed-off-by: Pavan Chebbi <pavan.chebbi@broadcom.com> Signed-off-by: Michael Chan <michael.chan@broadcom.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
a9094ba607
commit
2e5fb428a6
@ -2461,58 +2461,54 @@ int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware
|
|||||||
install_type >>= 16;
|
install_type >>= 16;
|
||||||
install.install_type = cpu_to_le32(install_type);
|
install.install_type = cpu_to_le32(install_type);
|
||||||
|
|
||||||
rc = bnxt_find_nvram_item(dev, BNX_DIR_TYPE_UPDATE,
|
do {
|
||||||
BNX_DIR_ORDINAL_FIRST, BNX_DIR_EXT_NONE,
|
rc = bnxt_find_nvram_item(dev, BNX_DIR_TYPE_UPDATE,
|
||||||
&index, &item_len, NULL);
|
BNX_DIR_ORDINAL_FIRST,
|
||||||
if (rc) {
|
BNX_DIR_EXT_NONE,
|
||||||
netdev_err(dev, "PKG update area not created in nvram\n");
|
&index, &item_len, NULL);
|
||||||
return rc;
|
if (rc) {
|
||||||
}
|
netdev_err(dev, "PKG update area not created in nvram\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (fw->size > item_len) {
|
||||||
|
netdev_err(dev, "PKG insufficient update area in nvram: %lu\n",
|
||||||
|
(unsigned long)fw->size);
|
||||||
|
rc = -EFBIG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (fw->size > item_len) {
|
|
||||||
netdev_err(dev, "PKG insufficient update area in nvram: %lu\n",
|
|
||||||
(unsigned long)fw->size);
|
|
||||||
rc = -EFBIG;
|
|
||||||
} else {
|
|
||||||
modify.dir_idx = cpu_to_le16(index);
|
modify.dir_idx = cpu_to_le16(index);
|
||||||
modify.len = cpu_to_le32(fw->size);
|
modify.len = cpu_to_le32(fw->size);
|
||||||
|
|
||||||
memcpy(kmem, fw->data, fw->size);
|
memcpy(kmem, fw->data, fw->size);
|
||||||
rc = hwrm_send_message(bp, &modify, sizeof(modify),
|
rc = hwrm_send_message(bp, &modify, sizeof(modify),
|
||||||
FLASH_PACKAGE_TIMEOUT);
|
FLASH_PACKAGE_TIMEOUT);
|
||||||
}
|
if (rc)
|
||||||
if (rc)
|
break;
|
||||||
goto err_exit;
|
|
||||||
|
|
||||||
mutex_lock(&bp->hwrm_cmd_lock);
|
mutex_lock(&bp->hwrm_cmd_lock);
|
||||||
rc = _hwrm_send_message(bp, &install, sizeof(install),
|
rc = _hwrm_send_message(bp, &install, sizeof(install),
|
||||||
INSTALL_PACKAGE_TIMEOUT);
|
INSTALL_PACKAGE_TIMEOUT);
|
||||||
memcpy(&resp, bp->hwrm_cmd_resp_addr, sizeof(resp));
|
memcpy(&resp, bp->hwrm_cmd_resp_addr, sizeof(resp));
|
||||||
|
|
||||||
if (rc) {
|
if (rc && ((struct hwrm_err_output *)&resp)->cmd_err ==
|
||||||
u8 error_code = ((struct hwrm_err_output *)&resp)->cmd_err;
|
|
||||||
|
|
||||||
if (resp.error_code && error_code ==
|
|
||||||
NVM_INSTALL_UPDATE_CMD_ERR_CODE_FRAG_ERR) {
|
NVM_INSTALL_UPDATE_CMD_ERR_CODE_FRAG_ERR) {
|
||||||
install.flags |= cpu_to_le16(
|
install.flags |=
|
||||||
NVM_INSTALL_UPDATE_REQ_FLAGS_ALLOWED_TO_DEFRAG);
|
cpu_to_le16(NVM_INSTALL_UPDATE_REQ_FLAGS_ALLOWED_TO_DEFRAG);
|
||||||
|
|
||||||
rc = _hwrm_send_message(bp, &install, sizeof(install),
|
rc = _hwrm_send_message(bp, &install, sizeof(install),
|
||||||
INSTALL_PACKAGE_TIMEOUT);
|
INSTALL_PACKAGE_TIMEOUT);
|
||||||
memcpy(&resp, bp->hwrm_cmd_resp_addr, sizeof(resp));
|
memcpy(&resp, bp->hwrm_cmd_resp_addr, sizeof(resp));
|
||||||
}
|
}
|
||||||
if (rc)
|
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||||
goto flash_pkg_exit;
|
} while (false);
|
||||||
}
|
|
||||||
|
|
||||||
|
dma_free_coherent(&bp->pdev->dev, fw->size, kmem, dma_handle);
|
||||||
if (resp.result) {
|
if (resp.result) {
|
||||||
netdev_err(dev, "PKG install error = %d, problem_item = %d\n",
|
netdev_err(dev, "PKG install error = %d, problem_item = %d\n",
|
||||||
(s8)resp.result, (int)resp.problem_item);
|
(s8)resp.result, (int)resp.problem_item);
|
||||||
rc = -ENOPKG;
|
rc = -ENOPKG;
|
||||||
}
|
}
|
||||||
flash_pkg_exit:
|
|
||||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
|
||||||
err_exit:
|
|
||||||
dma_free_coherent(&bp->pdev->dev, fw->size, kmem, dma_handle);
|
|
||||||
if (rc == -EACCES)
|
if (rc == -EACCES)
|
||||||
bnxt_print_admin_err(bp);
|
bnxt_print_admin_err(bp);
|
||||||
return rc;
|
return rc;
|
||||||
|
Loading…
Reference in New Issue
Block a user