2020-07-09 11:59:29

by Stanimir Varbanov

[permalink] [raw]
Subject: [PATCH 0/2] Venus - fix firmware load failure

Hi,

These two patches fixed the problem with "failed to reset venus core"
seen with various firmware versions (including the one from linux-firmware)
on sdm845 and sdm850.

regards,
Stan

Stanimir Varbanov (2):
firmware: qcom_scm: Add memory protect virtual address ranges
venus: firmware: Set virtual address ranges

drivers/firmware/qcom_scm.c | 24 ++++++++++++++++++++
drivers/firmware/qcom_scm.h | 1 +
drivers/media/platform/qcom/venus/core.c | 4 ++++
drivers/media/platform/qcom/venus/core.h | 4 ++++
drivers/media/platform/qcom/venus/firmware.c | 18 ++++++++++++++-
include/linux/qcom_scm.h | 8 ++++++-
6 files changed, 57 insertions(+), 2 deletions(-)

--
2.17.1


2020-07-09 11:59:37

by Stanimir Varbanov

[permalink] [raw]
Subject: [PATCH 1/2] firmware: qcom_scm: Add memory protect virtual address ranges

This adds a new SCM memprotect command to set virtual address ranges.

Signed-off-by: Stanimir Varbanov <[email protected]>
---
drivers/firmware/qcom_scm.c | 24 ++++++++++++++++++++++++
drivers/firmware/qcom_scm.h | 1 +
include/linux/qcom_scm.h | 8 +++++++-
3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index 0e7233a20f34..a73870255c2e 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -864,6 +864,30 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
}
EXPORT_SYMBOL(qcom_scm_assign_mem);

+int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size,
+ u32 cp_nonpixel_start,
+ u32 cp_nonpixel_size)
+{
+ int ret;
+ struct qcom_scm_desc desc = {
+ .svc = QCOM_SCM_SVC_MP,
+ .cmd = QCOM_SCM_MP_VIDEO_VAR,
+ .arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_VAL, QCOM_SCM_VAL,
+ QCOM_SCM_VAL, QCOM_SCM_VAL),
+ .args[0] = cp_start,
+ .args[1] = cp_size,
+ .args[2] = cp_nonpixel_start,
+ .args[3] = cp_nonpixel_size,
+ .owner = ARM_SMCCC_OWNER_SIP,
+ };
+ struct qcom_scm_res res;
+
+ ret = qcom_scm_call(__scm->dev, &desc, &res);
+
+ return ret ? : res.result[0];
+}
+EXPORT_SYMBOL(qcom_scm_mem_protect_video_var);
+
/**
* qcom_scm_ocmem_lock_available() - is OCMEM lock/unlock interface available
*/
diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
index d9ed670da222..14da834ac593 100644
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -97,6 +97,7 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
#define QCOM_SCM_MP_RESTORE_SEC_CFG 0x02
#define QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE 0x03
#define QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT 0x04
+#define QCOM_SCM_MP_VIDEO_VAR 0x08
#define QCOM_SCM_MP_ASSIGN 0x16

#define QCOM_SCM_SVC_OCMEM 0x0f
diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h
index 3d6a24697761..19b5188d17f4 100644
--- a/include/linux/qcom_scm.h
+++ b/include/linux/qcom_scm.h
@@ -81,7 +81,9 @@ extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
unsigned int *src,
const struct qcom_scm_vmperm *newvm,
unsigned int dest_cnt);
-
+extern int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size,
+ u32 cp_nonpixel_start,
+ u32 cp_nonpixel_size);
extern bool qcom_scm_ocmem_lock_available(void);
extern int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset,
u32 size, u32 mode);
@@ -131,6 +133,10 @@ static inline int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
static inline int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
unsigned int *src, const struct qcom_scm_vmperm *newvm,
unsigned int dest_cnt) { return -ENODEV; }
+extern inline int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size,
+ u32 cp_nonpixel_start,
+ u32 cp_nonpixel_size)
+ { return -ENODEV; }

static inline bool qcom_scm_ocmem_lock_available(void) { return false; }
static inline int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset,
--
2.17.1

2020-07-09 12:01:49

by Stanimir Varbanov

[permalink] [raw]
Subject: [PATCH 2/2] venus: firmware: Set virtual address ranges

In order to boot some of the new Venus firmware versions TZ call to set
virtual address ranges is needed. Add virtual address ranges for CP and
CP_NONPIX in resource structure and use them when loading and booting
the firmware on remote processor.

Signed-off-by: Stanimir Varbanov <[email protected]>
---
drivers/media/platform/qcom/venus/core.c | 4 ++++
drivers/media/platform/qcom/venus/core.h | 4 ++++
drivers/media/platform/qcom/venus/firmware.c | 18 +++++++++++++++++-
3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
index 203c6538044f..5f8f7b72731c 100644
--- a/drivers/media/platform/qcom/venus/core.c
+++ b/drivers/media/platform/qcom/venus/core.c
@@ -527,6 +527,10 @@ static const struct venus_resources sdm845_res_v2 = {
.vmem_size = 0,
.vmem_addr = 0,
.dma_mask = 0xe0000000 - 1,
+ .cp_start = 0,
+ .cp_size = 0x70800000,
+ .cp_nonpixel_start = 0x1000000,
+ .cp_nonpixel_size = 0x24800000,
.fwname = "qcom/venus-5.2/venus.mdt",
};

diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h
index 7118612673c9..8c88516e4694 100644
--- a/drivers/media/platform/qcom/venus/core.h
+++ b/drivers/media/platform/qcom/venus/core.h
@@ -68,6 +68,10 @@ struct venus_resources {
unsigned int vmem_id;
u32 vmem_size;
u32 vmem_addr;
+ u32 cp_start;
+ u32 cp_size;
+ u32 cp_nonpixel_start;
+ u32 cp_nonpixel_size;
const char *fwname;
};

diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c
index 8801a6a7543d..ac906ffc608f 100644
--- a/drivers/media/platform/qcom/venus/firmware.c
+++ b/drivers/media/platform/qcom/venus/firmware.c
@@ -181,6 +181,7 @@ static int venus_shutdown_no_tz(struct venus_core *core)
int venus_boot(struct venus_core *core)
{
struct device *dev = core->dev;
+ const struct venus_resources *res = core->res;
phys_addr_t mem_phys;
size_t mem_size;
int ret;
@@ -200,7 +201,22 @@ int venus_boot(struct venus_core *core)
else
ret = venus_boot_no_tz(core, mem_phys, mem_size);

- return ret;
+ if (ret)
+ return ret;
+
+ if (core->use_tz && res->cp_size) {
+ ret = qcom_scm_mem_protect_video_var(res->cp_start,
+ res->cp_size,
+ res->cp_nonpixel_start,
+ res->cp_nonpixel_size);
+ if (ret) {
+ dev_err(dev, "set virtual address ranges fail (%d)\n",
+ ret);
+ return ret;
+ }
+ }
+
+ return 0;
}

int venus_shutdown(struct venus_core *core)
--
2.17.1

2020-07-24 15:05:26

by Stanimir Varbanov

[permalink] [raw]
Subject: Re: [PATCH 1/2] firmware: qcom_scm: Add memory protect virtual address ranges

Hi,

Gentle ping for review.

On 7/9/20 2:58 PM, Stanimir Varbanov wrote:
> This adds a new SCM memprotect command to set virtual address ranges.
>
> Signed-off-by: Stanimir Varbanov <[email protected]>
> ---
> drivers/firmware/qcom_scm.c | 24 ++++++++++++++++++++++++
> drivers/firmware/qcom_scm.h | 1 +
> include/linux/qcom_scm.h | 8 +++++++-
> 3 files changed, 32 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
> index 0e7233a20f34..a73870255c2e 100644
> --- a/drivers/firmware/qcom_scm.c
> +++ b/drivers/firmware/qcom_scm.c
> @@ -864,6 +864,30 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
> }
> EXPORT_SYMBOL(qcom_scm_assign_mem);
>
> +int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size,
> + u32 cp_nonpixel_start,
> + u32 cp_nonpixel_size)
> +{
> + int ret;
> + struct qcom_scm_desc desc = {
> + .svc = QCOM_SCM_SVC_MP,
> + .cmd = QCOM_SCM_MP_VIDEO_VAR,
> + .arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_VAL, QCOM_SCM_VAL,
> + QCOM_SCM_VAL, QCOM_SCM_VAL),
> + .args[0] = cp_start,
> + .args[1] = cp_size,
> + .args[2] = cp_nonpixel_start,
> + .args[3] = cp_nonpixel_size,
> + .owner = ARM_SMCCC_OWNER_SIP,
> + };
> + struct qcom_scm_res res;
> +
> + ret = qcom_scm_call(__scm->dev, &desc, &res);
> +
> + return ret ? : res.result[0];
> +}
> +EXPORT_SYMBOL(qcom_scm_mem_protect_video_var);
> +
> /**
> * qcom_scm_ocmem_lock_available() - is OCMEM lock/unlock interface available
> */
> diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
> index d9ed670da222..14da834ac593 100644
> --- a/drivers/firmware/qcom_scm.h
> +++ b/drivers/firmware/qcom_scm.h
> @@ -97,6 +97,7 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
> #define QCOM_SCM_MP_RESTORE_SEC_CFG 0x02
> #define QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE 0x03
> #define QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT 0x04
> +#define QCOM_SCM_MP_VIDEO_VAR 0x08
> #define QCOM_SCM_MP_ASSIGN 0x16
>
> #define QCOM_SCM_SVC_OCMEM 0x0f
> diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h
> index 3d6a24697761..19b5188d17f4 100644
> --- a/include/linux/qcom_scm.h
> +++ b/include/linux/qcom_scm.h
> @@ -81,7 +81,9 @@ extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
> unsigned int *src,
> const struct qcom_scm_vmperm *newvm,
> unsigned int dest_cnt);
> -
> +extern int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size,
> + u32 cp_nonpixel_start,
> + u32 cp_nonpixel_size);
> extern bool qcom_scm_ocmem_lock_available(void);
> extern int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset,
> u32 size, u32 mode);
> @@ -131,6 +133,10 @@ static inline int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
> static inline int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
> unsigned int *src, const struct qcom_scm_vmperm *newvm,
> unsigned int dest_cnt) { return -ENODEV; }
> +extern inline int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size,
> + u32 cp_nonpixel_start,
> + u32 cp_nonpixel_size)
> + { return -ENODEV; }
>
> static inline bool qcom_scm_ocmem_lock_available(void) { return false; }
> static inline int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset,
>

--
regards,
Stan

2020-07-29 17:16:42

by Elliot Berman

[permalink] [raw]
Subject: Re: [PATCH 1/2] firmware: qcom_scm: Add memory protect virtual address ranges

++

On 7/24/2020 8:04 AM, Stanimir Varbanov wrote:
> Hi,
>
> Gentle ping for review.
>
> On 7/9/20 2:58 PM, Stanimir Varbanov wrote:
>> This adds a new SCM memprotect command to set virtual address ranges.
>>
>> Signed-off-by: Stanimir Varbanov <[email protected]>
>> ---
>> drivers/firmware/qcom_scm.c | 24 ++++++++++++++++++++++++
>> drivers/firmware/qcom_scm.h | 1 +
>> include/linux/qcom_scm.h | 8 +++++++-
>> 3 files changed, 32 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
>> index 0e7233a20f34..a73870255c2e 100644
>> --- a/drivers/firmware/qcom_scm.c
>> +++ b/drivers/firmware/qcom_scm.c
>> @@ -864,6 +864,30 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
>> }
>> EXPORT_SYMBOL(qcom_scm_assign_mem);
>>
>> +int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size,
>> + u32 cp_nonpixel_start,
>> + u32 cp_nonpixel_size)
>> +{
>> + int ret;
>> + struct qcom_scm_desc desc = {
>> + .svc = QCOM_SCM_SVC_MP,
>> + .cmd = QCOM_SCM_MP_VIDEO_VAR,
>> + .arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_VAL, QCOM_SCM_VAL,
>> + QCOM_SCM_VAL, QCOM_SCM_VAL),
>> + .args[0] = cp_start,
>> + .args[1] = cp_size,
>> + .args[2] = cp_nonpixel_start,
>> + .args[3] = cp_nonpixel_size,
>> + .owner = ARM_SMCCC_OWNER_SIP,
>> + };
>> + struct qcom_scm_res res;
>> +
>> + ret = qcom_scm_call(__scm->dev, &desc, &res);
>> +
>> + return ret ? : res.result[0];
>> +}
>> +EXPORT_SYMBOL(qcom_scm_mem_protect_video_var);
>> +

Small nit, can you bump the function above assign_mem? It would keep order aligned with
the macros in qcom_scm.h

>> /**
>> * qcom_scm_ocmem_lock_available() - is OCMEM lock/unlock interface available
>> */
>> diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
>> index d9ed670da222..14da834ac593 100644
>> --- a/drivers/firmware/qcom_scm.h
>> +++ b/drivers/firmware/qcom_scm.h
>> @@ -97,6 +97,7 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
>> #define QCOM_SCM_MP_RESTORE_SEC_CFG 0x02
>> #define QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE 0x03
>> #define QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT 0x04
>> +#define QCOM_SCM_MP_VIDEO_VAR 0x08
>> #define QCOM_SCM_MP_ASSIGN 0x16
>>
>> #define QCOM_SCM_SVC_OCMEM 0x0f
>> diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h
>> index 3d6a24697761..19b5188d17f4 100644
>> --- a/include/linux/qcom_scm.h
>> +++ b/include/linux/qcom_scm.h
>> @@ -81,7 +81,9 @@ extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
>> unsigned int *src,
>> const struct qcom_scm_vmperm *newvm,
>> unsigned int dest_cnt);
>> -
>> +extern int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size,
>> + u32 cp_nonpixel_start,
>> + u32 cp_nonpixel_size);

Same here.

>> extern bool qcom_scm_ocmem_lock_available(void);
>> extern int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset,
>> u32 size, u32 mode);
>> @@ -131,6 +133,10 @@ static inline int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
>> static inline int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
>> unsigned int *src, const struct qcom_scm_vmperm *newvm,
>> unsigned int dest_cnt) { return -ENODEV; }
>> +extern inline int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size,
>> + u32 cp_nonpixel_start,
>> + u32 cp_nonpixel_size)
>> + { return -ENODEV; }

Same here.

>>
>> static inline bool qcom_scm_ocmem_lock_available(void) { return false; }
>> static inline int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset,
>>
>

--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

2020-07-31 09:50:53

by Stanimir Varbanov

[permalink] [raw]
Subject: Re: [PATCH 1/2] firmware: qcom_scm: Add memory protect virtual address ranges

Hi Elliot,

Thanks for the comments!

On 7/29/20 8:15 PM, Elliot Berman wrote:
> ++
>
> On 7/24/2020 8:04 AM, Stanimir Varbanov wrote:
>> Hi,
>>
>> Gentle ping for review.
>>
>> On 7/9/20 2:58 PM, Stanimir Varbanov wrote:
>>> This adds a new SCM memprotect command to set virtual address ranges.
>>>
>>> Signed-off-by: Stanimir Varbanov <[email protected]>
>>> ---
>>> drivers/firmware/qcom_scm.c | 24 ++++++++++++++++++++++++
>>> drivers/firmware/qcom_scm.h | 1 +
>>> include/linux/qcom_scm.h | 8 +++++++-
>>> 3 files changed, 32 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
>>> index 0e7233a20f34..a73870255c2e 100644
>>> --- a/drivers/firmware/qcom_scm.c
>>> +++ b/drivers/firmware/qcom_scm.c
>>> @@ -864,6 +864,30 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
>>> }
>>> EXPORT_SYMBOL(qcom_scm_assign_mem);
>>>
>>> +int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size,
>>> + u32 cp_nonpixel_start,
>>> + u32 cp_nonpixel_size)
>>> +{
>>> + int ret;
>>> + struct qcom_scm_desc desc = {
>>> + .svc = QCOM_SCM_SVC_MP,
>>> + .cmd = QCOM_SCM_MP_VIDEO_VAR,
>>> + .arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_VAL, QCOM_SCM_VAL,
>>> + QCOM_SCM_VAL, QCOM_SCM_VAL),
>>> + .args[0] = cp_start,
>>> + .args[1] = cp_size,
>>> + .args[2] = cp_nonpixel_start,
>>> + .args[3] = cp_nonpixel_size,
>>> + .owner = ARM_SMCCC_OWNER_SIP,
>>> + };
>>> + struct qcom_scm_res res;
>>> +
>>> + ret = qcom_scm_call(__scm->dev, &desc, &res);
>>> +
>>> + return ret ? : res.result[0];
>>> +}
>>> +EXPORT_SYMBOL(qcom_scm_mem_protect_video_var);
>>> +
>
> Small nit, can you bump the function above assign_mem? It would keep order aligned with
> the macros in qcom_scm.h

Sure, I will do that.

>
>>> /**
>>> * qcom_scm_ocmem_lock_available() - is OCMEM lock/unlock interface available
>>> */
>>> diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
>>> index d9ed670da222..14da834ac593 100644
>>> --- a/drivers/firmware/qcom_scm.h
>>> +++ b/drivers/firmware/qcom_scm.h
>>> @@ -97,6 +97,7 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
>>> #define QCOM_SCM_MP_RESTORE_SEC_CFG 0x02
>>> #define QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE 0x03
>>> #define QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT 0x04
>>> +#define QCOM_SCM_MP_VIDEO_VAR 0x08
>>> #define QCOM_SCM_MP_ASSIGN 0x16
>>>
>>> #define QCOM_SCM_SVC_OCMEM 0x0f
>>> diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h
>>> index 3d6a24697761..19b5188d17f4 100644
>>> --- a/include/linux/qcom_scm.h
>>> +++ b/include/linux/qcom_scm.h
>>> @@ -81,7 +81,9 @@ extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
>>> unsigned int *src,
>>> const struct qcom_scm_vmperm *newvm,
>>> unsigned int dest_cnt);
>>> -
>>> +extern int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size,
>>> + u32 cp_nonpixel_start,
>>> + u32 cp_nonpixel_size);
>
> Same here.
>
>>> extern bool qcom_scm_ocmem_lock_available(void);
>>> extern int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset,
>>> u32 size, u32 mode);
>>> @@ -131,6 +133,10 @@ static inline int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
>>> static inline int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
>>> unsigned int *src, const struct qcom_scm_vmperm *newvm,
>>> unsigned int dest_cnt) { return -ENODEV; }
>>> +extern inline int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size,
>>> + u32 cp_nonpixel_start,
>>> + u32 cp_nonpixel_size)
>>> + { return -ENODEV; }
>
> Same here.
>
>>>
>>> static inline bool qcom_scm_ocmem_lock_available(void) { return false; }
>>> static inline int qcom_scm_ocmem_lock(enum qcom_scm_ocmem_client id, u32 offset,
>>>
>>
>

--
regards,
Stan