Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* [PATCH v2 0/2] HID: picolcd: Fix output-request and framebuffer locking
@ 2026-09-28 16:15 Aveline Noir
  2026-09-28 16:17 ` [PATCH v2 2/2] HID: picolcd: Avoid framebuffer last-close deadlock Aveline Noir
  2026-10-14 11:06 ` [PATCH v2 0/2] HID: picolcd: Fix output-request and framebuffer locking Aveline Noir
  0 siblings, 2 replies; 5+ messages in thread
From: Aveline Noir @ 2026-09-28 16:15 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires
  Cc: linux-input, linux-kernel, syzbot+912222e4cb82423535fa, bigeasy,
	linux-rt-devel, deller, simona, linux-fbdev, dri-devel

This series fixes two PicoLCD locking problems. The first moves output
requests into sleepable context and serializes LED state updates. The
second breaks the last-close/deferred-worker lock dependency using a
private framebuffer update mutex.

The first patch was tested separately with the original syzkaller C
reproducer and bounded concurrent sysfs/UHID-destroy workloads on
PREEMPT_RT. The complete series additionally passed repeated framebuffer
open/write/close and persistent-open framebuffer tests. Pre-fix modules
reproduced the respective failures. Physical hardware, prolonged stress
and suspend/resume have not been tested.

Patch 2's Fixes tag identifies the fbdev change that began draining
deferred work from fb_release() while holding info->lock. Patch 1's Fixes
tag was checked against the upstream transport-conversion diff.

Changes in v2:
- Address Sebastian Andrzej Siewior's feedback: clarify that the issue
  is not specific to PREEMPT_RT and identify picolcd_data::lock as a
  spinlock_t in patch 1. The code changes are identical to v1.

Aveline Noir (2):
  HID: picolcd: Move output requests out of spinlocked sections
  HID: picolcd: Avoid framebuffer last-close deadlock

 drivers/hid/hid-picolcd.h           |  4 +++
 drivers/hid/hid-picolcd_backlight.c |  7 ++--
 drivers/hid/hid-picolcd_core.c      | 46 +++++++++++++++---------
 drivers/hid/hid-picolcd_fb.c        | 56 ++++++++++++++++++-----------
 drivers/hid/hid-picolcd_lcd.c       |  7 ++--
 drivers/hid/hid-picolcd_leds.c      | 31 +++++++++-------
 6 files changed, 93 insertions(+), 58 deletions(-)


base-commit: 72d3fcf802c45d00b300f25b848a93c3a2bd7c7e
-- 
2.55.0

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 2/2] HID: picolcd: Avoid framebuffer last-close deadlock
  2026-09-28 16:15 [PATCH v2 0/2] HID: picolcd: Fix output-request and framebuffer locking Aveline Noir
@ 2026-09-28 16:17 ` Aveline Noir
  2026-10-25  8:20   ` Helge Deller
  2026-10-14 11:06 ` [PATCH v2 0/2] HID: picolcd: Fix output-request and framebuffer locking Aveline Noir
  1 sibling, 1 reply; 5+ messages in thread
From: Aveline Noir @ 2026-09-28 16:17 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires
  Cc: linux-input, linux-kernel, deller, simona, linux-fbdev, dri-devel

Closing the last framebuffer descriptor can deadlock against PicoLCD's
deferred update worker. fb_release() holds info->lock while waiting for
deferred work, and picolcd_fb_update() takes the same lock. Lockdep
reports the cycle through deferred-work completion and fbdefio_state->lock.
Repeated framebuffer open/write/close with concurrent device destruction
reproduces the hang in a PREEMPT_RT QEMU guest.

Use a private update mutex in the deferred worker instead of info->lock.
Take it in picolcd_set_par() as well to preserve serialization of pixel
format conversion and framebuffer updates. Initialize it before exposing
the framebuffer.

The test with the preceding output-request fix hung in the first round
and reported a circular locking dependency. With this change, all five
rounds completed, including 29 successful framebuffer write cycles and
concurrent LCD, backlight, two LED and UHID destroy operations, without
BUG/WARNING. The original syzkaller reproducer and persistent-open
framebuffer tests also passed again. These are bounded virtual-device
tests; physical hardware and suspend/resume remain untested.

Fixes: 3efc61d95259 ("fbdev: Fix invalid page access after closing
deferred I/O devices")
Signed-off-by: Aveline Noir <jm5905938@gmail.com>
---
 drivers/hid/hid-picolcd.h    |  2 ++
 drivers/hid/hid-picolcd_fb.c | 33 ++++++++++++++++++++++-----------
 2 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/drivers/hid/hid-picolcd.h b/drivers/hid/hid-picolcd.h
index 846a8ceb95..33e6654ca0 100644
--- a/drivers/hid/hid-picolcd.h
+++ b/drivers/hid/hid-picolcd.h
@@ -115,6 +115,8 @@ struct picolcd_data {
 struct picolcd_fb_data {
 	/* Framebuffer stuff */
 	spinlock_t lock;
+	/* Deferred I/O runs while fbdefio_state->lock is held. */
+	struct mutex update_lock;
 	struct picolcd_data *picolcd;
 	u8 update_rate;
 	u8 bpp;
diff --git a/drivers/hid/hid-picolcd_fb.c b/drivers/hid/hid-picolcd_fb.c
index c17104fd60..258c7c4fa2 100644
--- a/drivers/hid/hid-picolcd_fb.c
+++ b/drivers/hid/hid-picolcd_fb.c
@@ -231,7 +231,8 @@ static void picolcd_fb_update(struct fb_info *info)
 	struct picolcd_fb_data *fbdata = info->par;
 	struct picolcd_data *data;

-	mutex_lock(&info->lock);
+	/* fb_release() flushes this work while holding info->lock. */
+	mutex_lock(&fbdata->update_lock);

 	spin_lock_irqsave(&fbdata->lock, flags);
 	data = !fbdata->ready ? fbdata->picolcd : NULL;
@@ -258,11 +259,11 @@ static void picolcd_fb_update(struct fb_info *info)
 				spin_lock_irqsave(&fbdata->lock, flags);
 				data = fbdata->picolcd;
 				spin_unlock_irqrestore(&fbdata->lock, flags);
-				mutex_unlock(&info->lock);
+				mutex_unlock(&fbdata->update_lock);
 				if (!data)
 					return;
 				hid_hw_wait(data->hdev);
-				mutex_lock(&info->lock);
+				mutex_lock(&fbdata->update_lock);
 				n = 0;
 			}
 			spin_lock_irqsave(&fbdata->lock, flags);
@@ -277,13 +278,13 @@ static void picolcd_fb_update(struct fb_info *info)
 		spin_lock_irqsave(&fbdata->lock, flags);
 		data = fbdata->picolcd;
 		spin_unlock_irqrestore(&fbdata->lock, flags);
-		mutex_unlock(&info->lock);
+		mutex_unlock(&fbdata->update_lock);
 		if (data)
 			hid_hw_wait(data->hdev);
 		return;
 	}
 out:
-	mutex_unlock(&info->lock);
+	mutex_unlock(&fbdata->update_lock);
 }

 static int picolcd_fb_blank(int blank, struct fb_info *info)
@@ -332,17 +333,24 @@ static int picolcd_set_par(struct fb_info *info)
 {
 	struct picolcd_fb_data *fbdata = info->par;
 	u8 *tmp_fb, *o_fb;
+	int ret = 0;
+
+	mutex_lock(&fbdata->update_lock);
 	if (info->var.bits_per_pixel == fbdata->bpp)
-		return 0;
+		goto out;
 	/* switch between 1/8 bit depths */
-	if (info->var.bits_per_pixel != 1 && info->var.bits_per_pixel != 8)
-		return -EINVAL;
+	if (info->var.bits_per_pixel != 1 && info->var.bits_per_pixel != 8) {
+		ret = -EINVAL;
+		goto out;
+	}

 	o_fb   = fbdata->bitmap;
 	tmp_fb = kmalloc_array(PICOLCDFB_SIZE, info->var.bits_per_pixel,
 			       GFP_KERNEL);
-	if (!tmp_fb)
-		return -ENOMEM;
+	if (!tmp_fb) {
+		ret = -ENOMEM;
+		goto out;
+	}

 	/* translate FB content to new bits-per-pixel */
 	if (info->var.bits_per_pixel == 1) {
@@ -369,7 +377,9 @@ static int picolcd_set_par(struct fb_info *info)

 	kfree(tmp_fb);
 	fbdata->bpp = info->var.bits_per_pixel;
-	return 0;
+out:
+	mutex_unlock(&fbdata->update_lock);
+	return ret;
 }

 static void picolcdfb_ops_damage_range(struct fb_info *info, off_t
off, size_t len)
@@ -506,6 +516,7 @@ int picolcd_init_framebuffer(struct picolcd_data *data)

 	fbdata = info->par;
 	spin_lock_init(&fbdata->lock);
+	mutex_init(&fbdata->update_lock);
 	fbdata->picolcd = data;
 	fbdata->update_rate = PICOLCDFB_UPDATE_RATE_DEFAULT;
 	fbdata->bpp     = picolcdfb_var.bits_per_pixel;
-- 
2.55.0

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 0/2] HID: picolcd: Fix output-request and framebuffer locking
  2026-09-28 16:15 [PATCH v2 0/2] HID: picolcd: Fix output-request and framebuffer locking Aveline Noir
  2026-09-28 16:17 ` [PATCH v2 2/2] HID: picolcd: Avoid framebuffer last-close deadlock Aveline Noir
@ 2026-10-14 11:06 ` Aveline Noir
  1 sibling, 0 replies; 5+ messages in thread
From: Aveline Noir @ 2026-10-14 11:06 UTC (permalink / raw)
  To: Aveline Noir
  Cc: Jiri Kosina, Benjamin Tissoires, linux-input, linux-kernel,
	syzbot+912222e4cb82423535fa, bigeasy, linux-rt-devel, deller,
	simona, linux-fbdev, dri-devel

Hi Jiri, Benjamin,

Just a quick ping on this v2 series. Have you had a chance to take a look?

Both fixes have been tested with QEMU/UHID, though not on physical hardware. I'd appreciate any feedback and would be happy to make changes or run additional tests if needed.

Thanks,
Aveline

On 2026-09-28 18:15 +0200, Aveline Noir wrote:
> This series fixes two PicoLCD locking problems. The first moves output
> requests into sleepable context and serializes LED state updates. The
> second breaks the last-close/deferred-worker lock dependency using a
> private framebuffer update mutex.
> 
> The first patch was tested separately with the original syzkaller C
> reproducer and bounded concurrent sysfs/UHID-destroy workloads on
> PREEMPT_RT. The complete series additionally passed repeated framebuffer
> open/write/close and persistent-open framebuffer tests. Pre-fix modules
> reproduced the respective failures. Physical hardware, prolonged stress
> and suspend/resume have not been tested.
> 
> Patch 2's Fixes tag identifies the fbdev change that began draining
> deferred work from fb_release() while holding info->lock. Patch 1's Fixes
> tag was checked against the upstream transport-conversion diff.
> 
> Changes in v2:
> - Address Sebastian Andrzej Siewior's feedback: clarify that the issue
>   is not specific to PREEMPT_RT and identify picolcd_data::lock as a
>   spinlock_t in patch 1. The code changes are identical to v1.
> 
> Aveline Noir (2):
>   HID: picolcd: Move output requests out of spinlocked sections
>   HID: picolcd: Avoid framebuffer last-close deadlock
> 
>  drivers/hid/hid-picolcd.h           |  4 +++
>  drivers/hid/hid-picolcd_backlight.c |  7 ++--
>  drivers/hid/hid-picolcd_core.c      | 46 +++++++++++++++---------
>  drivers/hid/hid-picolcd_fb.c        | 56 ++++++++++++++++++-----------
>  drivers/hid/hid-picolcd_lcd.c       |  7 ++--
>  drivers/hid/hid-picolcd_leds.c      | 31 +++++++++-------
>  6 files changed, 93 insertions(+), 58 deletions(-)
> 
> 
> base-commit: 72d3fcf802c45d00b300f25b848a93c3a2bd7c7e
> -- 
> 2.55.0
> 



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 2/2] HID: picolcd: Avoid framebuffer last-close deadlock
  2026-09-28 16:17 ` [PATCH v2 2/2] HID: picolcd: Avoid framebuffer last-close deadlock Aveline Noir
@ 2026-10-25  8:20   ` Helge Deller
  2026-10-27  8:22     ` Aveline Noir
  0 siblings, 1 reply; 5+ messages in thread
From: Helge Deller @ 2026-10-25  8:20 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Aveline Noir, Bruno Prémont
  Cc: linux-input, linux-fbdev

On 9/28/26 18:17, Aveline Noir wrote:
> Closing the last framebuffer descriptor can deadlock against PicoLCD's
> deferred update worker. fb_release() holds info->lock while waiting for
> deferred work, and picolcd_fb_update() takes the same lock. Lockdep
> reports the cycle through deferred-work completion and fbdefio_state->lock.
> Repeated framebuffer open/write/close with concurrent device destruction
> reproduces the hang in a PREEMPT_RT QEMU guest.
> 
> Use a private update mutex in the deferred worker instead of info->lock.
> Take it in picolcd_set_par() as well to preserve serialization of pixel
> format conversion and framebuffer updates. Initialize it before exposing
> the framebuffer.
> 
> The test with the preceding output-request fix hung in the first round
> and reported a circular locking dependency. With this change, all five
> rounds completed, including 29 successful framebuffer write cycles and
> concurrent LCD, backlight, two LED and UHID destroy operations, without
> BUG/WARNING. The original syzkaller reproducer and persistent-open
> framebuffer tests also passed again. These are bounded virtual-device
> tests; physical hardware and suspend/resume remain untested.
> 
> Fixes: 3efc61d95259 ("fbdev: Fix invalid page access after closing
> deferred I/O devices")
> Signed-off-by: Aveline Noir <jm5905938@gmail.com>

For this patch:
Acked-by: Helge Deller <deller@gmx.de> # fbdev

I'm not sure about how to handle this patch series at all.
There is still a review missing for patch #1.
Shall I take this patch (#2 of 2) via fbdev git tree?

Helge

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 2/2] HID: picolcd: Avoid framebuffer last-close deadlock
  2026-10-25  8:20   ` Helge Deller
@ 2026-10-27  8:22     ` Aveline Noir
  0 siblings, 0 replies; 5+ messages in thread
From: Aveline Noir @ 2026-10-27  8:22 UTC (permalink / raw)
  To: Helge Deller; +Cc: Jiri Kosina, Benjamin Tissoires, linux-input, linux-fbdev

Hi Helge,

On Sun, 25 Oct 2026 09:20:36 +0100, Helge Deller wrote:
> For this patch:
> Acked-by: Helge Deller <deller@gmx.de> # fbdev

Thanks for the ack!

> I'm not sure about how to handle this patch series at all.
> There is still a review missing for patch #1.
> Shall I take this patch (#2 of 2) via fbdev git tree?

Since patch #2 depends on patch #1, I think it would make sense
to keep both patches together, perhaps through the HID tree.

Jiri, Benjamin, could you take a look at patch #1 and let us
know how you'd prefer to handle the series?

Thanks,
Aveline

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-10-27  8:22 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-28 16:15 [PATCH v2 0/2] HID: picolcd: Fix output-request and framebuffer locking Aveline Noir
2026-09-28 16:17 ` [PATCH v2 2/2] HID: picolcd: Avoid framebuffer last-close deadlock Aveline Noir
2026-10-25  8:20   ` Helge Deller
2026-10-27  8:22     ` Aveline Noir
2026-10-14 11:06 ` [PATCH v2 0/2] HID: picolcd: Fix output-request and framebuffer locking Aveline Noir

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox