drm/exynos: use pm_runtime_resume_and_get()
Use pm_runtime_resume_and_get() instead of pm_runtime_get_sync() to deal with usage counter. pm_runtime_get_sync() increases the usage counter even when it failed, which makes callers to forget to decrease the usage counter and resulted in reference leak. pm_runtime_resume_and_get() function decreases the usage counter when it failed internally so it can avoid the reference leak. Changelog v1: - Fix an build error reported by kernel test robot of Intel. Signed-off-by: Inki Dae <inki.dae@samsung.com> Reported-by: kernel test robot <lkp@intel.com>
This commit is contained in:
parent
a89b6c8f86
commit
445d3bed75
@ -513,8 +513,13 @@ static void decon_swreset(struct decon_context *ctx)
|
|||||||
static void decon_atomic_enable(struct exynos_drm_crtc *crtc)
|
static void decon_atomic_enable(struct exynos_drm_crtc *crtc)
|
||||||
{
|
{
|
||||||
struct decon_context *ctx = crtc->ctx;
|
struct decon_context *ctx = crtc->ctx;
|
||||||
|
int ret;
|
||||||
|
|
||||||
pm_runtime_get_sync(ctx->dev);
|
ret = pm_runtime_resume_and_get(ctx->dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
DRM_DEV_ERROR(ctx->dev, "failed to enable DECON device.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
exynos_drm_pipe_clk_enable(crtc, true);
|
exynos_drm_pipe_clk_enable(crtc, true);
|
||||||
|
|
||||||
|
@ -531,11 +531,16 @@ static void decon_init(struct decon_context *ctx)
|
|||||||
static void decon_atomic_enable(struct exynos_drm_crtc *crtc)
|
static void decon_atomic_enable(struct exynos_drm_crtc *crtc)
|
||||||
{
|
{
|
||||||
struct decon_context *ctx = crtc->ctx;
|
struct decon_context *ctx = crtc->ctx;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (!ctx->suspended)
|
if (!ctx->suspended)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pm_runtime_get_sync(ctx->dev);
|
ret = pm_runtime_resume_and_get(ctx->dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
DRM_DEV_ERROR(ctx->dev, "failed to enable DECON device.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
decon_init(ctx);
|
decon_init(ctx);
|
||||||
|
|
||||||
|
@ -1383,7 +1383,12 @@ static void exynos_dsi_enable(struct drm_encoder *encoder)
|
|||||||
if (dsi->state & DSIM_STATE_ENABLED)
|
if (dsi->state & DSIM_STATE_ENABLED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pm_runtime_get_sync(dsi->dev);
|
ret = pm_runtime_resume_and_get(dsi->dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(dsi->dev, "failed to enable DSI device.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dsi->state |= DSIM_STATE_ENABLED;
|
dsi->state |= DSIM_STATE_ENABLED;
|
||||||
|
|
||||||
if (dsi->panel) {
|
if (dsi->panel) {
|
||||||
|
@ -1085,8 +1085,14 @@ static int fimc_commit(struct exynos_drm_ipp *ipp,
|
|||||||
{
|
{
|
||||||
struct fimc_context *ctx =
|
struct fimc_context *ctx =
|
||||||
container_of(ipp, struct fimc_context, ipp);
|
container_of(ipp, struct fimc_context, ipp);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = pm_runtime_resume_and_get(ctx->dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ctx->dev, "failed to enable FIMC device.\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
pm_runtime_get_sync(ctx->dev);
|
|
||||||
ctx->task = task;
|
ctx->task = task;
|
||||||
|
|
||||||
fimc_src_set_fmt(ctx, task->src.buf.fourcc, task->src.buf.modifier);
|
fimc_src_set_fmt(ctx, task->src.buf.fourcc, task->src.buf.modifier);
|
||||||
|
@ -343,13 +343,18 @@ static void fimd_enable_shadow_channel_path(struct fimd_context *ctx,
|
|||||||
writel(val, ctx->regs + SHADOWCON);
|
writel(val, ctx->regs + SHADOWCON);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fimd_clear_channels(struct exynos_drm_crtc *crtc)
|
static int fimd_clear_channels(struct exynos_drm_crtc *crtc)
|
||||||
{
|
{
|
||||||
struct fimd_context *ctx = crtc->ctx;
|
struct fimd_context *ctx = crtc->ctx;
|
||||||
unsigned int win, ch_enabled = 0;
|
unsigned int win, ch_enabled = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* Hardware is in unknown state, so ensure it gets enabled properly */
|
/* Hardware is in unknown state, so ensure it gets enabled properly */
|
||||||
pm_runtime_get_sync(ctx->dev);
|
ret = pm_runtime_resume_and_get(ctx->dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ctx->dev, "failed to enable FIMD device.\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
clk_prepare_enable(ctx->bus_clk);
|
clk_prepare_enable(ctx->bus_clk);
|
||||||
clk_prepare_enable(ctx->lcd_clk);
|
clk_prepare_enable(ctx->lcd_clk);
|
||||||
@ -384,6 +389,8 @@ static void fimd_clear_channels(struct exynos_drm_crtc *crtc)
|
|||||||
clk_disable_unprepare(ctx->bus_clk);
|
clk_disable_unprepare(ctx->bus_clk);
|
||||||
|
|
||||||
pm_runtime_put(ctx->dev);
|
pm_runtime_put(ctx->dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -905,7 +912,10 @@ static void fimd_atomic_enable(struct exynos_drm_crtc *crtc)
|
|||||||
|
|
||||||
ctx->suspended = false;
|
ctx->suspended = false;
|
||||||
|
|
||||||
pm_runtime_get_sync(ctx->dev);
|
if (pm_runtime_resume_and_get(ctx->dev) < 0) {
|
||||||
|
dev_warn(ctx->dev, "failed to enable FIMD device.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* if vblank was enabled status, enable it again. */
|
/* if vblank was enabled status, enable it again. */
|
||||||
if (test_and_clear_bit(0, &ctx->irq_flags))
|
if (test_and_clear_bit(0, &ctx->irq_flags))
|
||||||
@ -1089,8 +1099,13 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
|
|||||||
if (ctx->encoder)
|
if (ctx->encoder)
|
||||||
exynos_dpi_bind(drm_dev, ctx->encoder);
|
exynos_dpi_bind(drm_dev, ctx->encoder);
|
||||||
|
|
||||||
if (is_drm_iommu_supported(drm_dev))
|
if (is_drm_iommu_supported(drm_dev)) {
|
||||||
fimd_clear_channels(ctx->crtc);
|
int ret;
|
||||||
|
|
||||||
|
ret = fimd_clear_channels(ctx->crtc);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return exynos_drm_register_dma(drm_dev, dev, &ctx->dma_priv);
|
return exynos_drm_register_dma(drm_dev, dev, &ctx->dma_priv);
|
||||||
}
|
}
|
||||||
|
@ -892,7 +892,14 @@ static void g2d_runqueue_worker(struct work_struct *work)
|
|||||||
g2d->runqueue_node = g2d_get_runqueue_node(g2d);
|
g2d->runqueue_node = g2d_get_runqueue_node(g2d);
|
||||||
|
|
||||||
if (g2d->runqueue_node) {
|
if (g2d->runqueue_node) {
|
||||||
pm_runtime_get_sync(g2d->dev);
|
int ret;
|
||||||
|
|
||||||
|
ret = pm_runtime_resume_and_get(g2d->dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(g2d->dev, "failed to enable G2D device.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
g2d_dma_start(g2d, g2d->runqueue_node);
|
g2d_dma_start(g2d, g2d->runqueue_node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1118,7 +1118,12 @@ static int gsc_commit(struct exynos_drm_ipp *ipp,
|
|||||||
struct gsc_context *ctx = container_of(ipp, struct gsc_context, ipp);
|
struct gsc_context *ctx = container_of(ipp, struct gsc_context, ipp);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
pm_runtime_get_sync(ctx->dev);
|
ret = pm_runtime_resume_and_get(ctx->dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ctx->dev, "failed to enable GScaler device.\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ctx->task = task;
|
ctx->task = task;
|
||||||
|
|
||||||
ret = gsc_reset(ctx);
|
ret = gsc_reset(ctx);
|
||||||
|
@ -219,8 +219,13 @@ static int rotator_commit(struct exynos_drm_ipp *ipp,
|
|||||||
{
|
{
|
||||||
struct rot_context *rot =
|
struct rot_context *rot =
|
||||||
container_of(ipp, struct rot_context, ipp);
|
container_of(ipp, struct rot_context, ipp);
|
||||||
|
int ret;
|
||||||
|
|
||||||
pm_runtime_get_sync(rot->dev);
|
ret = pm_runtime_resume_and_get(rot->dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(rot->dev, "failed to enable ROTATOR device.\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
rot->task = task;
|
rot->task = task;
|
||||||
|
|
||||||
rotator_src_set_fmt(rot, task->src.buf.fourcc);
|
rotator_src_set_fmt(rot, task->src.buf.fourcc);
|
||||||
|
@ -362,15 +362,17 @@ static int scaler_commit(struct exynos_drm_ipp *ipp,
|
|||||||
struct drm_exynos_ipp_task_rect *src_pos = &task->src.rect;
|
struct drm_exynos_ipp_task_rect *src_pos = &task->src.rect;
|
||||||
struct drm_exynos_ipp_task_rect *dst_pos = &task->dst.rect;
|
struct drm_exynos_ipp_task_rect *dst_pos = &task->dst.rect;
|
||||||
const struct scaler_format *src_fmt, *dst_fmt;
|
const struct scaler_format *src_fmt, *dst_fmt;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
src_fmt = scaler_get_format(task->src.buf.fourcc);
|
src_fmt = scaler_get_format(task->src.buf.fourcc);
|
||||||
dst_fmt = scaler_get_format(task->dst.buf.fourcc);
|
dst_fmt = scaler_get_format(task->dst.buf.fourcc);
|
||||||
|
|
||||||
pm_runtime_get_sync(scaler->dev);
|
ret = pm_runtime_resume_and_get(scaler->dev);
|
||||||
if (scaler_reset(scaler)) {
|
if (ret < 0)
|
||||||
pm_runtime_put(scaler->dev);
|
return ret;
|
||||||
|
|
||||||
|
if (scaler_reset(scaler))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
|
||||||
|
|
||||||
scaler->task = task;
|
scaler->task = task;
|
||||||
|
|
||||||
|
@ -1483,10 +1483,16 @@ static void hdmi_set_refclk(struct hdmi_context *hdata, bool on)
|
|||||||
/* Should be called with hdata->mutex mutex held. */
|
/* Should be called with hdata->mutex mutex held. */
|
||||||
static void hdmiphy_enable(struct hdmi_context *hdata)
|
static void hdmiphy_enable(struct hdmi_context *hdata)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (hdata->powered)
|
if (hdata->powered)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pm_runtime_get_sync(hdata->dev);
|
ret = pm_runtime_resume_and_get(hdata->dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(hdata->dev, "failed to enable HDMIPHY device.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (regulator_bulk_enable(ARRAY_SIZE(supply), hdata->regul_bulk))
|
if (regulator_bulk_enable(ARRAY_SIZE(supply), hdata->regul_bulk))
|
||||||
DRM_DEV_DEBUG_KMS(hdata->dev,
|
DRM_DEV_DEBUG_KMS(hdata->dev,
|
||||||
|
@ -992,11 +992,16 @@ static void mixer_atomic_flush(struct exynos_drm_crtc *crtc)
|
|||||||
static void mixer_atomic_enable(struct exynos_drm_crtc *crtc)
|
static void mixer_atomic_enable(struct exynos_drm_crtc *crtc)
|
||||||
{
|
{
|
||||||
struct mixer_context *ctx = crtc->ctx;
|
struct mixer_context *ctx = crtc->ctx;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (test_bit(MXR_BIT_POWERED, &ctx->flags))
|
if (test_bit(MXR_BIT_POWERED, &ctx->flags))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pm_runtime_get_sync(ctx->dev);
|
ret = pm_runtime_resume_and_get(ctx->dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ctx->dev, "failed to enable MIXER device.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
exynos_drm_pipe_clk_enable(crtc, true);
|
exynos_drm_pipe_clk_enable(crtc, true);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user