All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eliav Farber <farbere@amazon.com>
To: <rafael@kernel.org>, <tony.luck@intel.com>, <bp@alien8.de>,
	<guohanjun@huawei.com>, <mchehab@kernel.org>,
	<xueshuai@linux.alibaba.com>, <lenb@kernel.org>,
	<laurent.pinchart@ideasonboard.com>, <linusw@kernel.org>,
	<brgl@kernel.org>, <orsonzhai@gmail.com>,
	<baolin.wang@linux.alibaba.com>, <zhang.lyra@gmail.com>,
	<jic23@kernel.org>, <dlechner@baylibre.com>, <nuno.sa@analog.com>,
	<andy@kernel.org>, <dmitry.torokhov@gmail.com>,
	<hansg@kernel.org>, <ilpo.jarvinen@linux.intel.com>,
	<W_Armin@gmx.de>, <ukleinek@kernel.org>,
	<fabio.m.de.francesco@linux.intel.com>, <kaihengf@nvidia.com>,
	<ankita@nvidia.com>, <leitao@debian.org>, <farbere@amazon.com>,
	<pedro.pbg@usp.br>, <paulmck@kernel.org>, <frederic@kernel.org>,
	<kees@kernel.org>, <linux-acpi@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>, <linux-gpio@vger.kernel.org>,
	<linux-pwm@vger.kernel.org>, <linux-iio@vger.kernel.org>,
	<linux-input@vger.kernel.org>,
	<platform-driver-x86@vger.kernel.org>
Subject: [PATCH v2 01/12] notifier: add device-managed registration APIs
Date: Sun, 26 Jul 2026 04:56:55 +0000	[thread overview]
Message-ID: <20260726045706.8169-2-farbere@amazon.com> (raw)
In-Reply-To: <20260726045706.8169-1-farbere@amazon.com>

Add devm_atomic_notifier_chain_register(),
devm_blocking_notifier_chain_register(), and
devm_raw_notifier_chain_register() that automatically unregister the
notifier when the device is unbound.

Many drivers repeat the same boilerplate pattern:

  1. Register the notifier with *_notifier_chain_register()
  2. Check for error
  3. Register a devm action to unregister on teardown
  4. Implement a per-driver static unregister callback

With the new devm_*_notifier_chain_register() APIs, this reduces to a
single call with one error path, eliminating per-driver unregister
callbacks entirely.

The implementation follows the established devres pattern used by other
device-managed kernel APIs.

Signed-off-by: Eliav Farber <farbere@amazon.com>
---
Changes in v2:
- Drop 'extern' from new function prototypes (Bart Van Assche)
- Fix kerneldoc to use 'Return:' format (Bart Van Assche)
- Use <linux/device/devres.h> instead of <linux/device.h> (Andy Shevchenko)

 include/linux/notifier.h |  10 +++
 kernel/notifier.c        | 154 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 164 insertions(+)

diff --git a/include/linux/notifier.h b/include/linux/notifier.h
index 01b6c9d9956f..ccac9382478c 100644
--- a/include/linux/notifier.h
+++ b/include/linux/notifier.h
@@ -46,6 +46,7 @@
  * often but notifier_blocks will seldom be removed.
  */
 
+struct device;
 struct notifier_block;
 
 typedef	int (*notifier_fn_t)(struct notifier_block *nb,
@@ -145,10 +146,19 @@ extern void srcu_init_notifier_head(struct srcu_notifier_head *nh);
 
 extern int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
 		struct notifier_block *nb);
+int devm_atomic_notifier_chain_register(struct device *dev,
+		struct atomic_notifier_head *nh,
+		struct notifier_block *nb);
 extern int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
 		struct notifier_block *nb);
+int devm_blocking_notifier_chain_register(struct device *dev,
+		struct blocking_notifier_head *nh,
+		struct notifier_block *nb);
 extern int raw_notifier_chain_register(struct raw_notifier_head *nh,
 		struct notifier_block *nb);
+int devm_raw_notifier_chain_register(struct device *dev,
+		struct raw_notifier_head *nh,
+		struct notifier_block *nb);
 extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
 		struct notifier_block *nb);
 
diff --git a/kernel/notifier.c b/kernel/notifier.c
index 2f9fe7c30287..d8c82b237586 100644
--- a/kernel/notifier.c
+++ b/kernel/notifier.c
@@ -1,4 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-only
+#include <linux/device/devres.h>
 #include <linux/kdebug.h>
 #include <linux/kprobes.h>
 #include <linux/export.h>
@@ -197,6 +198,56 @@ int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
 }
 EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
 
+struct atomic_notifier_chain_devres {
+	struct atomic_notifier_head *nh;
+	struct notifier_block *nb;
+};
+
+static void devm_atomic_notifier_chain_unregister(struct device *dev, void *res)
+{
+	struct atomic_notifier_chain_devres *dr = res;
+
+	atomic_notifier_chain_unregister(dr->nh, dr->nb);
+}
+
+/**
+ *	devm_atomic_notifier_chain_register - Device-managed atomic notifier registration
+ *	@dev: Device to tie the notifier lifetime to
+ *	@nh: Pointer to head of the atomic notifier chain
+ *	@n: New entry in notifier chain
+ *
+ *	Adds a notifier to an atomic notifier chain and registers a cleanup
+ *	action to automatically unregister it when @dev is unbound.
+ *
+ *	Return:
+ *	0 on success, negative errno on error.
+ */
+int devm_atomic_notifier_chain_register(struct device *dev,
+					struct atomic_notifier_head *nh,
+					struct notifier_block *n)
+{
+	struct atomic_notifier_chain_devres *dr;
+	int ret;
+
+	dr = devres_alloc(devm_atomic_notifier_chain_unregister,
+			  sizeof(*dr), GFP_KERNEL);
+	if (!dr)
+		return -ENOMEM;
+
+	ret = atomic_notifier_chain_register(nh, n);
+	if (ret) {
+		devres_free(dr);
+		return ret;
+	}
+
+	dr->nh = nh;
+	dr->nb = n;
+	devres_add(dev, dr);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(devm_atomic_notifier_chain_register);
+
 /**
  *	atomic_notifier_call_chain - Call functions in an atomic notifier chain
  *	@nh: Pointer to head of the atomic notifier chain
@@ -349,6 +400,58 @@ int blocking_notifier_call_chain_robust(struct blocking_notifier_head *nh,
 }
 EXPORT_SYMBOL_GPL(blocking_notifier_call_chain_robust);
 
+struct blocking_notifier_chain_devres {
+	struct blocking_notifier_head *nh;
+	struct notifier_block *nb;
+};
+
+static void devm_blocking_notifier_chain_unregister(struct device *dev,
+						    void *res)
+{
+	struct blocking_notifier_chain_devres *dr = res;
+
+	blocking_notifier_chain_unregister(dr->nh, dr->nb);
+}
+
+/**
+ *	devm_blocking_notifier_chain_register - Device-managed blocking notifier registration
+ *	@dev: Device to tie the notifier lifetime to
+ *	@nh: Pointer to head of the blocking notifier chain
+ *	@n: New entry in notifier chain
+ *
+ *	Adds a notifier to a blocking notifier chain and registers a cleanup
+ *	action to automatically unregister it when @dev is unbound.
+ *	Must be called in process context.
+ *
+ *	Return:
+ *	0 on success, negative errno on error.
+ */
+int devm_blocking_notifier_chain_register(struct device *dev,
+					  struct blocking_notifier_head *nh,
+					  struct notifier_block *n)
+{
+	struct blocking_notifier_chain_devres *dr;
+	int ret;
+
+	dr = devres_alloc(devm_blocking_notifier_chain_unregister,
+			  sizeof(*dr), GFP_KERNEL);
+	if (!dr)
+		return -ENOMEM;
+
+	ret = blocking_notifier_chain_register(nh, n);
+	if (ret) {
+		devres_free(dr);
+		return ret;
+	}
+
+	dr->nh = nh;
+	dr->nb = n;
+	devres_add(dev, dr);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(devm_blocking_notifier_chain_register);
+
 /**
  *	blocking_notifier_call_chain - Call functions in a blocking notifier chain
  *	@nh: Pointer to head of the blocking notifier chain
@@ -430,6 +533,57 @@ int raw_notifier_call_chain_robust(struct raw_notifier_head *nh,
 }
 EXPORT_SYMBOL_GPL(raw_notifier_call_chain_robust);
 
+struct raw_notifier_chain_devres {
+	struct raw_notifier_head *nh;
+	struct notifier_block *nb;
+};
+
+static void devm_raw_notifier_chain_unregister(struct device *dev, void *res)
+{
+	struct raw_notifier_chain_devres *dr = res;
+
+	raw_notifier_chain_unregister(dr->nh, dr->nb);
+}
+
+/**
+ *	devm_raw_notifier_chain_register - Device-managed raw notifier registration
+ *	@dev: Device to tie the notifier lifetime to
+ *	@nh: Pointer to head of the raw notifier chain
+ *	@n: New entry in notifier chain
+ *
+ *	Adds a notifier to a raw notifier chain and registers a cleanup
+ *	action to automatically unregister it when @dev is unbound.
+ *	All locking must be provided by the caller.
+ *
+ *	Return:
+ *	0 on success, negative errno on error.
+ */
+int devm_raw_notifier_chain_register(struct device *dev,
+				     struct raw_notifier_head *nh,
+				     struct notifier_block *n)
+{
+	struct raw_notifier_chain_devres *dr;
+	int ret;
+
+	dr = devres_alloc(devm_raw_notifier_chain_unregister,
+			  sizeof(*dr), GFP_KERNEL);
+	if (!dr)
+		return -ENOMEM;
+
+	ret = raw_notifier_chain_register(nh, n);
+	if (ret) {
+		devres_free(dr);
+		return ret;
+	}
+
+	dr->nh = nh;
+	dr->nb = n;
+	devres_add(dev, dr);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(devm_raw_notifier_chain_register);
+
 /**
  *	raw_notifier_call_chain - Call functions in a raw notifier chain
  *	@nh: Pointer to head of the raw notifier chain
-- 
2.47.3


  reply	other threads:[~2026-07-26  4:57 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-26  4:56 [PATCH v2 00/12] notifier: add device-managed registration APIs and convert drivers Eliav Farber
2026-07-26  4:56 ` Eliav Farber [this message]
2026-07-26  5:06   ` [PATCH v2 01/12] notifier: add device-managed registration APIs sashiko-bot
2026-07-26  4:56 ` [PATCH v2 02/12] pwm: iqs620a: use devm_blocking_notifier_chain_register() Eliav Farber
2026-07-26  4:56 ` [PATCH v2 03/12] iio: light: iqs621-als: " Eliav Farber
2026-07-26  4:56 ` [PATCH v2 04/12] iio: position: iqs624: " Eliav Farber
2026-07-26  4:56 ` [PATCH v2 05/12] gpio: adp5585: " Eliav Farber
2026-07-26  4:57 ` [PATCH v2 06/12] platform/x86: bitland-mifs-wmi: " Eliav Farber
2026-07-26  4:57 ` [PATCH v2 07/12] Input: adp5585: " Eliav Farber
2026-07-26  4:57 ` [PATCH v2 08/12] ACPI: APEI: GHES: " Eliav Farber
2026-07-26  4:57 ` [PATCH v2 09/12] platform/x86: uniwill-wmi: " Eliav Farber
2026-07-26  4:57 ` [PATCH v2 10/12] gpio: eic-sprd: use devm_atomic_notifier_chain_register() Eliav Farber
2026-07-26  4:57 ` [PATCH v2 11/12] gpio: gpiolib-kunit: use devm_blocking_notifier_chain_register() Eliav Farber
2026-07-26  4:57 ` [PATCH v2 12/12] reboot: " Eliav Farber
2026-07-26  5:07   ` sashiko-bot

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=20260726045706.8169-2-farbere@amazon.com \
    --to=farbere@amazon.com \
    --cc=W_Armin@gmx.de \
    --cc=andy@kernel.org \
    --cc=ankita@nvidia.com \
    --cc=baolin.wang@linux.alibaba.com \
    --cc=bp@alien8.de \
    --cc=brgl@kernel.org \
    --cc=dlechner@baylibre.com \
    --cc=dmitry.torokhov@gmail.com \
    --cc=fabio.m.de.francesco@linux.intel.com \
    --cc=frederic@kernel.org \
    --cc=guohanjun@huawei.com \
    --cc=hansg@kernel.org \
    --cc=ilpo.jarvinen@linux.intel.com \
    --cc=jic23@kernel.org \
    --cc=kaihengf@nvidia.com \
    --cc=kees@kernel.org \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=leitao@debian.org \
    --cc=lenb@kernel.org \
    --cc=linusw@kernel.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-gpio@vger.kernel.org \
    --cc=linux-iio@vger.kernel.org \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pwm@vger.kernel.org \
    --cc=mchehab@kernel.org \
    --cc=nuno.sa@analog.com \
    --cc=orsonzhai@gmail.com \
    --cc=paulmck@kernel.org \
    --cc=pedro.pbg@usp.br \
    --cc=platform-driver-x86@vger.kernel.org \
    --cc=rafael@kernel.org \
    --cc=tony.luck@intel.com \
    --cc=ukleinek@kernel.org \
    --cc=xueshuai@linux.alibaba.com \
    --cc=zhang.lyra@gmail.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.