Merge tag 'exynos-drm-fixes-for-v6.16-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-fixes
Fixups
- Fixed raw pointer leakage and unsafe behavior in printk()
. Switch from %pK to %p for pointer formatting, as %p is now safer
and prevents issues like raw pointer leakage and acquiring sleeping
locks in atomic contexts.
- Fixed kernel panic during boot
. A NULL pointer dereference issue occasionally occurred
when the vblank interrupt handler was called before
the DRM driver was fully initialized during boot.
So this patch fixes the issue by adding a check in the interrupt handler
to ensure the DRM driver is properly initialized.
- Fixed a lockup issue on Samsung Peach-Pit/Pi Chromebooks
. The issue occurred after commit c9b1150a68 changed
the call order of CRTC enable/disable and bridge pre_enable/post_disable
methods, causing fimd_dp_clock_enable() to be called
before the FIMD device was activated. To fix this,
runtime PM guards were added to fimd_dp_clock_enable()
to ensure proper operation even when CRTC is not enabled.
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Inki Dae <inki.dae@samsung.com>
Link: https://lore.kernel.org/r/20250629083554.28628-1-inki.dae@samsung.com
This commit is contained in:
@@ -636,6 +636,10 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id)
|
||||
if (!ctx->drm_dev)
|
||||
goto out;
|
||||
|
||||
/* check if crtc and vblank have been initialized properly */
|
||||
if (!drm_dev_has_vblank(ctx->drm_dev))
|
||||
goto out;
|
||||
|
||||
if (!ctx->i80_if) {
|
||||
drm_crtc_handle_vblank(&ctx->crtc->base);
|
||||
|
||||
|
||||
@@ -187,6 +187,7 @@ struct fimd_context {
|
||||
u32 i80ifcon;
|
||||
bool i80_if;
|
||||
bool suspended;
|
||||
bool dp_clk_enabled;
|
||||
wait_queue_head_t wait_vsync_queue;
|
||||
atomic_t wait_vsync_event;
|
||||
atomic_t win_updated;
|
||||
@@ -1047,7 +1048,18 @@ static void fimd_dp_clock_enable(struct exynos_drm_clk *clk, bool enable)
|
||||
struct fimd_context *ctx = container_of(clk, struct fimd_context,
|
||||
dp_clk);
|
||||
u32 val = enable ? DP_MIE_CLK_DP_ENABLE : DP_MIE_CLK_DISABLE;
|
||||
|
||||
if (enable == ctx->dp_clk_enabled)
|
||||
return;
|
||||
|
||||
if (enable)
|
||||
pm_runtime_resume_and_get(ctx->dev);
|
||||
|
||||
ctx->dp_clk_enabled = enable;
|
||||
writel(val, ctx->regs + DP_MIE_CLKCON);
|
||||
|
||||
if (!enable)
|
||||
pm_runtime_put(ctx->dev);
|
||||
}
|
||||
|
||||
static const struct exynos_drm_crtc_ops fimd_crtc_ops = {
|
||||
|
||||
@@ -174,7 +174,7 @@ static struct exynos_drm_gem *exynos_drm_gem_init(struct drm_device *dev,
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
DRM_DEV_DEBUG_KMS(dev->dev, "created file object = %pK\n", obj->filp);
|
||||
DRM_DEV_DEBUG_KMS(dev->dev, "created file object = %p\n", obj->filp);
|
||||
|
||||
return exynos_gem;
|
||||
}
|
||||
|
||||
@@ -271,7 +271,7 @@ static inline struct exynos_drm_ipp_task *
|
||||
task->src.rect.h = task->dst.rect.h = UINT_MAX;
|
||||
task->transform.rotation = DRM_MODE_ROTATE_0;
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(task->dev, "Allocated task %pK\n", task);
|
||||
DRM_DEV_DEBUG_DRIVER(task->dev, "Allocated task %p\n", task);
|
||||
|
||||
return task;
|
||||
}
|
||||
@@ -339,7 +339,7 @@ static int exynos_drm_ipp_task_set(struct exynos_drm_ipp_task *task,
|
||||
}
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(task->dev,
|
||||
"Got task %pK configuration from userspace\n",
|
||||
"Got task %p configuration from userspace\n",
|
||||
task);
|
||||
return 0;
|
||||
}
|
||||
@@ -394,7 +394,7 @@ static void exynos_drm_ipp_task_release_buf(struct exynos_drm_ipp_buffer *buf)
|
||||
static void exynos_drm_ipp_task_free(struct exynos_drm_ipp *ipp,
|
||||
struct exynos_drm_ipp_task *task)
|
||||
{
|
||||
DRM_DEV_DEBUG_DRIVER(task->dev, "Freeing task %pK\n", task);
|
||||
DRM_DEV_DEBUG_DRIVER(task->dev, "Freeing task %p\n", task);
|
||||
|
||||
exynos_drm_ipp_task_release_buf(&task->src);
|
||||
exynos_drm_ipp_task_release_buf(&task->dst);
|
||||
@@ -559,7 +559,7 @@ static int exynos_drm_ipp_check_format(struct exynos_drm_ipp_task *task,
|
||||
DRM_EXYNOS_IPP_FORMAT_DESTINATION);
|
||||
if (!fmt) {
|
||||
DRM_DEV_DEBUG_DRIVER(task->dev,
|
||||
"Task %pK: %s format not supported\n",
|
||||
"Task %p: %s format not supported\n",
|
||||
task, buf == src ? "src" : "dst");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -609,7 +609,7 @@ static int exynos_drm_ipp_task_check(struct exynos_drm_ipp_task *task)
|
||||
bool rotate = (rotation != DRM_MODE_ROTATE_0);
|
||||
bool scale = false;
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(task->dev, "Checking task %pK\n", task);
|
||||
DRM_DEV_DEBUG_DRIVER(task->dev, "Checking task %p\n", task);
|
||||
|
||||
if (src->rect.w == UINT_MAX)
|
||||
src->rect.w = src->buf.width;
|
||||
@@ -625,7 +625,7 @@ static int exynos_drm_ipp_task_check(struct exynos_drm_ipp_task *task)
|
||||
dst->rect.x + dst->rect.w > (dst->buf.width) ||
|
||||
dst->rect.y + dst->rect.h > (dst->buf.height)) {
|
||||
DRM_DEV_DEBUG_DRIVER(task->dev,
|
||||
"Task %pK: defined area is outside provided buffers\n",
|
||||
"Task %p: defined area is outside provided buffers\n",
|
||||
task);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -642,7 +642,7 @@ static int exynos_drm_ipp_task_check(struct exynos_drm_ipp_task *task)
|
||||
(!(ipp->capabilities & DRM_EXYNOS_IPP_CAP_SCALE) && scale) ||
|
||||
(!(ipp->capabilities & DRM_EXYNOS_IPP_CAP_CONVERT) &&
|
||||
src->buf.fourcc != dst->buf.fourcc)) {
|
||||
DRM_DEV_DEBUG_DRIVER(task->dev, "Task %pK: hw capabilities exceeded\n",
|
||||
DRM_DEV_DEBUG_DRIVER(task->dev, "Task %p: hw capabilities exceeded\n",
|
||||
task);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -655,7 +655,7 @@ static int exynos_drm_ipp_task_check(struct exynos_drm_ipp_task *task)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(ipp->dev, "Task %pK: all checks done.\n",
|
||||
DRM_DEV_DEBUG_DRIVER(ipp->dev, "Task %p: all checks done.\n",
|
||||
task);
|
||||
|
||||
return ret;
|
||||
@@ -667,25 +667,25 @@ static int exynos_drm_ipp_task_setup_buffers(struct exynos_drm_ipp_task *task,
|
||||
struct exynos_drm_ipp_buffer *src = &task->src, *dst = &task->dst;
|
||||
int ret = 0;
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(task->dev, "Setting buffer for task %pK\n",
|
||||
DRM_DEV_DEBUG_DRIVER(task->dev, "Setting buffer for task %p\n",
|
||||
task);
|
||||
|
||||
ret = exynos_drm_ipp_task_setup_buffer(src, filp);
|
||||
if (ret) {
|
||||
DRM_DEV_DEBUG_DRIVER(task->dev,
|
||||
"Task %pK: src buffer setup failed\n",
|
||||
"Task %p: src buffer setup failed\n",
|
||||
task);
|
||||
return ret;
|
||||
}
|
||||
ret = exynos_drm_ipp_task_setup_buffer(dst, filp);
|
||||
if (ret) {
|
||||
DRM_DEV_DEBUG_DRIVER(task->dev,
|
||||
"Task %pK: dst buffer setup failed\n",
|
||||
"Task %p: dst buffer setup failed\n",
|
||||
task);
|
||||
return ret;
|
||||
}
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(task->dev, "Task %pK: buffers prepared.\n",
|
||||
DRM_DEV_DEBUG_DRIVER(task->dev, "Task %p: buffers prepared.\n",
|
||||
task);
|
||||
|
||||
return ret;
|
||||
@@ -764,7 +764,7 @@ void exynos_drm_ipp_task_done(struct exynos_drm_ipp_task *task, int ret)
|
||||
struct exynos_drm_ipp *ipp = task->ipp;
|
||||
unsigned long flags;
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(task->dev, "ipp: %d, task %pK done: %d\n",
|
||||
DRM_DEV_DEBUG_DRIVER(task->dev, "ipp: %d, task %p done: %d\n",
|
||||
ipp->id, task, ret);
|
||||
|
||||
spin_lock_irqsave(&ipp->lock, flags);
|
||||
@@ -807,7 +807,7 @@ static void exynos_drm_ipp_next_task(struct exynos_drm_ipp *ipp)
|
||||
spin_unlock_irqrestore(&ipp->lock, flags);
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(ipp->dev,
|
||||
"ipp: %d, selected task %pK to run\n", ipp->id,
|
||||
"ipp: %d, selected task %p to run\n", ipp->id,
|
||||
task);
|
||||
|
||||
ret = ipp->funcs->commit(ipp, task);
|
||||
@@ -917,14 +917,14 @@ int exynos_drm_ipp_commit_ioctl(struct drm_device *dev, void *data,
|
||||
*/
|
||||
if (arg->flags & DRM_EXYNOS_IPP_FLAG_NONBLOCK) {
|
||||
DRM_DEV_DEBUG_DRIVER(ipp->dev,
|
||||
"ipp: %d, nonblocking processing task %pK\n",
|
||||
"ipp: %d, nonblocking processing task %p\n",
|
||||
ipp->id, task);
|
||||
|
||||
task->flags |= DRM_EXYNOS_IPP_TASK_ASYNC;
|
||||
exynos_drm_ipp_schedule_task(task->ipp, task);
|
||||
ret = 0;
|
||||
} else {
|
||||
DRM_DEV_DEBUG_DRIVER(ipp->dev, "ipp: %d, processing task %pK\n",
|
||||
DRM_DEV_DEBUG_DRIVER(ipp->dev, "ipp: %d, processing task %p\n",
|
||||
ipp->id, task);
|
||||
exynos_drm_ipp_schedule_task(ipp, task);
|
||||
ret = wait_event_interruptible(ipp->done_wq,
|
||||
|
||||
Reference in New Issue
Block a user