Re: [PATCH v2] drm/panthor: use local variables for firmware interface counts
Boris Brezillon <[email protected]> Mon, 3 Aug 2026 15:35:55 +0200
| Newsgroups | org.freedesktop.lists.dri-devel,org.kernel.vger.linux-kernel |
|---|---|
| Organization | Collabora |
| Message-ID | <[email protected]> |
On Mon, 3 Aug 2026 14:48:06 +0200 Osama Abdelkader <[email protected]> wrote: > panthor_fw_init_ifaces() validates the firmware interface group count > before iterating over the CSG interfaces. panthor_init_csg_iface() does > the same for the per-group stream count before iterating over the CS > interfaces. > > Store those validated counts in local variables and use the locals as the > loop bounds. This avoids reading the same control interface fields twice > and makes it explicit that the loops use the values that were just > validated. > > Signed-off-by: Osama Abdelkader <[email protected]> > Reviewed-by: Steven Price <[email protected]> > --- > v2: > - Reword as an optimization/cleanup instead of a firmware trust-boundary fix. > - Drop the Fixes and stable tags. > > drivers/gpu/drm/panthor/panthor_fw.c | 11 +++++++---- > 1 file changed, 7 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/panthor/panthor_fw.c b/drivers/gpu/drm/panthor/panthor_fw.c > index e2fcbd639c3c..6e6da98d795e 100644 > --- a/drivers/gpu/drm/panthor/panthor_fw.c > +++ b/drivers/gpu/drm/panthor/panthor_fw.c > @@ -959,6 +959,7 @@ static int panthor_init_csg_iface(struct panthor_device *ptdev, > u64 shared_section_sz = panthor_kernel_bo_size(ptdev->fw->shared_section->mem); > u64 iface_offset = CSF_GROUP_CONTROL_OFFSET + > ((u64)csg_idx * glb_iface->control->group_stride); > + u32 stream_num; > unsigned int i; > > if (iface_offset > shared_section_sz || > @@ -972,8 +973,8 @@ static int panthor_init_csg_iface(struct panthor_device *ptdev, > csg_iface->output = iface_fw_to_cpu_addr(ptdev, csg_iface->control->output_va, > sizeof(*csg_iface->output)); > > - if (csg_iface->control->stream_num < MIN_CS_PER_CSG || > - csg_iface->control->stream_num > MAX_CS_PER_CSG) > + stream_num = READ_ONCE(csg_iface->control->stream_num); We need a comment to explain the READ_ONCE(), otherwise new readers (and given my inability to remember things, I consider myself a new reader after 2 weeks :-)) will keep wondering why we're forcing the compiler to read the memory only once. IIUC, that's here to protect against self-modifying control sections, so maybe say that. Or if we consider that the FW is trusted/sure, drop the READ_ONCE()... > + if (stream_num < MIN_CS_PER_CSG || stream_num > MAX_CS_PER_CSG) > return -EINVAL; > > if (!csg_iface->input || !csg_iface->output) { > @@ -990,7 +991,7 @@ static int panthor_init_csg_iface(struct panthor_device *ptdev, > } > } > > - for (i = 0; i < csg_iface->control->stream_num; i++) { > + for (i = 0; i < stream_num; i++) { > int ret = panthor_init_cs_iface(ptdev, csg_idx, i); > > if (ret) > @@ -1015,6 +1016,7 @@ static int panthor_fw_init_ifaces(struct panthor_device *ptdev) > { > struct panthor_fw_global_iface *glb_iface = &ptdev->fw->iface.global; > u64 shared_section_sz = panthor_kernel_bo_size(ptdev->fw->shared_section->mem); > + u32 group_num; > unsigned int i; > > if (!ptdev->fw->shared_section->mem->kmap) > @@ -1034,17 +1036,17 @@ static int panthor_fw_init_ifaces(struct panthor_device *ptdev) > return -EINVAL; > } > > - if (glb_iface->control->group_num > MAX_CSGS || > - glb_iface->control->group_num < MIN_CSGS) { > + group_num = READ_ONCE(glb_iface->control->group_num); > + if (group_num > MAX_CSGS || group_num < MIN_CSGS) { > drm_err(&ptdev->base, "Invalid number of control groups"); > return -EINVAL; > } > > - for (i = 0; i < glb_iface->control->group_num; i++) { > + for (i = 0; i < group_num; i++) { > int ret = panthor_init_csg_iface(ptdev, i); > > if (ret) > return ret; > } > > drm_info(&ptdev->base, "CSF FW using interface v%d.%d.%d, Features %#x Instrumentation features %#x",