From: Bartosz Golaszewski <[email protected]>
This series contains nvmem framework changes prerequisite for further
development of my previous series[1] that aims at removal of the
platform data struct from at24 EEPROM driver.
First we remove unused APIs and the global cell list. We then switch
to using kref instead of manual user counting. Next we simplify the
provider unregistration by removing the return value from
nvmem_unregister().
Next three patches improve the framework by adding a notifier chain
for future use and fixing the issue with nvmem device names.
Finally we add support for cell definitions, cell lookups and make
DT systems resolve the nvmem cells during provider's registration.
Last patch just uses the SPDX license identifiers.
Tested both DT and non-DT use cases.
[1] https://lkml.org/lkml/2018/8/10/149
Bartosz Golaszewski (13):
nvmem: remove unused APIs
nvmem: remove the global cell list
nvmem: use kref
nvmem: lpc18xx_eeprom: use devm_nvmem_register()
nvmem: change the signature of nvmem_unregister()
nvmem: provide nvmem_dev_name()
nvmem: remove the name field from struct nvmem_device
nvmem: add a notifier chain
nvmem: add support for cell info
nvmem: resolve cells from DT at registration time
nvmem: add support for cell lookups from machine code
Documentation: nvmem: document cell tables and lookup entries
nvmem: use SPDX license identifiers
Documentation/nvmem/nvmem.txt | 30 ++
MAINTAINERS | 1 +
drivers/nvmem/core.c | 650 ++++++++++++++++++---------------
drivers/nvmem/lpc18xx_eeprom.c | 6 +-
include/linux/nvmem-consumer.h | 50 ++-
include/linux/nvmem-machine.h | 56 +++
include/linux/nvmem-provider.h | 22 +-
7 files changed, 465 insertions(+), 350 deletions(-)
create mode 100644 include/linux/nvmem-machine.h
--
2.18.0
From: Bartosz Golaszewski <[email protected]>
Use SPDX license identiefiers to core nvmem files and remove GPL 2.0
license boilerplate.
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
drivers/nvmem/core.c | 10 +---------
include/linux/nvmem-consumer.h | 5 +----
include/linux/nvmem-provider.h | 5 +----
3 files changed, 3 insertions(+), 17 deletions(-)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index d7c609109cfd..9a4eaedaa5ea 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -1,17 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* nvmem framework core.
*
* Copyright (C) 2015 Srinivas Kandagatla <[email protected]>
* Copyright (C) 2013 Maxime Ripard <[email protected]>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#include <linux/device.h>
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
index 8a6405febc32..e417e28d6aa2 100644
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -1,12 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* nvmem framework consumer.
*
* Copyright (C) 2015 Srinivas Kandagatla <[email protected]>
* Copyright (C) 2013 Maxime Ripard <[email protected]>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
*/
#ifndef _LINUX_NVMEM_CONSUMER_H
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index 07ab1ea73520..02ac0dcb2001 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -1,12 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* nvmem framework provider.
*
* Copyright (C) 2015 Srinivas Kandagatla <[email protected]>
* Copyright (C) 2013 Maxime Ripard <[email protected]>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
*/
#ifndef _LINUX_NVMEM_PROVIDER_H
--
2.18.0
From: Bartosz Golaszewski <[email protected]>
Use kref for reference counting. Use an approach similar to the one
seen in the common clock subsystem: don't actually destroy the nvmem
device until the last user puts it. This way we can get rid of the
users check from nvmem_unregister().
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
drivers/nvmem/core.c | 45 +++++++++++++++++++++-----------------------
1 file changed, 21 insertions(+), 24 deletions(-)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 86af62e2df47..2335b72d4b3e 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -32,7 +32,7 @@ struct nvmem_device {
int stride;
int word_size;
int id;
- int users;
+ struct kref refcnt;
size_t size;
bool read_only;
int flags;
@@ -368,6 +368,8 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
return ERR_PTR(rval);
}
+ kref_init(&nvmem->refcnt);
+
nvmem->id = rval;
nvmem->owner = config->owner;
if (!nvmem->owner && config->dev->driver)
@@ -430,6 +432,20 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
}
EXPORT_SYMBOL_GPL(nvmem_register);
+static void nvmem_device_release(struct kref *kref)
+{
+ struct nvmem_device *nvmem;
+
+ nvmem = container_of(kref, struct nvmem_device, refcnt);
+
+ if (nvmem->flags & FLAG_COMPAT)
+ device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
+
+ nvmem_device_remove_all_cells(nvmem);
+ device_del(&nvmem->dev);
+ put_device(&nvmem->dev);
+}
+
/**
* nvmem_unregister() - Unregister previously registered nvmem device
*
@@ -439,19 +455,7 @@ EXPORT_SYMBOL_GPL(nvmem_register);
*/
int nvmem_unregister(struct nvmem_device *nvmem)
{
- mutex_lock(&nvmem_mutex);
- if (nvmem->users) {
- mutex_unlock(&nvmem_mutex);
- return -EBUSY;
- }
- mutex_unlock(&nvmem_mutex);
-
- if (nvmem->flags & FLAG_COMPAT)
- device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
-
- nvmem_device_remove_all_cells(nvmem);
- device_del(&nvmem->dev);
- put_device(&nvmem->dev);
+ kref_put(&nvmem->refcnt, nvmem_device_release);
return 0;
}
@@ -517,7 +521,6 @@ int devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem)
}
EXPORT_SYMBOL(devm_nvmem_unregister);
-
static struct nvmem_device *__nvmem_device_get(struct device_node *np)
{
struct nvmem_device *nvmem = NULL;
@@ -533,30 +536,24 @@ static struct nvmem_device *__nvmem_device_get(struct device_node *np)
return ERR_PTR(-EPROBE_DEFER);
}
- nvmem->users++;
mutex_unlock(&nvmem_mutex);
if (!try_module_get(nvmem->owner)) {
dev_err(&nvmem->dev,
"could not increase module refcount for cell %s\n",
nvmem->name);
-
- mutex_lock(&nvmem_mutex);
- nvmem->users--;
- mutex_unlock(&nvmem_mutex);
-
return ERR_PTR(-EINVAL);
}
+ kref_get(&nvmem->refcnt);
+
return nvmem;
}
static void __nvmem_device_put(struct nvmem_device *nvmem)
{
module_put(nvmem->owner);
- mutex_lock(&nvmem_mutex);
- nvmem->users--;
- mutex_unlock(&nvmem_mutex);
+ kref_put(&nvmem->refcnt, nvmem_device_release);
}
static struct nvmem_device *nvmem_find(const char *name)
--
2.18.0
From: Bartosz Golaszewski <[email protected]>
Add a way for machine code users to associate devices with nvmem cells.
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
drivers/nvmem/core.c | 142 +++++++++++++++++++++++++++-------
include/linux/nvmem-machine.h | 15 ++++
2 files changed, 130 insertions(+), 27 deletions(-)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index da7a9d5beb33..d7c609109cfd 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -62,6 +62,9 @@ static DEFINE_IDA(nvmem_ida);
static DEFINE_MUTEX(nvmem_cell_mutex);
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
@@ -285,6 +288,18 @@ static struct nvmem_device *of_nvmem_find(struct device_node *nvmem_np)
return to_nvmem_device(d);
}
+static struct nvmem_device *nvmem_find(const char *name)
+{
+ struct device *d;
+
+ d = bus_find_device_by_name(&nvmem_bus_type, NULL, name);
+
+ if (!d)
+ return NULL;
+
+ return to_nvmem_device(d);
+}
+
static void nvmem_cell_drop(struct nvmem_cell *cell)
{
mutex_lock(&nvmem_mutex);
@@ -421,6 +436,21 @@ nvmem_find_cell_by_index(struct nvmem_device *nvmem, int index)
return cell;
}
+static struct nvmem_cell *
+nvmem_find_cell_by_name(struct nvmem_device *nvmem, const char *cell_id)
+{
+ struct nvmem_cell *cell = NULL;
+
+ mutex_lock(&nvmem_mutex);
+ list_for_each_entry(cell, &nvmem->cells, node) {
+ if (strcmp(cell_id, cell->name) == 0)
+ break;
+ }
+ mutex_unlock(&nvmem_mutex);
+
+ return cell;
+}
+
static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
{
struct device_node *parent, *child;
@@ -691,22 +721,16 @@ int devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem)
}
EXPORT_SYMBOL(devm_nvmem_unregister);
-static struct nvmem_device *__nvmem_device_get(struct device_node *np)
+static struct nvmem_device *
+__nvmem_device_get(struct device_node *np, const char *name)
{
struct nvmem_device *nvmem = NULL;
- if (!np)
- return ERR_PTR(-EINVAL);
-
mutex_lock(&nvmem_mutex);
-
- nvmem = of_nvmem_find(np);
- if (!nvmem) {
- mutex_unlock(&nvmem_mutex);
- return ERR_PTR(-EPROBE_DEFER);
- }
-
+ nvmem = np ? of_nvmem_find(np) : nvmem_find(name);
mutex_unlock(&nvmem_mutex);
+ if (!nvmem)
+ return ERR_PTR(-EPROBE_DEFER);
if (!try_module_get(nvmem->owner)) {
dev_err(&nvmem->dev,
@@ -726,18 +750,6 @@ static void __nvmem_device_put(struct nvmem_device *nvmem)
kref_put(&nvmem->refcnt, nvmem_device_release);
}
-static struct nvmem_device *nvmem_find(const char *name)
-{
- struct device *d;
-
- d = bus_find_device_by_name(&nvmem_bus_type, NULL, name);
-
- if (!d)
- return NULL;
-
- return to_nvmem_device(d);
-}
-
#if IS_ENABLED(CONFIG_OF)
/**
* of_nvmem_device_get() - Get nvmem device from a given id
@@ -760,7 +772,7 @@ struct nvmem_device *of_nvmem_device_get(struct device_node *np, const char *id)
if (!nvmem_np)
return ERR_PTR(-EINVAL);
- return __nvmem_device_get(nvmem_np);
+ return __nvmem_device_get(nvmem_np, NULL);
}
EXPORT_SYMBOL_GPL(of_nvmem_device_get);
#endif
@@ -897,7 +909,7 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
if (!nvmem_np)
return ERR_PTR(-EINVAL);
- nvmem = __nvmem_device_get(nvmem_np);
+ nvmem = __nvmem_device_get(nvmem_np, NULL);
of_node_put(nvmem_np);
if (IS_ERR(nvmem))
return ERR_CAST(nvmem);
@@ -913,6 +925,43 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
EXPORT_SYMBOL_GPL(of_nvmem_cell_get);
#endif
+static struct nvmem_cell *
+nvmem_cell_get_from_lookup(struct device *dev, const char *cell_id)
+{
+ struct nvmem_cell *cell = ERR_PTR(-ENOENT);
+ struct nvmem_cell_lookup *lookup;
+ struct nvmem_device *nvmem;
+ const char *dev_id;
+
+ if (!dev)
+ return ERR_PTR(-EINVAL);
+
+ dev_id = dev_name(dev);
+
+ mutex_lock(&nvmem_lookup_mutex);
+
+ list_for_each_entry(lookup, &nvmem_lookup_list, node) {
+ if ((strcmp(lookup->dev_id, dev_id) == 0) &&
+ (strcmp(lookup->cell_id, cell_id) == 0)) {
+ /* This is the right entry. */
+ nvmem = __nvmem_device_get(NULL, lookup->nvmem_name);
+ if (!nvmem) {
+ /* Provider may not be registered yet. */
+ cell = ERR_PTR(-EPROBE_DEFER);
+ goto out;
+ }
+
+ cell = nvmem_find_cell_by_name(nvmem, cell_id);
+ if (!cell)
+ goto out;
+ }
+ }
+
+out:
+ mutex_unlock(&nvmem_lookup_mutex);
+ return cell;
+}
+
/**
* nvmem_cell_get() - Get nvmem cell of device form a given cell name
*
@@ -925,10 +974,14 @@ EXPORT_SYMBOL_GPL(of_nvmem_cell_get);
*/
struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *cell_id)
{
- if (!dev->of_node)
+ if (dev->of_node)
+ return of_nvmem_cell_get(dev->of_node, cell_id);
+
+ /* Only allow empty cell_id for DT systems. */
+ if (!cell_id)
return ERR_PTR(-EINVAL);
- return of_nvmem_cell_get(dev->of_node, cell_id);
+ return nvmem_cell_get_from_lookup(dev, cell_id);
}
EXPORT_SYMBOL_GPL(nvmem_cell_get);
@@ -1300,6 +1353,41 @@ void nvmem_del_cell_table(struct nvmem_cell_table *table)
}
EXPORT_SYMBOL_GPL(nvmem_del_cell_table);
+/**
+ * nvmem_add_cell_lookups() - register a list of cell lookup entries
+ *
+ * @entries: array of cell lookup entries
+ * @nentries: number of cell lookup entries in the array
+ */
+void nvmem_add_cell_lookups(struct nvmem_cell_lookup *entries, size_t nentries)
+{
+ int i;
+
+ mutex_lock(&nvmem_lookup_mutex);
+ for (i = 0; i < nentries; i++)
+ list_add_tail(&entries[i].node, &nvmem_lookup_list);
+ mutex_unlock(&nvmem_lookup_mutex);
+}
+EXPORT_SYMBOL_GPL(nvmem_add_cell_lookups);
+
+/**
+ * nvmem_del_cell_lookups() - remove a list of previously added cell lookup
+ * entries
+ *
+ * @entries: array of cell lookup entries
+ * @nentries: number of cell lookup entries in the array
+ */
+void nvmem_del_cell_lookups(struct nvmem_cell_lookup *entries, size_t nentries)
+{
+ int i;
+
+ mutex_lock(&nvmem_lookup_mutex);
+ for (i = 0; i < nentries; i++)
+ list_del(&entries[i].node);
+ mutex_unlock(&nvmem_lookup_mutex);
+}
+EXPORT_SYMBOL_GPL(nvmem_del_cell_lookups);
+
/**
* nvmem_dev_name() - Get the name of a given nvmem device.
*
diff --git a/include/linux/nvmem-machine.h b/include/linux/nvmem-machine.h
index 1e199dfaacab..79421bbf9d13 100644
--- a/include/linux/nvmem-machine.h
+++ b/include/linux/nvmem-machine.h
@@ -26,16 +26,31 @@ struct nvmem_cell_table {
struct list_head node;
};
+struct nvmem_cell_lookup {
+ const char *nvmem_name;
+ const char *dev_id;
+ const char *cell_id;
+ struct list_head node;
+};
+
#if IS_ENABLED(CONFIG_NVMEM)
void nvmem_add_cell_table(struct nvmem_cell_table *table);
void nvmem_del_cell_table(struct nvmem_cell_table *table);
+void nvmem_add_cell_lookups(struct nvmem_cell_lookup *entries, size_t nentries);
+void nvmem_del_cell_lookups(struct nvmem_cell_lookup *entries, size_t nentries);
+
#else /* CONFIG_NVMEM */
static inline void nvmem_add_cell_table(struct nvmem_cell_table *table) {}
static inline void nvmem_del_cell_table(struct nvmem_cell_table *table) {}
+static inline void
+nvmem_add_cell_lookups(struct nvmem_cell_lookup *entries, size_t nentries) {}
+static inline void
+nvmem_del_cell_lookups(struct nvmem_cell_lookup *entries, size_t nentries) {}
+
#endif /* CONFIG_NVMEM */
#endif /* ifndef _LINUX_NVMEM_MACHINE_H */
--
2.18.0
From: Bartosz Golaszewski <[email protected]>
Document the new nvmem kernel APIs.
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
Documentation/nvmem/nvmem.txt | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/Documentation/nvmem/nvmem.txt b/Documentation/nvmem/nvmem.txt
index 8d8d8f58f96f..2cb01cdf87c8 100644
--- a/Documentation/nvmem/nvmem.txt
+++ b/Documentation/nvmem/nvmem.txt
@@ -58,6 +58,36 @@ static int qfprom_probe(struct platform_device *pdev)
It is mandatory that the NVMEM provider has a regmap associated with its
struct device. Failure to do would return error code from nvmem_register().
+Users of board files can define and register nvmem cells using the
+nvmem_cell_table struct:
+
+static struct nvmem_cell_info foo_nvmem_cells[] = {
+ {
+ .name = "mac-address",
+ .offset = 0x7f00,
+ .bytes = ETH_ALEN,
+ }
+};
+
+static struct nvmem_cell_table foo_nvmem_cell_table = {
+ .nvmem_name = "i2c-eeprom",
+ .cells = foo_nvmem_cells,
+ .ncells = ARRAY_SIZE(foo_nvmem_cells),
+};
+
+nvmem_add_cell_table(&foo_nvmem_cell_table);
+
+Additionally it is possible to create nvmem cell lookup entries and register
+them with the nvmem framework from machine code as shown in the example below:
+
+static struct nvmem_cell_lookup foo_nvmem_lookup = {
+ .nvmem_name = "i2c-eeprom",
+ .dev_id = "foo_mac.0",
+ .cell_id = "mac-address",
+};
+
+nvmem_add_cell_lookups(&foo_nvmem_lookup, 1);
+
NVMEM Consumers
+++++++++++++++
--
2.18.0
From: Bartosz Golaszewski <[email protected]>
Add new structs and routines allowing users to define nvmem cells from
machine code. This global list of entries is parsed when a provider
is registered and cells are associated with the relevant nvmem_device
struct.
A possible improvement for the future is to allow users to register
cell tables after the nvmem provider has been registered by updating
the cell list at each call to nvmem_(add|del)_cell_table().
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
MAINTAINERS | 1 +
drivers/nvmem/core.c | 97 ++++++++++++++++++++++++++++++++++-
include/linux/nvmem-machine.h | 41 +++++++++++++++
3 files changed, 138 insertions(+), 1 deletion(-)
create mode 100644 include/linux/nvmem-machine.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 9ad052aeac39..a520924bf0a9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10391,6 +10391,7 @@ F: drivers/nvmem/
F: Documentation/devicetree/bindings/nvmem/
F: Documentation/ABI/stable/sysfs-bus-nvmem
F: include/linux/nvmem-consumer.h
+F: include/linux/nvmem-machine.h
F: include/linux/nvmem-provider.h
NXP SGTL5000 DRIVER
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 17307015905a..854baa0559a1 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/nvmem-consumer.h>
+#include <linux/nvmem-machine.h>
#include <linux/nvmem-provider.h>
#include <linux/of.h>
#include <linux/slab.h>
@@ -58,6 +59,9 @@ struct nvmem_cell {
static DEFINE_MUTEX(nvmem_mutex);
static DEFINE_IDA(nvmem_ida);
+static DEFINE_MUTEX(nvmem_cell_mutex);
+static LIST_HEAD(nvmem_cell_tables);
+
static BLOCKING_NOTIFIER_HEAD(nvmem_notifier);
#ifdef CONFIG_DEBUG_LOCK_ALLOC
@@ -341,6 +345,66 @@ static int nvmem_setup_compat(struct nvmem_device *nvmem,
return 0;
}
+static struct nvmem_cell *
+nvmem_cell_from_cell_info(struct nvmem_device *nvmem,
+ struct nvmem_cell_info *info)
+{
+ struct nvmem_cell *cell;
+
+ cell = kzalloc(sizeof(*cell), GFP_KERNEL);
+ if (!cell)
+ return ERR_PTR(-ENOMEM);
+
+ cell->nvmem = nvmem;
+ cell->offset = info->offset;
+ cell->bytes = info->bytes;
+ cell->name = info->name;
+ cell->bit_offset = info->bit_offset;
+ cell->nbits = info->nbits;
+
+ if (cell->nbits)
+ cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
+ BITS_PER_BYTE);
+
+ if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
+ dev_err(&nvmem->dev,
+ "cell %s unaligned to nvmem stride %d\n",
+ cell->name, nvmem->stride);
+ kfree(cell);
+ return ERR_PTR(-EINVAL);
+ }
+
+ return cell;
+}
+
+static int nvmem_add_cells_from_list(struct nvmem_device *nvmem)
+{
+ struct nvmem_cell_table *table;
+ struct nvmem_cell_info *info;
+ struct nvmem_cell *cell;
+ int rval = 0, i;
+
+ mutex_lock(&nvmem_cell_mutex);
+ list_for_each_entry(table, &nvmem_cell_tables, node) {
+ if (strcmp(nvmem_dev_name(nvmem), table->nvmem_name) == 0) {
+ for (i = 0; i < table->ncells; i++) {
+ info = &table->cells[i];
+ cell = nvmem_cell_from_cell_info(nvmem, info);
+ if (IS_ERR(cell)) {
+ rval = PTR_ERR(cell);
+ goto out;
+ }
+
+ nvmem_cell_add(cell);
+ }
+ }
+ }
+
+out:
+ mutex_unlock(&nvmem_cell_mutex);
+ return rval;
+}
+
/**
* nvmem_register_notifier() - Register a notifier block for nvmem events.
*
@@ -447,13 +511,18 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
}
INIT_LIST_HEAD(&nvmem->cells);
+ rval = nvmem_add_cells_from_list(nvmem);
+ if (rval)
+ goto err_teardown_compat;
rval = blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem);
if (rval)
- goto err_teardown_compat;
+ goto err_remove_cells;
return nvmem;
+err_remove_cells:
+ nvmem_device_remove_all_cells(nvmem);
err_teardown_compat:
if (config->compat)
device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
@@ -1179,6 +1248,32 @@ int nvmem_device_write(struct nvmem_device *nvmem,
}
EXPORT_SYMBOL_GPL(nvmem_device_write);
+/**
+ * nvmem_add_cell_table() - register a table of cell info entries
+ *
+ * @table: table of cell info entries
+ */
+void nvmem_add_cell_table(struct nvmem_cell_table *table)
+{
+ mutex_lock(&nvmem_cell_mutex);
+ list_add_tail(&table->node, &nvmem_cell_tables);
+ mutex_unlock(&nvmem_cell_mutex);
+}
+EXPORT_SYMBOL_GPL(nvmem_add_cell_table);
+
+/**
+ * nvmem_del_cell_table() - remove a previously registered cell info table
+ *
+ * @table: table of cell info entries
+ */
+void nvmem_del_cell_table(struct nvmem_cell_table *table)
+{
+ mutex_lock(&nvmem_cell_mutex);
+ list_del(&table->node);
+ mutex_unlock(&nvmem_cell_mutex);
+}
+EXPORT_SYMBOL_GPL(nvmem_del_cell_table);
+
/**
* nvmem_dev_name() - Get the name of a given nvmem device.
*
diff --git a/include/linux/nvmem-machine.h b/include/linux/nvmem-machine.h
new file mode 100644
index 000000000000..1e199dfaacab
--- /dev/null
+++ b/include/linux/nvmem-machine.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * nvmem framework machine code bindings
+ *
+ * Copyright (C) 2018 Bartosz Golaszewski <[email protected]>
+ */
+
+#ifndef _LINUX_NVMEM_MACHINE_H
+#define _LINUX_NVMEM_MACHINE_H
+
+#include <linux/nvmem-provider.h>
+#include <linux/list.h>
+
+struct nvmem_cell_info {
+ const char *name;
+ unsigned int offset;
+ unsigned int bytes;
+ unsigned int bit_offset;
+ unsigned int nbits;
+};
+
+struct nvmem_cell_table {
+ const char *nvmem_name;
+ struct nvmem_cell_info *cells;
+ size_t ncells;
+ struct list_head node;
+};
+
+#if IS_ENABLED(CONFIG_NVMEM)
+
+void nvmem_add_cell_table(struct nvmem_cell_table *table);
+void nvmem_del_cell_table(struct nvmem_cell_table *table);
+
+#else /* CONFIG_NVMEM */
+
+static inline void nvmem_add_cell_table(struct nvmem_cell_table *table) {}
+static inline void nvmem_del_cell_table(struct nvmem_cell_table *table) {}
+
+#endif /* CONFIG_NVMEM */
+
+#endif /* ifndef _LINUX_NVMEM_MACHINE_H */
--
2.18.0
From: Bartosz Golaszewski <[email protected]>
Currently we're creating a new cell structure everytime a DT users
calls nvmem_cell_get().
Change this behavior by resolving the cells during nvmem provider
registration and adding all cells to the provider's list. Make
of_nvmem_cell_get() just parse the phandle and look the cell up
in the relevant provider's list.
Don't drop the cell in nvmem_cell_put().
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
drivers/nvmem/core.c | 122 ++++++++++++++++++++++++++-----------------
1 file changed, 74 insertions(+), 48 deletions(-)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 854baa0559a1..da7a9d5beb33 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -405,6 +405,73 @@ static int nvmem_add_cells_from_list(struct nvmem_device *nvmem)
return rval;
}
+static struct nvmem_cell *
+nvmem_find_cell_by_index(struct nvmem_device *nvmem, int index)
+{
+ struct nvmem_cell *cell = NULL;
+ int i = 0;
+
+ mutex_lock(&nvmem_mutex);
+ list_for_each_entry(cell, &nvmem->cells, node) {
+ if (index == i++)
+ break;
+ }
+ mutex_unlock(&nvmem_mutex);
+
+ return cell;
+}
+
+static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
+{
+ struct device_node *parent, *child;
+ struct device *dev = &nvmem->dev;
+ struct nvmem_cell *cell;
+ const __be32 *addr;
+ int len;
+
+ parent = dev->of_node;
+
+ for_each_child_of_node(parent, child) {
+ addr = of_get_property(child, "reg", &len);
+ if (!addr || (len < 2 * sizeof(u32))) {
+ dev_err(dev, "nvmem: invalid reg on %pOF\n", child);
+ return -EINVAL;
+ }
+
+ cell = kzalloc(sizeof(*cell), GFP_KERNEL);
+ if (!cell)
+ return -ENOMEM;
+
+ cell->nvmem = nvmem;
+ cell->offset = be32_to_cpup(addr++);
+ cell->bytes = be32_to_cpup(addr);
+ cell->name = child->name;
+
+ addr = of_get_property(child, "bits", &len);
+ if (addr && len == (2 * sizeof(u32))) {
+ cell->bit_offset = be32_to_cpup(addr++);
+ cell->nbits = be32_to_cpup(addr);
+ }
+
+ if (cell->nbits)
+ cell->bytes = DIV_ROUND_UP(
+ cell->nbits + cell->bit_offset,
+ BITS_PER_BYTE);
+
+ if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
+ dev_err(dev, "cell %s unaligned to nvmem stride %d\n",
+ cell->name, nvmem->stride);
+ /* Cells already added will be freed later. */
+ kfree(cell);
+ return -EINVAL;
+ }
+
+ nvmem_cell_add(cell);
+ }
+
+ return 0;
+}
+
/**
* nvmem_register_notifier() - Register a notifier block for nvmem events.
*
@@ -514,6 +581,9 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
rval = nvmem_add_cells_from_list(nvmem);
if (rval)
goto err_teardown_compat;
+ rval = nvmem_add_cells_from_of(nvmem);
+ if (rval)
+ goto err_remove_cells;
rval = blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem);
if (rval)
@@ -811,10 +881,8 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
const char *name)
{
struct device_node *cell_np, *nvmem_np;
- struct nvmem_cell *cell;
struct nvmem_device *nvmem;
- const __be32 *addr;
- int rval, len;
+ struct nvmem_cell *cell;
int index = 0;
/* if cell name exists, find index to the name */
@@ -834,54 +902,13 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
if (IS_ERR(nvmem))
return ERR_CAST(nvmem);
- addr = of_get_property(cell_np, "reg", &len);
- if (!addr || (len < 2 * sizeof(u32))) {
- dev_err(&nvmem->dev, "nvmem: invalid reg on %pOF\n",
- cell_np);
- rval = -EINVAL;
- goto err_mem;
- }
-
- cell = kzalloc(sizeof(*cell), GFP_KERNEL);
+ cell = nvmem_find_cell_by_index(nvmem, index);
if (!cell) {
- rval = -ENOMEM;
- goto err_mem;
- }
-
- cell->nvmem = nvmem;
- cell->offset = be32_to_cpup(addr++);
- cell->bytes = be32_to_cpup(addr);
- cell->name = cell_np->name;
-
- addr = of_get_property(cell_np, "bits", &len);
- if (addr && len == (2 * sizeof(u32))) {
- cell->bit_offset = be32_to_cpup(addr++);
- cell->nbits = be32_to_cpup(addr);
- }
-
- if (cell->nbits)
- cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
- BITS_PER_BYTE);
-
- if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
- dev_err(&nvmem->dev,
- "cell %s unaligned to nvmem stride %d\n",
- cell->name, nvmem->stride);
- rval = -EINVAL;
- goto err_sanity;
+ __nvmem_device_put(nvmem);
+ return ERR_PTR(-ENOENT);
}
- nvmem_cell_add(cell);
-
return cell;
-
-err_sanity:
- kfree(cell);
-
-err_mem:
- __nvmem_device_put(nvmem);
-
- return ERR_PTR(rval);
}
EXPORT_SYMBOL_GPL(of_nvmem_cell_get);
#endif
@@ -978,7 +1005,6 @@ void nvmem_cell_put(struct nvmem_cell *cell)
struct nvmem_device *nvmem = cell->nvmem;
__nvmem_device_put(nvmem);
- nvmem_cell_drop(cell);
}
EXPORT_SYMBOL_GPL(nvmem_cell_put);
--
2.18.0
From: Bartosz Golaszewski <[email protected]>
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.
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
drivers/nvmem/core.c | 36 ++++++++++++++++++++++++++++++++++
include/linux/nvmem-consumer.h | 19 ++++++++++++++++++
2 files changed, 55 insertions(+)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index e456aaa6184a..17307015905a 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -58,6 +58,8 @@ struct nvmem_cell {
static DEFINE_MUTEX(nvmem_mutex);
static DEFINE_IDA(nvmem_ida);
+static BLOCKING_NOTIFIER_HEAD(nvmem_notifier);
+
#ifdef CONFIG_DEBUG_LOCK_ALLOC
static struct lock_class_key eeprom_lock_key;
#endif
@@ -339,6 +341,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);
+
/**
* nvmem_register() - Register a nvmem device for given nvmem_config.
* Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
@@ -420,8 +448,15 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
INIT_LIST_HEAD(&nvmem->cells);
+ rval = blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem);
+ if (rval)
+ goto err_teardown_compat;
+
return nvmem;
+err_teardown_compat:
+ if (config->compat)
+ device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
err_device_del:
device_del(&nvmem->dev);
err_put_device:
@@ -436,6 +471,7 @@ static void nvmem_device_release(struct kref *kref)
struct nvmem_device *nvmem;
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);
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
index 1313da6731ff..8a6405febc32 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;
@@ -21,6 +22,11 @@ struct device_node;
struct nvmem_cell;
struct nvmem_device;
+enum {
+ NVMEM_ADD = 1,
+ NVMEM_REMOVE,
+};
+
#if IS_ENABLED(CONFIG_NVMEM)
/* Cell based interface */
@@ -45,6 +51,9 @@ int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
const char *nvmem_dev_name(struct nvmem_device *nvmem);
+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,
@@ -125,6 +134,16 @@ static inline const char *nvmem_dev_name(struct nvmem_device *nvmem)
return NULL;
}
+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)
--
2.18.0
From: Bartosz Golaszewski <[email protected]>
This field is never set and is only used in a single error message.
Remove the field and use nvmem_dev_name() instead.
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
drivers/nvmem/core.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 364ee16e7d6a..e456aaa6184a 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -26,7 +26,6 @@
#include <linux/slab.h>
struct nvmem_device {
- const char *name;
struct module *owner;
struct device dev;
int stride;
@@ -537,7 +536,7 @@ static struct nvmem_device *__nvmem_device_get(struct device_node *np)
if (!try_module_get(nvmem->owner)) {
dev_err(&nvmem->dev,
"could not increase module refcount for cell %s\n",
- nvmem->name);
+ nvmem_dev_name(nvmem));
return ERR_PTR(-EINVAL);
}
--
2.18.0
From: Bartosz Golaszewski <[email protected]>
This function can no longer fail and there are no more users that check
it return value. Change it to return void.
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
drivers/nvmem/core.c | 8 ++------
include/linux/nvmem-provider.h | 4 ++--
2 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 2335b72d4b3e..89b91f73d08a 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -450,20 +450,16 @@ static void nvmem_device_release(struct kref *kref)
* nvmem_unregister() - Unregister previously registered nvmem device
*
* @nvmem: Pointer to previously registered nvmem device.
- *
- * Return: Will be an negative on error or a zero on success.
*/
-int nvmem_unregister(struct nvmem_device *nvmem)
+void nvmem_unregister(struct nvmem_device *nvmem)
{
kref_put(&nvmem->refcnt, nvmem_device_release);
-
- return 0;
}
EXPORT_SYMBOL_GPL(nvmem_unregister);
static void devm_nvmem_release(struct device *dev, void *res)
{
- WARN_ON(nvmem_unregister(*(struct nvmem_device **)res));
+ nvmem_unregister(*(struct nvmem_device **)res);
}
/**
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index cc8556e3c825..07ab1ea73520 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -67,7 +67,7 @@ struct nvmem_config {
#if IS_ENABLED(CONFIG_NVMEM)
struct nvmem_device *nvmem_register(const struct nvmem_config *cfg);
-int nvmem_unregister(struct nvmem_device *nvmem);
+void nvmem_unregister(struct nvmem_device *nvmem);
struct nvmem_device *devm_nvmem_register(struct device *dev,
const struct nvmem_config *cfg);
@@ -81,7 +81,7 @@ static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c)
return ERR_PTR(-ENOSYS);
}
-static inline int nvmem_unregister(struct nvmem_device *nvmem)
+static inline void nvmem_unregister(struct nvmem_device *nvmem)
{
return -ENOSYS;
}
--
2.18.0
From: Bartosz Golaszewski <[email protected]>
Make each nvmem device the owner of its nvmem cells.
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
drivers/nvmem/core.c | 28 ++++++++++++----------------
1 file changed, 12 insertions(+), 16 deletions(-)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index bb475c2688f9..86af62e2df47 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -38,6 +38,7 @@ struct nvmem_device {
int flags;
struct bin_attribute eeprom;
struct device *base_dev;
+ struct list_head cells;
nvmem_reg_read_t reg_read;
nvmem_reg_write_t reg_write;
void *priv;
@@ -58,9 +59,6 @@ struct nvmem_cell {
static DEFINE_MUTEX(nvmem_mutex);
static DEFINE_IDA(nvmem_ida);
-static LIST_HEAD(nvmem_cells);
-static DEFINE_MUTEX(nvmem_cells_mutex);
-
#ifdef CONFIG_DEBUG_LOCK_ALLOC
static struct lock_class_key eeprom_lock_key;
#endif
@@ -284,29 +282,25 @@ static struct nvmem_device *of_nvmem_find(struct device_node *nvmem_np)
static void nvmem_cell_drop(struct nvmem_cell *cell)
{
- mutex_lock(&nvmem_cells_mutex);
+ mutex_lock(&nvmem_mutex);
list_del(&cell->node);
- mutex_unlock(&nvmem_cells_mutex);
+ mutex_unlock(&nvmem_mutex);
kfree(cell);
}
-static void nvmem_device_remove_all_cells(const struct nvmem_device *nvmem)
+static void nvmem_device_remove_all_cells(struct nvmem_device *nvmem)
{
- struct nvmem_cell *cell;
- struct list_head *p, *n;
+ struct nvmem_cell *cell, *p;
- list_for_each_safe(p, n, &nvmem_cells) {
- cell = list_entry(p, struct nvmem_cell, node);
- if (cell->nvmem == nvmem)
- nvmem_cell_drop(cell);
- }
+ list_for_each_entry_safe(cell, p, &nvmem->cells, node)
+ nvmem_cell_drop(cell);
}
static void nvmem_cell_add(struct nvmem_cell *cell)
{
- mutex_lock(&nvmem_cells_mutex);
- list_add_tail(&cell->node, &nvmem_cells);
- mutex_unlock(&nvmem_cells_mutex);
+ mutex_lock(&nvmem_mutex);
+ list_add_tail(&cell->node, &cell->nvmem->cells);
+ mutex_unlock(&nvmem_mutex);
}
/*
@@ -423,6 +417,8 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
goto err_device_del;
}
+ INIT_LIST_HEAD(&nvmem->cells);
+
return nvmem;
err_device_del:
--
2.18.0
From: Bartosz Golaszewski <[email protected]>
Kernel users don't have any means of checking the names of nvmem
devices. Add a routine that returns the name of the nvmem provider.
This will be useful for nvmem notifier subscribers - otherwise they
can't check what device is being added/removed.
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
drivers/nvmem/core.c | 13 +++++++++++++
include/linux/nvmem-consumer.h | 8 ++++++++
2 files changed, 21 insertions(+)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 89b91f73d08a..364ee16e7d6a 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -1144,6 +1144,19 @@ int nvmem_device_write(struct nvmem_device *nvmem,
}
EXPORT_SYMBOL_GPL(nvmem_device_write);
+/**
+ * nvmem_dev_name() - Get the name of a given nvmem device.
+ *
+ * @nvmem: nvmem device.
+ *
+ * Return: name of the nvmem device.
+ */
+const char *nvmem_dev_name(struct nvmem_device *nvmem)
+{
+ return dev_name(&nvmem->dev);
+}
+EXPORT_SYMBOL_GPL(nvmem_dev_name);
+
static int __init nvmem_init(void)
{
return bus_register(&nvmem_bus_type);
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
index 7e9fb5a19d91..1313da6731ff 100644
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -43,6 +43,8 @@ int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
size_t bytes, void *buf);
+const char *nvmem_dev_name(struct nvmem_device *nvmem);
+
#else
static inline struct nvmem_cell *nvmem_cell_get(struct device *dev,
@@ -117,6 +119,12 @@ static inline int nvmem_device_write(struct nvmem_device *nvmem,
{
return -ENOSYS;
}
+
+static inline const char *nvmem_dev_name(struct nvmem_device *nvmem)
+{
+ return NULL;
+}
+
#endif /* CONFIG_NVMEM */
#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
--
2.18.0
From: Bartosz Golaszewski <[email protected]>
Remove all APIs dealing with nvmem_cell_info. There are no users and
this part of the subsystem will be reworked.
This patch temprarily disables support for non-DT users.
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
drivers/nvmem/core.c | 212 ++-------------------------------
include/linux/nvmem-consumer.h | 26 ----
include/linux/nvmem-provider.h | 13 --
3 files changed, 12 insertions(+), 239 deletions(-)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index aa1657831b70..bb475c2688f9 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -282,23 +282,6 @@ static struct nvmem_device *of_nvmem_find(struct device_node *nvmem_np)
return to_nvmem_device(d);
}
-static struct nvmem_cell *nvmem_find_cell(const char *cell_id)
-{
- struct nvmem_cell *p;
-
- mutex_lock(&nvmem_cells_mutex);
-
- list_for_each_entry(p, &nvmem_cells, node)
- if (!strcmp(p->name, cell_id)) {
- mutex_unlock(&nvmem_cells_mutex);
- return p;
- }
-
- mutex_unlock(&nvmem_cells_mutex);
-
- return NULL;
-}
-
static void nvmem_cell_drop(struct nvmem_cell *cell)
{
mutex_lock(&nvmem_cells_mutex);
@@ -326,82 +309,6 @@ static void nvmem_cell_add(struct nvmem_cell *cell)
mutex_unlock(&nvmem_cells_mutex);
}
-static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
- const struct nvmem_cell_info *info,
- struct nvmem_cell *cell)
-{
- cell->nvmem = nvmem;
- cell->offset = info->offset;
- cell->bytes = info->bytes;
- cell->name = info->name;
-
- cell->bit_offset = info->bit_offset;
- cell->nbits = info->nbits;
-
- if (cell->nbits)
- cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
- BITS_PER_BYTE);
-
- if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
- dev_err(&nvmem->dev,
- "cell %s unaligned to nvmem stride %d\n",
- cell->name, nvmem->stride);
- return -EINVAL;
- }
-
- return 0;
-}
-
-/**
- * nvmem_add_cells() - Add cell information to an nvmem device
- *
- * @nvmem: nvmem device to add cells to.
- * @info: nvmem cell info to add to the device
- * @ncells: number of cells in info
- *
- * Return: 0 or negative error code on failure.
- */
-int nvmem_add_cells(struct nvmem_device *nvmem,
- const struct nvmem_cell_info *info,
- int ncells)
-{
- struct nvmem_cell **cells;
- int i, rval;
-
- cells = kcalloc(ncells, sizeof(*cells), GFP_KERNEL);
- if (!cells)
- return -ENOMEM;
-
- for (i = 0; i < ncells; i++) {
- cells[i] = kzalloc(sizeof(**cells), GFP_KERNEL);
- if (!cells[i]) {
- rval = -ENOMEM;
- goto err;
- }
-
- rval = nvmem_cell_info_to_nvmem_cell(nvmem, &info[i], cells[i]);
- if (rval) {
- kfree(cells[i]);
- goto err;
- }
-
- nvmem_cell_add(cells[i]);
- }
-
- /* remove tmp array */
- kfree(cells);
-
- return 0;
-err:
- while (i--)
- nvmem_cell_drop(cells[i]);
-
- kfree(cells);
-
- return rval;
-}
-EXPORT_SYMBOL_GPL(nvmem_add_cells);
-
/*
* nvmem_setup_compat() - Create an additional binary entry in
* drivers sys directory, to be backwards compatible with the older
@@ -516,9 +423,6 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
goto err_device_del;
}
- if (config->cells)
- nvmem_add_cells(nvmem, config->cells, config->ncells);
-
return nvmem;
err_device_del:
@@ -618,32 +522,19 @@ int devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem)
EXPORT_SYMBOL(devm_nvmem_unregister);
-static struct nvmem_device *__nvmem_device_get(struct device_node *np,
- struct nvmem_cell **cellp,
- const char *cell_id)
+static struct nvmem_device *__nvmem_device_get(struct device_node *np)
{
struct nvmem_device *nvmem = NULL;
- mutex_lock(&nvmem_mutex);
-
- if (np) {
- nvmem = of_nvmem_find(np);
- if (!nvmem) {
- mutex_unlock(&nvmem_mutex);
- return ERR_PTR(-EPROBE_DEFER);
- }
- } else {
- struct nvmem_cell *cell = nvmem_find_cell(cell_id);
+ if (!np)
+ return ERR_PTR(-EINVAL);
- if (cell) {
- nvmem = cell->nvmem;
- *cellp = cell;
- }
+ mutex_lock(&nvmem_mutex);
- if (!nvmem) {
- mutex_unlock(&nvmem_mutex);
- return ERR_PTR(-ENOENT);
- }
+ nvmem = of_nvmem_find(np);
+ if (!nvmem) {
+ mutex_unlock(&nvmem_mutex);
+ return ERR_PTR(-EPROBE_DEFER);
}
nvmem->users++;
@@ -706,7 +597,7 @@ struct nvmem_device *of_nvmem_device_get(struct device_node *np, const char *id)
if (!nvmem_np)
return ERR_PTR(-EINVAL);
- return __nvmem_device_get(nvmem_np, NULL, NULL);
+ return __nvmem_device_get(nvmem_np);
}
EXPORT_SYMBOL_GPL(of_nvmem_device_get);
#endif
@@ -810,18 +701,6 @@ struct nvmem_device *devm_nvmem_device_get(struct device *dev, const char *id)
}
EXPORT_SYMBOL_GPL(devm_nvmem_device_get);
-static struct nvmem_cell *nvmem_cell_get_from_list(const char *cell_id)
-{
- struct nvmem_cell *cell = NULL;
- struct nvmem_device *nvmem;
-
- nvmem = __nvmem_device_get(NULL, &cell, cell_id);
- if (IS_ERR(nvmem))
- return ERR_CAST(nvmem);
-
- return cell;
-}
-
#if IS_ENABLED(CONFIG_OF)
/**
* of_nvmem_cell_get() - Get a nvmem cell from given device node and cell id
@@ -857,7 +736,7 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
if (!nvmem_np)
return ERR_PTR(-EINVAL);
- nvmem = __nvmem_device_get(nvmem_np, NULL, NULL);
+ nvmem = __nvmem_device_get(nvmem_np);
of_node_put(nvmem_np);
if (IS_ERR(nvmem))
return ERR_CAST(nvmem);
@@ -926,19 +805,10 @@ EXPORT_SYMBOL_GPL(of_nvmem_cell_get);
*/
struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *cell_id)
{
- struct nvmem_cell *cell;
-
- if (dev->of_node) { /* try dt first */
- cell = of_nvmem_cell_get(dev->of_node, cell_id);
- if (!IS_ERR(cell) || PTR_ERR(cell) == -EPROBE_DEFER)
- return cell;
- }
-
- /* NULL cell_id only allowed for device tree; invalid otherwise */
- if (!cell_id)
+ if (!dev->of_node)
return ERR_PTR(-EINVAL);
- return nvmem_cell_get_from_list(cell_id);
+ return of_nvmem_cell_get(dev->of_node, cell_id);
}
EXPORT_SYMBOL_GPL(nvmem_cell_get);
@@ -1227,64 +1097,6 @@ int nvmem_cell_read_u32(struct device *dev, const char *cell_id, u32 *val)
}
EXPORT_SYMBOL_GPL(nvmem_cell_read_u32);
-/**
- * nvmem_device_cell_read() - Read a given nvmem device and cell
- *
- * @nvmem: nvmem device to read from.
- * @info: nvmem cell info to be read.
- * @buf: buffer pointer which will be populated on successful read.
- *
- * Return: length of successful bytes read on success and negative
- * error code on error.
- */
-ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
- struct nvmem_cell_info *info, void *buf)
-{
- struct nvmem_cell cell;
- int rc;
- ssize_t len;
-
- if (!nvmem)
- return -EINVAL;
-
- rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
- if (rc)
- return rc;
-
- rc = __nvmem_cell_read(nvmem, &cell, buf, &len);
- if (rc)
- return rc;
-
- return len;
-}
-EXPORT_SYMBOL_GPL(nvmem_device_cell_read);
-
-/**
- * nvmem_device_cell_write() - Write cell to a given nvmem device
- *
- * @nvmem: nvmem device to be written to.
- * @info: nvmem cell info to be written.
- * @buf: buffer to be written to cell.
- *
- * Return: length of bytes written or negative error code on failure.
- * */
-int nvmem_device_cell_write(struct nvmem_device *nvmem,
- struct nvmem_cell_info *info, void *buf)
-{
- struct nvmem_cell cell;
- int rc;
-
- if (!nvmem)
- return -EINVAL;
-
- rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
- if (rc)
- return rc;
-
- return nvmem_cell_write(&cell, buf, cell.bytes);
-}
-EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
-
/**
* nvmem_device_read() - Read from a given nvmem device
*
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
index 4e85447f7860..7e9fb5a19d91 100644
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -21,14 +21,6 @@ struct device_node;
struct nvmem_cell;
struct nvmem_device;
-struct nvmem_cell_info {
- const char *name;
- unsigned int offset;
- unsigned int bytes;
- unsigned int bit_offset;
- unsigned int nbits;
-};
-
#if IS_ENABLED(CONFIG_NVMEM)
/* Cell based interface */
@@ -50,10 +42,6 @@ int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
size_t bytes, void *buf);
int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
size_t bytes, void *buf);
-ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
- struct nvmem_cell_info *info, void *buf);
-int nvmem_device_cell_write(struct nvmem_device *nvmem,
- struct nvmem_cell_info *info, void *buf);
#else
@@ -116,20 +104,6 @@ static inline void devm_nvmem_device_put(struct device *dev,
{
}
-static inline ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
- struct nvmem_cell_info *info,
- void *buf)
-{
- return -ENOSYS;
-}
-
-static inline int nvmem_device_cell_write(struct nvmem_device *nvmem,
- struct nvmem_cell_info *info,
- void *buf)
-{
- return -ENOSYS;
-}
-
static inline int nvmem_device_read(struct nvmem_device *nvmem,
unsigned int offset, size_t bytes,
void *buf)
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index 24def6ad09bb..cc8556e3c825 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -16,7 +16,6 @@
#include <linux/errno.h>
struct nvmem_device;
-struct nvmem_cell_info;
typedef int (*nvmem_reg_read_t)(void *priv, unsigned int offset,
void *val, size_t bytes);
typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset,
@@ -52,8 +51,6 @@ struct nvmem_config {
const char *name;
int id;
struct module *owner;
- const struct nvmem_cell_info *cells;
- int ncells;
bool read_only;
bool root_only;
nvmem_reg_read_t reg_read;
@@ -77,9 +74,6 @@ struct nvmem_device *devm_nvmem_register(struct device *dev,
int devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem);
-int nvmem_add_cells(struct nvmem_device *nvmem,
- const struct nvmem_cell_info *info,
- int ncells);
#else
static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c)
@@ -105,12 +99,5 @@ devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem)
}
-static inline int nvmem_add_cells(struct nvmem_device *nvmem,
- const struct nvmem_cell_info *info,
- int ncells)
-{
- return -ENOSYS;
-}
-
#endif /* CONFIG_NVMEM */
#endif /* ifndef _LINUX_NVMEM_PROVIDER_H */
--
2.18.0
From: Bartosz Golaszewski <[email protected]>
Use the managed version of nvmem_register().
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
drivers/nvmem/lpc18xx_eeprom.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/nvmem/lpc18xx_eeprom.c b/drivers/nvmem/lpc18xx_eeprom.c
index a9534a6e8636..b42dbaddb419 100644
--- a/drivers/nvmem/lpc18xx_eeprom.c
+++ b/drivers/nvmem/lpc18xx_eeprom.c
@@ -236,7 +236,7 @@ static int lpc18xx_eeprom_probe(struct platform_device *pdev)
lpc18xx_nvmem_config.dev = dev;
lpc18xx_nvmem_config.priv = eeprom;
- eeprom->nvmem = nvmem_register(&lpc18xx_nvmem_config);
+ eeprom->nvmem = devm_nvmem_register(dev, &lpc18xx_nvmem_config);
if (IS_ERR(eeprom->nvmem)) {
ret = PTR_ERR(eeprom->nvmem);
goto err_clk;
@@ -257,10 +257,6 @@ static int lpc18xx_eeprom_remove(struct platform_device *pdev)
struct lpc18xx_eeprom_dev *eeprom = platform_get_drvdata(pdev);
int ret;
- ret = nvmem_unregister(eeprom->nvmem);
- if (ret < 0)
- return ret;
-
clk_disable_unprepare(eeprom->clk);
return 0;
--
2.18.0
On Wed, 5 Sep 2018 11:57:36 +0200
Bartosz Golaszewski <[email protected]> wrote:
>
> +struct nvmem_cell_lookup {
> + const char *nvmem_name;
> + const char *dev_id;
Shouldn't we have a con_id here?
> + const char *cell_id;
> + struct list_head node;
> +};
2018-09-05 15:57 GMT+02:00 Boris Brezillon <[email protected]>:
> On Wed, 5 Sep 2018 11:57:36 +0200
> Bartosz Golaszewski <[email protected]> wrote:
>
>>
>> +struct nvmem_cell_lookup {
>> + const char *nvmem_name;
>> + const char *dev_id;
>
> Shouldn't we have a con_id here?
>
>> + const char *cell_id;
>> + struct list_head node;
>> +};
I wanted to stay in line with the current API - nvmem_cell_get() takes
as argument a string called cell_id. I wanted to reflect that here.
Bart
On Wed, 5 Sep 2018 16:00:36 +0200
Bartosz Golaszewski <[email protected]> wrote:
> 2018-09-05 15:57 GMT+02:00 Boris Brezillon <[email protected]>:
> > On Wed, 5 Sep 2018 11:57:36 +0200
> > Bartosz Golaszewski <[email protected]> wrote:
> >
> >>
> >> +struct nvmem_cell_lookup {
> >> + const char *nvmem_name;
> >> + const char *dev_id;
> >
> > Shouldn't we have a con_id here?
> >
> >> + const char *cell_id;
> >> + struct list_head node;
> >> +};
>
> I wanted to stay in line with the current API - nvmem_cell_get() takes
> as argument a string called cell_id. I wanted to reflect that here.
Actually, you need both. con_id is the name you would have in your DT
in the nvmem-cell-names property, cell_id is the name of the cell
you'd find under the nvmem device node.
Let's take an example:
mydev {
#nvmem-cell-names = "mac-address", "revision";
#nvmem-cells = <&cell1>, <&cell2>;
};
mynvmemdev {
#size-cells = <1>;
#address-cells = <1>;
cell1: foo@0 {
reg = <0x0 0x6>;
};
cell2: bar@6 {
reg = <0x6 0x10>;
};
};
this can be described the same way using a consumer lookup table:
struct nvmem_cell_lookup_entry {
const char *con_id;
const char *nvmem_name;
const char *cell_name;
};
struct nvmem_cell_lookup_table {
struct list_head node;
const char *dev_id;
unsigned int nentries;
const struct nvmem_cell_lookup_entry *entries;
}
static const struct nvmem_cell_lookup_entry mydev_nvmem_cells[] = {
{
.con_id = "mac-address",
.nvmem_name = "mynvmemdev",
.cell_name = "foo",
},
{
.con_id = "revision",
.nvmem_name = "mynvmemdev",
.cell_name = "bar",
},
}
static const struct nvmem_cell_lookup_table mydev_nvmem_lookup = {
.dev_id = "mydev.0",
.nentries = ARRAY_SIZE(mydev_nvmem_cells),
.entries = mydev_nvmem_cells,
};
...
nvmem_add_cell_lookups(&mydev_nvmem_lookup);
2018-09-05 16:21 GMT+02:00 Boris Brezillon <[email protected]>:
> On Wed, 5 Sep 2018 16:00:36 +0200
> Bartosz Golaszewski <[email protected]> wrote:
>
>> 2018-09-05 15:57 GMT+02:00 Boris Brezillon <[email protected]>:
>> > On Wed, 5 Sep 2018 11:57:36 +0200
>> > Bartosz Golaszewski <[email protected]> wrote:
>> >
>> >>
>> >> +struct nvmem_cell_lookup {
>> >> + const char *nvmem_name;
>> >> + const char *dev_id;
>> >
>> > Shouldn't we have a con_id here?
>> >
>> >> + const char *cell_id;
>> >> + struct list_head node;
>> >> +};
>>
>> I wanted to stay in line with the current API - nvmem_cell_get() takes
>> as argument a string called cell_id. I wanted to reflect that here.
>
> Actually, you need both. con_id is the name you would have in your DT
> in the nvmem-cell-names property, cell_id is the name of the cell
> you'd find under the nvmem device node.
>
> Let's take an example:
>
> mydev {
> #nvmem-cell-names = "mac-address", "revision";
> #nvmem-cells = <&cell1>, <&cell2>;
> };
>
> mynvmemdev {
> #size-cells = <1>;
> #address-cells = <1>;
>
> cell1: foo@0 {
> reg = <0x0 0x6>;
> };
>
> cell2: bar@6 {
> reg = <0x6 0x10>;
> };
> };
>
> this can be described the same way using a consumer lookup table:
>
> struct nvmem_cell_lookup_entry {
> const char *con_id;
> const char *nvmem_name;
> const char *cell_name;
> };
>
> struct nvmem_cell_lookup_table {
> struct list_head node;
> const char *dev_id;
> unsigned int nentries;
> const struct nvmem_cell_lookup_entry *entries;
> }
>
> static const struct nvmem_cell_lookup_entry mydev_nvmem_cells[] = {
> {
> .con_id = "mac-address",
> .nvmem_name = "mynvmemdev",
> .cell_name = "foo",
> },
> {
> .con_id = "revision",
> .nvmem_name = "mynvmemdev",
> .cell_name = "bar",
> },
> }
>
> static const struct nvmem_cell_lookup_table mydev_nvmem_lookup = {
> .dev_id = "mydev.0",
> .nentries = ARRAY_SIZE(mydev_nvmem_cells),
> .entries = mydev_nvmem_cells,
> };
>
>
> ...
>
> nvmem_add_cell_lookups(&mydev_nvmem_lookup);
Ok I get it. Shouldn't we change the argument name of nvmem_cell_get()
and friends from 'name' to 'con_id' or simply 'id' similarly to what
other frameworks do to avoid such confusion?
I also don't see a need for splitting the lookup into two structures
here. Something like:
struct nvmem_cell_lookup {
const char *nvmem_name;
const char *cell_name;
const char *dev_id;
const char *con_id;
};
Would be perfectly fine and would allow to register all lookups for
given machine with a single call. How often does it happen that a
single device needs multiple nvmem cells anyway?
Bart
On Wed, 5 Sep 2018 16:47:57 +0200
Bartosz Golaszewski <[email protected]> wrote:
> 2018-09-05 16:21 GMT+02:00 Boris Brezillon <[email protected]>:
> > On Wed, 5 Sep 2018 16:00:36 +0200
> > Bartosz Golaszewski <[email protected]> wrote:
> >
> >> 2018-09-05 15:57 GMT+02:00 Boris Brezillon <[email protected]>:
> >> > On Wed, 5 Sep 2018 11:57:36 +0200
> >> > Bartosz Golaszewski <[email protected]> wrote:
> >> >
> >> >>
> >> >> +struct nvmem_cell_lookup {
> >> >> + const char *nvmem_name;
> >> >> + const char *dev_id;
> >> >
> >> > Shouldn't we have a con_id here?
> >> >
> >> >> + const char *cell_id;
> >> >> + struct list_head node;
> >> >> +};
> >>
> >> I wanted to stay in line with the current API - nvmem_cell_get() takes
> >> as argument a string called cell_id. I wanted to reflect that here.
> >
> > Actually, you need both. con_id is the name you would have in your DT
> > in the nvmem-cell-names property, cell_id is the name of the cell
> > you'd find under the nvmem device node.
> >
> > Let's take an example:
> >
> > mydev {
> > #nvmem-cell-names = "mac-address", "revision";
> > #nvmem-cells = <&cell1>, <&cell2>;
> > };
> >
> > mynvmemdev {
> > #size-cells = <1>;
> > #address-cells = <1>;
> >
> > cell1: foo@0 {
> > reg = <0x0 0x6>;
> > };
> >
> > cell2: bar@6 {
> > reg = <0x6 0x10>;
> > };
> > };
> >
> > this can be described the same way using a consumer lookup table:
> >
> > struct nvmem_cell_lookup_entry {
> > const char *con_id;
> > const char *nvmem_name;
> > const char *cell_name;
> > };
> >
> > struct nvmem_cell_lookup_table {
> > struct list_head node;
> > const char *dev_id;
> > unsigned int nentries;
> > const struct nvmem_cell_lookup_entry *entries;
> > }
> >
> > static const struct nvmem_cell_lookup_entry mydev_nvmem_cells[] = {
> > {
> > .con_id = "mac-address",
> > .nvmem_name = "mynvmemdev",
> > .cell_name = "foo",
> > },
> > {
> > .con_id = "revision",
> > .nvmem_name = "mynvmemdev",
> > .cell_name = "bar",
> > },
> > }
> >
> > static const struct nvmem_cell_lookup_table mydev_nvmem_lookup = {
> > .dev_id = "mydev.0",
> > .nentries = ARRAY_SIZE(mydev_nvmem_cells),
> > .entries = mydev_nvmem_cells,
> > };
> >
> >
> > ...
> >
> > nvmem_add_cell_lookups(&mydev_nvmem_lookup);
>
> Ok I get it. Shouldn't we change the argument name of nvmem_cell_get()
> and friends from 'name' to 'con_id' or simply 'id' similarly to what
> other frameworks do to avoid such confusion?
I'll let Srinivas answer that one.
>
> I also don't see a need for splitting the lookup into two structures
> here. Something like:
>
> struct nvmem_cell_lookup {
> const char *nvmem_name;
> const char *cell_name;
> const char *dev_id;
> const char *con_id;
> };
>
> Would be perfectly fine and would allow to register all lookups for
> given machine with a single call.
Yep, makes sense.
Hi Bartosz,
I love your patch! Yet something to improve:
[auto build test ERROR on linus/master]
[also build test ERROR on v4.19-rc2 next-20180906]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Bartosz-Golaszewski/nvmem-rework-of-the-subsystem-for-non-DT-users/20180907-112400
config: xtensa-allmodconfig (attached as .config)
compiler: xtensa-linux-gcc (GCC) 8.1.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=8.1.0 make.cross ARCH=xtensa
All error/warnings (new ones prefixed by >>):
drivers//nvmem/mxs-ocotp.c: In function 'mxs_ocotp_remove':
>> drivers//nvmem/mxs-ocotp.c:202:9: error: void value not ignored as it ought to be
return nvmem_unregister(otp->nvmem);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers//nvmem/mxs-ocotp.c:203:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
vim +202 drivers//nvmem/mxs-ocotp.c
c01e9a11 Stefan Wahren 2015-09-30 195
c01e9a11 Stefan Wahren 2015-09-30 196 static int mxs_ocotp_remove(struct platform_device *pdev)
c01e9a11 Stefan Wahren 2015-09-30 197 {
c01e9a11 Stefan Wahren 2015-09-30 198 struct mxs_ocotp *otp = platform_get_drvdata(pdev);
c01e9a11 Stefan Wahren 2015-09-30 199
c01e9a11 Stefan Wahren 2015-09-30 200 clk_unprepare(otp->clk);
c01e9a11 Stefan Wahren 2015-09-30 201
c01e9a11 Stefan Wahren 2015-09-30 @202 return nvmem_unregister(otp->nvmem);
c01e9a11 Stefan Wahren 2015-09-30 @203 }
c01e9a11 Stefan Wahren 2015-09-30 204
:::::: The code at line 202 was first introduced by commit
:::::: c01e9a11ab6f3096a54574c3224d8732a374f135 nvmem: add driver for ocotp in i.MX23 and i.MX28
:::::: TO: Stefan Wahren <[email protected]>
:::::: CC: Greg Kroah-Hartman <[email protected]>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Bartosz,
I love your patch! Yet something to improve:
[auto build test ERROR on linus/master]
[also build test ERROR on v4.19-rc2 next-20180906]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Bartosz-Golaszewski/nvmem-rework-of-the-subsystem-for-non-DT-users/20180907-112400
config: i386-randconfig-s3-09061342 (attached as .config)
compiler: gcc-6 (Debian 6.4.0-9) 6.4.0 20171026
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
All error/warnings (new ones prefixed by >>):
In file included from include/linux/rtc.h:18:0,
from include/linux/efi.h:20,
from drivers//char/tpm/eventlog/tpm1.c:24:
include/linux/nvmem-provider.h: In function 'nvmem_unregister':
>> include/linux/nvmem-provider.h:86:9: warning: 'return' with a value, in function returning void
return -ENOSYS;
^
include/linux/nvmem-provider.h:84:20: note: declared here
static inline void nvmem_unregister(struct nvmem_device *nvmem)
^~~~~~~~~~~~~~~~
include/linux/nvmem-provider.h: In function 'devm_nvmem_unregister':
>> include/linux/nvmem-provider.h:98:9: error: void value not ignored as it ought to be
return nvmem_unregister(nvmem);
^~~~~~~~~~~~~~~~~~~~~~~
vim +98 include/linux/nvmem-provider.h
eace75cf Srinivas Kandagatla 2015-07-27 83
fd7df99e Bartosz Golaszewski 2018-09-05 84 static inline void nvmem_unregister(struct nvmem_device *nvmem)
eace75cf Srinivas Kandagatla 2015-07-27 85 {
eace75cf Srinivas Kandagatla 2015-07-27 @86 return -ENOSYS;
eace75cf Srinivas Kandagatla 2015-07-27 87 }
eace75cf Srinivas Kandagatla 2015-07-27 88
f1f50eca Andrey Smirnov 2018-03-09 89 static inline struct nvmem_device *
f1f50eca Andrey Smirnov 2018-03-09 90 devm_nvmem_register(struct device *dev, const struct nvmem_config *c)
f1f50eca Andrey Smirnov 2018-03-09 91 {
f1f50eca Andrey Smirnov 2018-03-09 92 return nvmem_register(c);
f1f50eca Andrey Smirnov 2018-03-09 93 }
f1f50eca Andrey Smirnov 2018-03-09 94
f1f50eca Andrey Smirnov 2018-03-09 95 static inline int
f1f50eca Andrey Smirnov 2018-03-09 96 devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem)
f1f50eca Andrey Smirnov 2018-03-09 97 {
f1f50eca Andrey Smirnov 2018-03-09 @98 return nvmem_unregister(nvmem);
b3db17e4 Andrew Lunn 2018-05-11 99
:::::: The code at line 98 was first introduced by commit
:::::: f1f50eca5f90527d2cca3479cda08883958777f6 nvmem: Introduce devm_nvmem_(un)register()
:::::: TO: Andrey Smirnov <[email protected]>
:::::: CC: Greg Kroah-Hartman <[email protected]>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Bartosz,
I love your patch! Yet something to improve:
[auto build test ERROR on linus/master]
[also build test ERROR on v4.19-rc2 next-20180906]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Bartosz-Golaszewski/nvmem-rework-of-the-subsystem-for-non-DT-users/20180907-112400
config: i386-randconfig-s3-09061342 (attached as .config)
compiler: gcc-6 (Debian 6.4.0-9) 6.4.0 20171026
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
All errors (new ones prefixed by >>):
In file included from drivers//of/of_net.c:10:0:
>> include/linux/nvmem-consumer.h:142:19: error: two or more data types in declaration specifiers
static inline int int nvmem_unregister_notifier(struct notifier_block *nb)
^~~
vim +142 include/linux/nvmem-consumer.h
141
> 142 static inline int int nvmem_unregister_notifier(struct notifier_block *nb)
143 {
144 return -ENOSYS;
145 }
146
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation