[PATCH 4/8] media: qcom: camss: vfe-17x: use the write master matching the RDI line

From: Hitesh Patel

Date: Mon Sep 14 2026 - 10:02:45 EST


vfe_get_output() on VFE 17x reserves a write master with
vfe_reserve_wm(), which hands out the first free entry of
wm_output_map. That only coincides with the line being started when
lines are started in order and RDI0 goes first. There is no crossbar
programmed on this bus: RDI n feeds bus write master client n, so
the write master an RDI line uses is not a free choice.

The mismatch is not visible as long as a single line of the VFE is
streaming: RDI0 always gets write master 0. It breaks when a CSID
demultiplexes two virtual channels to RDI0 and RDI1 on the same VFE.
Whichever line starts second is handed the other line's write
master, and both clients are then programmed with the wrong buffer
address and frame size. Frames are truncated at the smaller of the
two buffer sizes and the SMMU faults on the overrun of the larger
one.

Reserve write master line->id for RDI lines, as the gen2 VFE path in
vfe_get_output_v2() already does, and fail if it is in use. A PIX
line is not an RDI and its write master is not fixed by the same
rule, so it keeps using vfe_reserve_wm().

This also removes the error_get_wm label, which released
output->wm_idx[0] before it had been assigned.

Signed-off-by: Hitesh Patel <hitesh@xxxxxxxxxxxxxx>
---
.../media/platform/qcom/camss/camss-vfe-17x.c | 22 +++++++++++++------
1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/qcom/camss/camss-vfe-17x.c b/drivers/media/platform/qcom/camss/camss-vfe-17x.c
index f62fdabbc..0cfc24255 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe-17x.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe-17x.c
@@ -403,10 +403,20 @@ static int vfe_get_output(struct vfe_line *line)

output->wm_num = 1;

- wm_idx = vfe_reserve_wm(vfe, line->id);
- if (wm_idx < 0) {
- dev_err(vfe->camss->dev, "Can not reserve wm\n");
- goto error_get_wm;
+ if (line->id == VFE_LINE_PIX) {
+ wm_idx = vfe_reserve_wm(vfe, line->id);
+ if (wm_idx < 0) {
+ dev_err(vfe->camss->dev, "Can not reserve wm\n");
+ goto error;
+ }
+ } else {
+ wm_idx = line->id;
+ if (vfe->wm_output_map[wm_idx] != VFE_LINE_NONE) {
+ dev_err(vfe->camss->dev, "Can not reserve wm %d\n",
+ wm_idx);
+ goto error;
+ }
+ vfe->wm_output_map[wm_idx] = line->id;
}
output->wm_idx[0] = wm_idx;

@@ -416,10 +426,8 @@ static int vfe_get_output(struct vfe_line *line)

return 0;

-error_get_wm:
- vfe_release_wm(vfe, output->wm_idx[0]);
- output->state = VFE_OUTPUT_OFF;
error:
+ output->state = VFE_OUTPUT_OFF;
spin_unlock_irqrestore(&vfe->output_lock, flags);

return -EINVAL;
--
2.43.0