From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
To: linux-kernel@vger.kernel.org
Cc: kernel-dev@igalia.com, dri-devel@lists.freedesktop.org,
Boris Brezillon <boris.brezillon@collabora.com>,
Bradley Morgan <include@grrlz.net>, Chia-I Wu <olv@google.com>,
Liviu Dudau <liviu.dudau@arm.com>,
Matthew Brost <matthew.brost@intel.com>,
Steven Price <steven.price@arm.com>, Tejun Heo <tj@kernel.org>
Subject: Re: [RFC v5 1/3] workqueue: Simplify unbound sysfs attribute registration
Date: Wed, 23 Sep 2026 18:12:19 +0100 [thread overview]
Message-ID: <282b1fc2-3305-4784-8f83-0f3bc461ec18@igalia.com> (raw)
In-Reply-To: <20260923161251.45428-2-tvrtko.ursulin@igalia.com>
On 23/09/2026 17:12, Tvrtko Ursulin wrote:
> Instead of manually registering each attribute we can put them in an
> attribute group with a visibility check and device core will handle the
> rest, which simplifies the registration and error unwind.
>
> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
> Cc: Boris Brezillon <boris.brezillon@collabora.com>
> Cc: Bradley Morgan <include@grrlz.net>
> Cc: Chia-I Wu <olv@google.com>
> Cc: Liviu Dudau <liviu.dudau@arm.com>
> Cc: Matthew Brost <matthew.brost@intel.com>
> Cc: Steven Price <steven.price@arm.com>
> Cc: Tejun Heo <tj@kernel.org>
> ---
> kernel/workqueue.c | 98 ++++++++++++++++++++++++----------------------
> 1 file changed, 52 insertions(+), 46 deletions(-)
>
> diff --git a/kernel/workqueue.c b/kernel/workqueue.c
> index e618108c6127..e3a4ad56dae8 100644
> --- a/kernel/workqueue.c
> +++ b/kernel/workqueue.c
> @@ -7599,8 +7599,8 @@ static const struct attribute_group wq_sysfs_group = {
> };
> __ATTRIBUTE_GROUPS(wq_sysfs);
>
> -static ssize_t wq_nice_show(struct device *dev, struct device_attribute *attr,
> - char *buf)
> +static ssize_t nice_show(struct device *dev, struct device_attribute *attr,
> + char *buf)
> {
> struct workqueue_struct *wq = dev_to_wq(dev);
> int written;
> @@ -7627,8 +7627,8 @@ static struct workqueue_attrs *wq_sysfs_prep_attrs(struct workqueue_struct *wq)
> return attrs;
> }
>
> -static ssize_t wq_nice_store(struct device *dev, struct device_attribute *attr,
> - const char *buf, size_t count)
> +static ssize_t nice_store(struct device *dev, struct device_attribute *attr,
> + const char *buf, size_t count)
> {
> struct workqueue_struct *wq = dev_to_wq(dev);
> struct workqueue_attrs *attrs;
> @@ -7652,8 +7652,8 @@ static ssize_t wq_nice_store(struct device *dev, struct device_attribute *attr,
> return ret ?: count;
> }
>
> -static ssize_t wq_cpumask_show(struct device *dev,
> - struct device_attribute *attr, char *buf)
> +static ssize_t unbound_cpumask_show(struct device *dev,
> + struct device_attribute *attr, char *buf)
> {
> struct workqueue_struct *wq = dev_to_wq(dev);
> int written;
> @@ -7665,9 +7665,9 @@ static ssize_t wq_cpumask_show(struct device *dev,
> return written;
> }
>
> -static ssize_t wq_cpumask_store(struct device *dev,
> - struct device_attribute *attr,
> - const char *buf, size_t count)
> +static ssize_t unbound_cpumask_store(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t count)
> {
> struct workqueue_struct *wq = dev_to_wq(dev);
> struct workqueue_attrs *attrs;
> @@ -7689,8 +7689,8 @@ static ssize_t wq_cpumask_store(struct device *dev,
> return ret ?: count;
> }
>
> -static ssize_t wq_affn_scope_show(struct device *dev,
> - struct device_attribute *attr, char *buf)
> +static ssize_t affn_scope_show(struct device *dev,
> + struct device_attribute *attr, char *buf)
> {
> struct workqueue_struct *wq = dev_to_wq(dev);
> int written;
> @@ -7708,9 +7708,9 @@ static ssize_t wq_affn_scope_show(struct device *dev,
> return written;
> }
>
> -static ssize_t wq_affn_scope_store(struct device *dev,
> - struct device_attribute *attr,
> - const char *buf, size_t count)
> +static ssize_t affn_scope_store(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t count)
> {
> struct workqueue_struct *wq = dev_to_wq(dev);
> struct workqueue_attrs *attrs;
> @@ -7731,8 +7731,8 @@ static ssize_t wq_affn_scope_store(struct device *dev,
> return ret ?: count;
> }
>
> -static ssize_t wq_affinity_strict_show(struct device *dev,
> - struct device_attribute *attr, char *buf)
> +static ssize_t affinity_strict_show(struct device *dev,
> + struct device_attribute *attr, char *buf)
> {
> struct workqueue_struct *wq = dev_to_wq(dev);
>
> @@ -7740,9 +7740,9 @@ static ssize_t wq_affinity_strict_show(struct device *dev,
> wq->attrs->affn_strict);
> }
>
> -static ssize_t wq_affinity_strict_store(struct device *dev,
> - struct device_attribute *attr,
> - const char *buf, size_t count)
> +static ssize_t affinity_strict_store(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t count)
> {
> struct workqueue_struct *wq = dev_to_wq(dev);
> struct workqueue_attrs *attrs;
> @@ -7762,14 +7762,40 @@ static ssize_t wq_affinity_strict_store(struct device *dev,
> return ret ?: count;
> }
>
> -static struct device_attribute wq_sysfs_unbound_attrs[] = {
> - __ATTR(nice, 0644, wq_nice_show, wq_nice_store),
> - __ATTR(cpumask, 0644, wq_cpumask_show, wq_cpumask_store),
> - __ATTR(affinity_scope, 0644, wq_affn_scope_show, wq_affn_scope_store),
> - __ATTR(affinity_strict, 0644, wq_affinity_strict_show, wq_affinity_strict_store),
> - __ATTR_NULL,
> +static DEVICE_ATTR_RW(nice);
> +static DEVICE_ATTR_RW(affn_scope);
Sashiko on dri-devel pointed out I blundered with the accidental rename
here. But lets first see if people think this simplification is desired
to begin with. I think it is nicer than having to suppress and re-enable
uvents, and unwind on errors, plus, it's handy for the WQ_RTPRI patch to
restrict write access to the nice attribute.
Regards,
Tvrtko
> +static DEVICE_ATTR_RW(affinity_strict);
> +/* Avoid naming clash with the other cpumask */
> +static struct device_attribute dev_attr_unbound_cpumask =
> + __ATTR(cpumask, 0644, unbound_cpumask_show, unbound_cpumask_store);
> +
> +static struct attribute *wq_sysfs_unbound_attrs[] = {
> + &dev_attr_nice.attr,
> + &dev_attr_unbound_cpumask.attr,
> + &dev_attr_affn_scope.attr,
> + &dev_attr_affinity_strict.attr,
> + NULL,
> };
>
> +static umode_t wq_sysfs_unbound_group_visible(struct kobject *kobj,
> + struct attribute *attr, int n)
> +{
> + struct device *dev = kobj_to_dev(kobj);
> + struct workqueue_struct *wq = dev_to_wq(dev);
> +
> + if (!(wq->flags & WQ_UNBOUND))
> + return SYSFS_GROUP_INVISIBLE;
> +
> + return attr->mode;
> +}
> +
> +static const struct attribute_group wq_sysfs_unbound_group = {
> + .is_visible = wq_sysfs_unbound_group_visible,
> + .attrs = wq_sysfs_unbound_attrs,
> +};
> +
> +__ATTRIBUTE_GROUPS(wq_sysfs_unbound);
> +
> static const struct bus_type wq_subsys = {
> .name = "workqueue",
> .dev_groups = wq_sysfs_groups,
> @@ -7907,14 +7933,9 @@ int workqueue_sysfs_register(struct workqueue_struct *wq)
> wq_dev->wq = wq;
> wq_dev->dev.bus = &wq_subsys;
> wq_dev->dev.release = wq_device_release;
> + wq_dev->dev.groups = wq_sysfs_unbound_groups;
> dev_set_name(&wq_dev->dev, "%s", wq->name);
>
> - /*
> - * attrs are created separately. Suppress uevent until
> - * everything is ready.
> - */
> - dev_set_uevent_suppress(&wq_dev->dev, true);
> -
> ret = device_register(&wq_dev->dev);
> if (ret) {
> put_device(&wq_dev->dev);
> @@ -7922,21 +7943,6 @@ int workqueue_sysfs_register(struct workqueue_struct *wq)
> return ret;
> }
>
> - if (wq->flags & WQ_UNBOUND) {
> - struct device_attribute *attr;
> -
> - for (attr = wq_sysfs_unbound_attrs; attr->attr.name; attr++) {
> - ret = device_create_file(&wq_dev->dev, attr);
> - if (ret) {
> - device_unregister(&wq_dev->dev);
> - wq->wq_dev = NULL;
> - return ret;
> - }
> - }
> - }
> -
> - dev_set_uevent_suppress(&wq_dev->dev, false);
> - kobject_uevent(&wq_dev->dev.kobj, KOBJ_ADD);
> return 0;
> }
>
next prev parent reply other threads:[~2026-09-23 17:12 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-23 16:12 [RFC v5 0/3] Realtime workqueues and panthor realtime submission Tvrtko Ursulin
2026-09-23 16:12 ` [RFC v5 1/3] workqueue: Simplify unbound sysfs attribute registration Tvrtko Ursulin
2026-09-23 16:22 ` sashiko-bot
2026-09-23 17:12 ` Tvrtko Ursulin [this message]
2026-09-23 16:12 ` [RFC v5 2/3] workqueue: Add support for real-time workers Tvrtko Ursulin
2026-09-23 16:25 ` sashiko-bot
2026-09-29 0:00 ` Tejun Heo
2026-10-01 9:22 ` Tvrtko Ursulin
2026-09-23 16:12 ` [RFC v5 3/3] drm/panthor: Create per queue priority workqueues Tvrtko Ursulin
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=282b1fc2-3305-4784-8f83-0f3bc461ec18@igalia.com \
--to=tvrtko.ursulin@igalia.com \
--cc=boris.brezillon@collabora.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=include@grrlz.net \
--cc=kernel-dev@igalia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=liviu.dudau@arm.com \
--cc=matthew.brost@intel.com \
--cc=olv@google.com \
--cc=steven.price@arm.com \
--cc=tj@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.