From 12ae3808c160b7be0de3c633ac4cbe8c5f2937bf Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 19 Feb 2018 15:43:01 -0600 Subject: [PATCH 1/7] regmap: Allow missing device in regmap_name_read_file() This fixes a possible NULL pointer dereference oops in regmap_name_read_file() when the regmap does not have a device associated with it. For example syscon regmaps retrieved with syscon_regmap_lookup_by_compatible() don't have a device. Signed-off-by: David Lechner Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-debugfs.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index f3266334063e..7eb512ba2828 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -40,6 +40,7 @@ static ssize_t regmap_name_read_file(struct file *file, loff_t *ppos) { struct regmap *map = file->private_data; + const char *name = "nodev"; int ret; char *buf; @@ -47,7 +48,10 @@ static ssize_t regmap_name_read_file(struct file *file, if (!buf) return -ENOMEM; - ret = snprintf(buf, PAGE_SIZE, "%s\n", map->dev->driver->name); + if (map->dev && map->dev->driver) + name = map->dev->driver->name; + + ret = snprintf(buf, PAGE_SIZE, "%s\n", name); if (ret < 0) { kfree(buf); return ret; From 9b947a13e7f6017f18470f665992dbae267852b3 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 19 Feb 2018 15:43:02 -0600 Subject: [PATCH 2/7] regmap: use debugfs even when no device This registers regmaps with debugfs even when they do not have an associated device. For example, this is common for syscon regmaps. Signed-off-by: David Lechner Signed-off-by: Mark Brown --- drivers/base/regmap/regmap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index ee302ccdfbc8..f5fa1ddc65e9 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -1116,6 +1116,8 @@ skip_format_initialization: ret = regmap_attach_dev(dev, map, config); if (ret != 0) goto err_regcache; + } else { + regmap_debugfs_init(map, config->name); } return map; From 31895662f9ba81e8ea9ef05abf8edcb29d4b9c18 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 21 Feb 2018 10:20:25 +0100 Subject: [PATCH 3/7] regmap: mmio: Add function to attach a clock regmap_init_mmio_clk allows to specify a clock that needs to be enabled while accessing the registers. However, that clock is retrieved through its clock ID, which means it will lookup that clock based on the current device that registers the regmap, and, in the DT case, will only look in that device OF node. This might be problematic if the clock to enable is stored in another node. Let's add a function that allows to attach a clock that has already been retrieved to a regmap in order to fix this. Signed-off-by: Maxime Ripard Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-mmio.c | 24 ++++++++++++++++++++++++ include/linux/regmap.h | 3 +++ 2 files changed, 27 insertions(+) diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c index 5189fd6182f6..5cadfd3394d8 100644 --- a/drivers/base/regmap/regmap-mmio.c +++ b/drivers/base/regmap/regmap-mmio.c @@ -28,6 +28,8 @@ struct regmap_mmio_context { void __iomem *regs; unsigned val_bytes; + + bool attached_clk; struct clk *clk; void (*reg_write)(struct regmap_mmio_context *ctx, @@ -363,4 +365,26 @@ struct regmap *__devm_regmap_init_mmio_clk(struct device *dev, } EXPORT_SYMBOL_GPL(__devm_regmap_init_mmio_clk); +int regmap_mmio_attach_clk(struct regmap *map, struct clk *clk) +{ + struct regmap_mmio_context *ctx = map->bus_context; + + ctx->clk = clk; + ctx->attached_clk = true; + + return clk_prepare(ctx->clk); +} +EXPORT_SYMBOL_GPL(regmap_mmio_attach_clk); + +void regmap_mmio_detach_clk(struct regmap *map) +{ + struct regmap_mmio_context *ctx = map->bus_context; + + clk_unprepare(ctx->clk); + + ctx->attached_clk = false; + ctx->clk = NULL; +} +EXPORT_SYMBOL_GPL(regmap_mmio_detach_clk); + MODULE_LICENSE("GPL v2"); diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 6a3aeba40e9e..5f7ad0552c03 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -21,6 +21,7 @@ #include struct module; +struct clk; struct device; struct i2c_client; struct irq_domain; @@ -905,6 +906,8 @@ bool regmap_ac97_default_volatile(struct device *dev, unsigned int reg); __regmap_lockdep_wrapper(__devm_regmap_init_sdw, #config, \ sdw, config) +int regmap_mmio_attach_clk(struct regmap *map, struct clk *clk); +void regmap_mmio_detach_clk(struct regmap *map); void regmap_exit(struct regmap *map); int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config); From a430ab205d29e7d1537b220fcf989b8080d8267f Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 5 Mar 2018 15:52:09 -0300 Subject: [PATCH 4/7] regmap: debugfs: Disambiguate dummy debugfs file name Since commit 9b947a13e7f6 ("regmap: use debugfs even when no device") allows the usage of regmap debugfs even when there is no device associated, which causes several warnings like this: (NULL device *): Failed to create debugfs directory This happens when the debugfs file name is 'dummy'. The first dummy debugfs creation works fine, but subsequent creations fail as they have all the same name. Disambiguate the 'dummy' debugfs file name by adding a suffix entry, so that the names become dummy0, dummy1, dummy2, etc. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-debugfs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index 7eb512ba2828..e3e7b91cc421 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -25,6 +25,7 @@ struct regmap_debugfs_node { struct list_head link; }; +static unsigned int dummy_index; static struct dentry *regmap_debugfs_root; static LIST_HEAD(regmap_debugfs_early_list); static DEFINE_MUTEX(regmap_debugfs_early_lock); @@ -573,6 +574,11 @@ void regmap_debugfs_init(struct regmap *map, const char *name) name = devname; } + if (!strcmp(name, "dummy")) { + name = kasprintf(GFP_KERNEL, "dummy%d", dummy_index); + dummy_index++; + } + map->debugfs = debugfs_create_dir(name, regmap_debugfs_root); if (!map->debugfs) { dev_warn(map->dev, "Failed to create debugfs directory\n"); From 46589e9c753b7c905e8671a89cbb9728f3b99855 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 5 Mar 2018 20:26:51 +0000 Subject: [PATCH 5/7] regmap: debugfs: Don't leak dummy names When allocating dummy names we need to store a pointer to the string we allocate so that we don't leak it on free. Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-debugfs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index e3e7b91cc421..dd3a16894e3c 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -575,7 +575,9 @@ void regmap_debugfs_init(struct regmap *map, const char *name) } if (!strcmp(name, "dummy")) { - name = kasprintf(GFP_KERNEL, "dummy%d", dummy_index); + map->debugfs_name = kasprintf(GFP_KERNEL, "dummy%d", + dummy_index); + name = map->debugfs_name; dummy_index++; } From 17cf46cfe975f1dd04db6bd38398923846512d49 Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Tue, 6 Mar 2018 19:04:03 +0800 Subject: [PATCH 6/7] regmap: debugfs: Free map->debugfs_name when debugfs_create_dir() failed Free map->debugfs_name when debugfs_create_dir() failed to avoid memory leak. Signed-off-by: Jeffy Chen Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-debugfs.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index dd3a16894e3c..c84f5ceb015a 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -584,6 +584,9 @@ void regmap_debugfs_init(struct regmap *map, const char *name) map->debugfs = debugfs_create_dir(name, regmap_debugfs_root); if (!map->debugfs) { dev_warn(map->dev, "Failed to create debugfs directory\n"); + + kfree(map->debugfs_name); + map->debugfs_name = NULL; return; } From 59dd2a85040103e95b1c87b1b920d357ee91dada Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 5 Mar 2018 23:13:04 -0300 Subject: [PATCH 7/7] regmap: debugfs: Improve warning message on debugfs_create_dir() failure Currently when debugfs_create_dir() fails we receive a warning message that provides no indication as to what was the directory entry that failed to be created. Improve the warning message by printing the directory name that failed in order to help debugging. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-debugfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index c84f5ceb015a..87b562e49a43 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -583,7 +583,8 @@ void regmap_debugfs_init(struct regmap *map, const char *name) map->debugfs = debugfs_create_dir(name, regmap_debugfs_root); if (!map->debugfs) { - dev_warn(map->dev, "Failed to create debugfs directory\n"); + dev_warn(map->dev, + "Failed to create %s debugfs directory\n", name); kfree(map->debugfs_name); map->debugfs_name = NULL;