msm: vidc: Use upstream api to load firmware image

Use upstream compliant APIs to, load and authenticate firmware image.
Downstream api, PIL/SSR, are deprecated.

Change-Id: I121c3c0276cdd84fa18ff8f65df45b3ac00e7443
Signed-off-by: Akshata Sahukar <asahukar@codeaurora.org>
Signed-off-by: Chinmay Sawarkar <chinmays@codeaurora.org>
This commit is contained in:
Akshata Sahukar
2020-06-02 14:33:47 -07:00
committed by Gerrit - the friendly Code Review server
parent 9b4556df59
commit 9099609e92
2 changed files with 120 additions and 13 deletions

View File

@@ -218,7 +218,7 @@ struct msm_vidc_dt {
struct list_head context_banks;
struct mutex cb_lock;
const char *fw_name;
void *fw_cookie;
int fw_cookie;
};
int msm_vidc_init_dt(struct platform_device *pdev);

View File

@@ -13,6 +13,10 @@
#include <linux/reset.h>
#include <linux/interconnect.h>
#include <soc/qcom/subsystem_restart.h>
#include <linux/of_address.h>
#include <linux/firmware.h>
#include <linux/qcom_scm.h>
#include <linux/soc/qcom/mdt_loader.h>
#include "venus_hfi.h"
#include "msm_vidc_core.h"
@@ -27,6 +31,8 @@
#define MIN_PAYLOAD_SIZE 3
#define MAX_FIRMWARE_NAME_SIZE 128
static int __resume(struct msm_vidc_core *core);
static int __suspend(struct msm_vidc_core *core);
@@ -2246,13 +2252,112 @@ fail_alloc_queue:
return -ENOMEM;
}
static int __load_fw_to_memory(struct platform_device *pdev,
const char *fw_name)
{
int rc = 0;
const struct firmware *firmware = NULL;
char firmware_name[MAX_FIRMWARE_NAME_SIZE] = { 0 };
struct device_node *node = NULL;
struct resource res = { 0 };
phys_addr_t phys = 0;
size_t res_size = 0;
ssize_t fw_size = 0;
void *virt = NULL;
int pas_id = 0;
if (!fw_name || !(*fw_name) || !pdev) {
d_vpr_e("%s: Invalid inputs\n", __func__);
return -EINVAL;
}
if (strlen(fw_name) >= MAX_FIRMWARE_NAME_SIZE - 4) {
d_vpr_e("%s: Invalid fw name\n", __func__);
return -EINVAL;
}
scnprintf(firmware_name, ARRAY_SIZE(firmware_name), "%s.mdt", fw_name);
rc = of_property_read_u32(pdev->dev.of_node, "pas-id", &pas_id);
if (rc) {
d_vpr_e("%s: failed to read \"pas-id\". error %d\n",
__func__, rc);
goto exit;
}
node = of_parse_phandle(pdev->dev.of_node, "memory-region", 0);
if (!node) {
d_vpr_e("%s: failed to read \"memory-region\"\n",
__func__);
return -EINVAL;
}
rc = of_address_to_resource(node, 0, &res);
if (rc) {
d_vpr_e("%s: failed to read \"memory-region\", error %d\n",
__func__, rc);
goto exit;
}
phys = res.start;
res_size = (size_t)resource_size(&res);
rc = request_firmware(&firmware, firmware_name, &pdev->dev);
if (rc) {
d_vpr_e("%s: failed to request fw \"%s\", error %d\n",
__func__, rc, firmware_name);
goto exit;
}
fw_size = qcom_mdt_get_size(firmware);
if (fw_size < 0 || res_size < (size_t)fw_size) {
rc = -EINVAL;
d_vpr_e("%s: out of bound fw image fw size: %ld, res_size: %lu",
__func__, fw_size, res_size);
goto exit;
}
virt = memremap(phys, res_size, MEMREMAP_WC);
if (!virt) {
d_vpr_e("%s: failed to remap fw memory phys %pa[p]\n",
__func__, phys);
return -ENOMEM;
}
rc = qcom_mdt_load(&pdev->dev, firmware, firmware_name,
pas_id, virt, phys, res_size, NULL);
if (rc) {
d_vpr_e("%s: error %d loading fw \"%s\"\n",
__func__, rc, firmware_name);
goto exit;
}
rc = qcom_scm_pas_auth_and_reset(pas_id);
if (rc) {
d_vpr_e("%s: error %d authenticating fw \"%s\"\n",
__func__, rc, firmware_name);
goto exit;
}
memunmap(virt);
release_firmware(firmware);
d_vpr_h("%s: firmware \"%s\" loaded successfully\n",
__func__, firmware_name);
return pas_id;
exit:
if (virt)
memunmap(virt);
if (firmware)
release_firmware(firmware);
return rc;
}
static int __load_fw(struct msm_vidc_core *core)
{
int rc = 0;
rc = __init_resources(core);
if (rc) {
d_vpr_e("Failed to init resources: %d\n", rc);
d_vpr_e("%s: Failed to init resources: %d\n", __func__, rc);
goto fail_init_res;
}
@@ -2263,11 +2368,12 @@ static int __load_fw(struct msm_vidc_core *core)
}
if (!core->dt->fw_cookie) {
core->dt->fw_cookie = subsystem_get_with_fwname("venus",
core->dt->fw_name);
if (IS_ERR_OR_NULL(core->dt->fw_cookie)) {
d_vpr_e("%s: firmware download failed\n", __func__);
core->dt->fw_cookie = NULL;
core->dt->fw_cookie = __load_fw_to_memory(core->pdev,
core->dt->fw_name);
if (core->dt->fw_cookie <= 0) {
d_vpr_e("%s: firmware download failed %d\n",
__func__, core->dt->fw_cookie);
core->dt->fw_cookie = 0;
rc = -ENOMEM;
goto fail_load_fw;
}
@@ -2284,14 +2390,13 @@ static int __load_fw(struct msm_vidc_core *core)
* (s/w triggered) to fast (HW triggered) unless the h/w vote is
* present.
*/
if (__enable_hw_power_collapse(core))
d_vpr_e("%s: hardware power collapse unsuccessful\n", __func__);
__enable_hw_power_collapse(core);
return rc;
fail_protect_mem:
if (core->dt->fw_cookie)
subsystem_put(core->dt->fw_cookie);
core->dt->fw_cookie = NULL;
qcom_scm_pas_shutdown(core->dt->fw_cookie);
core->dt->fw_cookie = 0;
fail_load_fw:
call_venus_op(core, power_off, core);
fail_venus_power_on:
@@ -2309,10 +2414,12 @@ static void __unload_fw(struct msm_vidc_core *core)
if (core->state != MSM_VIDC_CORE_DEINIT)
flush_workqueue(core->pm_workq);
subsystem_put(core->dt->fw_cookie);
qcom_scm_pas_shutdown(core->dt->fw_cookie);
core->dt->fw_cookie = 0;
__interface_queues_release(core);
call_venus_op(core, power_off, core);
core->dt->fw_cookie = NULL;
__deinit_resources(core);
d_vpr_h("Firmware unloaded successfully\n");