From: Konrad Dybcio konrad.dybcio@linaro.org
[ Upstream commit bbfc89e6f67ccb1ddefc3e8a284248bcfea58544 ]
Currently we have macros to access these, but they don't provide a way to override the remapped fields. Replace the macros with actual get/set pairs to fix that.
Reviewed-by: Bryan O'Donoghue bryan.odonoghue@linaro.org Signed-off-by: Konrad Dybcio konrad.dybcio@linaro.org Signed-off-by: Stanimir Varbanov stanimir.k.varbanov@gmail.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Stable-dep-of: 06d6770ff0d8 ("media: venus: Fix OOB read due to missing payload bound check") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/platform/qcom/venus/helpers.c | 2 +- .../media/platform/qcom/venus/hfi_helper.h | 61 ++++++++++++++++--- drivers/media/platform/qcom/venus/hfi_msgs.c | 2 +- drivers/media/platform/qcom/venus/vdec.c | 8 +-- .../media/platform/qcom/venus/vdec_ctrls.c | 2 +- drivers/media/platform/qcom/venus/venc.c | 4 +- .../media/platform/qcom/venus/venc_ctrls.c | 2 +- 7 files changed, 63 insertions(+), 18 deletions(-)
diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index ca6555bdc92f..652ad33cbc4b 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -189,7 +189,7 @@ int venus_helper_alloc_dpb_bufs(struct venus_inst *inst) if (ret) return ret;
- count = HFI_BUFREQ_COUNT_MIN(&bufreq, ver); + count = hfi_bufreq_get_count_min(&bufreq, ver);
for (i = 0; i < count; i++) { buf = kzalloc(sizeof(*buf), GFP_KERNEL); diff --git a/drivers/media/platform/qcom/venus/hfi_helper.h b/drivers/media/platform/qcom/venus/hfi_helper.h index d2d6719a2ba4..d71355a64c91 100644 --- a/drivers/media/platform/qcom/venus/hfi_helper.h +++ b/drivers/media/platform/qcom/venus/hfi_helper.h @@ -1150,14 +1150,6 @@ struct hfi_buffer_display_hold_count_actual { u32 hold_count; };
-/* HFI 4XX reorder the fields, use these macros */ -#define HFI_BUFREQ_HOLD_COUNT(bufreq, ver) \ - ((ver) == HFI_VERSION_4XX ? 0 : (bufreq)->hold_count) -#define HFI_BUFREQ_COUNT_MIN(bufreq, ver) \ - ((ver) == HFI_VERSION_4XX ? (bufreq)->hold_count : (bufreq)->count_min) -#define HFI_BUFREQ_COUNT_MIN_HOST(bufreq, ver) \ - ((ver) == HFI_VERSION_4XX ? (bufreq)->count_min : 0) - struct hfi_buffer_requirements { u32 type; u32 size; @@ -1169,6 +1161,59 @@ struct hfi_buffer_requirements { u32 alignment; };
+/* On HFI 4XX, some of the struct members have been swapped. */ +static inline u32 hfi_bufreq_get_hold_count(struct hfi_buffer_requirements *req, + u32 ver) +{ + if (ver == HFI_VERSION_4XX) + return 0; + + return req->hold_count; +}; + +static inline u32 hfi_bufreq_get_count_min(struct hfi_buffer_requirements *req, + u32 ver) +{ + if (ver == HFI_VERSION_4XX) + return req->hold_count; + + return req->count_min; +}; + +static inline u32 hfi_bufreq_get_count_min_host(struct hfi_buffer_requirements *req, + u32 ver) +{ + if (ver == HFI_VERSION_4XX) + return req->count_min; + + return 0; +}; + +static inline void hfi_bufreq_set_hold_count(struct hfi_buffer_requirements *req, + u32 ver, u32 val) +{ + if (ver == HFI_VERSION_4XX) + return; + + req->hold_count = val; +}; + +static inline void hfi_bufreq_set_count_min(struct hfi_buffer_requirements *req, + u32 ver, u32 val) +{ + if (ver == HFI_VERSION_4XX) + req->hold_count = val; + + req->count_min = val; +}; + +static inline void hfi_bufreq_set_count_min_host(struct hfi_buffer_requirements *req, + u32 ver, u32 val) +{ + if (ver == HFI_VERSION_4XX) + req->count_min = val; +}; + struct hfi_data_payload { u32 size; u8 data[1]; diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c index 1c5cc5a5f89a..c11bf20daace 100644 --- a/drivers/media/platform/qcom/venus/hfi_msgs.c +++ b/drivers/media/platform/qcom/venus/hfi_msgs.c @@ -99,7 +99,7 @@ static void event_seq_changed(struct venus_core *core, struct venus_inst *inst, case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS: data_ptr += sizeof(u32); bufreq = (struct hfi_buffer_requirements *)data_ptr; - event.buf_count = HFI_BUFREQ_COUNT_MIN(bufreq, ver); + event.buf_count = hfi_bufreq_get_count_min(bufreq, ver); data_ptr += sizeof(*bufreq); break; case HFI_INDEX_EXTRADATA_INPUT_CROP: diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 3b51d603605e..e803a405cc35 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -865,13 +865,13 @@ static int vdec_num_buffers(struct venus_inst *inst, unsigned int *in_num, if (ret) return ret;
- *in_num = HFI_BUFREQ_COUNT_MIN(&bufreq, ver); + *in_num = hfi_bufreq_get_count_min(&bufreq, ver);
ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq); if (ret) return ret;
- *out_num = HFI_BUFREQ_COUNT_MIN(&bufreq, ver); + *out_num = hfi_bufreq_get_count_min(&bufreq, ver);
return 0; } @@ -985,14 +985,14 @@ static int vdec_verify_conf(struct venus_inst *inst) return ret;
if (inst->num_output_bufs < bufreq.count_actual || - inst->num_output_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver)) + inst->num_output_bufs < hfi_bufreq_get_count_min(&bufreq, ver)) return -EINVAL;
ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq); if (ret) return ret;
- if (inst->num_input_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver)) + if (inst->num_input_bufs < hfi_bufreq_get_count_min(&bufreq, ver)) return -EINVAL;
return 0; diff --git a/drivers/media/platform/qcom/venus/vdec_ctrls.c b/drivers/media/platform/qcom/venus/vdec_ctrls.c index fbe12a608b21..7e0f29bf7fae 100644 --- a/drivers/media/platform/qcom/venus/vdec_ctrls.c +++ b/drivers/media/platform/qcom/venus/vdec_ctrls.c @@ -79,7 +79,7 @@ static int vdec_op_g_volatile_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq); if (!ret) - ctrl->val = HFI_BUFREQ_COUNT_MIN(&bufreq, ver); + ctrl->val = hfi_bufreq_get_count_min(&bufreq, ver); break; default: return -EINVAL; diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index abd25720b96b..43b033623f3a 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -1177,7 +1177,7 @@ static int venc_verify_conf(struct venus_inst *inst) return ret;
if (inst->num_output_bufs < bufreq.count_actual || - inst->num_output_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver)) + inst->num_output_bufs < hfi_bufreq_get_count_min(&bufreq, ver)) return -EINVAL;
ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq); @@ -1185,7 +1185,7 @@ static int venc_verify_conf(struct venus_inst *inst) return ret;
if (inst->num_input_bufs < bufreq.count_actual || - inst->num_input_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver)) + inst->num_input_bufs < hfi_bufreq_get_count_min(&bufreq, ver)) return -EINVAL;
return 0; diff --git a/drivers/media/platform/qcom/venus/venc_ctrls.c b/drivers/media/platform/qcom/venus/venc_ctrls.c index 7468e43800a9..d9d2a293f3ef 100644 --- a/drivers/media/platform/qcom/venus/venc_ctrls.c +++ b/drivers/media/platform/qcom/venus/venc_ctrls.c @@ -358,7 +358,7 @@ static int venc_op_g_volatile_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT: ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq); if (!ret) - ctrl->val = HFI_BUFREQ_COUNT_MIN(&bufreq, ver); + ctrl->val = hfi_bufreq_get_count_min(&bufreq, ver); break; default: return -EINVAL;