soc: qcom: geni-se: Use HW PROG_RAM_DEPTH to validate firmware size

The hardcoded MAX_GENI_CFG_RAMn_CNT limit is not accurate for all SoCs:
some targets have less CFG RAM than the constant implies, while others
like QCS615 need more entries than the old limit of 455 allowed, causing
valid firmware to be rejected at load time.

Rather than hardcoding a constant, read PROG_RAM_DEPTH from SE_HW_PARAM_2
at runtime to get the actual CFG RAM depth of the hardware instance and
use that as the upper bound for firmware size validation.

Fixes: d4bf06592a ("soc: qcom: geni-se: Add support to load QUP SE Firmware via Linux subsystem")
Cc: stable@vger.kernel.org
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20260702-qup-se-increase-ram-cnt-v3-1-80b363373a5b@oss.qualcomm.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
This commit is contained in:
Viken Dadhaniya 2026-07-02 11:12:23 +05:30 committed by Bjorn Andersson
parent b255c6f4e6
commit 522bfb4f33
2 changed files with 17 additions and 11 deletions

View File

@ -154,8 +154,6 @@ struct se_fw_hdr {
/*Magic numbers*/
#define SE_MAGIC_NUM 0x57464553
#define MAX_GENI_CFG_RAMn_CNT 455
#define MI_PBT_NON_PAGED_SEGMENT 0x0
#define MI_PBT_HASH_SEGMENT 0x2
#define MI_PBT_NOTUSED_SEGMENT 0x3
@ -1224,24 +1222,27 @@ EXPORT_SYMBOL_GPL(geni_se_resources_init);
/**
* geni_find_protocol_fw() - Locate and validate SE firmware for a protocol.
* @dev: Pointer to the device structure.
* @se: Pointer to the serial engine structure.
* @fw: Pointer to the firmware image.
* @protocol: Expected serial engine protocol type.
*
* Identifies the appropriate firmware image or configuration required for a
* specific communication protocol instance running on a Qualcomm GENI
* controller.
* specific communication protocol instance running on a Qualcomm GENI
* controller. Validates the firmware size against the hardware PROG_RAM_DEPTH
* read from SE_HW_PARAM_2.
*
* Return: pointer to a valid 'struct se_fw_hdr' if found, or NULL otherwise.
*/
static struct se_fw_hdr *geni_find_protocol_fw(struct device *dev, const struct firmware *fw,
static struct se_fw_hdr *geni_find_protocol_fw(struct geni_se *se, const struct firmware *fw,
enum geni_se_protocol_type protocol)
{
struct device *dev = se->dev;
const struct elf32_hdr *ehdr;
const struct elf32_phdr *phdrs;
const struct elf32_phdr *phdr;
struct se_fw_hdr *sefw;
u32 fw_end, cfg_idx_end, cfg_val_end;
u32 prog_ram_depth;
u16 fw_size;
int i;
@ -1300,10 +1301,11 @@ static struct se_fw_hdr *geni_find_protocol_fw(struct device *dev, const struct
sefw->fw_size_in_items = cpu_to_le16(fw_size);
}
if (fw_size >= MAX_GENI_CFG_RAMn_CNT) {
dev_err(dev,
"Firmware size (%u) exceeds max allowed RAMn count (%u)\n",
fw_size, MAX_GENI_CFG_RAMn_CNT);
prog_ram_depth = FIELD_GET(PROG_RAM_DEPTH_MSK,
readl_relaxed(se->base + SE_HW_PARAM_2));
if (fw_size >= prog_ram_depth) {
dev_err(dev, "Firmware size (%u) exceeds RAM size (%u)\n",
fw_size, prog_ram_depth);
continue;
}
@ -1427,7 +1429,7 @@ static int geni_load_se_fw(struct geni_se *se, const struct firmware *fw,
int ret;
struct se_fw_hdr *hdr;
hdr = geni_find_protocol_fw(se->dev, fw, protocol);
hdr = geni_find_protocol_fw(se, fw, protocol);
if (!hdr)
return -EINVAL;

View File

@ -124,6 +124,7 @@ struct geni_se {
#define SE_DMA_RX_FSM_RST 0xd58
#define SE_HW_PARAM_0 0xe24
#define SE_HW_PARAM_1 0xe28
#define SE_HW_PARAM_2 0xe2c
/* GENI_FORCE_DEFAULT_REG fields */
#define FORCE_DEFAULT BIT(0)
@ -291,6 +292,9 @@ struct geni_se {
#define RX_FIFO_DEPTH_MSK GENMASK(21, 16)
#define RX_FIFO_DEPTH_SHFT 16
/* SE_HW_PARAM_2 fields */
#define PROG_RAM_DEPTH_MSK GENMASK(10, 0)
#define HW_VER_MAJOR_MASK GENMASK(31, 28)
#define HW_VER_MAJOR_SHFT 28
#define HW_VER_MINOR_MASK GENMASK(27, 16)