Message ID | 20180808153150.23444-4-brgl@bgdev.pl (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | at24: remove at24_platform_data | expand |
On Wed, Aug 08, 2018 at 05:31:25PM +0200, Bartosz Golaszewski wrote: > From: Bartosz Golaszewski <bgolaszewski@baylibre.com> > > Add a blocking notifier chain with two events (add and remove) so that > users can get notified about the addition of nvmem devices they're > waiting for. > > We'll use this instead of the at24 setup callback in the mityomapl138 > board file. Hi Bartosz What context is this notifier chain called in? I did something similar using the i2c notifier to try to work around the impending disappearing of the setup callback. But i got lockdep splats, because the notifier was called while some locks were being held, so it was not possible to register other i2c devices. The at24 setup callback is done as part of probe, so no important locks are held. Are any locks held when this notifier chain is called? Thanks Andrew -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
2018-08-08 18:13 GMT+02:00 Andrew Lunn <andrew@lunn.ch>: > On Wed, Aug 08, 2018 at 05:31:25PM +0200, Bartosz Golaszewski wrote: >> From: Bartosz Golaszewski <bgolaszewski@baylibre.com> >> >> Add a blocking notifier chain with two events (add and remove) so that >> users can get notified about the addition of nvmem devices they're >> waiting for. >> >> We'll use this instead of the at24 setup callback in the mityomapl138 >> board file. > > Hi Bartosz > > What context is this notifier chain called in? > > I did something similar using the i2c notifier to try to work around > the impending disappearing of the setup callback. But i got lockdep > splats, because the notifier was called while some locks were being > held, so it was not possible to register other i2c devices. > > The at24 setup callback is done as part of probe, so no important > locks are held. Are any locks held when this notifier chain is called? > > Thanks > Andrew In the case of at24 it would be called from at24_probe() -> nvmem_register() in process context. Would you mind testing it? Would be great to see if it works on multiple setups. Bart -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 329ea5b8f809..128c8e51bff2 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -65,6 +65,8 @@ static DEFINE_MUTEX(nvmem_cells_mutex); static LIST_HEAD(nvmem_cell_lookups); static DEFINE_MUTEX(nvmem_lookup_mutex); +static BLOCKING_NOTIFIER_HEAD(nvmem_notifier); + #ifdef CONFIG_DEBUG_LOCK_ALLOC static struct lock_class_key eeprom_lock_key; #endif @@ -479,6 +481,18 @@ static int nvmem_setup_compat(struct nvmem_device *nvmem, return 0; } +int nvmem_register_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&nvmem_notifier, nb); +} +EXPORT_SYMBOL_GPL(nvmem_register_notifier); + +int nvmem_unregister_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&nvmem_notifier, nb); +} +EXPORT_SYMBOL_GPL(nvmem_unregister_notifier); + /** * nvmem_register() - Register a nvmem device for given nvmem_config. * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem @@ -559,6 +573,10 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) if (config->cells) nvmem_add_cells(nvmem, config->cells, config->ncells); + rval = blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem); + if (rval) + goto err_device_del; + return nvmem; err_device_del: @@ -586,6 +604,8 @@ int nvmem_unregister(struct nvmem_device *nvmem) } mutex_unlock(&nvmem_mutex); + blocking_notifier_call_chain(&nvmem_notifier, NVMEM_REMOVE, nvmem); + if (nvmem->flags & FLAG_COMPAT) device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom); diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h index f4b5d3186e94..ae4d30347602 100644 --- a/include/linux/nvmem-consumer.h +++ b/include/linux/nvmem-consumer.h @@ -14,6 +14,7 @@ #include <linux/err.h> #include <linux/errno.h> +#include <linux/notifier.h> struct device; struct device_node; @@ -35,6 +36,11 @@ struct nvmem_cell_lookup { const char *nvmem_name; }; +enum { + NVMEM_ADD = 1, + NVMEM_REMOVE, +}; + #if IS_ENABLED(CONFIG_NVMEM) /* Cell based interface */ @@ -61,6 +67,8 @@ ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem, int nvmem_device_cell_write(struct nvmem_device *nvmem, struct nvmem_cell_info *info, void *buf); +int nvmem_register_notifier(struct notifier_block *nb); +int nvmem_unregister_notifier(struct notifier_block *nb); #else static inline struct nvmem_cell *nvmem_cell_get(struct device *dev, @@ -149,6 +157,16 @@ static inline int nvmem_device_write(struct nvmem_device *nvmem, { return -ENOSYS; } + +static inline int nvmem_register_notifier(struct notifier_block *nb) +{ + return -ENOSYS; +} + +static inline int int nvmem_unregister_notifier(struct notifier_block *nb) +{ + return -ENOSYS; +} #endif /* CONFIG_NVMEM */ #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)