[PATCH v12 85/86] media: ipu6: Don't track power status, rely on runtime PM

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

Rely on runtime PM suspending and resuming the device and so remove
tracking of power state. Also remove the power_lock spinlock that
serialised firmware initialisation and cleanup with the ISR. This is no
longer necessary as the ISR now runs when the device is in RPM_ACTIVE
state.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
drivers/media/pci/intel/ipu6/ipu6-fw-isys.c | 5 ----
drivers/media/pci/intel/ipu6/ipu6-isys.c | 31 ++++-----------------
drivers/media/pci/intel/ipu6/ipu6-isys.h | 5 ----
3 files changed, 6 insertions(+), 35 deletions(-)

diff --git a/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c b/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c
index 62ed92ff1d30..e239905f899c 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-fw-isys.c
@@ -137,7 +137,6 @@ int ipu6_fw_isys_close(struct ipu6_isys *isys)
{
struct device *dev = &isys->adev->auxdev.dev;
int retry = IPU6_ISYS_CLOSE_RETRY;
- unsigned long flags;
void *fwcom;
int ret;

@@ -147,11 +146,9 @@ int ipu6_fw_isys_close(struct ipu6_isys *isys)
* to SP icache.
* spinlock to wait the interrupt handler to be finished
*/
- spin_lock_irqsave(&isys->power_lock, flags);
ret = ipu6_fw_com_close(isys->fwcom);
fwcom = isys->fwcom;
isys->fwcom = NULL;
- spin_unlock_irqrestore(&isys->power_lock, flags);
if (ret)
dev_err(dev, "Device close failure: %d\n", ret);

@@ -164,9 +161,7 @@ int ipu6_fw_isys_close(struct ipu6_isys *isys)

if (ret) {
dev_err(dev, "Device release time out %d\n", ret);
- spin_lock_irqsave(&isys->power_lock, flags);
isys->fwcom = fwcom;
- spin_unlock_irqrestore(&isys->power_lock, flags);
}

return ret;
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.c b/drivers/media/pci/intel/ipu6/ipu6-isys.c
index 8258a6dbf43c..eac0d696754c 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.c
@@ -345,12 +345,11 @@ static irqreturn_t isys_isr(struct ipu6_bus_device *adev)
void __iomem *base = isys->pdata->base;
u32 status_sw, status_csi;
u32 ctrl0_status, ctrl0_clear;
+ int pm_status;

- spin_lock(&isys->power_lock);
- if (!isys->power) {
- spin_unlock(&isys->power_lock);
- return IRQ_NONE;
- }
+ pm_status = pm_runtime_get_if_active(&adev->auxdev.dev);
+ if (!pm_status)
+ return 0;

ctrl0_status = isys->pdata->ipdata->csi2.ctrl0_irq_status;
ctrl0_clear = isys->pdata->ipdata->csi2.ctrl0_irq_clear;
@@ -395,7 +394,8 @@ static irqreturn_t isys_isr(struct ipu6_bus_device *adev)

writel(ISYS_UNISPART_IRQS, base + IPU6_REG_ISYS_UNISPART_IRQ_MASK);

- spin_unlock(&isys->power_lock);
+ if (pm_status > 0)
+ pm_runtime_put(&adev->auxdev.dev);

return IRQ_HANDLED;
}
@@ -801,7 +801,6 @@ static int isys_runtime_pm_resume(struct device *dev)
struct ipu6_isys *isys = ipu6_bus_get_drvdata(adev);
const struct ipu6_isys_internal_pdata *ipdata = isys->pdata->ipdata;
struct ipu6_device *isp = adev->isp;
- unsigned long flags;
int ret;

ret = ipu6_mmu_hw_init(adev->mmu);
@@ -814,10 +813,6 @@ static int isys_runtime_pm_resume(struct device *dev)
if (ret)
goto err_mmu_hw_cleanup;

- spin_lock_irqsave(&isys->power_lock, flags);
- isys->power = 1;
- spin_unlock_irqrestore(&isys->power_lock, flags);
-
isys_setup_hw(isys);

set_iwake_ltrdid(isys, 0, 0, LTR_ISYS_ON);
@@ -845,10 +840,6 @@ static int isys_runtime_pm_resume(struct device *dev)
if (!ret)
return 0;

- spin_lock_irqsave(&isys->power_lock, flags);
- isys->power = 0;
- spin_unlock_irqrestore(&isys->power_lock, flags);
-
isys->phy_termcal_val = 0;
cpu_latency_qos_update_request(&isys->pm_qos, PM_QOS_DEFAULT_VALUE);

@@ -864,7 +855,6 @@ static int isys_runtime_pm_suspend(struct device *dev)
{
struct ipu6_bus_device *adev = to_ipu6_bus_device(dev);
struct ipu6_isys *isys = dev_get_drvdata(dev);
- unsigned long flags;
int ret = 0;

ipu6_fw_isys_close(isys);
@@ -873,10 +863,6 @@ static int isys_runtime_pm_suspend(struct device *dev)
ret = -EIO;
}

- spin_lock_irqsave(&isys->power_lock, flags);
- isys->power = 0;
- spin_unlock_irqrestore(&isys->power_lock, flags);
-
isys->phy_termcal_val = 0;
cpu_latency_qos_update_request(&isys->pm_qos, PM_QOS_DEFAULT_VALUE);

@@ -1053,8 +1039,6 @@ static int isys_probe(struct auxiliary_device *auxdev,
isys->sensor_type = isys->pdata->ipdata->sensor_type_start;

spin_lock_init(&isys->streams_lock);
- spin_lock_init(&isys->power_lock);
- isys->power = 0;
isys->phy_termcal_val = 0;

mutex_init(&isys->mutex);
@@ -1189,9 +1173,6 @@ static int isys_isr_one(struct ipu6_bus_device *adev)
u32 index;
u64 ts;

- if (!isys->fwcom)
- return 1;
-
resp = ipu6_fw_isys_get_resp(isys->fwcom, IPU6_BASE_MSG_RECV_QUEUES);
if (!resp)
return 1;
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.h b/drivers/media/pci/intel/ipu6/ipu6-isys.h
index c8f9059bc83e..8755d80e8fcf 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.h
@@ -77,9 +77,6 @@ struct sensor_async_sd {
* @media_dev: Media device
* @v4l2_dev: V4L2 device
* @adev: ISYS bus device
- * @power: Is ISYS powered on or not?
- * @isr_bits: Which bits does the ISR handle?
- * @power_lock: Serialise access to power (power state in general)
* @csi2_rx_ctrl_cached: cached shared value between all CSI2 receivers
* @streams_lock: serialise access to streams
* @streams: streams per firmware stream ID
@@ -97,8 +94,6 @@ struct ipu6_isys {
struct v4l2_device v4l2_dev;
struct ipu6_bus_device *adev;

- int power;
- spinlock_t power_lock;
u32 isr_csi2_bits;
u32 csi2_rx_ctrl_cached;
spinlock_t streams_lock;
--
2.47.3