From 52ea72ad0daa0f29535b4cef39257616c5a211d3 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 24 Oct 2023 00:00:19 +0200 Subject: [PATCH 1/5] net: ethernet: mtk_wed: fix firmware loading for MT7986 SoC The WED mcu firmware does not contain all the memory regions defined in the dts reserved_memory node (e.g. MT7986 WED firmware does not contain cpu-boot region). Reverse the mtk_wed_mcu_run_firmware() logic to check all the fw sections are defined in the dts reserved_memory node. Fixes: c6d961aeaa77 ("net: ethernet: mtk_wed: move mem_region array out of mtk_wed_mcu_load_firmware") Tested-by: Frank Wunderlich Signed-off-by: Lorenzo Bianconi Reviewed-by: Jacob Keller Link: https://lore.kernel.org/r/d983cbfe8ea562fef9264de8f0c501f7d5705bd5.1698098381.git.lorenzo@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 48 +++++++++++---------- 1 file changed, 25 insertions(+), 23 deletions(-) --- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c +++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c @@ -258,16 +258,12 @@ mtk_wed_get_memory_region(struct mtk_wed } static int -mtk_wed_mcu_run_firmware(struct mtk_wed_wo *wo, const struct firmware *fw, - struct mtk_wed_wo_memory_region *region) +mtk_wed_mcu_run_firmware(struct mtk_wed_wo *wo, const struct firmware *fw) { const u8 *first_region_ptr, *region_ptr, *trailer_ptr, *ptr = fw->data; const struct mtk_wed_fw_trailer *trailer; const struct mtk_wed_fw_region *fw_region; - if (!region->phy_addr || !region->size) - return 0; - trailer_ptr = fw->data + fw->size - sizeof(*trailer); trailer = (const struct mtk_wed_fw_trailer *)trailer_ptr; region_ptr = trailer_ptr - trailer->num_region * sizeof(*fw_region); @@ -275,33 +271,41 @@ mtk_wed_mcu_run_firmware(struct mtk_wed_ while (region_ptr < trailer_ptr) { u32 length; + int i; fw_region = (const struct mtk_wed_fw_region *)region_ptr; length = le32_to_cpu(fw_region->len); - - if (region->phy_addr != le32_to_cpu(fw_region->addr)) - goto next; - - if (region->size < length) - goto next; - if (first_region_ptr < ptr + length) goto next; - if (region->shared && region->consumed) - return 0; + for (i = 0; i < ARRAY_SIZE(mem_region); i++) { + struct mtk_wed_wo_memory_region *region; - if (!region->shared || !region->consumed) { - memcpy_toio(region->addr, ptr, length); - region->consumed = true; - return 0; + region = &mem_region[i]; + if (region->phy_addr != le32_to_cpu(fw_region->addr)) + continue; + + if (region->size < length) + continue; + + if (region->shared && region->consumed) + break; + + if (!region->shared || !region->consumed) { + memcpy_toio(region->addr, ptr, length); + region->consumed = true; + break; + } } + + if (i == ARRAY_SIZE(mem_region)) + return -EINVAL; next: region_ptr += sizeof(*fw_region); ptr += length; } - return -EINVAL; + return 0; } static int @@ -360,11 +364,9 @@ mtk_wed_mcu_load_firmware(struct mtk_wed dev_info(wo->hw->dev, "MTK WED WO Chip ID %02x Region %d\n", trailer->chip_id, trailer->num_region); - for (i = 0; i < ARRAY_SIZE(mem_region); i++) { - ret = mtk_wed_mcu_run_firmware(wo, fw, &mem_region[i]); - if (ret) - goto out; - } + ret = mtk_wed_mcu_run_firmware(wo, fw); + if (ret) + goto out; /* set the start address */ if (!mtk_wed_is_v3_or_greater(wo->hw) && wo->hw->index)