From: kr494167@gmail.com
To: andy.shevchenko@gmail.com, andy@kernel.org, geert@linux-m68k.org
Cc: chris.packham@alliedtelesis.co.nz, linux-kernel@vger.kernel.org,
Surendra Singh Chouhan <kr494167@gmail.com>
Subject: [PATCH 0/3 2/3] auxdisplay: seg-led-gpio: fix work initialization race and convert to devm_linedisp_register()
Date: Wed, 19 Aug 2026 08:15:55 +0530 [thread overview]
Message-ID: <20260819024556.63534-3-kr494167@gmail.com> (raw)
In-Reply-To: <20260819024556.63534-1-kr494167@gmail.com>
From: Surendra Singh Chouhan <kr494167@gmail.com>
INIT_DELAYED_WORK(&priv->work, seg_led_update) was previously called inside
seg_led_linedisp_get_map_type(), which is invoked during/after
linedisp_register(). Initializing a delayed_work structure inside a map
query callback can re-initialize an active work item or race with
seg_led_linedisp_update().
In addition, seg_led_remove() called cancel_delayed_work_sync(&priv->work)
before linedisp_unregister(&priv->linedisp), allowing sysfs updates to
reschedule work after cancel_delayed_work_sync() completed.
Fix these by moving INIT_DELAYED_WORK() to probe(), using
devm_add_action_or_reset() for work cancellation, and converting to
devm_linedisp_register(). Registering devm_linedisp_register() after
work cancellation action ensures proper LIFO teardown order (sysfs
interface unregistered first, followed by work cancellation), allowing
seg_led_remove() to be removed entirely.
Fixes: 899383f9ecf5 ("auxdisplay: Add 7-segment LED display driver")
Reviewed-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
Tested-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
Signed-off-by: Surendra Singh Chouhan <kr494167@gmail.com>
---
drivers/auxdisplay/seg-led-gpio.c | 27 ++++++++++++++-------------
1 file changed, 14 insertions(+), 13 deletions(-)
diff --git a/drivers/auxdisplay/seg-led-gpio.c b/drivers/auxdisplay/seg-led-gpio.c
index bc463118fe51..ca39c9071688 100644
--- a/drivers/auxdisplay/seg-led-gpio.c
+++ b/drivers/auxdisplay/seg-led-gpio.c
@@ -38,11 +38,15 @@ static void seg_led_update(struct work_struct *work)
gpiod_multi_set_value_cansleep(priv->segment_gpios, values);
}
-static int seg_led_linedisp_get_map_type(struct linedisp *linedisp)
+static void seg_led_cancel_work(void *data)
{
- struct seg_led_priv *priv = container_of(linedisp, struct seg_led_priv, linedisp);
+ struct delayed_work *work = data;
- INIT_DELAYED_WORK(&priv->work, seg_led_update);
+ cancel_delayed_work_sync(work);
+}
+
+static int seg_led_linedisp_get_map_type(struct linedisp *linedisp)
+{
return LINEDISP_MAP_SEG7;
}
@@ -62,11 +66,17 @@ static int seg_led_probe(struct platform_device *pdev)
{
struct seg_led_priv *priv;
struct device *dev = &pdev->dev;
+ int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
+ INIT_DELAYED_WORK(&priv->work, seg_led_update);
+ ret = devm_add_action_or_reset(dev, seg_led_cancel_work, &priv->work);
+ if (ret)
+ return ret;
+
platform_set_drvdata(pdev, priv);
priv->segment_gpios = devm_gpiod_get_array(dev, "segment", GPIOD_OUT_LOW);
@@ -76,15 +86,7 @@ static int seg_led_probe(struct platform_device *pdev)
if (priv->segment_gpios->ndescs < 7 || priv->segment_gpios->ndescs > 8)
return -EINVAL;
- return linedisp_register(&priv->linedisp, dev, 1, &seg_led_linedisp_ops);
-}
-
-static void seg_led_remove(struct platform_device *pdev)
-{
- struct seg_led_priv *priv = platform_get_drvdata(pdev);
-
- cancel_delayed_work_sync(&priv->work);
- linedisp_unregister(&priv->linedisp);
+ return devm_linedisp_register(dev, &priv->linedisp, 1, &seg_led_linedisp_ops);
}
static const struct of_device_id seg_led_of_match[] = {
@@ -95,7 +97,6 @@ MODULE_DEVICE_TABLE(of, seg_led_of_match);
static struct platform_driver seg_led_driver = {
.probe = seg_led_probe,
- .remove = seg_led_remove,
.driver = {
.name = "seg-led-gpio",
.of_match_table = seg_led_of_match,
--
2.55.0
next prev parent reply other threads:[~2026-08-19 2:46 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-19 2:45 [PATCH 0/3] auxdisplay: add devm_linedisp_register() and fix work initialization races kr494167
2026-08-19 2:45 ` [PATCH 0/3 1/3] auxdisplay: line-display: add devm_linedisp_register() kr494167
2026-08-19 2:45 ` kr494167 [this message]
2026-08-19 2:45 ` [PATCH 0/3 3/3] auxdisplay: max6959: fix work initialization race and convert to devm_linedisp_register() kr494167
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=20260819024556.63534-3-kr494167@gmail.com \
--to=kr494167@gmail.com \
--cc=andy.shevchenko@gmail.com \
--cc=andy@kernel.org \
--cc=chris.packham@alliedtelesis.co.nz \
--cc=geert@linux-m68k.org \
--cc=linux-kernel@vger.kernel.org \
/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.