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