From 2899872b627e99b7586fe3b6c9f861da1b4d5072 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Fri, 17 May 2019 13:23:49 +0000 Subject: regmap: debugfs: Fix memory leak in regmap_debugfs_init As detected by kmemleak running on i.MX6ULL board: nreferenced object 0xd8366600 (size 64): comm "swapper/0", pid 1, jiffies 4294937370 (age 933.220s) hex dump (first 32 bytes): 64 75 6d 6d 79 2d 69 6f 6d 75 78 63 2d 67 70 72 dummy-iomuxc-gpr 40 32 30 65 34 30 30 30 00 e3 f3 ab fe d1 1b dd @20e4000........ backtrace: [] kasprintf+0x2c/0x54 [] regmap_debugfs_init+0x7c/0x31c [<9c8d91fa>] __regmap_init+0xb5c/0xcf4 [<5b1c3d2a>] of_syscon_register+0x164/0x2c4 [<596a5d80>] syscon_node_to_regmap+0x64/0x90 [<49bd597b>] imx6ul_init_machine+0x34/0xa0 [<250a4dac>] customize_machine+0x1c/0x30 [<2d19fdaf>] do_one_initcall+0x7c/0x398 [] kernel_init_freeable+0x328/0x448 [<168c9101>] kernel_init+0x8/0x114 [<913268aa>] ret_from_fork+0x14/0x20 [] 0x0 Root cause is that map->debugfs_name is allocated using kasprintf and then the pointer is lost by assigning it other memory address. Reported-by: Stefan Wahren Signed-off-by: Daniel Baluta Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-debugfs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index 263f82516ff4..e5e1b3a01b1a 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -579,6 +579,8 @@ void regmap_debugfs_init(struct regmap *map, const char *name) } if (!strcmp(name, "dummy")) { + kfree(map->debugfs_name); + map->debugfs_name = kasprintf(GFP_KERNEL, "dummy%d", dummy_index); name = map->debugfs_name; -- cgit From 6445500b43129baac36c56d629cf1dd9e1104167 Mon Sep 17 00:00:00 2001 From: Vitor Soares Date: Thu, 6 Jun 2019 17:12:02 +0200 Subject: regmap: add i3c bus support Add basic support for i3c bus. This is a simple implementation that only give support for SDR Read and Write commands. Signed-off-by: Vitor Soares Signed-off-by: Mark Brown --- drivers/base/regmap/Kconfig | 6 +++- drivers/base/regmap/Makefile | 1 + drivers/base/regmap/regmap-i3c.c | 60 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 drivers/base/regmap/regmap-i3c.c (limited to 'drivers') diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig index 6ad5ef48b61e..c8bbf5322720 100644 --- a/drivers/base/regmap/Kconfig +++ b/drivers/base/regmap/Kconfig @@ -4,7 +4,7 @@ # subsystems should select the appropriate symbols. config REGMAP - default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ) + default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_I3C) select IRQ_DOMAIN if REGMAP_IRQ bool @@ -49,3 +49,7 @@ config REGMAP_SOUNDWIRE config REGMAP_SCCB tristate depends on I2C + +config REGMAP_I3C + tristate + depends on I3C diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile index f5b4e8851d00..ff6c7d8ec1cd 100644 --- a/drivers/base/regmap/Makefile +++ b/drivers/base/regmap/Makefile @@ -16,3 +16,4 @@ obj-$(CONFIG_REGMAP_IRQ) += regmap-irq.o obj-$(CONFIG_REGMAP_W1) += regmap-w1.o obj-$(CONFIG_REGMAP_SOUNDWIRE) += regmap-sdw.o obj-$(CONFIG_REGMAP_SCCB) += regmap-sccb.o +obj-$(CONFIG_REGMAP_I3C) += regmap-i3c.o diff --git a/drivers/base/regmap/regmap-i3c.c b/drivers/base/regmap/regmap-i3c.c new file mode 100644 index 000000000000..1578fb506683 --- /dev/null +++ b/drivers/base/regmap/regmap-i3c.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2018 Synopsys, Inc. and/or its affiliates. + +#include +#include +#include +#include + +static int regmap_i3c_write(void *context, const void *data, size_t count) +{ + struct device *dev = context; + struct i3c_device *i3c = dev_to_i3cdev(dev); + struct i3c_priv_xfer xfers[] = { + { + .rnw = false, + .len = count, + .data.out = data, + }, + }; + + return i3c_device_do_priv_xfers(i3c, xfers, 1); +} + +static int regmap_i3c_read(void *context, + const void *reg, size_t reg_size, + void *val, size_t val_size) +{ + struct device *dev = context; + struct i3c_device *i3c = dev_to_i3cdev(dev); + struct i3c_priv_xfer xfers[2]; + + xfers[0].rnw = false; + xfers[0].len = reg_size; + xfers[0].data.out = reg; + + xfers[1].rnw = true; + xfers[1].len = val_size; + xfers[1].data.in = val; + + return i3c_device_do_priv_xfers(i3c, xfers, 2); +} + +static struct regmap_bus regmap_i3c = { + .write = regmap_i3c_write, + .read = regmap_i3c_read, +}; + +struct regmap *__devm_regmap_init_i3c(struct i3c_device *i3c, + const struct regmap_config *config, + struct lock_class_key *lock_key, + const char *lock_name) +{ + return __devm_regmap_init(&i3c->dev, ®map_i3c, &i3c->dev, config, + lock_key, lock_name); +} +EXPORT_SYMBOL_GPL(__devm_regmap_init_i3c); + +MODULE_AUTHOR("Vitor Soares "); +MODULE_DESCRIPTION("Regmap I3C Module"); +MODULE_LICENSE("GPL v2"); -- cgit From db057679de3e9e6a03c1bcd5aee09b0d25fd9f5b Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Wed, 12 Jun 2019 12:03:43 +0100 Subject: regmap: fix bulk writes on paged registers On buses like SlimBus and SoundWire which does not support gather_writes yet in regmap, A bulk write on paged register would be silently ignored after programming page. This is because local variable 'ret' value in regmap_raw_write_impl() gets reset to 0 once page register is written successfully and the code below checks for 'ret' value to be -ENOTSUPP before linearising the write buffer to send to bus->write(). Fix this by resetting the 'ret' value to -ENOTSUPP in cases where gather_writes() is not supported or single register write is not possible. Signed-off-by: Srinivas Kandagatla Signed-off-by: Mark Brown --- drivers/base/regmap/regmap.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index f1025452bb39..19f57ccfbe1d 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -1637,6 +1637,8 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg, map->format.reg_bytes + map->format.pad_bytes, val, val_len); + else + ret = -ENOTSUPP; /* If that didn't work fall back on linearising by hand. */ if (ret == -ENOTSUPP) { -- cgit From 55535589eb7f46898621668fb2044ca0d21ca21e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 17 Jun 2019 14:54:03 +0300 Subject: regmap: lzo: Switch to bitmap_zalloc() Switch to bitmap_zalloc() to show clearly what we are allocating. Besides that it returns pointer of bitmap type instead of opaque void *. Signed-off-by: Andy Shevchenko Signed-off-by: Mark Brown --- drivers/base/regmap/regcache-lzo.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/base/regmap/regcache-lzo.c b/drivers/base/regmap/regcache-lzo.c index fc14e8b9344f..7886303eb026 100644 --- a/drivers/base/regmap/regcache-lzo.c +++ b/drivers/base/regmap/regcache-lzo.c @@ -148,20 +148,18 @@ static int regcache_lzo_init(struct regmap *map) * that register. */ bmp_size = map->num_reg_defaults_raw; - sync_bmp = kmalloc_array(BITS_TO_LONGS(bmp_size), sizeof(long), - GFP_KERNEL); + sync_bmp = bitmap_zalloc(bmp_size, GFP_KERNEL); if (!sync_bmp) { ret = -ENOMEM; goto err; } - bitmap_zero(sync_bmp, bmp_size); /* allocate the lzo blocks and initialize them */ for (i = 0; i < blkcount; i++) { lzo_blocks[i] = kzalloc(sizeof **lzo_blocks, GFP_KERNEL); if (!lzo_blocks[i]) { - kfree(sync_bmp); + bitmap_free(sync_bmp); ret = -ENOMEM; goto err; } @@ -213,7 +211,7 @@ static int regcache_lzo_exit(struct regmap *map) * only once. */ if (lzo_blocks[0]) - kfree(lzo_blocks[0]->sync_bmp); + bitmap_free(lzo_blocks[0]->sync_bmp); for (i = 0; i < blkcount; i++) { if (lzo_blocks[i]) { kfree(lzo_blocks[i]->wmem); -- cgit From eff5a850017193ae879948944be05cc814c29621 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 4 Jul 2019 17:35:53 +0800 Subject: regmap: select CONFIG_REGMAP while REGMAP_SCCB is set REGMAP_SCCB is selected by ov772x and ov9650 drivers, but CONFIG_REGMAP may not, so building will fails: rivers/media/i2c/ov772x.c: In function ov772x_probe: drivers/media/i2c/ov772x.c:1360:22: error: variable ov772x_regmap_config has initializer but incomplete type static const struct regmap_config ov772x_regmap_config = { ^~~~~~~~~~~~~ drivers/media/i2c/ov772x.c:1361:4: error: const struct regmap_config has no member named reg_bits Reported-by: Hulk Robot Fixes: 5bbf32217bf9 ("media: ov772x: use SCCB regmap") Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190704093553.49904-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- drivers/base/regmap/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig index c8bbf5322720..a4984136c19d 100644 --- a/drivers/base/regmap/Kconfig +++ b/drivers/base/regmap/Kconfig @@ -4,7 +4,7 @@ # subsystems should select the appropriate symbols. config REGMAP - default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_I3C) + default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SCCB || REGMAP_I3C) select IRQ_DOMAIN if REGMAP_IRQ bool -- cgit