From: sh_def@163.com
To: andy@kernel.org, gregkh@linuxfoundation.org
Cc: dri-devel@lists.freedesktop.org, linux-fbdev@vger.kernel.org,
linux-staging@lists.linux.dev, linux-kernel@vger.kernel.org,
sh_def@163.com, thomas.petazzoni@free-electrons.com,
notro@tronnes.org
Subject: [PATCH] staging: fbtft: make dirty_lock IRQ-safe
Date: Wed, 5 Aug 2026 01:37:12 +0800 [thread overview]
Message-ID: <20260804173712.176017-1-sh_def@163.com> (raw)
From: Hui Su <sh_def@163.com>
fbtft_mkdirty() can be reached from the fbcon rendering path while
processing printk() in hardirq context. Meanwhile, dirty_lock is also
taken by fbtft_deferred_io() in workqueue context with local interrupts
enabled.
Lockdep reports a possible IRQ lock inversion involving dirty_lock and
console_owner. A hardirq can interrupt a CPU holding dirty_lock and
enter the console rendering path, which can attempt to acquire
dirty_lock again.
The following lockdep report was observed on an RK3566 system with
CONFIG_PROVE_LOCKING enabled:
WARNING: possible irq lock inversion dependency detected
swapper/2/0 just changed the state of lock:
(console_owner){-...}-{0:0}
but this lock took another, HARDIRQ-unsafe lock in the past:
(&par->dirty_lock){+.+.}-{2:2}
CPU0 CPU1
---- ----
lock(&par->dirty_lock);
local_irq_disable();
lock(console_owner);
lock(&par->dirty_lock);
<Interrupt>
lock(console_owner);
*** DEADLOCK ***
Use spin_lock_irqsave() for both dirty_lock critical sections. They
only access the dirty line range, so the IRQ-off regions remain short.
Fixes: c296d5f9957c ("staging: fbtft: core support")
Signed-off-by: Hui Su <sh_def@163.com>
---
drivers/staging/fbtft/fbtft-core.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c
index ca0c38221c16..193643d0329d 100644
--- a/drivers/staging/fbtft/fbtft-core.c
+++ b/drivers/staging/fbtft/fbtft-core.c
@@ -298,14 +298,20 @@ static void fbtft_mkdirty(struct fb_info *info, int y, int height)
{
struct fbtft_par *par = info->par;
struct fb_deferred_io *fbdefio = info->fbdefio;
+ unsigned long flags;
/* Mark display lines/area as dirty */
- spin_lock(&par->dirty_lock);
+ /*
+ * fbcon takes dirty_lock while holding console_owner. Disable local
+ * interrupts here so a printk hardirq cannot acquire console_owner
+ * while dirty_lock is held and create the inverse lock ordering.
+ */
+ spin_lock_irqsave(&par->dirty_lock, flags);
if (y < par->dirty_lines_start)
par->dirty_lines_start = y;
if (y + height - 1 > par->dirty_lines_end)
par->dirty_lines_end = y + height - 1;
- spin_unlock(&par->dirty_lock);
+ spin_unlock_irqrestore(&par->dirty_lock, flags);
/* Schedule deferred_io to update display (no-op if already on queue)*/
schedule_delayed_work(&info->deferred_work, fbdefio->delay);
@@ -317,14 +323,15 @@ static void fbtft_deferred_io(struct fb_info *info, struct list_head *pagereflis
unsigned int dirty_lines_start, dirty_lines_end;
struct fb_deferred_io_pageref *pageref;
unsigned int y_low = 0, y_high = 0;
+ unsigned long flags;
- spin_lock(&par->dirty_lock);
+ spin_lock_irqsave(&par->dirty_lock, flags);
dirty_lines_start = par->dirty_lines_start;
dirty_lines_end = par->dirty_lines_end;
/* set display line markers as clean */
par->dirty_lines_start = par->info->var.yres - 1;
par->dirty_lines_end = 0;
- spin_unlock(&par->dirty_lock);
+ spin_unlock_irqrestore(&par->dirty_lock, flags);
/* Mark display lines as dirty */
list_for_each_entry(pageref, pagereflist, list) {
--
2.43.0
next reply other threads:[~2026-08-04 17:38 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-04 17:37 sh_def [this message]
2026-08-07 12:53 ` [PATCH] staging: fbtft: make dirty_lock IRQ-safe Nam Cao
2026-08-07 13:08 ` Dan Carpenter
2026-08-07 14:37 ` Hui Su
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260804173712.176017-1-sh_def@163.com \
--to=sh_def@163.com \
--cc=andy@kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=gregkh@linuxfoundation.org \
--cc=linux-fbdev@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-staging@lists.linux.dev \
--cc=notro@tronnes.org \
--cc=thomas.petazzoni@free-electrons.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.