Skip to content

Commit a86b313

Browse files
Michael Chankuba-moo
authored andcommitted
bnxt_en: Enable batch mode when using HWRM_NVM_MODIFY to flash packages.
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 <[email protected]> Signed-off-by: Michael Chan <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 1432c3f commit a86b313

File tree

1 file changed

+40
-9
lines changed

1 file changed

+40
-9
lines changed

drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2432,6 +2432,10 @@ static int bnxt_flash_firmware_from_file(struct net_device *dev,
24322432
return rc;
24332433
}
24342434

2435+
#define BNXT_PKG_DMA_SIZE 0x40000
2436+
#define BNXT_NVM_MORE_FLAG (cpu_to_le16(NVM_MODIFY_REQ_FLAGS_BATCH_MODE))
2437+
#define BNXT_NVM_LAST_FLAG (cpu_to_le16(NVM_MODIFY_REQ_FLAGS_BATCH_LAST))
2438+
24352439
int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware *fw,
24362440
u32 install_type)
24372441
{
@@ -2442,6 +2446,7 @@ int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware
24422446
bool defrag_attempted = false;
24432447
dma_addr_t dma_handle;
24442448
u8 *kmem = NULL;
2449+
u32 modify_len;
24452450
u32 item_len;
24462451
int rc = 0;
24472452
u16 index;
@@ -2450,8 +2455,19 @@ int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware
24502455

24512456
bnxt_hwrm_cmd_hdr_init(bp, &modify, HWRM_NVM_MODIFY, -1, -1);
24522457

2453-
kmem = dma_alloc_coherent(&bp->pdev->dev, fw->size, &dma_handle,
2454-
GFP_KERNEL);
2458+
/* Try allocating a large DMA buffer first. Older fw will
2459+
* cause excessive NVRAM erases when using small blocks.
2460+
*/
2461+
modify_len = roundup_pow_of_two(fw->size);
2462+
modify_len = min_t(u32, modify_len, BNXT_PKG_DMA_SIZE);
2463+
while (1) {
2464+
kmem = dma_alloc_coherent(&bp->pdev->dev, modify_len,
2465+
&dma_handle, GFP_KERNEL);
2466+
if (!kmem && modify_len > PAGE_SIZE)
2467+
modify_len /= 2;
2468+
else
2469+
break;
2470+
}
24552471
if (!kmem)
24562472
return -ENOMEM;
24572473

@@ -2463,6 +2479,8 @@ int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware
24632479
install.install_type = cpu_to_le32(install_type);
24642480

24652481
do {
2482+
u32 copied = 0, len = modify_len;
2483+
24662484
rc = bnxt_find_nvram_item(dev, BNX_DIR_TYPE_UPDATE,
24672485
BNX_DIR_ORDINAL_FIRST,
24682486
BNX_DIR_EXT_NONE,
@@ -2479,14 +2497,26 @@ int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware
24792497
}
24802498

24812499
modify.dir_idx = cpu_to_le16(index);
2482-
modify.len = cpu_to_le32(fw->size);
24832500

2484-
memcpy(kmem, fw->data, fw->size);
2485-
rc = hwrm_send_message(bp, &modify, sizeof(modify),
2486-
FLASH_PACKAGE_TIMEOUT);
2487-
if (rc)
2488-
break;
2501+
if (fw->size > modify_len)
2502+
modify.flags = BNXT_NVM_MORE_FLAG;
2503+
while (copied < fw->size) {
2504+
u32 balance = fw->size - copied;
24892505

2506+
if (balance <= modify_len) {
2507+
len = balance;
2508+
if (copied)
2509+
modify.flags |= BNXT_NVM_LAST_FLAG;
2510+
}
2511+
memcpy(kmem, fw->data + copied, len);
2512+
modify.len = cpu_to_le32(len);
2513+
modify.offset = cpu_to_le32(copied);
2514+
rc = hwrm_send_message(bp, &modify, sizeof(modify),
2515+
FLASH_PACKAGE_TIMEOUT);
2516+
if (rc)
2517+
goto pkg_abort;
2518+
copied += len;
2519+
}
24902520
mutex_lock(&bp->hwrm_cmd_lock);
24912521
rc = _hwrm_send_message_silent(bp, &install, sizeof(install),
24922522
INSTALL_PACKAGE_TIMEOUT);
@@ -2530,7 +2560,8 @@ int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware
25302560
mutex_unlock(&bp->hwrm_cmd_lock);
25312561
} while (defrag_attempted && !rc);
25322562

2533-
dma_free_coherent(&bp->pdev->dev, fw->size, kmem, dma_handle);
2563+
pkg_abort:
2564+
dma_free_coherent(&bp->pdev->dev, modify_len, kmem, dma_handle);
25342565
if (resp.result) {
25352566
netdev_err(dev, "PKG install error = %d, problem_item = %d\n",
25362567
(s8)resp.result, (int)resp.problem_item);

0 commit comments

Comments
 (0)