summaryrefslogtreecommitdiff
path: root/drivers/nvmem
diff options
context:
space:
mode:
authorBartosz Golaszewski <bgolaszewski@baylibre.com>2018-09-21 06:40:19 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-09-28 15:14:54 +0200
commitbee1138bea15a640aaa9e9bb909af5b2762520e0 (patch)
tree9745fdb09b3a5b08ace8a0bdb097eb40951f1095 /drivers/nvmem
parent4903d19c209529bd2e127d483dc93b472980f33e (diff)
nvmem: add a notifier chain
Add a blocking notifier chain with four events (add and remove for both devices and cells) so that users can get notified about the addition of nvmem resources they're waiting for. We'll use this instead of the at24 setup callback in the mityomapl138 board file. Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/nvmem')
-rw-r--r--drivers/nvmem/core.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 9cc86d131e1e..da441019b609 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -65,6 +65,8 @@ static LIST_HEAD(nvmem_cell_tables);
static DEFINE_MUTEX(nvmem_lookup_mutex);
static LIST_HEAD(nvmem_lookup_list);
+static BLOCKING_NOTIFIER_HEAD(nvmem_notifier);
+
#ifdef CONFIG_DEBUG_LOCK_ALLOC
static struct lock_class_key eeprom_lock_key;
#endif
@@ -300,6 +302,7 @@ static struct nvmem_device *nvmem_find(const char *name)
static void nvmem_cell_drop(struct nvmem_cell *cell)
{
+ blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_REMOVE, cell);
mutex_lock(&nvmem_mutex);
list_del(&cell->node);
mutex_unlock(&nvmem_mutex);
@@ -319,6 +322,7 @@ static void nvmem_cell_add(struct nvmem_cell *cell)
mutex_lock(&nvmem_mutex);
list_add_tail(&cell->node, &cell->nvmem->cells);
mutex_unlock(&nvmem_mutex);
+ blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_ADD, cell);
}
static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
@@ -434,6 +438,32 @@ static int nvmem_setup_compat(struct nvmem_device *nvmem,
return 0;
}
+/**
+ * nvmem_register_notifier() - Register a notifier block for nvmem events.
+ *
+ * @nb: notifier block to be called on nvmem events.
+ *
+ * Return: 0 on success, negative error number on failure.
+ */
+int nvmem_register_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&nvmem_notifier, nb);
+}
+EXPORT_SYMBOL_GPL(nvmem_register_notifier);
+
+/**
+ * nvmem_unregister_notifier() - Unregister a notifier block for nvmem events.
+ *
+ * @nb: notifier block to be unregistered.
+ *
+ * Return: 0 on success, negative error number on failure.
+ */
+int nvmem_unregister_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(&nvmem_notifier, nb);
+}
+EXPORT_SYMBOL_GPL(nvmem_unregister_notifier);
+
static int nvmem_add_cells_from_table(struct nvmem_device *nvmem)
{
const struct nvmem_cell_info *info;
@@ -647,6 +677,10 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
if (rval)
goto err_remove_cells;
+ rval = blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem);
+ if (rval)
+ goto err_remove_cells;
+
return nvmem;
err_remove_cells:
@@ -669,6 +703,8 @@ static void nvmem_device_release(struct kref *kref)
nvmem = container_of(kref, struct nvmem_device, refcnt);
+ blocking_notifier_call_chain(&nvmem_notifier, NVMEM_REMOVE, nvmem);
+
if (nvmem->flags & FLAG_COMPAT)
device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);