* [PATCH net-next 1/5] bnxt_en: Refactor bnxt_flash_nvram.
2020-12-13 11:51 [PATCH net-next 0/5] bnxt_en: Improve firmware flashing Michael Chan
@ 2020-12-13 11:51 ` Michael Chan
2020-12-13 11:51 ` [PATCH net-next 2/5] bnxt_en: Rearrange the logic in bnxt_flash_package_from_fw_obj() Michael Chan
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Michael Chan @ 2020-12-13 11:51 UTC (permalink / raw)
To: davem; +Cc: netdev, kuba, Pavan Chebbi
From: Pavan Chebbi <pavan.chebbi@broadcom.com>
Refactor bnxt_flash_nvram() into __bnxt_flash_nvram() that takes an
additional dir_item_len parameter. The new function will be used
in subsequent patches with the dir_item_len parameter set to create
the UPDATE directory during flashing.
Signed-off-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
---
.../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 51 ++++++++++++-------
1 file changed, 32 insertions(+), 19 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
index 7b444fcb6289..11edf4998de7 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -2100,19 +2100,16 @@ static int bnxt_find_nvram_item(struct net_device *dev, u16 type, u16 ordinal,
u16 ext, u16 *index, u32 *item_length,
u32 *data_length);
-static int bnxt_flash_nvram(struct net_device *dev,
- u16 dir_type,
- u16 dir_ordinal,
- u16 dir_ext,
- u16 dir_attr,
- const u8 *data,
- size_t data_len)
+static int __bnxt_flash_nvram(struct net_device *dev, u16 dir_type,
+ u16 dir_ordinal, u16 dir_ext, u16 dir_attr,
+ u32 dir_item_len, const u8 *data,
+ size_t data_len)
{
struct bnxt *bp = netdev_priv(dev);
int rc;
struct hwrm_nvm_write_input req = {0};
dma_addr_t dma_handle;
- u8 *kmem;
+ u8 *kmem = NULL;
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_WRITE, -1, -1);
@@ -2120,26 +2117,42 @@ static int bnxt_flash_nvram(struct net_device *dev,
req.dir_ordinal = cpu_to_le16(dir_ordinal);
req.dir_ext = cpu_to_le16(dir_ext);
req.dir_attr = cpu_to_le16(dir_attr);
- req.dir_data_length = cpu_to_le32(data_len);
+ req.dir_item_length = cpu_to_le32(dir_item_len);
+ if (data_len && data) {
+ req.dir_data_length = cpu_to_le32(data_len);
- kmem = dma_alloc_coherent(&bp->pdev->dev, data_len, &dma_handle,
- GFP_KERNEL);
- if (!kmem) {
- netdev_err(dev, "dma_alloc_coherent failure, length = %u\n",
- (unsigned)data_len);
- return -ENOMEM;
+ kmem = dma_alloc_coherent(&bp->pdev->dev, data_len, &dma_handle,
+ GFP_KERNEL);
+ if (!kmem)
+ return -ENOMEM;
+
+ memcpy(kmem, data, data_len);
+ req.host_src_addr = cpu_to_le64(dma_handle);
}
- memcpy(kmem, data, data_len);
- req.host_src_addr = cpu_to_le64(dma_handle);
- rc = hwrm_send_message(bp, &req, sizeof(req), FLASH_NVRAM_TIMEOUT);
- dma_free_coherent(&bp->pdev->dev, data_len, kmem, dma_handle);
+ rc = _hwrm_send_message(bp, &req, sizeof(req), FLASH_NVRAM_TIMEOUT);
+ if (kmem)
+ dma_free_coherent(&bp->pdev->dev, data_len, kmem, dma_handle);
if (rc == -EACCES)
bnxt_print_admin_err(bp);
return rc;
}
+static int bnxt_flash_nvram(struct net_device *dev, u16 dir_type,
+ u16 dir_ordinal, u16 dir_ext, u16 dir_attr,
+ const u8 *data, size_t data_len)
+{
+ struct bnxt *bp = netdev_priv(dev);
+ int rc;
+
+ mutex_lock(&bp->hwrm_cmd_lock);
+ rc = __bnxt_flash_nvram(dev, dir_type, dir_ordinal, dir_ext, dir_attr,
+ 0, data, data_len);
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ return rc;
+}
+
static int bnxt_hwrm_firmware_reset(struct net_device *dev, u8 proc_type,
u8 self_reset, u8 flags)
{
--
2.18.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH net-next 2/5] bnxt_en: Rearrange the logic in bnxt_flash_package_from_fw_obj().
2020-12-13 11:51 [PATCH net-next 0/5] bnxt_en: Improve firmware flashing Michael Chan
2020-12-13 11:51 ` [PATCH net-next 1/5] bnxt_en: Refactor bnxt_flash_nvram Michael Chan
@ 2020-12-13 11:51 ` Michael Chan
2020-12-13 11:51 ` [PATCH net-next 3/5] bnxt_en: Restructure bnxt_flash_package_from_fw_obj() to execute in a loop Michael Chan
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Michael Chan @ 2020-12-13 11:51 UTC (permalink / raw)
To: davem; +Cc: netdev, kuba, Michael Chan
This function will be modified in the next patch to retry flashing
the firmware in a loop. To facilate that, we rearrange the code so
that the steps that only need to be done once before the loop will be
moved to the top of the function.
Signed-off-by: Michael Chan <michael.chan@broadocm.com>
---
.../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 63 +++++++++----------
1 file changed, 30 insertions(+), 33 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
index 11edf4998de7..7635ff84b928 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -2435,15 +2435,32 @@ static int bnxt_flash_firmware_from_file(struct net_device *dev,
int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware *fw,
u32 install_type)
{
- struct bnxt *bp = netdev_priv(dev);
- struct hwrm_nvm_install_update_output *resp = bp->hwrm_cmd_resp_addr;
struct hwrm_nvm_install_update_input install = {0};
+ struct hwrm_nvm_install_update_output resp = {0};
+ struct hwrm_nvm_modify_input modify = {0};
+ struct bnxt *bp = netdev_priv(dev);
+ dma_addr_t dma_handle;
+ u8 *kmem = NULL;
u32 item_len;
int rc = 0;
u16 index;
bnxt_hwrm_fw_set_time(bp);
+ bnxt_hwrm_cmd_hdr_init(bp, &modify, HWRM_NVM_MODIFY, -1, -1);
+
+ kmem = dma_alloc_coherent(&bp->pdev->dev, fw->size, &dma_handle,
+ GFP_KERNEL);
+ if (!kmem)
+ return -ENOMEM;
+
+ modify.host_src_addr = cpu_to_le64(dma_handle);
+
+ bnxt_hwrm_cmd_hdr_init(bp, &install, HWRM_NVM_INSTALL_UPDATE, -1, -1);
+ if ((install_type & 0xffff) == 0)
+ install_type >>= 16;
+ install.install_type = cpu_to_le32(install_type);
+
rc = bnxt_find_nvram_item(dev, BNX_DIR_TYPE_UPDATE,
BNX_DIR_ORDINAL_FIRST, BNX_DIR_EXT_NONE,
&index, &item_len, NULL);
@@ -2457,65 +2474,45 @@ int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware
(unsigned long)fw->size);
rc = -EFBIG;
} else {
- dma_addr_t dma_handle;
- u8 *kmem;
- struct hwrm_nvm_modify_input modify = {0};
-
- bnxt_hwrm_cmd_hdr_init(bp, &modify, HWRM_NVM_MODIFY, -1, -1);
-
modify.dir_idx = cpu_to_le16(index);
modify.len = cpu_to_le32(fw->size);
- kmem = dma_alloc_coherent(&bp->pdev->dev, fw->size,
- &dma_handle, GFP_KERNEL);
- if (!kmem) {
- netdev_err(dev,
- "dma_alloc_coherent failure, length = %u\n",
- (unsigned int)fw->size);
- rc = -ENOMEM;
- } else {
- memcpy(kmem, fw->data, fw->size);
- modify.host_src_addr = cpu_to_le64(dma_handle);
-
- rc = hwrm_send_message(bp, &modify, sizeof(modify),
- FLASH_PACKAGE_TIMEOUT);
- dma_free_coherent(&bp->pdev->dev, fw->size, kmem,
- dma_handle);
- }
+ memcpy(kmem, fw->data, fw->size);
+ rc = hwrm_send_message(bp, &modify, sizeof(modify),
+ FLASH_PACKAGE_TIMEOUT);
}
if (rc)
goto err_exit;
- if ((install_type & 0xffff) == 0)
- install_type >>= 16;
- bnxt_hwrm_cmd_hdr_init(bp, &install, HWRM_NVM_INSTALL_UPDATE, -1, -1);
- install.install_type = cpu_to_le32(install_type);
-
mutex_lock(&bp->hwrm_cmd_lock);
rc = _hwrm_send_message(bp, &install, sizeof(install),
INSTALL_PACKAGE_TIMEOUT);
+ memcpy(&resp, bp->hwrm_cmd_resp_addr, sizeof(resp));
+
if (rc) {
- u8 error_code = ((struct hwrm_err_output *)resp)->cmd_err;
+ u8 error_code = ((struct hwrm_err_output *)&resp)->cmd_err;
- if (resp->error_code && error_code ==
+ if (resp.error_code && error_code ==
NVM_INSTALL_UPDATE_CMD_ERR_CODE_FRAG_ERR) {
install.flags |= cpu_to_le16(
NVM_INSTALL_UPDATE_REQ_FLAGS_ALLOWED_TO_DEFRAG);
rc = _hwrm_send_message(bp, &install, sizeof(install),
INSTALL_PACKAGE_TIMEOUT);
+ memcpy(&resp, bp->hwrm_cmd_resp_addr, sizeof(resp));
}
if (rc)
goto flash_pkg_exit;
}
- if (resp->result) {
+ if (resp.result) {
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;
}
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)
bnxt_print_admin_err(bp);
return rc;
--
2.18.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH net-next 3/5] bnxt_en: Restructure bnxt_flash_package_from_fw_obj() to execute in a loop.
2020-12-13 11:51 [PATCH net-next 0/5] bnxt_en: Improve firmware flashing Michael Chan
2020-12-13 11:51 ` [PATCH net-next 1/5] bnxt_en: Refactor bnxt_flash_nvram Michael Chan
2020-12-13 11:51 ` [PATCH net-next 2/5] bnxt_en: Rearrange the logic in bnxt_flash_package_from_fw_obj() Michael Chan
@ 2020-12-13 11:51 ` Michael Chan
2020-12-13 11:51 ` [PATCH net-next 4/5] bnxt_en: Retry installing FW package under NO_SPACE error condition Michael Chan
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Michael Chan @ 2020-12-13 11:51 UTC (permalink / raw)
To: davem; +Cc: netdev, kuba, Pavan Chebbi
From: Pavan Chebbi <pavan.chebbi@broadcom.com>
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>
---
.../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 60 +++++++++----------
1 file changed, 28 insertions(+), 32 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
index 7635ff84b928..fa4f9941498e 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -2461,58 +2461,54 @@ int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware
install_type >>= 16;
install.install_type = cpu_to_le32(install_type);
- rc = bnxt_find_nvram_item(dev, BNX_DIR_TYPE_UPDATE,
- BNX_DIR_ORDINAL_FIRST, BNX_DIR_EXT_NONE,
- &index, &item_len, NULL);
- if (rc) {
- netdev_err(dev, "PKG update area not created in nvram\n");
- return rc;
- }
+ do {
+ rc = bnxt_find_nvram_item(dev, BNX_DIR_TYPE_UPDATE,
+ BNX_DIR_ORDINAL_FIRST,
+ BNX_DIR_EXT_NONE,
+ &index, &item_len, NULL);
+ 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.len = cpu_to_le32(fw->size);
memcpy(kmem, fw->data, fw->size);
rc = hwrm_send_message(bp, &modify, sizeof(modify),
FLASH_PACKAGE_TIMEOUT);
- }
- if (rc)
- goto err_exit;
-
- mutex_lock(&bp->hwrm_cmd_lock);
- rc = _hwrm_send_message(bp, &install, sizeof(install),
- INSTALL_PACKAGE_TIMEOUT);
- memcpy(&resp, bp->hwrm_cmd_resp_addr, sizeof(resp));
+ if (rc)
+ break;
- if (rc) {
- u8 error_code = ((struct hwrm_err_output *)&resp)->cmd_err;
+ mutex_lock(&bp->hwrm_cmd_lock);
+ rc = _hwrm_send_message(bp, &install, sizeof(install),
+ INSTALL_PACKAGE_TIMEOUT);
+ memcpy(&resp, bp->hwrm_cmd_resp_addr, sizeof(resp));
- if (resp.error_code && error_code ==
+ if (rc && ((struct hwrm_err_output *)&resp)->cmd_err ==
NVM_INSTALL_UPDATE_CMD_ERR_CODE_FRAG_ERR) {
- install.flags |= cpu_to_le16(
- NVM_INSTALL_UPDATE_REQ_FLAGS_ALLOWED_TO_DEFRAG);
+ install.flags |=
+ cpu_to_le16(NVM_INSTALL_UPDATE_REQ_FLAGS_ALLOWED_TO_DEFRAG);
+
rc = _hwrm_send_message(bp, &install, sizeof(install),
INSTALL_PACKAGE_TIMEOUT);
memcpy(&resp, bp->hwrm_cmd_resp_addr, sizeof(resp));
}
- if (rc)
- goto flash_pkg_exit;
- }
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ } while (false);
+ dma_free_coherent(&bp->pdev->dev, fw->size, kmem, dma_handle);
if (resp.result) {
netdev_err(dev, "PKG install error = %d, problem_item = %d\n",
(s8)resp.result, (int)resp.problem_item);
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)
bnxt_print_admin_err(bp);
return rc;
--
2.18.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH net-next 4/5] bnxt_en: Retry installing FW package under NO_SPACE error condition.
2020-12-13 11:51 [PATCH net-next 0/5] bnxt_en: Improve firmware flashing Michael Chan
` (2 preceding siblings ...)
2020-12-13 11:51 ` [PATCH net-next 3/5] bnxt_en: Restructure bnxt_flash_package_from_fw_obj() to execute in a loop Michael Chan
@ 2020-12-13 11:51 ` Michael Chan
2020-12-13 11:51 ` [PATCH net-next 5/5] bnxt_en: Enable batch mode when using HWRM_NVM_MODIFY to flash packages Michael Chan
2020-12-15 3:10 ` [PATCH net-next 0/5] bnxt_en: Improve firmware flashing patchwork-bot+netdevbpf
5 siblings, 0 replies; 7+ messages in thread
From: Michael Chan @ 2020-12-13 11:51 UTC (permalink / raw)
To: davem; +Cc: netdev, kuba, Pavan Chebbi
From: Pavan Chebbi <pavan.chebbi@broadcom.com>
In bnxt_flash_package_from_fw_obj(), if firmware returns the NO_SPACE
error, call __bnxt_flash_nvram() to create the UPDATE directory and
then loop back and retry one more time.
Since the first try may fail, we use the silent version to send the
firmware commands.
Reviewed-by: Vasundhara Volam <vasundhara-v.volam@broadcom.com>
Reviewed-by: Edwin Peer <edwin.peer@broadcom.com>
Signed-off-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
---
.../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 37 ++++++++++++++++---
1 file changed, 32 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
index fa4f9941498e..38ab882715c4 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -2439,6 +2439,7 @@ int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware
struct hwrm_nvm_install_update_output resp = {0};
struct hwrm_nvm_modify_input modify = {0};
struct bnxt *bp = netdev_priv(dev);
+ bool defrag_attempted = false;
dma_addr_t dma_handle;
u8 *kmem = NULL;
u32 item_len;
@@ -2487,21 +2488,47 @@ int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware
break;
mutex_lock(&bp->hwrm_cmd_lock);
- rc = _hwrm_send_message(bp, &install, sizeof(install),
- INSTALL_PACKAGE_TIMEOUT);
+ rc = _hwrm_send_message_silent(bp, &install, sizeof(install),
+ INSTALL_PACKAGE_TIMEOUT);
memcpy(&resp, bp->hwrm_cmd_resp_addr, sizeof(resp));
+ if (defrag_attempted) {
+ /* We have tried to defragment already in the previous
+ * iteration. Return with the result for INSTALL_UPDATE
+ */
+ mutex_unlock(&bp->hwrm_cmd_lock);
+ break;
+ }
+
if (rc && ((struct hwrm_err_output *)&resp)->cmd_err ==
NVM_INSTALL_UPDATE_CMD_ERR_CODE_FRAG_ERR) {
install.flags |=
cpu_to_le16(NVM_INSTALL_UPDATE_REQ_FLAGS_ALLOWED_TO_DEFRAG);
- rc = _hwrm_send_message(bp, &install, sizeof(install),
- INSTALL_PACKAGE_TIMEOUT);
+ rc = _hwrm_send_message_silent(bp, &install,
+ sizeof(install),
+ INSTALL_PACKAGE_TIMEOUT);
memcpy(&resp, bp->hwrm_cmd_resp_addr, sizeof(resp));
+
+ if (rc && ((struct hwrm_err_output *)&resp)->cmd_err ==
+ NVM_INSTALL_UPDATE_CMD_ERR_CODE_NO_SPACE) {
+ /* FW has cleared NVM area, driver will create
+ * UPDATE directory and try the flash again
+ */
+ defrag_attempted = true;
+ rc = __bnxt_flash_nvram(bp->dev,
+ BNX_DIR_TYPE_UPDATE,
+ BNX_DIR_ORDINAL_FIRST,
+ 0, 0, item_len, NULL,
+ 0);
+ } else if (rc) {
+ netdev_err(dev, "HWRM_NVM_INSTALL_UPDATE failure rc :%x\n", rc);
+ }
+ } else if (rc) {
+ netdev_err(dev, "HWRM_NVM_INSTALL_UPDATE failure rc :%x\n", rc);
}
mutex_unlock(&bp->hwrm_cmd_lock);
- } while (false);
+ } while (defrag_attempted && !rc);
dma_free_coherent(&bp->pdev->dev, fw->size, kmem, dma_handle);
if (resp.result) {
--
2.18.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH net-next 5/5] bnxt_en: Enable batch mode when using HWRM_NVM_MODIFY to flash packages.
2020-12-13 11:51 [PATCH net-next 0/5] bnxt_en: Improve firmware flashing Michael Chan
` (3 preceding siblings ...)
2020-12-13 11:51 ` [PATCH net-next 4/5] bnxt_en: Retry installing FW package under NO_SPACE error condition Michael Chan
@ 2020-12-13 11:51 ` Michael Chan
2020-12-15 3:10 ` [PATCH net-next 0/5] bnxt_en: Improve firmware flashing patchwork-bot+netdevbpf
5 siblings, 0 replies; 7+ messages in thread
From: Michael Chan @ 2020-12-13 11:51 UTC (permalink / raw)
To: davem; +Cc: netdev, kuba
The current scheme allocates a DMA buffer as big as the requested
firmware package file and DMAs the contents to firmware in one
operation. The buffer size can be several hundred kilo bytes and
the driver may not be able to allocate the memory. This will cause
firmware upgrade to fail.
Improve the scheme by using smaller DMA blocks and calling firmware to
DMA each block in a batch mode. Older firmware can cause excessive
NVRAM erases if the block size is too small so we try to allocate a
256K buffer to begin with and size it down successively if we cannot
allocate the memory.
Reviewed-by: Edwin Peer <edwin.peer@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
---
.../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 49 +++++++++++++++----
1 file changed, 40 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
index 38ab882715c4..9ff79d5d14c4 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -2432,6 +2432,10 @@ static int bnxt_flash_firmware_from_file(struct net_device *dev,
return rc;
}
+#define BNXT_PKG_DMA_SIZE 0x40000
+#define BNXT_NVM_MORE_FLAG (cpu_to_le16(NVM_MODIFY_REQ_FLAGS_BATCH_MODE))
+#define BNXT_NVM_LAST_FLAG (cpu_to_le16(NVM_MODIFY_REQ_FLAGS_BATCH_LAST))
+
int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware *fw,
u32 install_type)
{
@@ -2442,6 +2446,7 @@ int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware
bool defrag_attempted = false;
dma_addr_t dma_handle;
u8 *kmem = NULL;
+ u32 modify_len;
u32 item_len;
int rc = 0;
u16 index;
@@ -2450,8 +2455,19 @@ int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware
bnxt_hwrm_cmd_hdr_init(bp, &modify, HWRM_NVM_MODIFY, -1, -1);
- kmem = dma_alloc_coherent(&bp->pdev->dev, fw->size, &dma_handle,
- GFP_KERNEL);
+ /* Try allocating a large DMA buffer first. Older fw will
+ * cause excessive NVRAM erases when using small blocks.
+ */
+ modify_len = roundup_pow_of_two(fw->size);
+ modify_len = min_t(u32, modify_len, BNXT_PKG_DMA_SIZE);
+ while (1) {
+ kmem = dma_alloc_coherent(&bp->pdev->dev, modify_len,
+ &dma_handle, GFP_KERNEL);
+ if (!kmem && modify_len > PAGE_SIZE)
+ modify_len /= 2;
+ else
+ break;
+ }
if (!kmem)
return -ENOMEM;
@@ -2463,6 +2479,8 @@ int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware
install.install_type = cpu_to_le32(install_type);
do {
+ u32 copied = 0, len = modify_len;
+
rc = bnxt_find_nvram_item(dev, BNX_DIR_TYPE_UPDATE,
BNX_DIR_ORDINAL_FIRST,
BNX_DIR_EXT_NONE,
@@ -2479,14 +2497,26 @@ int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware
}
modify.dir_idx = cpu_to_le16(index);
- modify.len = cpu_to_le32(fw->size);
- memcpy(kmem, fw->data, fw->size);
- rc = hwrm_send_message(bp, &modify, sizeof(modify),
- FLASH_PACKAGE_TIMEOUT);
- if (rc)
- break;
+ if (fw->size > modify_len)
+ modify.flags = BNXT_NVM_MORE_FLAG;
+ while (copied < fw->size) {
+ u32 balance = fw->size - copied;
+ if (balance <= modify_len) {
+ len = balance;
+ if (copied)
+ modify.flags |= BNXT_NVM_LAST_FLAG;
+ }
+ memcpy(kmem, fw->data + copied, len);
+ modify.len = cpu_to_le32(len);
+ modify.offset = cpu_to_le32(copied);
+ rc = hwrm_send_message(bp, &modify, sizeof(modify),
+ FLASH_PACKAGE_TIMEOUT);
+ if (rc)
+ goto pkg_abort;
+ copied += len;
+ }
mutex_lock(&bp->hwrm_cmd_lock);
rc = _hwrm_send_message_silent(bp, &install, sizeof(install),
INSTALL_PACKAGE_TIMEOUT);
@@ -2530,7 +2560,8 @@ int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware
mutex_unlock(&bp->hwrm_cmd_lock);
} while (defrag_attempted && !rc);
- dma_free_coherent(&bp->pdev->dev, fw->size, kmem, dma_handle);
+pkg_abort:
+ dma_free_coherent(&bp->pdev->dev, modify_len, kmem, dma_handle);
if (resp.result) {
netdev_err(dev, "PKG install error = %d, problem_item = %d\n",
(s8)resp.result, (int)resp.problem_item);
--
2.18.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH net-next 0/5] bnxt_en: Improve firmware flashing.
2020-12-13 11:51 [PATCH net-next 0/5] bnxt_en: Improve firmware flashing Michael Chan
` (4 preceding siblings ...)
2020-12-13 11:51 ` [PATCH net-next 5/5] bnxt_en: Enable batch mode when using HWRM_NVM_MODIFY to flash packages Michael Chan
@ 2020-12-15 3:10 ` patchwork-bot+netdevbpf
5 siblings, 0 replies; 7+ messages in thread
From: patchwork-bot+netdevbpf @ 2020-12-15 3:10 UTC (permalink / raw)
To: Michael Chan; +Cc: davem, netdev, kuba
Hello:
This series was applied to netdev/net-next.git (refs/heads/master):
On Sun, 13 Dec 2020 06:51:41 -0500 you wrote:
> This patchset improves firmware flashing in 2 ways:
>
> - If firmware returns NO_SPACE error during flashing, the driver will
> create the UPDATE directory with more staging area and retry.
> - Instead of allocating a big DMA buffer for the entire contents of
> the firmware package size, fallback to a smaller buffer to DMA the
> contents in multiple DMA operations.
>
> [...]
Here is the summary with links:
- [net-next,1/5] bnxt_en: Refactor bnxt_flash_nvram.
https://git.kernel.org/netdev/net-next/c/93ff343528ce
- [net-next,2/5] bnxt_en: Rearrange the logic in bnxt_flash_package_from_fw_obj().
https://git.kernel.org/netdev/net-next/c/a9094ba6072b
- [net-next,3/5] bnxt_en: Restructure bnxt_flash_package_from_fw_obj() to execute in a loop.
https://git.kernel.org/netdev/net-next/c/2e5fb428a61c
- [net-next,4/5] bnxt_en: Retry installing FW package under NO_SPACE error condition.
https://git.kernel.org/netdev/net-next/c/1432c3f6a6ca
- [net-next,5/5] bnxt_en: Enable batch mode when using HWRM_NVM_MODIFY to flash packages.
https://git.kernel.org/netdev/net-next/c/a86b313e1817
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 7+ messages in thread