From 8164b072b3506dd40d2285e9a216f35efdfb010c Mon Sep 17 00:00:00 2001 From: Yiqing Zeng Date: Wed, 29 Sep 2021 16:13:28 +0800 Subject: [PATCH] media: rockchip: cif: fix pm runtime error at a high frame rate (120fps), the fast switch test has a higher probability of the following errors: Failed to get runtime pm, -22 Signed-off-by: Yiqing Zeng Change-Id: I6d9fdd86cc69368ba340ab7e43d2b6030a72ce8c --- drivers/media/platform/rockchip/cif/capture.c | 4 ++-- drivers/media/platform/rockchip/cif/dev.c | 13 ++++++++++--- drivers/media/platform/rockchip/cif/hw.c | 3 +++ drivers/media/platform/rockchip/cif/hw.h | 1 + 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 42ec7b735f8f..ae6deb00fa0d 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -2491,7 +2491,7 @@ static void rkcif_stop_streaming(struct vb2_queue *queue) dev->can_be_reset = false; dev->reset_work_cancel = true; } - pm_runtime_put(dev->dev); + pm_runtime_put_sync(dev->dev); if (!atomic_read(&dev->pipe.stream_cnt) && dev->dummy_buf.vaddr) rkcif_destroy_dummy_buf(stream); @@ -3189,7 +3189,7 @@ stop_stream: pipe_stream_off: dev->pipe.set_stream(&dev->pipe, false); runtime_put: - pm_runtime_put(dev->dev); + pm_runtime_put_sync(dev->dev); destroy_buf: if (stream->next_buf) vb2_buffer_done(&stream->next_buf->vb.vb2_buf, diff --git a/drivers/media/platform/rockchip/cif/dev.c b/drivers/media/platform/rockchip/cif/dev.c index ca0c17cca7ee..08422f4c4e22 100644 --- a/drivers/media/platform/rockchip/cif/dev.c +++ b/drivers/media/platform/rockchip/cif/dev.c @@ -1306,21 +1306,28 @@ static int rkcif_plat_remove(struct platform_device *pdev) static int __maybe_unused rkcif_runtime_suspend(struct device *dev) { struct rkcif_device *cif_dev = dev_get_drvdata(dev); + int ret = 0; if (atomic_dec_return(&cif_dev->hw_dev->power_cnt)) return 0; - return pm_runtime_put(cif_dev->hw_dev->dev); + mutex_lock(&cif_dev->hw_dev->dev_lock); + ret = pm_runtime_put_sync(cif_dev->hw_dev->dev); + mutex_unlock(&cif_dev->hw_dev->dev_lock); + return (ret > 0) ? 0 : ret; } static int __maybe_unused rkcif_runtime_resume(struct device *dev) { struct rkcif_device *cif_dev = dev_get_drvdata(dev); + int ret = 0; if (atomic_inc_return(&cif_dev->hw_dev->power_cnt) > 1) return 0; - - return pm_runtime_get_sync(cif_dev->hw_dev->dev); + mutex_lock(&cif_dev->hw_dev->dev_lock); + ret = pm_runtime_get_sync(cif_dev->hw_dev->dev); + mutex_unlock(&cif_dev->hw_dev->dev_lock); + return (ret > 0) ? 0 : ret; } static int __maybe_unused __rkcif_clr_unready_dev(void) diff --git a/drivers/media/platform/rockchip/cif/hw.c b/drivers/media/platform/rockchip/cif/hw.c index 4181e0d135d6..1dc663366227 100644 --- a/drivers/media/platform/rockchip/cif/hw.c +++ b/drivers/media/platform/rockchip/cif/hw.c @@ -942,6 +942,8 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev) rkcif_hw_soft_reset(cif_hw, true); + mutex_init(&cif_hw->dev_lock); + pm_runtime_enable(&pdev->dev); if (data->chip_id == CHIP_RK1808_CIF || @@ -962,6 +964,7 @@ static int rkcif_plat_remove(struct platform_device *pdev) if (cif_hw->iommu_en) rkcif_iommu_cleanup(cif_hw); + mutex_destroy(&cif_hw->dev_lock); if (cif_hw->chip_id != CHIP_RK1808_CIF && cif_hw->chip_id != CHIP_RV1126_CIF && cif_hw->chip_id != CHIP_RV1126_CIF_LITE && diff --git a/drivers/media/platform/rockchip/cif/hw.h b/drivers/media/platform/rockchip/cif/hw.h index 82adfd185f00..573abe48c8b9 100644 --- a/drivers/media/platform/rockchip/cif/hw.h +++ b/drivers/media/platform/rockchip/cif/hw.h @@ -84,6 +84,7 @@ struct rkcif_hw { atomic_t power_cnt; const struct rkcif_hw_match_data *match_data; + struct mutex dev_lock; }; void rkcif_hw_soft_reset(struct rkcif_hw *cif_hw, bool is_rst_iommu);