[PATCH v12 83/86] media: ipu6: Serialise access to stream pointers by isys stream_lock

Sakari Ailus
2026-04-09T20:15:19Z

Re-purpose the unused stream_lock in struct ipu6_isys to serialise access
to streams_by_handle (struct ipu6_isys) and streams_by_vc (struct
ipu6_isys_csi2). Switch to scoped_guard() while at it.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
.../media/pci/intel/ipu6/ipu6-isys-video.c | 6 ++---
drivers/media/pci/intel/ipu6/ipu6-isys.c | 23 ++++++++++---------
2 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
index 9eb22e456834..0c3223c4d019 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c
@@ -714,7 +714,7 @@ static int ipu6_isys_close_streaming_firmware(struct ipu6_isys_stream *stream,
else
dev_dbg(dev, "close stream: complete\n");

- scoped_guard(spinlock_irqsave, &stream->isys->power_lock) {
+ scoped_guard(spinlock_irqsave, &stream->isys->streams_lock) {
stream->isys->streams_by_handle[stream->stream_handle] = NULL;
csi2->streams_by_vc[stream->vc] = NULL;
}
@@ -794,8 +794,6 @@ int ipu6_isys_alloc_start_streams_firmware(struct ipu6_isys_csi2 *csi2,
break;

if (list_entry_is_head(stream, &csi2->streams, csi2_entry)) {
- unsigned long flags;
-
stream = kzalloc(sizeof(*stream), GFP_KERNEL);
if (!stream) {
ret = -ENOMEM;
@@ -821,7 +819,7 @@ int ipu6_isys_alloc_start_streams_firmware(struct ipu6_isys_csi2 *csi2,
stream->asd = &csi2->asd;
stream->vc = entry->bus.csi2.vc;

- scoped_guard(spinlock_irqsave, &stream->isys->power_lock) {
+ scoped_guard(spinlock_irqsave, &stream->isys->streams_lock) {
stream->isys->streams_by_handle[stream->stream_handle] =
stream;
csi2->streams_by_vc[stream->vc] = stream;
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.c b/drivers/media/pci/intel/ipu6/ipu6-isys.c
index fb46ded122fa..0c2adfa01034 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.c
@@ -311,10 +311,8 @@ static void isys_setup_hw(struct ipu6_isys *isys)

static void ipu6_isys_csi2_isr(struct ipu6_isys_csi2 *csi2)
{
- struct ipu6_isys_stream *stream;
unsigned int i;
u32 status;
- int source;

ipu6_isys_register_errors(csi2);

@@ -324,17 +322,18 @@ static void ipu6_isys_csi2_isr(struct ipu6_isys_csi2 *csi2)
writel(status, csi2->base + CSI_PORT_REG_BASE_IRQ_CSI_SYNC +
CSI_PORT_REG_BASE_IRQ_CLEAR_OFFSET);

- source = csi2->asd.source;
- for (i = 0; i < NR_OF_CSI2_VC; i++) {
- if (status & IPU_CSI_RX_IRQ_FS_VC(i)) {
- stream = csi2->streams_by_vc[i];
- if (stream)
+ scoped_guard(spinlock, &csi2->isys->streams_lock) {
+ for (i = 0; i < NR_OF_CSI2_VC; i++) {
+ struct ipu6_isys_stream *stream =
+ csi2->streams_by_vc[i];
+
+ if (!stream)
+ continue;
+
+ if (status & IPU_CSI_RX_IRQ_FS_VC(i))
ipu6_isys_csi2_sof_event_by_stream(stream);
- }

- if (status & IPU_CSI_RX_IRQ_FE_VC(i)) {
- stream = csi2->streams_by_vc[i];
- if (stream)
+ if (status & IPU_CSI_RX_IRQ_FE_VC(i))
ipu6_isys_csi2_eof_event_by_stream(stream);
}
}
@@ -1176,6 +1175,8 @@ static int isys_isr_one(struct ipu6_bus_device *adev)
"FW error resp error %d, details %d\n",
resp->error_info.error, resp->error_info.error_details);

+ guard(spinlock_irqsave)(&isys->streams_lock);
+
if (resp->stream_handle >= IPU6_ISYS_MAX_STREAMS) {
dev_err(&adev->auxdev.dev, "bad stream handle %u\n",
resp->stream_handle);
--
2.47.3