diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 54c0a66d6dd6..11ca8223fbcd 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -1230,6 +1230,8 @@ EXPORT_SYMBOL_GPL(geni_se_resources_init); * @se: Pointer to the serial engine structure. * @fw: Pointer to the firmware image. * @protocol: Expected serial engine protocol type. + * @fw_size_out: Non-NULL output parameter; receives the rounded, validated + * firmware word count on success. * * Identifies the appropriate firmware image or configuration required for a * specific communication protocol instance running on a Qualcomm GENI @@ -1239,7 +1241,8 @@ EXPORT_SYMBOL_GPL(geni_se_resources_init); * Return: pointer to a valid 'struct se_fw_hdr' if found, or NULL otherwise. */ static struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const struct firmware *fw, - enum geni_se_protocol_type protocol) + enum geni_se_protocol_type protocol, + u32 *fw_size_out) { struct device *dev = se->dev; const struct elf32_hdr *ehdr; @@ -1289,11 +1292,6 @@ static struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const struct sefw = (struct se_fw_hdr *)(fw->data + phdr->p_offset); fw_size = le16_to_cpu(sefw->fw_size_in_items); - fw_end = le16_to_cpu(sefw->fw_offset) + fw_size * sizeof(u32); - cfg_idx_end = le16_to_cpu(sefw->cfg_idx_offset) + - le16_to_cpu(sefw->cfg_size_in_items) * sizeof(u8); - cfg_val_end = le16_to_cpu(sefw->cfg_val_offset) + - le16_to_cpu(sefw->cfg_size_in_items) * sizeof(u32); if (le32_to_cpu(sefw->magic) != SE_MAGIC_NUM || le32_to_cpu(sefw->version) != 1) continue; @@ -1306,6 +1304,12 @@ static struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const struct sefw->fw_size_in_items = cpu_to_le16(fw_size); } + fw_end = le16_to_cpu(sefw->fw_offset) + fw_size * sizeof(u32); + cfg_idx_end = le16_to_cpu(sefw->cfg_idx_offset) + + le16_to_cpu(sefw->cfg_size_in_items) * sizeof(u8); + cfg_val_end = le16_to_cpu(sefw->cfg_val_offset) + + le16_to_cpu(sefw->cfg_size_in_items) * sizeof(u32); + prog_ram_depth = FIELD_GET(PROG_RAM_DEPTH_MSK, readl_relaxed(se->base + SE_HW_PARAM_2)); if (fw_size >= prog_ram_depth) { @@ -1320,6 +1324,7 @@ static struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const struct continue; } + *fw_size_out = fw_size; return sefw; } @@ -1430,11 +1435,11 @@ static int geni_load_se_fw(struct geni_se *se, const struct firmware *fw, { const u32 *fw_data, *cfg_val_arr; const u8 *cfg_idx_arr; - u32 i, reg_value; + u32 i, reg_value, fw_size_in_items; int ret; struct se_fw_hdr *hdr; - hdr = geni_find_protocol_fw(se, fw, protocol); + hdr = geni_find_protocol_fw(se, fw, protocol, &fw_size_in_items); if (!hdr) return -EINVAL; @@ -1511,7 +1516,7 @@ static int geni_load_se_fw(struct geni_se *se, const struct firmware *fw, /* Program RAM address space. */ memcpy_toio(se->base + SE_GENI_CFG_RAMN, fw_data, - le16_to_cpu(hdr->fw_size_in_items) * sizeof(u32)); + fw_size_in_items * sizeof(u32)); /* Put default values on GENI's output pads. */ writel_relaxed(0x1, se->base + GENI_FORCE_DEFAULT_REG);