Commit 5792ae7c authored by Stanimir Varbanov's avatar Stanimir Varbanov Committed by Mauro Carvalho Chehab

media: venus: firmware: check fw size against DT memory region size

By historical reasons we defined firmware memory size to be 6MB even
that the firmware size for all supported Venus versions is 5MBs. Correct
that by compare the required firmware size returned from mdt loader and
the one provided by DT reserved memory region. We proceed further if the
required firmware size is smaller than provided by DT memory region.
Reviewed-by: default avatarAlexandre Courbot <acourbot@chromium.org>
Tested-by: default avatarAlexandre Courbot <acourbot@chromium.org>
Signed-off-by: default avatarStanimir Varbanov <stanimir.varbanov@linaro.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent adbd2969
...@@ -134,6 +134,7 @@ struct venus_core { ...@@ -134,6 +134,7 @@ struct venus_core {
struct video_firmware { struct video_firmware {
struct device *dev; struct device *dev;
struct iommu_domain *iommu_domain; struct iommu_domain *iommu_domain;
size_t mapped_mem_size;
} fw; } fw;
struct mutex lock; struct mutex lock;
struct list_head instances; struct list_head instances;
......
...@@ -35,14 +35,15 @@ ...@@ -35,14 +35,15 @@
static void venus_reset_cpu(struct venus_core *core) static void venus_reset_cpu(struct venus_core *core)
{ {
u32 fw_size = core->fw.mapped_mem_size;
void __iomem *base = core->base; void __iomem *base = core->base;
writel(0, base + WRAPPER_FW_START_ADDR); writel(0, base + WRAPPER_FW_START_ADDR);
writel(VENUS_FW_MEM_SIZE, base + WRAPPER_FW_END_ADDR); writel(fw_size, base + WRAPPER_FW_END_ADDR);
writel(0, base + WRAPPER_CPA_START_ADDR); writel(0, base + WRAPPER_CPA_START_ADDR);
writel(VENUS_FW_MEM_SIZE, base + WRAPPER_CPA_END_ADDR); writel(fw_size, base + WRAPPER_CPA_END_ADDR);
writel(VENUS_FW_MEM_SIZE, base + WRAPPER_NONPIX_START_ADDR); writel(fw_size, base + WRAPPER_NONPIX_START_ADDR);
writel(VENUS_FW_MEM_SIZE, base + WRAPPER_NONPIX_END_ADDR); writel(fw_size, base + WRAPPER_NONPIX_END_ADDR);
writel(0x0, base + WRAPPER_CPU_CGC_DIS); writel(0x0, base + WRAPPER_CPU_CGC_DIS);
writel(0x0, base + WRAPPER_CPU_CLOCK_CONFIG); writel(0x0, base + WRAPPER_CPU_CLOCK_CONFIG);
...@@ -74,6 +75,9 @@ static int venus_load_fw(struct venus_core *core, const char *fwname, ...@@ -74,6 +75,9 @@ static int venus_load_fw(struct venus_core *core, const char *fwname,
void *mem_va; void *mem_va;
int ret; int ret;
*mem_phys = 0;
*mem_size = 0;
dev = core->dev; dev = core->dev;
node = of_parse_phandle(dev->of_node, "memory-region", 0); node = of_parse_phandle(dev->of_node, "memory-region", 0);
if (!node) { if (!node) {
...@@ -85,28 +89,30 @@ static int venus_load_fw(struct venus_core *core, const char *fwname, ...@@ -85,28 +89,30 @@ static int venus_load_fw(struct venus_core *core, const char *fwname,
if (ret) if (ret)
return ret; return ret;
ret = request_firmware(&mdt, fwname, dev);
if (ret < 0)
return ret;
fw_size = qcom_mdt_get_size(mdt);
if (fw_size < 0) {
ret = fw_size;
goto err_release_fw;
}
*mem_phys = r.start; *mem_phys = r.start;
*mem_size = resource_size(&r); *mem_size = resource_size(&r);
if (*mem_size < VENUS_FW_MEM_SIZE) if (*mem_size < fw_size || fw_size > VENUS_FW_MEM_SIZE) {
return -EINVAL; ret = -EINVAL;
goto err_release_fw;
}
mem_va = memremap(r.start, *mem_size, MEMREMAP_WC); mem_va = memremap(r.start, *mem_size, MEMREMAP_WC);
if (!mem_va) { if (!mem_va) {
dev_err(dev, "unable to map memory region: %pa+%zx\n", dev_err(dev, "unable to map memory region: %pa+%zx\n",
&r.start, *mem_size); &r.start, *mem_size);
return -ENOMEM; ret = -ENOMEM;
} goto err_release_fw;
ret = request_firmware(&mdt, fwname, dev);
if (ret < 0)
goto err_unmap;
fw_size = qcom_mdt_get_size(mdt);
if (fw_size < 0) {
ret = fw_size;
release_firmware(mdt);
goto err_unmap;
} }
if (core->use_tz) if (core->use_tz)
...@@ -116,10 +122,9 @@ static int venus_load_fw(struct venus_core *core, const char *fwname, ...@@ -116,10 +122,9 @@ static int venus_load_fw(struct venus_core *core, const char *fwname,
ret = qcom_mdt_load_no_init(dev, mdt, fwname, VENUS_PAS_ID, ret = qcom_mdt_load_no_init(dev, mdt, fwname, VENUS_PAS_ID,
mem_va, *mem_phys, *mem_size, NULL); mem_va, *mem_phys, *mem_size, NULL);
release_firmware(mdt);
err_unmap:
memunmap(mem_va); memunmap(mem_va);
err_release_fw:
release_firmware(mdt);
return ret; return ret;
} }
...@@ -135,6 +140,7 @@ static int venus_boot_no_tz(struct venus_core *core, phys_addr_t mem_phys, ...@@ -135,6 +140,7 @@ static int venus_boot_no_tz(struct venus_core *core, phys_addr_t mem_phys,
return -EPROBE_DEFER; return -EPROBE_DEFER;
iommu = core->fw.iommu_domain; iommu = core->fw.iommu_domain;
core->fw.mapped_mem_size = mem_size;
ret = iommu_map(iommu, VENUS_FW_START_ADDR, mem_phys, mem_size, ret = iommu_map(iommu, VENUS_FW_START_ADDR, mem_phys, mem_size,
IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV); IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV);
...@@ -150,6 +156,7 @@ static int venus_boot_no_tz(struct venus_core *core, phys_addr_t mem_phys, ...@@ -150,6 +156,7 @@ static int venus_boot_no_tz(struct venus_core *core, phys_addr_t mem_phys,
static int venus_shutdown_no_tz(struct venus_core *core) static int venus_shutdown_no_tz(struct venus_core *core)
{ {
const size_t mapped = core->fw.mapped_mem_size;
struct iommu_domain *iommu; struct iommu_domain *iommu;
size_t unmapped; size_t unmapped;
u32 reg; u32 reg;
...@@ -166,8 +173,8 @@ static int venus_shutdown_no_tz(struct venus_core *core) ...@@ -166,8 +173,8 @@ static int venus_shutdown_no_tz(struct venus_core *core)
iommu = core->fw.iommu_domain; iommu = core->fw.iommu_domain;
unmapped = iommu_unmap(iommu, VENUS_FW_START_ADDR, VENUS_FW_MEM_SIZE); unmapped = iommu_unmap(iommu, VENUS_FW_START_ADDR, mapped);
if (unmapped != VENUS_FW_MEM_SIZE) if (unmapped != mapped)
dev_err(dev, "failed to unmap firmware\n"); dev_err(dev, "failed to unmap firmware\n");
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment