Re: [PATCH 01/12] notifier: add device-managed registration APIs

Bartosz Golaszewski <[email protected]> Fri, 24 Jul 2026 00:45:31 -0700
Newsgroups org.kernel.vger.linux-pwm,org.kernel.vger.linux-acpi,org.kernel.vger.linux-gpio,org.kernel.vger.linux-iio,org.kernel.vger.linux-input,org.kernel.vger.linux-kernel,org.kernel.vger.platform-driver-x86
Message-ID <CAMRc=MeE_FdDMpXzzBB2dwH18DWmmT9B=CeouoaG1tV=y6-fXQ@mail.gmail.com>
On Thu, 23 Jul 2026 19:53:14 +0200, Eliav Farber <[email protected]> said:
> 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 <[email protected]>
> ---
>  include/linux/notifier.h |  10 +++
>  kernel/notifier.c        | 151 +++++++++++++++++++++++++++++++++++++++
>  2 files changed, 161 insertions(+)
>
> diff --git a/include/linux/notifier.h b/include/linux/notifier.h
> index 01b6c9d9956f..aa3745d7459b 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);
> +extern int devm_atomic_notifier_chain_register(struct device *dev,
> +		struct atomic_notifier_head *nh,
> +		struct notifier_block *nb);

Please don't use extern with function prototypes in new code.

>  extern int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
>  		struct notifier_block *nb);
> +extern 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);
> +extern 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..b811638aa878 100644
> --- a/kernel/notifier.c
> +++ b/kernel/notifier.c
> @@ -1,4 +1,5 @@
>  // SPDX-License-Identifier: GPL-2.0-only
> +#include <linux/device.h>
>  #include <linux/kdebug.h>
>  #include <linux/kprobes.h>
>  #include <linux/export.h>
> @@ -197,6 +198,55 @@ 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.
> + *
> + *	Returns 0 on success, negative errno on error.

Should be:

Returns:
0 on success...

Bart