From ca6ac25cecf0e740d7cc8e03e0ebbf8acbeca3df Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 7 Aug 2018 13:19:35 +0100 Subject: nvmem: core: return error code instead of NULL from nvmem_device_get nvmem_device_get() should return ERR_PTR() on error or valid pointer on success, but one of the code path seems to return NULL, so fix it. Reported-by: Niklas Cassel Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index aa1657831b70..6f064002f439 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -679,7 +679,7 @@ static struct nvmem_device *nvmem_find(const char *name) d = bus_find_device_by_name(&nvmem_bus_type, NULL, name); if (!d) - return NULL; + return ERR_PTR(-ENOENT); return to_nvmem_device(d); } -- cgit v1.2.3 From d7b9fd1669d4a4f38281c4e29f1408e1bdce09b3 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 21 Sep 2018 06:40:03 -0700 Subject: nvmem: provide nvmem_dev_name() 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 future nvmem notifier subscribers - otherwise they can't check what device is being added/removed. Signed-off-by: Bartosz Golaszewski Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 13 +++++++++++++ include/linux/nvmem-consumer.h | 8 ++++++++ 2 files changed, 21 insertions(+) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 6f064002f439..11afa3b6d551 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -1343,6 +1343,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 4e85447f7860..0389fe00b177 100644 --- a/include/linux/nvmem-consumer.h +++ b/include/linux/nvmem-consumer.h @@ -55,6 +55,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); +const char *nvmem_dev_name(struct nvmem_device *nvmem); + #else static inline struct nvmem_cell *nvmem_cell_get(struct device *dev, @@ -143,6 +145,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) -- cgit v1.2.3 From 5db652c9f331ce7ae8662d9380ea4a404ba09344 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 21 Sep 2018 06:40:04 -0700 Subject: nvmem: remove the name field from struct nvmem_device 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 Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 11afa3b6d551..72313a1d215f 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -26,7 +26,6 @@ #include struct nvmem_device { - const char *name; struct module *owner; struct device dev; int stride; @@ -652,7 +651,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)); mutex_lock(&nvmem_mutex); nvmem->users--; -- cgit v1.2.3 From 1852183e142e01cff391b630a7578ff8ddb1a5fa Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 21 Sep 2018 06:40:05 -0700 Subject: nvmem: use list_for_each_entry_safe in nvmem_device_remove_all_cells() Use the provided helper for iterating over list entries without having to use the list_entry() macro. Signed-off-by: Bartosz Golaszewski Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 72313a1d215f..0e963d83a099 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -308,14 +308,11 @@ static void nvmem_cell_drop(struct nvmem_cell *cell) static void nvmem_device_remove_all_cells(const 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); + list_for_each_entry_safe(cell, p, &nvmem_cells, node) if (cell->nvmem == nvmem) nvmem_cell_drop(cell); - } } static void nvmem_cell_add(struct nvmem_cell *cell) -- cgit v1.2.3 From f9fcb7e36cdec27e996606b8b33337056559f8da Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 21 Sep 2018 06:40:06 -0700 Subject: nvmem: remove a stray newline There are two empty lines between devm_nvmem_unregister() and __nvmem_device_get(). Remove one. Signed-off-by: Bartosz Golaszewski Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 0e963d83a099..1ced9caa811b 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -613,7 +613,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_cell **cellp, const char *cell_id) -- cgit v1.2.3 From fa72d847d68d7833b77a4bef944cf2c5baf56f49 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 21 Sep 2018 06:40:07 -0700 Subject: nvmem: check the return value of nvmem_add_cells() This function can fail so check its return value in nvmem_register() and act accordingly. Signed-off-by: Bartosz Golaszewski Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 1ced9caa811b..0ef84441ebe5 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -512,11 +512,17 @@ 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); + if (config->cells) { + rval = nvmem_add_cells(nvmem, config->cells, config->ncells); + 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: -- cgit v1.2.3 From c1de7f43bd84271e438a4f2dadc4ba9a353baaea Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 21 Sep 2018 06:40:08 -0700 Subject: nvmem: use kref 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 Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 0ef84441ebe5..920b56e500cc 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -31,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; @@ -463,6 +464,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) @@ -532,6 +535,20 @@ err_put_device: } 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 * @@ -541,19 +558,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; } @@ -647,7 +652,6 @@ static struct nvmem_device *__nvmem_device_get(struct device_node *np, } } - nvmem->users++; mutex_unlock(&nvmem_mutex); if (!try_module_get(nvmem->owner)) { @@ -655,22 +659,18 @@ static struct nvmem_device *__nvmem_device_get(struct device_node *np, "could not increase module refcount for cell %s\n", nvmem_dev_name(nvmem)); - 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) -- cgit v1.2.3 From 424d7033add17ce897305242901e14df1ff90195 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 21 Sep 2018 06:40:09 -0700 Subject: nvmem: sunxi_sid: return -ENOMEM if kzalloc() fails The driver currently returns -EINVAL if kzalloc() fails in probe(). Change it to -ENOMEM as it should be. Signed-off-by: Bartosz Golaszewski Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/sunxi_sid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c index d020f89248fd..4d0b7e72aa2e 100644 --- a/drivers/nvmem/sunxi_sid.c +++ b/drivers/nvmem/sunxi_sid.c @@ -187,7 +187,7 @@ static int sunxi_sid_probe(struct platform_device *pdev) randomness = kzalloc(size, GFP_KERNEL); if (!randomness) { - ret = -EINVAL; + ret = -ENOMEM; goto err_unreg_nvmem; } -- cgit v1.2.3 From 6eed8dd9a513223185b62dd725fd35db60db7217 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 21 Sep 2018 06:40:10 -0700 Subject: nvmem: sunxi_sid: use devm_nvmem_register() Use the resource managed variant of nvmem_register(). Signed-off-by: Bartosz Golaszewski Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/sunxi_sid.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c index 4d0b7e72aa2e..1310f8af37f8 100644 --- a/drivers/nvmem/sunxi_sid.c +++ b/drivers/nvmem/sunxi_sid.c @@ -181,15 +181,13 @@ static int sunxi_sid_probe(struct platform_device *pdev) else econfig.reg_read = sunxi_sid_read; econfig.priv = sid; - nvmem = nvmem_register(&econfig); + nvmem = devm_nvmem_register(dev, &econfig); if (IS_ERR(nvmem)) return PTR_ERR(nvmem); randomness = kzalloc(size, GFP_KERNEL); - if (!randomness) { - ret = -ENOMEM; - goto err_unreg_nvmem; - } + if (!randomness) + return -ENOMEM; for (i = 0; i < size; i++) econfig.reg_read(sid, i, &randomness[i], 1); @@ -200,17 +198,6 @@ static int sunxi_sid_probe(struct platform_device *pdev) platform_set_drvdata(pdev, nvmem); return 0; - -err_unreg_nvmem: - nvmem_unregister(nvmem); - return ret; -} - -static int sunxi_sid_remove(struct platform_device *pdev) -{ - struct nvmem_device *nvmem = platform_get_drvdata(pdev); - - return nvmem_unregister(nvmem); } static const struct sunxi_sid_cfg sun4i_a10_cfg = { @@ -243,7 +230,6 @@ MODULE_DEVICE_TABLE(of, sunxi_sid_of_match); static struct platform_driver sunxi_sid_driver = { .probe = sunxi_sid_probe, - .remove = sunxi_sid_remove, .driver = { .name = "eeprom-sunxi-sid", .of_match_table = sunxi_sid_of_match, -- cgit v1.2.3 From 226014d13fa5aa8d26caeebbd47d12ffd0a3c399 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 21 Sep 2018 06:40:11 -0700 Subject: nvmem: lpc18xx_eeprom: use devm_nvmem_register() Use the managed version of nvmem_register(). Signed-off-by: Bartosz Golaszewski Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/lpc18xx_eeprom.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/nvmem') 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; -- cgit v1.2.3 From 7d9f9f24fac774ead58137dff13aa1f74eb5dd10 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 21 Sep 2018 06:40:12 -0700 Subject: nvmem: mxs-ocotp: use devm_nvmem_register() Use the resource managed variant of nvmem_register(); Signed-off-by: Bartosz Golaszewski Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/mxs-ocotp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/mxs-ocotp.c b/drivers/nvmem/mxs-ocotp.c index 7018e2ef5714..53122f59c4b2 100644 --- a/drivers/nvmem/mxs-ocotp.c +++ b/drivers/nvmem/mxs-ocotp.c @@ -177,7 +177,7 @@ static int mxs_ocotp_probe(struct platform_device *pdev) ocotp_config.size = data->size; ocotp_config.priv = otp; ocotp_config.dev = dev; - otp->nvmem = nvmem_register(&ocotp_config); + otp->nvmem = devm_nvmem_register(dev, &ocotp_config); if (IS_ERR(otp->nvmem)) { ret = PTR_ERR(otp->nvmem); goto err_clk; @@ -199,7 +199,7 @@ static int mxs_ocotp_remove(struct platform_device *pdev) clk_unprepare(otp->clk); - return nvmem_unregister(otp->nvmem); + return 0; } static struct platform_driver mxs_ocotp_driver = { -- cgit v1.2.3 From bf58e8820c48805394ec9e76339f0c4646050432 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 21 Sep 2018 06:40:13 -0700 Subject: nvmem: change the signature of nvmem_unregister() We switched the nvmem framework to using kref instead of manually checking the current number of users in nvmem_unregister() so this function can no longer fail. We also converted all remaining users that still checked the return value of nvmem_unregister() to using devm_nvmem_register(). Make the routine return void. Signed-off-by: Bartosz Golaszewski Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 8 ++------ include/linux/nvmem-provider.h | 9 +++------ 2 files changed, 5 insertions(+), 12 deletions(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 920b56e500cc..bd14d04782cd 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -553,20 +553,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 24def6ad09bb..0f357d0c1e75 100644 --- a/include/linux/nvmem-provider.h +++ b/include/linux/nvmem-provider.h @@ -70,7 +70,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); @@ -87,10 +87,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) -{ - return -ENOSYS; -} +static inline void nvmem_unregister(struct nvmem_device *nvmem) {} static inline struct nvmem_device * devm_nvmem_register(struct device *dev, const struct nvmem_config *c) @@ -101,7 +98,7 @@ devm_nvmem_register(struct device *dev, const struct nvmem_config *c) static inline int devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem) { - return nvmem_unregister(nvmem); + return -ENOSYS; } -- cgit v1.2.3 From c7235ee3f4b86a01507a12e96a4875ba9b4be842 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 21 Sep 2018 06:40:14 -0700 Subject: nvmem: remove the global cell list Nvmem subsystem keeps a global list of cells that, for non-DT systems, can only be referenced by cell name, which makes it impossible to have more than one nvmem device with cells named the same. This patch makes every nvmem device the owner of the list of its cells. This effectively removes the support for non-DT systems, but it will be reintroduced following a different approach in subsequent patches. This isn't a problem as support for board files in nvmem is currently broken anyway: any user that would try to get an nvmem cell from the global cell list would remove the cell after the calling nvmem_cell_put(). This can cause anything from a subsequent user not being able to get the cell to double free errors if more users hold reference to the same cell at the same time. Fortunately there are no such users which allows us to rework this part. Signed-off-by: Bartosz Golaszewski Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 64 ++++++++++++---------------------------------------- 1 file changed, 15 insertions(+), 49 deletions(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index bd14d04782cd..ee794613024c 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 @@ -282,28 +280,11 @@ 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); + mutex_lock(&nvmem_mutex); list_del(&cell->node); - mutex_unlock(&nvmem_cells_mutex); + mutex_unlock(&nvmem_mutex); kfree(cell); } @@ -311,16 +292,15 @@ static void nvmem_device_remove_all_cells(const struct nvmem_device *nvmem) { struct nvmem_cell *cell, *p; - list_for_each_entry_safe(cell, p, &nvmem_cells, 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); } static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem, @@ -465,6 +445,7 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) } kref_init(&nvmem->refcnt); + INIT_LIST_HEAD(&nvmem->cells); nvmem->id = rval; nvmem->owner = config->owner; @@ -626,29 +607,14 @@ 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 (cell) { - nvmem = cell->nvmem; - *cellp = cell; - } - - if (!nvmem) { - mutex_unlock(&nvmem_mutex); - return ERR_PTR(-ENOENT); - } - } + if (!np) + return ERR_PTR(-ENOENT); + mutex_lock(&nvmem_mutex); + nvmem = of_nvmem_find(np); mutex_unlock(&nvmem_mutex); + if (!nvmem) + return ERR_PTR(-EPROBE_DEFER); if (!try_module_get(nvmem->owner)) { dev_err(&nvmem->dev, -- cgit v1.2.3 From b985f4cba6dbb3b60ad119c6f7e5cbad6f0d7e45 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 21 Sep 2018 06:40:15 -0700 Subject: nvmem: add support for cell info 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 Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 72 ++++++++++++++++++++++++++++++++++++++++++ include/linux/nvmem-provider.h | 33 +++++++++++++------ 2 files changed, 96 insertions(+), 9 deletions(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index ee794613024c..8e0108806e65 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -59,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); + #ifdef CONFIG_DEBUG_LOCK_ALLOC static struct lock_class_key eeprom_lock_key; #endif @@ -416,6 +419,43 @@ static int nvmem_setup_compat(struct nvmem_device *nvmem, return 0; } +static int nvmem_add_cells_from_table(struct nvmem_device *nvmem) +{ + const struct nvmem_cell_info *info; + struct nvmem_cell_table *table; + 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 = kzalloc(sizeof(*cell), GFP_KERNEL); + if (!cell) { + rval = -ENOMEM; + goto out; + } + + rval = nvmem_cell_info_to_nvmem_cell(nvmem, + info, + cell); + if (rval) { + kfree(cell); + goto out; + } + + nvmem_cell_add(cell); + } + } + } + +out: + mutex_unlock(&nvmem_cell_mutex); + return rval; +} + /** * nvmem_register() - Register a nvmem device for given nvmem_config. * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem @@ -502,8 +542,14 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) goto err_teardown_compat; } + rval = nvmem_add_cells_from_table(nvmem); + if (rval) + 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); @@ -1306,6 +1352,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-provider.h b/include/linux/nvmem-provider.h index 0f357d0c1e75..5c9f205cac8f 100644 --- a/include/linux/nvmem-provider.h +++ b/include/linux/nvmem-provider.h @@ -67,6 +67,25 @@ struct nvmem_config { struct device *base_dev; }; +/** + * struct nvmem_cell_table - NVMEM cell definitions for given provider + * + * @nvmem_name: Provider name. + * @cells: Array of cell definitions. + * @ncells: Number of cell definitions in the array. + * @node: List node. + * + * This structure together with related helper functions is provided for users + * that don't can't access the nvmem provided structure but wish to register + * cell definitions for it e.g. board files registering an EEPROM device. + */ +struct nvmem_cell_table { + const char *nvmem_name; + const struct nvmem_cell_info *cells; + size_t ncells; + struct list_head node; +}; + #if IS_ENABLED(CONFIG_NVMEM) struct nvmem_device *nvmem_register(const struct nvmem_config *cfg); @@ -77,9 +96,9 @@ 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); +void nvmem_add_cell_table(struct nvmem_cell_table *table); +void nvmem_del_cell_table(struct nvmem_cell_table *table); + #else static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c) @@ -102,12 +121,8 @@ 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; -} +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_PROVIDER_H */ -- cgit v1.2.3 From e888d445ac33a5b0288d670ecd970908b13f07cd Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 21 Sep 2018 06:40:16 -0700 Subject: nvmem: resolve cells from DT at registration time Currently we're creating a new cell structure everytime a DT user 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 Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 123 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 75 insertions(+), 48 deletions(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 8e0108806e65..74b6b97680d5 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -456,6 +456,73 @@ out: 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() - Register a nvmem device for given nvmem_config. * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem @@ -546,6 +613,10 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) if (rval) goto err_remove_cells; + rval = nvmem_add_cells_from_of(nvmem); + if (rval) + goto err_remove_cells; + return nvmem; err_remove_cells: @@ -848,10 +919,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 */ @@ -871,54 +940,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 @@ -1024,7 +1052,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); -- cgit v1.2.3 From 506157be06ba28137b18b7419a4dccfa244f4983 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 21 Sep 2018 06:40:17 -0700 Subject: nvmem: add support for cell lookups from machine code Add a way for machine code users to associate devices with nvmem cells. This restores the support for non-DT systems but following a different approach. Cells must now be associated with devices using provided routines and data structures before they can be retrieved using nvmem_cell_get(). It's still possible to define cells statically in nvmem_config but cells created this way still need to be associated with consumers using lookup entries. Note that nvmem_find() must be moved higher in the source file as we want to call it from __nvmem_device_get() for devices that don't have a device node. The signature of __nvmem_device_get() is also changed as it's no longer used to retrieve cells. Signed-off-by: Bartosz Golaszewski Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 129 ++++++++++++++++++++++++++++++++--------- include/linux/nvmem-consumer.h | 28 +++++++++ 2 files changed, 131 insertions(+), 26 deletions(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 74b6b97680d5..9cc86d131e1e 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); + #ifdef CONFIG_DEBUG_LOCK_ALLOC static struct lock_class_key eeprom_lock_key; #endif @@ -283,6 +286,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); @@ -472,6 +487,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; @@ -719,16 +749,12 @@ 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) + const char *nvmem_name) { struct nvmem_device *nvmem = NULL; - if (!np) - return ERR_PTR(-ENOENT); - mutex_lock(&nvmem_mutex); - nvmem = of_nvmem_find(np); + nvmem = np ? of_nvmem_find(np) : nvmem_find(nvmem_name); mutex_unlock(&nvmem_mutex); if (!nvmem) return ERR_PTR(-EPROBE_DEFER); @@ -752,18 +778,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 ERR_PTR(-ENOENT); - - return to_nvmem_device(d); -} - #if IS_ENABLED(CONFIG_OF) /** * of_nvmem_device_get() - Get nvmem device from a given id @@ -786,7 +800,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, NULL); } EXPORT_SYMBOL_GPL(of_nvmem_device_get); #endif @@ -890,15 +904,43 @@ 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) +static struct nvmem_cell * +nvmem_cell_get_from_lookup(struct device *dev, const char *con_id) { - struct nvmem_cell *cell = NULL; + struct nvmem_cell *cell = ERR_PTR(-ENOENT); + struct nvmem_cell_lookup *lookup; struct nvmem_device *nvmem; + const char *dev_id; - nvmem = __nvmem_device_get(NULL, &cell, cell_id); - if (IS_ERR(nvmem)) - return ERR_CAST(nvmem); + 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->con_id, con_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, + lookup->cell_name); + if (!cell) { + __nvmem_device_put(nvmem); + goto out; + } + } + } +out: + mutex_unlock(&nvmem_lookup_mutex); return cell; } @@ -935,7 +977,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, NULL); of_node_put(nvmem_np); if (IS_ERR(nvmem)) return ERR_CAST(nvmem); @@ -975,7 +1017,7 @@ struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *cell_id) if (!cell_id) return ERR_PTR(-EINVAL); - return nvmem_cell_get_from_list(cell_id); + return nvmem_cell_get_from_lookup(dev, cell_id); } EXPORT_SYMBOL_GPL(nvmem_cell_get); @@ -1405,6 +1447,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-consumer.h b/include/linux/nvmem-consumer.h index 0389fe00b177..27eee3945405 100644 --- a/include/linux/nvmem-consumer.h +++ b/include/linux/nvmem-consumer.h @@ -29,6 +29,24 @@ struct nvmem_cell_info { unsigned int nbits; }; +/** + * struct nvmem_cell_lookup - cell lookup entry + * + * @nvmem_name: Name of the provider. + * @cell_name: Name of the nvmem cell as defined in the name field of + * struct nvmem_cell_info. + * @dev_id: Name of the consumer device that will be associated with + * this cell. + * @con_id: Connector id for this cell lookup. + */ +struct nvmem_cell_lookup { + const char *nvmem_name; + const char *cell_name; + const char *dev_id; + const char *con_id; + struct list_head node; +}; + #if IS_ENABLED(CONFIG_NVMEM) /* Cell based interface */ @@ -57,6 +75,11 @@ int nvmem_device_cell_write(struct nvmem_device *nvmem, const char *nvmem_dev_name(struct nvmem_device *nvmem); +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 static inline struct nvmem_cell *nvmem_cell_get(struct device *dev, @@ -151,6 +174,11 @@ static inline const char *nvmem_dev_name(struct nvmem_device *nvmem) return NULL; } +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 */ #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF) -- cgit v1.2.3 From bee1138bea15a640aaa9e9bb909af5b2762520e0 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 21 Sep 2018 06:40:19 -0700 Subject: 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 Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 36 ++++++++++++++++++++++++++++++++++++ include/linux/nvmem-consumer.h | 21 +++++++++++++++++++++ 2 files changed, 57 insertions(+) (limited to 'drivers/nvmem') 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); diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h index 27eee3945405..0326b52e906b 100644 --- a/include/linux/nvmem-consumer.h +++ b/include/linux/nvmem-consumer.h @@ -14,6 +14,7 @@ #include #include +#include struct device; struct device_node; @@ -47,6 +48,13 @@ struct nvmem_cell_lookup { struct list_head node; }; +enum { + NVMEM_ADD = 1, + NVMEM_REMOVE, + NVMEM_CELL_ADD, + NVMEM_CELL_REMOVE, +}; + #if IS_ENABLED(CONFIG_NVMEM) /* Cell based interface */ @@ -80,6 +88,9 @@ void nvmem_add_cell_lookups(struct nvmem_cell_lookup *entries, void nvmem_del_cell_lookups(struct nvmem_cell_lookup *entries, size_t nentries); +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, @@ -179,6 +190,16 @@ 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) {} +static inline int nvmem_register_notifier(struct notifier_block *nb) +{ + return -ENOSYS; +} + +static inline int nvmem_unregister_notifier(struct notifier_block *nb) +{ + return -ENOSYS; +} + #endif /* CONFIG_NVMEM */ #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF) -- cgit v1.2.3 From b1c1db9883c276fe41a04e9ce8f89576a64b1ac0 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 21 Sep 2018 06:40:20 -0700 Subject: nvmem: use SPDX license identifiers Use SPDX license identiefiers to core nvmem files and remove GPL 2.0 license boilerplate. Signed-off-by: Bartosz Golaszewski Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 10 +--------- include/linux/nvmem-consumer.h | 5 +---- include/linux/nvmem-provider.h | 5 +---- 3 files changed, 3 insertions(+), 17 deletions(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index da441019b609..ea05219e60b4 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 * Copyright (C) 2013 Maxime Ripard - * - * 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 diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h index 0326b52e906b..d18caae2f7ac 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 * Copyright (C) 2013 Maxime Ripard - * - * 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 5c9f205cac8f..8ae012f6545a 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 * Copyright (C) 2013 Maxime Ripard - * - * 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 -- cgit v1.2.3 From 165589f0cb52b34db12e15676a034b8f83dfa756 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 21 Sep 2018 06:40:21 -0700 Subject: nvmem: make the naming of arguments in nvmem_cell_get() consistent The argument representing the cell name in the nvmem_cell_get() family of functions is not consistend between function prototypes and definitions. Name it 'id' in all those routines. This is in line with other frameworks and can represent both the DT cell name from the nvmem-cell-names property as well as the con_id field from cell lookup entries. Signed-off-by: Bartosz Golaszewski Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 27 ++++++++++++++------------- include/linux/nvmem-consumer.h | 12 ++++++------ 2 files changed, 20 insertions(+), 19 deletions(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index ea05219e60b4..ff21402fbd7d 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -977,16 +977,15 @@ out: * of_nvmem_cell_get() - Get a nvmem cell from given device node and cell id * * @np: Device tree node that uses the nvmem cell. - * @name: nvmem cell name from nvmem-cell-names property, or NULL - * for the cell at index 0 (the lone cell with no accompanying - * nvmem-cell-names property). + * @id: nvmem cell name from nvmem-cell-names property, or NULL + * for the cell at index 0 (the lone cell with no accompanying + * nvmem-cell-names property). * * Return: Will be an ERR_PTR() on error or a valid pointer * to a struct nvmem_cell. The nvmem_cell will be freed by the * nvmem_cell_put(). */ -struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, - const char *name) +struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, const char *id) { struct device_node *cell_np, *nvmem_np; struct nvmem_device *nvmem; @@ -994,8 +993,8 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, int index = 0; /* if cell name exists, find index to the name */ - if (name) - index = of_property_match_string(np, "nvmem-cell-names", name); + if (id) + index = of_property_match_string(np, "nvmem-cell-names", id); cell_np = of_parse_phandle(np, "nvmem-cells", index); if (!cell_np) @@ -1025,27 +1024,29 @@ EXPORT_SYMBOL_GPL(of_nvmem_cell_get); * nvmem_cell_get() - Get nvmem cell of device form a given cell name * * @dev: Device that requests the nvmem cell. - * @cell_id: nvmem cell name to get. + * @id: nvmem cell name to get (this corresponds with the name from the + * nvmem-cell-names property for DT systems and with the con_id from + * the lookup entry for non-DT systems). * * Return: Will be an ERR_PTR() on error or a valid pointer * to a struct nvmem_cell. The nvmem_cell will be freed by the * nvmem_cell_put(). */ -struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *cell_id) +struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *id) { struct nvmem_cell *cell; if (dev->of_node) { /* try dt first */ - cell = of_nvmem_cell_get(dev->of_node, cell_id); + cell = of_nvmem_cell_get(dev->of_node, 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) + /* NULL cell id only allowed for device tree; invalid otherwise */ + if (!id) return ERR_PTR(-EINVAL); - return nvmem_cell_get_from_lookup(dev, cell_id); + return nvmem_cell_get_from_lookup(dev, id); } EXPORT_SYMBOL_GPL(nvmem_cell_get); diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h index d18caae2f7ac..e17617fa034f 100644 --- a/include/linux/nvmem-consumer.h +++ b/include/linux/nvmem-consumer.h @@ -55,8 +55,8 @@ enum { #if IS_ENABLED(CONFIG_NVMEM) /* Cell based interface */ -struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *name); -struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *name); +struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *id); +struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *id); void nvmem_cell_put(struct nvmem_cell *cell); void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell); void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len); @@ -91,13 +91,13 @@ int nvmem_unregister_notifier(struct notifier_block *nb); #else static inline struct nvmem_cell *nvmem_cell_get(struct device *dev, - const char *name) + const char *id) { return ERR_PTR(-ENOSYS); } static inline struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, - const char *name) + const char *id) { return ERR_PTR(-ENOSYS); } @@ -201,12 +201,12 @@ static inline int nvmem_unregister_notifier(struct notifier_block *nb) #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF) struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, - const char *name); + const char *id); struct nvmem_device *of_nvmem_device_get(struct device_node *np, const char *name); #else static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, - const char *name) + const char *id) { return ERR_PTR(-ENOSYS); } -- cgit v1.2.3 From 48f63a2c108a7d88562229f14124e464c6a40cb4 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 21 Sep 2018 06:40:23 -0700 Subject: nvmem: fix commenting style Remove a redundant '*/' as pointed out by checkpatch. Signed-off-by: Bartosz Golaszewski Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index ff21402fbd7d..e44a1860a2b3 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -1374,7 +1374,7 @@ EXPORT_SYMBOL_GPL(nvmem_device_cell_read); * @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) { @@ -1430,7 +1430,7 @@ EXPORT_SYMBOL_GPL(nvmem_device_read); * @buf: buffer to be written. * * Return: length of bytes written or negative error code on failure. - * */ + */ int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset, size_t bytes, void *buf) -- cgit v1.2.3 From e7e07f4f7b452c8c2a113db28902e41c9daca855 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 21 Sep 2018 06:40:24 -0700 Subject: nvmem: use octal permissions instead of constants Checkpatch emits a warning when using symbolic permissions. Use octal permissions instead. Signed-off-by: Bartosz Golaszewski Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index e44a1860a2b3..ad1227df1984 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -154,7 +154,7 @@ static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj, static struct bin_attribute bin_attr_rw_nvmem = { .attr = { .name = "nvmem", - .mode = S_IWUSR | S_IRUGO, + .mode = 0644, }, .read = bin_attr_nvmem_read, .write = bin_attr_nvmem_write, @@ -178,7 +178,7 @@ static const struct attribute_group *nvmem_rw_dev_groups[] = { static struct bin_attribute bin_attr_ro_nvmem = { .attr = { .name = "nvmem", - .mode = S_IRUGO, + .mode = 0444, }, .read = bin_attr_nvmem_read, }; @@ -201,7 +201,7 @@ static const struct attribute_group *nvmem_ro_dev_groups[] = { static struct bin_attribute bin_attr_rw_root_nvmem = { .attr = { .name = "nvmem", - .mode = S_IWUSR | S_IRUSR, + .mode = 0600, }, .read = bin_attr_nvmem_read, .write = bin_attr_nvmem_write, @@ -225,7 +225,7 @@ static const struct attribute_group *nvmem_rw_root_dev_groups[] = { static struct bin_attribute bin_attr_ro_root_nvmem = { .attr = { .name = "nvmem", - .mode = S_IRUSR, + .mode = 0400, }, .read = bin_attr_nvmem_read, }; -- cgit v1.2.3 From 4876bfe6cdecc5037fed6959425fe0cb2af19d98 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 21 Sep 2018 06:40:25 -0700 Subject: nvmem: sunxi_sid: remove unused variable in probe This patch fixes below warning: sunxi_sid.c:157:6: warning: unused variable 'ret' [-Wunused-variable] Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/sunxi_sid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c index 1310f8af37f8..570a2e354f30 100644 --- a/drivers/nvmem/sunxi_sid.c +++ b/drivers/nvmem/sunxi_sid.c @@ -154,7 +154,7 @@ static int sunxi_sid_probe(struct platform_device *pdev) struct resource *res; struct nvmem_device *nvmem; struct sunxi_sid *sid; - int ret, i, size; + int i, size; char *randomness; const struct sunxi_sid_cfg *cfg; -- cgit v1.2.3 From ef92ab3001c4656d3b9a7c4a8044b5bc08f6f6ef Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 21 Sep 2018 06:40:26 -0700 Subject: nvmem: make nvmem_add_cells() static Now we have new api nvmem_add/del_cell_table() we do not want users to use nvmem_add_cells() anymore. So mark it accordingly. I guess it was missed in original cleanup patch. This also fixes below warning: core.c:355:5: warning: no previous prototype for 'nvmem_add_cells' [-Wmissing-prototypes] Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index ad1227df1984..cc815bb2eebd 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -352,7 +352,7 @@ static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem, * * Return: 0 or negative error code on failure. */ -int nvmem_add_cells(struct nvmem_device *nvmem, +static int nvmem_add_cells(struct nvmem_device *nvmem, const struct nvmem_cell_info *info, int ncells) { @@ -391,7 +391,6 @@ err: return rval; } -EXPORT_SYMBOL_GPL(nvmem_add_cells); /* * nvmem_setup_compat() - Create an additional binary entry in -- cgit v1.2.3 From badcdff107cbfd7fef5f089260177efc56fe1a9f Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 3 Oct 2018 18:47:04 +0100 Subject: nvmem: Convert to using %pOFn instead of device_node.name In preparation to remove the node name pointer from struct device_node, convert printf users to use the %pOFn format specifier. Cc: Srinivas Kandagatla Signed-off-by: Rob Herring [srinivas: rebased on top of next] Signed-off-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index cc815bb2eebd..b4c09bc20b67 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -298,6 +298,7 @@ static void nvmem_cell_drop(struct nvmem_cell *cell) mutex_lock(&nvmem_mutex); list_del(&cell->node); mutex_unlock(&nvmem_mutex); + kfree(cell->name); kfree(cell); } @@ -547,7 +548,7 @@ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) cell->nvmem = nvmem; cell->offset = be32_to_cpup(addr++); cell->bytes = be32_to_cpup(addr); - cell->name = child->name; + cell->name = kasprintf(GFP_KERNEL, "%pOFn", child); addr = of_get_property(child, "bits", &len); if (addr && len == (2 * sizeof(u32))) { @@ -564,6 +565,7 @@ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) dev_err(dev, "cell %s unaligned to nvmem stride %d\n", cell->name, nvmem->stride); /* Cells already added will be freed later. */ + kfree(cell->name); kfree(cell); return -EINVAL; } -- cgit v1.2.3 From cccb3b19e762edc8ef0481be506967555cb9e317 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 3 Oct 2018 09:31:11 +0200 Subject: nvmem: fix nvmem_cell_get_from_lookup() We check if the pointer returned by __nvmem_device_get() is not NULL while we should actually check if it is not IS_ERR(nvmem). Fix it. While we're at it: fix the next error path where we should assign an error value to cell before returning. Signed-off-by: Bartosz Golaszewski Reported-by: Stephen Rothwell Acked-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index b4c09bc20b67..31ca04d46c1c 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -953,9 +953,9 @@ nvmem_cell_get_from_lookup(struct device *dev, const char *con_id) (strcmp(lookup->con_id, con_id) == 0)) { /* This is the right entry. */ nvmem = __nvmem_device_get(NULL, lookup->nvmem_name); - if (!nvmem) { + if (IS_ERR(nvmem)) { /* Provider may not be registered yet. */ - cell = ERR_PTR(-EPROBE_DEFER); + cell = ERR_CAST(nvmem); goto out; } @@ -963,6 +963,7 @@ nvmem_cell_get_from_lookup(struct device *dev, const char *con_id) lookup->cell_name); if (!cell) { __nvmem_device_put(nvmem); + cell = ERR_PTR(-ENOENT); goto out; } } -- cgit v1.2.3 From 098ec84f1ad2f7b9a4c88bf61fab021ac2876173 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 3 Oct 2018 09:24:30 +0200 Subject: nvmem: lpc18xx_eeprom: remove unused variable Remove a variable that's no longer used from lpc18xx_eeprom_remove(). Signed-off-by: Bartosz Golaszewski Reported-by: Stephen Rothwell Acked-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/lpc18xx_eeprom.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/lpc18xx_eeprom.c b/drivers/nvmem/lpc18xx_eeprom.c index b42dbaddb419..66cff1e2147a 100644 --- a/drivers/nvmem/lpc18xx_eeprom.c +++ b/drivers/nvmem/lpc18xx_eeprom.c @@ -255,7 +255,6 @@ err_clk: static int lpc18xx_eeprom_remove(struct platform_device *pdev) { struct lpc18xx_eeprom_dev *eeprom = platform_get_drvdata(pdev); - int ret; clk_disable_unprepare(eeprom->clk); -- cgit v1.2.3 From 3c53e2352a9bf87128e7a8ddb69c7543941a3092 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 2 Oct 2018 23:11:12 +0200 Subject: nvmem: hide unused nvmem_find_cell_by_index function nvmem_find_cell_by_index() is only called from inside an #ifdef, so we get a build warning without CONFIG_OF: drivers/nvmem/core.c:496:1: error: 'nvmem_find_cell_by_index' defined but not used [-Werror=unused-function] Move it into the same #ifdef as the caller to avoid the warning. Fixes: e888d445ac33 ("nvmem: resolve cells from DT at registration time") Signed-off-by: Arnd Bergmann Acked-by: Srinivas Kandagatla Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/nvmem') diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 31ca04d46c1c..9b18ce90f907 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -493,22 +493,6 @@ out: 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 struct nvmem_cell * nvmem_find_cell_by_name(struct nvmem_device *nvmem, const char *cell_id) { @@ -975,6 +959,22 @@ out: } #if IS_ENABLED(CONFIG_OF) +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; +} + /** * of_nvmem_cell_get() - Get a nvmem cell from given device node and cell id * -- cgit v1.2.3