linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHv7 0/7] Convert exiting EEPROM drivers to NVMEM
@ 2016-02-26 19:59 Andrew Lunn
  2016-02-26 19:59 ` [PATCHv7 1/7] nvmem: Add flag to export NVMEM to root only Andrew Lunn
                   ` (7 more replies)
  0 siblings, 8 replies; 19+ messages in thread
From: Andrew Lunn @ 2016-02-26 19:59 UTC (permalink / raw)
  To: GregKH
  Cc: srinivas.kandagatla, maxime.ripard, wsa, broonie, vz,
	linux-kernel, pantelis.antoniou, bgolaszewski, Andrew Lunn

This patch set converts the old EEPROM drivers in driver/misc/eeprom to
use the NVMEM framework. These drivers export there content in /sys as
read only to root, since the EEPROM may contain sensitive information.
So the first patch adds a flag so the NVMEM framework will create its
file in /sys as root read only.

To keep backwards compatibility with these older drivers, the contents
of the EEPROM must be exports in sysfs in a file called eeprom in the
devices node in sys, where as the NVMEM places them under class/nvmem.
So add this optional backwards compatible to the framework, again
using a flag.

Then convert the at24, at25 and 93xx46 by adding regmap support,
removing each drivers own /sys code and registering with the NVMEM
framework.

Lastly, the old memory accessor mechanism has been replaced with the
nvmem equivalent.

v7:
 Added more acked-by
 Added tested-by for patch #7
 Rebased onto current misc-char/misc-char-next.

Andrew Lunn (7):
  nvmem: Add flag to export NVMEM to root only
  nvmem: Add backwards compatibility support for older EEPROM drivers.
  eeprom: at24: extend driver to plug into the NVMEM framework
  eeprom: at25: Remove in kernel API for accessing the EEPROM
  eeprom: at25: extend driver to plug into the NVMEM framework
  eeprom: 93xx46: extend driver to plug into the NVMEM framework
  misc: at24: replace memory_accessor with nvmem_device_read

 arch/arm/mach-davinci/board-mityomapl138.c |   5 +-
 arch/arm/mach-davinci/common.c             |   4 +-
 drivers/misc/eeprom/Kconfig                |   6 ++
 drivers/misc/eeprom/at24.c                 | 130 +++++++++++++------------
 drivers/misc/eeprom/at25.c                 | 148 +++++++++++++----------------
 drivers/misc/eeprom/eeprom_93xx46.c        | 120 +++++++++++++++++------
 drivers/nvmem/core.c                       | 141 +++++++++++++++++++++++++--
 include/linux/davinci_emac.h               |   4 +-
 include/linux/memory.h                     |  11 ---
 include/linux/nvmem-provider.h             |   5 +-
 include/linux/platform_data/at24.h         |  10 +-
 include/linux/spi/eeprom.h                 |   2 -
 12 files changed, 384 insertions(+), 202 deletions(-)

-- 
2.7.0

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCHv7 1/7] nvmem: Add flag to export NVMEM to root only
  2016-02-26 19:59 [PATCHv7 0/7] Convert exiting EEPROM drivers to NVMEM Andrew Lunn
@ 2016-02-26 19:59 ` Andrew Lunn
  2016-02-26 19:59 ` [PATCHv7 2/7] nvmem: Add backwards compatibility support for older EEPROM drivers Andrew Lunn
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 19+ messages in thread
From: Andrew Lunn @ 2016-02-26 19:59 UTC (permalink / raw)
  To: GregKH
  Cc: srinivas.kandagatla, maxime.ripard, wsa, broonie, vz,
	linux-kernel, pantelis.antoniou, bgolaszewski, Andrew Lunn

Legacy AT24, AT25 EEPROMs are exported in sys so that only root can
read the contents. The EEPROMs may contain sensitive information. Add
a flag so the provide can indicate that NVMEM should also restrict
access to root only.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 drivers/nvmem/core.c           | 57 ++++++++++++++++++++++++++++++++++++++++--
 include/linux/nvmem-provider.h |  1 +
 2 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index de14fae6f7f6..b03690bc8f09 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -161,6 +161,53 @@ static const struct attribute_group *nvmem_ro_dev_groups[] = {
 	NULL,
 };
 
+/* default read/write permissions, root only */
+static struct bin_attribute bin_attr_rw_root_nvmem = {
+	.attr	= {
+		.name	= "nvmem",
+		.mode	= S_IWUSR | S_IRUSR,
+	},
+	.read	= bin_attr_nvmem_read,
+	.write	= bin_attr_nvmem_write,
+};
+
+static struct bin_attribute *nvmem_bin_rw_root_attributes[] = {
+	&bin_attr_rw_root_nvmem,
+	NULL,
+};
+
+static const struct attribute_group nvmem_bin_rw_root_group = {
+	.bin_attrs	= nvmem_bin_rw_root_attributes,
+};
+
+static const struct attribute_group *nvmem_rw_root_dev_groups[] = {
+	&nvmem_bin_rw_root_group,
+	NULL,
+};
+
+/* read only permission, root only */
+static struct bin_attribute bin_attr_ro_root_nvmem = {
+	.attr	= {
+		.name	= "nvmem",
+		.mode	= S_IRUSR,
+	},
+	.read	= bin_attr_nvmem_read,
+};
+
+static struct bin_attribute *nvmem_bin_ro_root_attributes[] = {
+	&bin_attr_ro_root_nvmem,
+	NULL,
+};
+
+static const struct attribute_group nvmem_bin_ro_root_group = {
+	.bin_attrs	= nvmem_bin_ro_root_attributes,
+};
+
+static const struct attribute_group *nvmem_ro_root_dev_groups[] = {
+	&nvmem_bin_ro_root_group,
+	NULL,
+};
+
 static void nvmem_release(struct device *dev)
 {
 	struct nvmem_device *nvmem = to_nvmem_device(dev);
@@ -355,8 +402,14 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
 	nvmem->read_only = of_property_read_bool(np, "read-only") |
 			   config->read_only;
 
-	nvmem->dev.groups = nvmem->read_only ? nvmem_ro_dev_groups :
-					       nvmem_rw_dev_groups;
+	if (config->root_only)
+		nvmem->dev.groups = nvmem->read_only ?
+			nvmem_ro_root_dev_groups :
+			nvmem_rw_root_dev_groups;
+	else
+		nvmem->dev.groups = nvmem->read_only ?
+			nvmem_ro_dev_groups :
+			nvmem_rw_dev_groups;
 
 	device_initialize(&nvmem->dev);
 
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index 0b68caff1b3c..d24fefa0c11d 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -23,6 +23,7 @@ struct nvmem_config {
 	const struct nvmem_cell_info	*cells;
 	int			ncells;
 	bool			read_only;
+	bool			root_only;
 };
 
 #if IS_ENABLED(CONFIG_NVMEM)
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCHv7 2/7] nvmem: Add backwards compatibility support for older EEPROM drivers.
  2016-02-26 19:59 [PATCHv7 0/7] Convert exiting EEPROM drivers to NVMEM Andrew Lunn
  2016-02-26 19:59 ` [PATCHv7 1/7] nvmem: Add flag to export NVMEM to root only Andrew Lunn
@ 2016-02-26 19:59 ` Andrew Lunn
  2016-02-26 19:59 ` [PATCHv7 3/7] eeprom: at24: extend driver to plug into the NVMEM framework Andrew Lunn
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 19+ messages in thread
From: Andrew Lunn @ 2016-02-26 19:59 UTC (permalink / raw)
  To: GregKH
  Cc: srinivas.kandagatla, maxime.ripard, wsa, broonie, vz,
	linux-kernel, pantelis.antoniou, bgolaszewski, Andrew Lunn

Older drivers made an 'eeprom' file available in the /sys device
directory. Have the NVMEM core provide this to retain backwards
compatibility.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
v4: Add lockdep support
---
 drivers/nvmem/core.c           | 84 ++++++++++++++++++++++++++++++++++++++----
 include/linux/nvmem-provider.h |  4 +-
 2 files changed, 79 insertions(+), 9 deletions(-)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index b03690bc8f09..0de3d878c439 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -38,8 +38,13 @@ struct nvmem_device {
 	int			users;
 	size_t			size;
 	bool			read_only;
+	int			flags;
+	struct bin_attribute	eeprom;
+	struct device		*base_dev;
 };
 
+#define FLAG_COMPAT		BIT(0)
+
 struct nvmem_cell {
 	const char		*name;
 	int			offset;
@@ -56,16 +61,26 @@ 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
+
 #define to_nvmem_device(d) container_of(d, struct nvmem_device, dev)
 
 static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
 				    struct bin_attribute *attr,
 				    char *buf, loff_t pos, size_t count)
 {
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct nvmem_device *nvmem = to_nvmem_device(dev);
+	struct device *dev;
+	struct nvmem_device *nvmem;
 	int rc;
 
+	if (attr->private)
+		dev = attr->private;
+	else
+		dev = container_of(kobj, struct device, kobj);
+	nvmem = to_nvmem_device(dev);
+
 	/* Stop the user from reading */
 	if (pos >= nvmem->size)
 		return 0;
@@ -90,10 +105,16 @@ static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
 				     struct bin_attribute *attr,
 				     char *buf, loff_t pos, size_t count)
 {
-	struct device *dev = container_of(kobj, struct device, kobj);
-	struct nvmem_device *nvmem = to_nvmem_device(dev);
+	struct device *dev;
+	struct nvmem_device *nvmem;
 	int rc;
 
+	if (attr->private)
+		dev = attr->private;
+	else
+		dev = container_of(kobj, struct device, kobj);
+	nvmem = to_nvmem_device(dev);
+
 	/* Stop the user from writing */
 	if (pos >= nvmem->size)
 		return 0;
@@ -349,6 +370,43 @@ err:
 	return rval;
 }
 
+/*
+ * nvmem_setup_compat() - Create an additional binary entry in
+ * drivers sys directory, to be backwards compatible with the older
+ * drivers/misc/eeprom drivers.
+ */
+static int nvmem_setup_compat(struct nvmem_device *nvmem,
+			      const struct nvmem_config *config)
+{
+	int rval;
+
+	if (!config->base_dev)
+		return -EINVAL;
+
+	if (nvmem->read_only)
+		nvmem->eeprom = bin_attr_ro_root_nvmem;
+	else
+		nvmem->eeprom = bin_attr_rw_root_nvmem;
+	nvmem->eeprom.attr.name = "eeprom";
+	nvmem->eeprom.size = nvmem->size;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+	nvmem->eeprom.attr.key = &eeprom_lock_key;
+#endif
+	nvmem->eeprom.private = &nvmem->dev;
+	nvmem->base_dev = config->base_dev;
+
+	rval = device_create_bin_file(nvmem->base_dev, &nvmem->eeprom);
+	if (rval) {
+		dev_err(&nvmem->dev,
+			"Failed to create eeprom binary file %d\n", rval);
+		return rval;
+	}
+
+	nvmem->flags |= FLAG_COMPAT;
+
+	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
@@ -416,16 +474,23 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
 	dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
 
 	rval = device_add(&nvmem->dev);
-	if (rval) {
-		ida_simple_remove(&nvmem_ida, nvmem->id);
-		kfree(nvmem);
-		return ERR_PTR(rval);
+	if (rval)
+		goto out;
+
+	if (config->compat) {
+		rval = nvmem_setup_compat(nvmem, config);
+		if (rval)
+			goto out;
 	}
 
 	if (config->cells)
 		nvmem_add_cells(nvmem, config);
 
 	return nvmem;
+out:
+	ida_simple_remove(&nvmem_ida, nvmem->id);
+	kfree(nvmem);
+	return ERR_PTR(rval);
 }
 EXPORT_SYMBOL_GPL(nvmem_register);
 
@@ -445,6 +510,9 @@ int nvmem_unregister(struct nvmem_device *nvmem)
 	}
 	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);
 
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index d24fefa0c11d..a4fcc90b0f20 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -24,6 +24,9 @@ struct nvmem_config {
 	int			ncells;
 	bool			read_only;
 	bool			root_only;
+	/* To be only used by old driver/misc/eeprom drivers */
+	bool			compat;
+	struct device		*base_dev;
 };
 
 #if IS_ENABLED(CONFIG_NVMEM)
@@ -44,5 +47,4 @@ static inline int nvmem_unregister(struct nvmem_device *nvmem)
 }
 
 #endif /* CONFIG_NVMEM */
-
 #endif  /* ifndef _LINUX_NVMEM_PROVIDER_H */
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCHv7 3/7] eeprom: at24: extend driver to plug into the NVMEM framework
  2016-02-26 19:59 [PATCHv7 0/7] Convert exiting EEPROM drivers to NVMEM Andrew Lunn
  2016-02-26 19:59 ` [PATCHv7 1/7] nvmem: Add flag to export NVMEM to root only Andrew Lunn
  2016-02-26 19:59 ` [PATCHv7 2/7] nvmem: Add backwards compatibility support for older EEPROM drivers Andrew Lunn
@ 2016-02-26 19:59 ` Andrew Lunn
  2016-03-02 21:46   ` Vladimir Zapolskiy
  2016-02-26 19:59 ` [PATCHv7 4/7] eeprom: at25: Remove in kernel API for accessing the EEPROM Andrew Lunn
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Andrew Lunn @ 2016-02-26 19:59 UTC (permalink / raw)
  To: GregKH
  Cc: srinivas.kandagatla, maxime.ripard, wsa, broonie, vz,
	linux-kernel, pantelis.antoniou, bgolaszewski, Andrew Lunn

Add a regmap for accessing the EEPROM, and then use that with the
NVMEM framework. Set the NVMEM config structure to enable backward, so
that the 'eeprom' file in sys is provided by the framework.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Tested-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 drivers/misc/eeprom/Kconfig |   2 +
 drivers/misc/eeprom/at24.c  | 121 +++++++++++++++++++++++++++++---------------
 2 files changed, 82 insertions(+), 41 deletions(-)

diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 04f2e1fa9dd1..24935473393b 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -3,6 +3,8 @@ menu "EEPROM support"
 config EEPROM_AT24
 	tristate "I2C EEPROMs / RAMs / ROMs from most vendors"
 	depends on I2C && SYSFS
+	select REGMAP
+	select NVMEM
 	help
 	  Enable this driver to get read/write support to most I2C EEPROMs
 	  and compatible devices like FRAMs, SRAMs, ROMs etc. After you
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index d105c2564400..f15cda93fc4c 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -15,7 +15,6 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
-#include <linux/sysfs.h>
 #include <linux/mod_devicetable.h>
 #include <linux/log2.h>
 #include <linux/bitops.h>
@@ -23,6 +22,8 @@
 #include <linux/of.h>
 #include <linux/acpi.h>
 #include <linux/i2c.h>
+#include <linux/nvmem-provider.h>
+#include <linux/regmap.h>
 #include <linux/platform_data/at24.h>
 
 /*
@@ -64,12 +65,15 @@ struct at24_data {
 	 * but not from changes by other I2C masters.
 	 */
 	struct mutex lock;
-	struct bin_attribute bin;
 
 	u8 *writebuf;
 	unsigned write_max;
 	unsigned num_addresses;
 
+	struct regmap_config regmap_config;
+	struct nvmem_config nvmem_config;
+	struct nvmem_device *nvmem;
+
 	/*
 	 * Some chips tie up multiple I2C addresses; dummy devices reserve
 	 * them for us, and we'll use them with SMBus calls.
@@ -283,17 +287,6 @@ static ssize_t at24_read(struct at24_data *at24,
 	return retval;
 }
 
-static ssize_t at24_bin_read(struct file *filp, struct kobject *kobj,
-		struct bin_attribute *attr,
-		char *buf, loff_t off, size_t count)
-{
-	struct at24_data *at24;
-
-	at24 = dev_get_drvdata(kobj_to_dev(kobj));
-	return at24_read(at24, buf, off, count);
-}
-
-
 /*
  * Note that if the hardware write-protect pin is pulled high, the whole
  * chip is normally write protected. But there are plenty of product
@@ -414,16 +407,6 @@ static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off,
 	return retval;
 }
 
-static ssize_t at24_bin_write(struct file *filp, struct kobject *kobj,
-		struct bin_attribute *attr,
-		char *buf, loff_t off, size_t count)
-{
-	struct at24_data *at24;
-
-	at24 = dev_get_drvdata(kobj_to_dev(kobj));
-	return at24_write(at24, buf, off, count);
-}
-
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -450,6 +433,49 @@ static ssize_t at24_macc_write(struct memory_accessor *macc, const char *buf,
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * Provide a regmap interface, which is registered with the NVMEM
+ * framework
+*/
+static int at24_regmap_read(void *context, const void *reg, size_t reg_size,
+			    void *val, size_t val_size)
+{
+	struct at24_data *at24 = context;
+	off_t offset = *(u32 *)reg;
+	int err;
+
+	err = at24_read(at24, val, offset, val_size);
+	if (err)
+		return err;
+	return 0;
+}
+
+static int at24_regmap_write(void *context, const void *data, size_t count)
+{
+	struct at24_data *at24 = context;
+	const char *buf;
+	u32 offset;
+	size_t len;
+	int err;
+
+	memcpy(&offset, data, sizeof(offset));
+	buf = (const char *)data + sizeof(offset);
+	len = count - sizeof(offset);
+
+	err = at24_write(at24, buf, offset, len);
+	if (err)
+		return err;
+	return 0;
+}
+
+static const struct regmap_bus at24_regmap_bus = {
+	.read = at24_regmap_read,
+	.write = at24_regmap_write,
+	.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+/*-------------------------------------------------------------------------*/
+
 #ifdef CONFIG_OF
 static void at24_get_ofdata(struct i2c_client *client,
 		struct at24_platform_data *chip)
@@ -481,6 +507,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	struct at24_data *at24;
 	int err;
 	unsigned i, num_addresses;
+	struct regmap *regmap;
 
 	if (client->dev.platform_data) {
 		chip = *(struct at24_platform_data *)client->dev.platform_data;
@@ -573,16 +600,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	at24->chip = chip;
 	at24->num_addresses = num_addresses;
 
-	/*
-	 * Export the EEPROM bytes through sysfs, since that's convenient.
-	 * By default, only root should see the data (maybe passwords etc)
-	 */
-	sysfs_bin_attr_init(&at24->bin);
-	at24->bin.attr.name = "eeprom";
-	at24->bin.attr.mode = chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR;
-	at24->bin.read = at24_bin_read;
-	at24->bin.size = chip.byte_len;
-
 	at24->macc.read = at24_macc_read;
 
 	writable = !(chip.flags & AT24_FLAG_READONLY);
@@ -593,9 +610,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 			at24->macc.write = at24_macc_write;
 
-			at24->bin.write = at24_bin_write;
-			at24->bin.attr.mode |= S_IWUSR;
-
 			if (write_max > io_limit)
 				write_max = io_limit;
 			if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX)
@@ -627,14 +641,38 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		}
 	}
 
-	err = sysfs_create_bin_file(&client->dev.kobj, &at24->bin);
-	if (err)
+	at24->regmap_config.reg_bits = 32;
+	at24->regmap_config.val_bits = 8;
+	at24->regmap_config.reg_stride = 1;
+	at24->regmap_config.max_register = chip.byte_len - 1;
+
+	regmap = devm_regmap_init(&client->dev, &at24_regmap_bus, at24,
+				  &at24->regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(&client->dev, "regmap init failed\n");
+		err = PTR_ERR(regmap);
 		goto err_clients;
+	}
+
+	at24->nvmem_config.name = dev_name(&client->dev);
+	at24->nvmem_config.dev = &client->dev;
+	at24->nvmem_config.read_only = !writable;
+	at24->nvmem_config.root_only = true;
+	at24->nvmem_config.owner = THIS_MODULE;
+	at24->nvmem_config.compat = true;
+	at24->nvmem_config.base_dev = &client->dev;
+
+	at24->nvmem = nvmem_register(&at24->nvmem_config);
+
+	if (IS_ERR(at24->nvmem)) {
+		err = PTR_ERR(at24->nvmem);
+		goto err_clients;
+	}
 
 	i2c_set_clientdata(client, at24);
 
-	dev_info(&client->dev, "%zu byte %s EEPROM, %s, %u bytes/write\n",
-		at24->bin.size, client->name,
+	dev_info(&client->dev, "%u byte %s EEPROM, %s, %u bytes/write\n",
+		chip.byte_len, client->name,
 		writable ? "writable" : "read-only", at24->write_max);
 	if (use_smbus == I2C_SMBUS_WORD_DATA ||
 	    use_smbus == I2C_SMBUS_BYTE_DATA) {
@@ -663,7 +701,8 @@ static int at24_remove(struct i2c_client *client)
 	int i;
 
 	at24 = i2c_get_clientdata(client);
-	sysfs_remove_bin_file(&client->dev.kobj, &at24->bin);
+
+	nvmem_unregister(at24->nvmem);
 
 	for (i = 1; i < at24->num_addresses; i++)
 		i2c_unregister_device(at24->client[i]);
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCHv7 4/7] eeprom: at25: Remove in kernel API for accessing the EEPROM
  2016-02-26 19:59 [PATCHv7 0/7] Convert exiting EEPROM drivers to NVMEM Andrew Lunn
                   ` (2 preceding siblings ...)
  2016-02-26 19:59 ` [PATCHv7 3/7] eeprom: at24: extend driver to plug into the NVMEM framework Andrew Lunn
@ 2016-02-26 19:59 ` Andrew Lunn
  2016-02-28 21:02   ` Wolfram Sang
  2016-02-26 19:59 ` [PATCHv7 5/7] eeprom: at25: extend driver to plug into the NVMEM framework Andrew Lunn
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Andrew Lunn @ 2016-02-26 19:59 UTC (permalink / raw)
  To: GregKH
  Cc: srinivas.kandagatla, maxime.ripard, wsa, broonie, vz,
	linux-kernel, pantelis.antoniou, bgolaszewski, Andrew Lunn

The setup() callback is not used by any in kernel code. Remove it.
Any new code which requires access to the eeprom can use the NVMEM
API.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 drivers/misc/eeprom/at25.c | 26 --------------------------
 include/linux/spi/eeprom.h |  2 --
 2 files changed, 28 deletions(-)

diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index 3e9e5a28acaa..00f859cc0955 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -29,7 +29,6 @@
 
 struct at25_data {
 	struct spi_device	*spi;
-	struct memory_accessor	mem;
 	struct mutex		lock;
 	struct spi_eeprom	chip;
 	struct bin_attribute	bin;
@@ -281,26 +280,6 @@ at25_bin_write(struct file *filp, struct kobject *kobj,
 
 /*-------------------------------------------------------------------------*/
 
-/* Let in-kernel code access the eeprom data. */
-
-static ssize_t at25_mem_read(struct memory_accessor *mem, char *buf,
-			 off_t offset, size_t count)
-{
-	struct at25_data *at25 = container_of(mem, struct at25_data, mem);
-
-	return at25_ee_read(at25, buf, offset, count);
-}
-
-static ssize_t at25_mem_write(struct memory_accessor *mem, const char *buf,
-			  off_t offset, size_t count)
-{
-	struct at25_data *at25 = container_of(mem, struct at25_data, mem);
-
-	return at25_ee_write(at25, buf, offset, count);
-}
-
-/*-------------------------------------------------------------------------*/
-
 static int at25_fw_to_chip(struct device *dev, struct spi_eeprom *chip)
 {
 	u32 val;
@@ -415,22 +394,17 @@ static int at25_probe(struct spi_device *spi)
 	at25->bin.attr.name = "eeprom";
 	at25->bin.attr.mode = S_IRUSR;
 	at25->bin.read = at25_bin_read;
-	at25->mem.read = at25_mem_read;
 
 	at25->bin.size = at25->chip.byte_len;
 	if (!(chip.flags & EE_READONLY)) {
 		at25->bin.write = at25_bin_write;
 		at25->bin.attr.mode |= S_IWUSR;
-		at25->mem.write = at25_mem_write;
 	}
 
 	err = sysfs_create_bin_file(&spi->dev.kobj, &at25->bin);
 	if (err)
 		return err;
 
-	if (chip.setup)
-		chip.setup(&at25->mem, chip.context);
-
 	dev_info(&spi->dev, "%Zd %s %s eeprom%s, pagesize %u\n",
 		(at25->bin.size < 1024)
 			? at25->bin.size
diff --git a/include/linux/spi/eeprom.h b/include/linux/spi/eeprom.h
index 403e007aef68..e34e169f9dcb 100644
--- a/include/linux/spi/eeprom.h
+++ b/include/linux/spi/eeprom.h
@@ -30,8 +30,6 @@ struct spi_eeprom {
 	 */
 #define EE_INSTR_BIT3_IS_ADDR	0x0010
 
-	/* for exporting this chip's data to other kernel code */
-	void (*setup)(struct memory_accessor *mem, void *context);
 	void *context;
 };
 
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCHv7 5/7] eeprom: at25: extend driver to plug into the NVMEM framework
  2016-02-26 19:59 [PATCHv7 0/7] Convert exiting EEPROM drivers to NVMEM Andrew Lunn
                   ` (3 preceding siblings ...)
  2016-02-26 19:59 ` [PATCHv7 4/7] eeprom: at25: Remove in kernel API for accessing the EEPROM Andrew Lunn
@ 2016-02-26 19:59 ` Andrew Lunn
  2016-03-02 21:56   ` Vladimir Zapolskiy
  2016-02-26 19:59 ` [PATCHv7 6/7] eeprom: 93xx46: " Andrew Lunn
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Andrew Lunn @ 2016-02-26 19:59 UTC (permalink / raw)
  To: GregKH
  Cc: srinivas.kandagatla, maxime.ripard, wsa, broonie, vz,
	linux-kernel, pantelis.antoniou, bgolaszewski, Andrew Lunn

Add a regmap for accessing the EEPROM, and then use that with the
NVMEM framework. Enable backwards compatibility in the NVMEM config,
so that the 'eeprom' file in sys is provided by the framework.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 drivers/misc/eeprom/Kconfig |   2 +
 drivers/misc/eeprom/at25.c  | 124 ++++++++++++++++++++++++--------------------
 2 files changed, 71 insertions(+), 55 deletions(-)

diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 24935473393b..8c43a222ae55 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -32,6 +32,8 @@ config EEPROM_AT24
 config EEPROM_AT25
 	tristate "SPI EEPROMs from most vendors"
 	depends on SPI && SYSFS
+	select REGMAP
+	select NVMEM
 	help
 	  Enable this driver to get read/write support to most SPI EEPROMs,
 	  after you configure the board init code to know about each eeprom
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index 00f859cc0955..fa36a6e37084 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -16,6 +16,8 @@
 #include <linux/device.h>
 #include <linux/sched.h>
 
+#include <linux/nvmem-provider.h>
+#include <linux/regmap.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/eeprom.h>
 #include <linux/property.h>
@@ -31,8 +33,10 @@ struct at25_data {
 	struct spi_device	*spi;
 	struct mutex		lock;
 	struct spi_eeprom	chip;
-	struct bin_attribute	bin;
 	unsigned		addrlen;
+	struct regmap_config	regmap_config;
+	struct nvmem_config	nvmem_config;
+	struct nvmem_device	*nvmem;
 };
 
 #define	AT25_WREN	0x06		/* latch the write enable */
@@ -76,10 +80,10 @@ at25_ee_read(
 	struct spi_message	m;
 	u8			instr;
 
-	if (unlikely(offset >= at25->bin.size))
+	if (unlikely(offset >= at25->chip.byte_len))
 		return 0;
-	if ((offset + count) > at25->bin.size)
-		count = at25->bin.size - offset;
+	if ((offset + count) > at25->chip.byte_len)
+		count = at25->chip.byte_len - offset;
 	if (unlikely(!count))
 		return count;
 
@@ -130,21 +134,19 @@ at25_ee_read(
 	return status ? status : count;
 }
 
-static ssize_t
-at25_bin_read(struct file *filp, struct kobject *kobj,
-	      struct bin_attribute *bin_attr,
-	      char *buf, loff_t off, size_t count)
+static int at25_regmap_read(void *context, const void *reg, size_t reg_size,
+			    void *val, size_t val_size)
 {
-	struct device		*dev;
-	struct at25_data	*at25;
-
-	dev = kobj_to_dev(kobj);
-	at25 = dev_get_drvdata(dev);
+	struct at25_data *at25 = context;
+	off_t offset = *(u32 *)reg;
+	int err;
 
-	return at25_ee_read(at25, buf, off, count);
+	err = at25_ee_read(at25, val, offset, val_size);
+	if (err)
+		return err;
+	return 0;
 }
 
-
 static ssize_t
 at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
 	      size_t count)
@@ -154,10 +156,10 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
 	unsigned		buf_size;
 	u8			*bounce;
 
-	if (unlikely(off >= at25->bin.size))
+	if (unlikely(off >= at25->chip.byte_len))
 		return -EFBIG;
-	if ((off + count) > at25->bin.size)
-		count = at25->bin.size - off;
+	if ((off + count) > at25->chip.byte_len)
+		count = at25->chip.byte_len - off;
 	if (unlikely(!count))
 		return count;
 
@@ -264,20 +266,30 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
 	return written ? written : status;
 }
 
-static ssize_t
-at25_bin_write(struct file *filp, struct kobject *kobj,
-	       struct bin_attribute *bin_attr,
-	       char *buf, loff_t off, size_t count)
+static int at25_regmap_write(void *context, const void *data, size_t count)
 {
-	struct device		*dev;
-	struct at25_data	*at25;
+	struct at25_data *at25 = context;
+	const char *buf;
+	u32 offset;
+	size_t len;
+	int err;
 
-	dev = kobj_to_dev(kobj);
-	at25 = dev_get_drvdata(dev);
+	memcpy(&offset, data, sizeof(offset));
+	buf = (const char *)data + sizeof(offset);
+	len = count - sizeof(offset);
 
-	return at25_ee_write(at25, buf, off, count);
+	err = at25_ee_write(at25, buf, offset, len);
+	if (err)
+		return err;
+	return 0;
 }
 
+static const struct regmap_bus at25_regmap_bus = {
+	.read = at25_regmap_read,
+	.write = at25_regmap_write,
+	.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
 /*-------------------------------------------------------------------------*/
 
 static int at25_fw_to_chip(struct device *dev, struct spi_eeprom *chip)
@@ -337,6 +349,7 @@ static int at25_probe(struct spi_device *spi)
 {
 	struct at25_data	*at25 = NULL;
 	struct spi_eeprom	chip;
+	struct regmap		*regmap;
 	int			err;
 	int			sr;
 	int			addrlen;
@@ -381,35 +394,35 @@ static int at25_probe(struct spi_device *spi)
 	spi_set_drvdata(spi, at25);
 	at25->addrlen = addrlen;
 
-	/* Export the EEPROM bytes through sysfs, since that's convenient.
-	 * And maybe to other kernel code; it might hold a board's Ethernet
-	 * address, or board-specific calibration data generated on the
-	 * manufacturing floor.
-	 *
-	 * Default to root-only access to the data; EEPROMs often hold data
-	 * that's sensitive for read and/or write, like ethernet addresses,
-	 * security codes, board-specific manufacturing calibrations, etc.
-	 */
-	sysfs_bin_attr_init(&at25->bin);
-	at25->bin.attr.name = "eeprom";
-	at25->bin.attr.mode = S_IRUSR;
-	at25->bin.read = at25_bin_read;
-
-	at25->bin.size = at25->chip.byte_len;
-	if (!(chip.flags & EE_READONLY)) {
-		at25->bin.write = at25_bin_write;
-		at25->bin.attr.mode |= S_IWUSR;
-	}
+	at25->regmap_config.reg_bits = 32;
+	at25->regmap_config.val_bits = 8;
+	at25->regmap_config.reg_stride = 1;
+	at25->regmap_config.max_register = chip.byte_len - 1;
 
-	err = sysfs_create_bin_file(&spi->dev.kobj, &at25->bin);
-	if (err)
-		return err;
+	regmap = devm_regmap_init(&spi->dev, &at25_regmap_bus, at25,
+				  &at25->regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(&spi->dev, "regmap init failed\n");
+		return PTR_ERR(regmap);
+	}
 
-	dev_info(&spi->dev, "%Zd %s %s eeprom%s, pagesize %u\n",
-		(at25->bin.size < 1024)
-			? at25->bin.size
-			: (at25->bin.size / 1024),
-		(at25->bin.size < 1024) ? "Byte" : "KByte",
+	at25->nvmem_config.name = dev_name(&spi->dev);
+	at25->nvmem_config.dev = &spi->dev;
+	at25->nvmem_config.read_only = chip.flags & EE_READONLY;
+	at25->nvmem_config.root_only = true;
+	at25->nvmem_config.owner = THIS_MODULE;
+	at25->nvmem_config.compat = true;
+	at25->nvmem_config.base_dev = &spi->dev;
+
+	at25->nvmem = nvmem_register(&at25->nvmem_config);
+	if (IS_ERR(at25->nvmem))
+		return PTR_ERR(at25->nvmem);
+
+	dev_info(&spi->dev, "%d %s %s eeprom%s, pagesize %u\n",
+		(chip.byte_len < 1024)
+			? chip.byte_len
+			: (chip.byte_len / 1024),
+		(chip.byte_len < 1024) ? "Byte" : "KByte",
 		at25->chip.name,
 		(chip.flags & EE_READONLY) ? " (readonly)" : "",
 		at25->chip.page_size);
@@ -421,7 +434,8 @@ static int at25_remove(struct spi_device *spi)
 	struct at25_data	*at25;
 
 	at25 = spi_get_drvdata(spi);
-	sysfs_remove_bin_file(&spi->dev.kobj, &at25->bin);
+	nvmem_unregister(at25->nvmem);
+
 	return 0;
 }
 
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCHv7 6/7] eeprom: 93xx46: extend driver to plug into the NVMEM framework
  2016-02-26 19:59 [PATCHv7 0/7] Convert exiting EEPROM drivers to NVMEM Andrew Lunn
                   ` (4 preceding siblings ...)
  2016-02-26 19:59 ` [PATCHv7 5/7] eeprom: at25: extend driver to plug into the NVMEM framework Andrew Lunn
@ 2016-02-26 19:59 ` Andrew Lunn
  2016-03-02 22:08   ` Vladimir Zapolskiy
  2016-02-26 19:59 ` [PATCHv7 7/7] misc: at24: replace memory_accessor with nvmem_device_read Andrew Lunn
  2016-03-02  0:56 ` [PATCHv7 0/7] Convert exiting EEPROM drivers to NVMEM Greg KH
  7 siblings, 1 reply; 19+ messages in thread
From: Andrew Lunn @ 2016-02-26 19:59 UTC (permalink / raw)
  To: GregKH
  Cc: srinivas.kandagatla, maxime.ripard, wsa, broonie, vz,
	linux-kernel, pantelis.antoniou, bgolaszewski, Andrew Lunn

Add a regmap for accessing the EEPROM, and then use that with the
NVMEM framework. Enable backward compatibility in the NVMEM config
structure, so that the 'eeprom' file in sys is provided by the
framework.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
v5: Remove useless test.
v6: Fix typ0 and removed stray newline.
---
 drivers/misc/eeprom/Kconfig         |   2 +
 drivers/misc/eeprom/eeprom_93xx46.c | 120 ++++++++++++++++++++++++++++--------
 2 files changed, 95 insertions(+), 27 deletions(-)

diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 8c43a222ae55..cfc493c2e30a 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -78,6 +78,8 @@ config EEPROM_93CX6
 config EEPROM_93XX46
 	tristate "Microwire EEPROM 93XX46 support"
 	depends on SPI && SYSFS
+	select REGMAP
+	select NVMEM
 	help
 	  Driver for the microwire EEPROM chipsets 93xx46x. The driver
 	  supports both read and write commands and also the command to
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c
index f62ab29e293c..426fe2fd5238 100644
--- a/drivers/misc/eeprom/eeprom_93xx46.c
+++ b/drivers/misc/eeprom/eeprom_93xx46.c
@@ -19,7 +19,8 @@
 #include <linux/of_gpio.h>
 #include <linux/slab.h>
 #include <linux/spi/spi.h>
-#include <linux/sysfs.h>
+#include <linux/nvmem-provider.h>
+#include <linux/regmap.h>
 #include <linux/eeprom_93xx46.h>
 
 #define OP_START	0x4
@@ -41,9 +42,12 @@ static const struct eeprom_93xx46_devtype_data atmel_at93c46d_data = {
 struct eeprom_93xx46_dev {
 	struct spi_device *spi;
 	struct eeprom_93xx46_platform_data *pdata;
-	struct bin_attribute bin;
 	struct mutex lock;
+	struct regmap_config regmap_config;
+	struct nvmem_config nvmem_config;
+	struct nvmem_device *nvmem;
 	int addrlen;
+	int size;
 };
 
 static inline bool has_quirk_single_word_read(struct eeprom_93xx46_dev *edev)
@@ -57,16 +61,17 @@ static inline bool has_quirk_instruction_length(struct eeprom_93xx46_dev *edev)
 }
 
 static ssize_t
-eeprom_93xx46_bin_read(struct file *filp, struct kobject *kobj,
-		       struct bin_attribute *bin_attr,
-		       char *buf, loff_t off, size_t count)
+eeprom_93xx46_read(struct eeprom_93xx46_dev *edev, char *buf,
+		   unsigned off, size_t count)
 {
-	struct eeprom_93xx46_dev *edev;
-	struct device *dev;
 	ssize_t ret = 0;
 
-	dev = kobj_to_dev(kobj);
-	edev = dev_get_drvdata(dev);
+	if (unlikely(off >= edev->size))
+		return 0;
+	if ((off + count) > edev->size)
+		count = edev->size - off;
+	if (unlikely(!count))
+		return count;
 
 	mutex_lock(&edev->lock);
 
@@ -226,16 +231,17 @@ eeprom_93xx46_write_word(struct eeprom_93xx46_dev *edev,
 }
 
 static ssize_t
-eeprom_93xx46_bin_write(struct file *filp, struct kobject *kobj,
-			struct bin_attribute *bin_attr,
-			char *buf, loff_t off, size_t count)
+eeprom_93xx46_write(struct eeprom_93xx46_dev *edev, const char *buf,
+		    loff_t off, size_t count)
 {
-	struct eeprom_93xx46_dev *edev;
-	struct device *dev;
 	int i, ret, step = 1;
 
-	dev = kobj_to_dev(kobj);
-	edev = dev_get_drvdata(dev);
+	if (unlikely(off >= edev->size))
+		return -EFBIG;
+	if ((off + count) > edev->size)
+		count = edev->size - off;
+	if (unlikely(!count))
+		return count;
 
 	/* only write even number of bytes on 16-bit devices */
 	if (edev->addrlen == 6) {
@@ -272,6 +278,49 @@ eeprom_93xx46_bin_write(struct file *filp, struct kobject *kobj,
 	return ret ? : count;
 }
 
+/*
+ * Provide a regmap interface, which is registered with the NVMEM
+ * framework
+*/
+static int eeprom_93xx46_regmap_read(void *context, const void *reg,
+				     size_t reg_size, void *val,
+				     size_t val_size)
+{
+	struct eeprom_93xx46_dev *eeprom_93xx46 = context;
+	off_t offset = *(u32 *)reg;
+	int err;
+
+	err = eeprom_93xx46_read(eeprom_93xx46, val, offset, val_size);
+	if (err)
+		return err;
+	return 0;
+}
+
+static int eeprom_93xx46_regmap_write(void *context, const void *data,
+				      size_t count)
+{
+	struct eeprom_93xx46_dev *eeprom_93xx46 = context;
+	const char *buf;
+	u32 offset;
+	size_t len;
+	int err;
+
+	memcpy(&offset, data, sizeof(offset));
+	buf = (const char *)data + sizeof(offset);
+	len = count - sizeof(offset);
+
+	err = eeprom_93xx46_write(eeprom_93xx46, buf, offset, len);
+	if (err)
+		return err;
+	return 0;
+}
+
+static const struct regmap_bus eeprom_93xx46_regmap_bus = {
+	.read = eeprom_93xx46_regmap_read,
+	.write = eeprom_93xx46_regmap_write,
+	.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
 static int eeprom_93xx46_eral(struct eeprom_93xx46_dev *edev)
 {
 	struct eeprom_93xx46_platform_data *pd = edev->pdata;
@@ -431,6 +480,7 @@ static int eeprom_93xx46_probe(struct spi_device *spi)
 {
 	struct eeprom_93xx46_platform_data *pd;
 	struct eeprom_93xx46_dev *edev;
+	struct regmap *regmap;
 	int err;
 
 	if (spi->dev.of_node) {
@@ -464,19 +514,34 @@ static int eeprom_93xx46_probe(struct spi_device *spi)
 	edev->spi = spi_dev_get(spi);
 	edev->pdata = pd;
 
-	sysfs_bin_attr_init(&edev->bin);
-	edev->bin.attr.name = "eeprom";
-	edev->bin.attr.mode = S_IRUSR;
-	edev->bin.read = eeprom_93xx46_bin_read;
-	edev->bin.size = 128;
-	if (!(pd->flags & EE_READONLY)) {
-		edev->bin.write = eeprom_93xx46_bin_write;
-		edev->bin.attr.mode |= S_IWUSR;
+	edev->size = 128;
+
+	edev->regmap_config.reg_bits = 32;
+	edev->regmap_config.val_bits = 8;
+	edev->regmap_config.reg_stride = 1;
+	edev->regmap_config.max_register = edev->size - 1;
+
+	regmap = devm_regmap_init(&spi->dev, &eeprom_93xx46_regmap_bus, edev,
+				  &edev->regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(&spi->dev, "regmap init failed\n");
+		err = PTR_ERR(regmap);
+		goto fail;
 	}
 
-	err = sysfs_create_bin_file(&spi->dev.kobj, &edev->bin);
-	if (err)
+	edev->nvmem_config.name = dev_name(&spi->dev);
+	edev->nvmem_config.dev = &spi->dev;
+	edev->nvmem_config.read_only = pd->flags & EE_READONLY;
+	edev->nvmem_config.root_only = true;
+	edev->nvmem_config.owner = THIS_MODULE;
+	edev->nvmem_config.compat = true;
+	edev->nvmem_config.base_dev = &spi->dev;
+
+	edev->nvmem = nvmem_register(&edev->nvmem_config);
+	if (IS_ERR(edev->nvmem)) {
+		err = PTR_ERR(edev->nvmem);
 		goto fail;
+	}
 
 	dev_info(&spi->dev, "%d-bit eeprom %s\n",
 		(pd->flags & EE_ADDR8) ? 8 : 16,
@@ -498,10 +563,11 @@ static int eeprom_93xx46_remove(struct spi_device *spi)
 {
 	struct eeprom_93xx46_dev *edev = spi_get_drvdata(spi);
 
+	nvmem_unregister(edev->nvmem);
+
 	if (!(edev->pdata->flags & EE_READONLY))
 		device_remove_file(&spi->dev, &dev_attr_erase);
 
-	sysfs_remove_bin_file(&spi->dev.kobj, &edev->bin);
 	kfree(edev);
 	return 0;
 }
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCHv7 7/7] misc: at24: replace memory_accessor with nvmem_device_read
  2016-02-26 19:59 [PATCHv7 0/7] Convert exiting EEPROM drivers to NVMEM Andrew Lunn
                   ` (5 preceding siblings ...)
  2016-02-26 19:59 ` [PATCHv7 6/7] eeprom: 93xx46: " Andrew Lunn
@ 2016-02-26 19:59 ` Andrew Lunn
  2016-02-28 21:01   ` Wolfram Sang
  2016-03-02  0:56 ` [PATCHv7 0/7] Convert exiting EEPROM drivers to NVMEM Greg KH
  7 siblings, 1 reply; 19+ messages in thread
From: Andrew Lunn @ 2016-02-26 19:59 UTC (permalink / raw)
  To: GregKH
  Cc: srinivas.kandagatla, maxime.ripard, wsa, broonie, vz,
	linux-kernel, pantelis.antoniou, bgolaszewski, Andrew Lunn

Now that the AT24 uses the NVMEM framework, replace the
memory_accessor in the setup() callback with nvmem API calls.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Tested-by: Sekhar Nori <nsekhar@ti.com>
---
 arch/arm/mach-davinci/board-mityomapl138.c |  5 +++--
 arch/arm/mach-davinci/common.c             |  4 ++--
 drivers/misc/eeprom/at24.c                 | 31 +-----------------------------
 include/linux/davinci_emac.h               |  4 ++--
 include/linux/memory.h                     | 11 -----------
 include/linux/platform_data/at24.h         | 10 +++++-----
 6 files changed, 13 insertions(+), 52 deletions(-)

diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c
index de1316bf643a..62ebac51bab9 100644
--- a/arch/arm/mach-davinci/board-mityomapl138.c
+++ b/arch/arm/mach-davinci/board-mityomapl138.c
@@ -115,13 +115,14 @@ static void mityomapl138_cpufreq_init(const char *partnum)
 static void mityomapl138_cpufreq_init(const char *partnum) { }
 #endif
 
-static void read_factory_config(struct memory_accessor *a, void *context)
+static void read_factory_config(struct nvmem_device *nvmem, void *context)
 {
 	int ret;
 	const char *partnum = NULL;
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
 
-	ret = a->read(a, (char *)&factory_config, 0, sizeof(factory_config));
+	ret = nvmem_device_read(nvmem, 0, sizeof(factory_config),
+				&factory_config);
 	if (ret != sizeof(struct factory_config)) {
 		pr_warn("Read Factory Config Failed: %d\n", ret);
 		goto bad_config;
diff --git a/arch/arm/mach-davinci/common.c b/arch/arm/mach-davinci/common.c
index a794f6d9d444..f55ef2ef2f92 100644
--- a/arch/arm/mach-davinci/common.c
+++ b/arch/arm/mach-davinci/common.c
@@ -28,13 +28,13 @@ EXPORT_SYMBOL(davinci_soc_info);
 void __iomem *davinci_intc_base;
 int davinci_intc_type;
 
-void davinci_get_mac_addr(struct memory_accessor *mem_acc, void *context)
+void davinci_get_mac_addr(struct nvmem_device *nvmem, void *context)
 {
 	char *mac_addr = davinci_soc_info.emac_pdata->mac_addr;
 	off_t offset = (off_t)context;
 
 	/* Read MAC addr from EEPROM */
-	if (mem_acc->read(mem_acc, mac_addr, offset, ETH_ALEN) == ETH_ALEN)
+	if (nvmem_device_read(nvmem, offset, ETH_ALEN, mac_addr) == ETH_ALEN)
 		pr_info("Read MAC addr from EEPROM: %pM\n", mac_addr);
 }
 
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index f15cda93fc4c..089d6943f68a 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -56,7 +56,6 @@
 
 struct at24_data {
 	struct at24_platform_data chip;
-	struct memory_accessor macc;
 	int use_smbus;
 	int use_smbus_write;
 
@@ -410,30 +409,6 @@ static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off,
 /*-------------------------------------------------------------------------*/
 
 /*
- * This lets other kernel code access the eeprom data. For example, it
- * might hold a board's Ethernet address, or board-specific calibration
- * data generated on the manufacturing floor.
- */
-
-static ssize_t at24_macc_read(struct memory_accessor *macc, char *buf,
-			 off_t offset, size_t count)
-{
-	struct at24_data *at24 = container_of(macc, struct at24_data, macc);
-
-	return at24_read(at24, buf, offset, count);
-}
-
-static ssize_t at24_macc_write(struct memory_accessor *macc, const char *buf,
-			  off_t offset, size_t count)
-{
-	struct at24_data *at24 = container_of(macc, struct at24_data, macc);
-
-	return at24_write(at24, buf, offset, count);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
  * Provide a regmap interface, which is registered with the NVMEM
  * framework
 */
@@ -600,16 +575,12 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	at24->chip = chip;
 	at24->num_addresses = num_addresses;
 
-	at24->macc.read = at24_macc_read;
-
 	writable = !(chip.flags & AT24_FLAG_READONLY);
 	if (writable) {
 		if (!use_smbus || use_smbus_write) {
 
 			unsigned write_max = chip.page_size;
 
-			at24->macc.write = at24_macc_write;
-
 			if (write_max > io_limit)
 				write_max = io_limit;
 			if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX)
@@ -683,7 +654,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 	/* export data to kernel code */
 	if (chip.setup)
-		chip.setup(&at24->macc, chip.context);
+		chip.setup(at24->nvmem, chip.context);
 
 	return 0;
 
diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h
index 542888504994..05b97144d342 100644
--- a/include/linux/davinci_emac.h
+++ b/include/linux/davinci_emac.h
@@ -12,7 +12,7 @@
 #define _LINUX_DAVINCI_EMAC_H
 
 #include <linux/if_ether.h>
-#include <linux/memory.h>
+#include <linux/nvmem-consumer.h>
 
 struct mdio_platform_data {
 	unsigned long		bus_freq;
@@ -46,5 +46,5 @@ enum {
 	EMAC_VERSION_2,	/* DM646x */
 };
 
-void davinci_get_mac_addr(struct memory_accessor *mem_acc, void *context);
+void davinci_get_mac_addr(struct nvmem_device *nvmem, void *context);
 #endif
diff --git a/include/linux/memory.h b/include/linux/memory.h
index 8b8d8d12348e..b723a686fc10 100644
--- a/include/linux/memory.h
+++ b/include/linux/memory.h
@@ -137,17 +137,6 @@ extern struct memory_block *find_memory_block(struct mem_section *);
 #endif
 
 /*
- * 'struct memory_accessor' is a generic interface to provide
- * in-kernel access to persistent memory such as i2c or SPI EEPROMs
- */
-struct memory_accessor {
-	ssize_t (*read)(struct memory_accessor *, char *buf, off_t offset,
-			size_t count);
-	ssize_t (*write)(struct memory_accessor *, const char *buf,
-			 off_t offset, size_t count);
-};
-
-/*
  * Kernel text modification mutex, used for code patching. Users of this lock
  * can sleep.
  */
diff --git a/include/linux/platform_data/at24.h b/include/linux/platform_data/at24.h
index c42aa89d34ee..dc9a13e5acda 100644
--- a/include/linux/platform_data/at24.h
+++ b/include/linux/platform_data/at24.h
@@ -9,7 +9,7 @@
 #define _LINUX_AT24_H
 
 #include <linux/types.h>
-#include <linux/memory.h>
+#include <linux/nvmem-consumer.h>
 
 /**
  * struct at24_platform_data - data to set up at24 (generic eeprom) driver
@@ -17,7 +17,7 @@
  * @page_size: number of byte which can be written in one go
  * @flags: tunable options, check AT24_FLAG_* defines
  * @setup: an optional callback invoked after eeprom is probed; enables kernel
-	code to access eeprom via memory_accessor, see example
+	code to access eeprom via nvmem, see example
  * @context: optional parameter passed to setup()
  *
  * If you set up a custom eeprom type, please double-check the parameters.
@@ -26,13 +26,13 @@
  *
  * An example in pseudo code for a setup() callback:
  *
- * void get_mac_addr(struct memory_accessor *mem_acc, void *context)
+ * void get_mac_addr(struct mvmem_device *nvmem, void *context)
  * {
  *	u8 *mac_addr = ethernet_pdata->mac_addr;
  *	off_t offset = context;
  *
  *	// Read MAC addr from EEPROM
- *	if (mem_acc->read(mem_acc, mac_addr, offset, ETH_ALEN) == ETH_ALEN)
+ *	if (nvmem_device_read(nvmem, offset, ETH_ALEN, mac_addr) == ETH_ALEN)
  *		pr_info("Read MAC addr from EEPROM: %pM\n", mac_addr);
  * }
  *
@@ -48,7 +48,7 @@ struct at24_platform_data {
 #define AT24_FLAG_IRUGO		0x20	/* sysfs-entry will be world-readable */
 #define AT24_FLAG_TAKE8ADDR	0x10	/* take always 8 addresses (24c00) */
 
-	void		(*setup)(struct memory_accessor *, void *context);
+	void		(*setup)(struct nvmem_device *nvmem, void *context);
 	void		*context;
 };
 
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCHv7 7/7] misc: at24: replace memory_accessor with nvmem_device_read
  2016-02-26 19:59 ` [PATCHv7 7/7] misc: at24: replace memory_accessor with nvmem_device_read Andrew Lunn
@ 2016-02-28 21:01   ` Wolfram Sang
  0 siblings, 0 replies; 19+ messages in thread
From: Wolfram Sang @ 2016-02-28 21:01 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: GregKH, srinivas.kandagatla, maxime.ripard, broonie, vz,
	linux-kernel, pantelis.antoniou, bgolaszewski

[-- Attachment #1: Type: text/plain, Size: 1076 bytes --]

On Fri, Feb 26, 2016 at 08:59:24PM +0100, Andrew Lunn wrote:
> Now that the AT24 uses the NVMEM framework, replace the
> memory_accessor in the setup() callback with nvmem API calls.

Yay, thanks for doing this! :)

> 
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
> Acked-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
> Tested-by: Sekhar Nori <nsekhar@ti.com>
> ---
>  arch/arm/mach-davinci/board-mityomapl138.c |  5 +++--
>  arch/arm/mach-davinci/common.c             |  4 ++--
>  drivers/misc/eeprom/at24.c                 | 31 +-----------------------------
>  include/linux/davinci_emac.h               |  4 ++--
>  include/linux/memory.h                     | 11 -----------
>  include/linux/platform_data/at24.h         | 10 +++++-----
>  6 files changed, 13 insertions(+), 52 deletions(-)

It could be argued to split this patch up, but since I'd like to have
the memory_accessor thing removed rather sooner than later, I'd be fine
with this all-in-one approach. So, for the at24 parts:

Acked-by: Wolfram Sang <wsa@the-dreams.de>


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCHv7 4/7] eeprom: at25: Remove in kernel API for accessing the EEPROM
  2016-02-26 19:59 ` [PATCHv7 4/7] eeprom: at25: Remove in kernel API for accessing the EEPROM Andrew Lunn
@ 2016-02-28 21:02   ` Wolfram Sang
  0 siblings, 0 replies; 19+ messages in thread
From: Wolfram Sang @ 2016-02-28 21:02 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: GregKH, srinivas.kandagatla, maxime.ripard, broonie, vz,
	linux-kernel, pantelis.antoniou, bgolaszewski

[-- Attachment #1: Type: text/plain, Size: 375 bytes --]

On Fri, Feb 26, 2016 at 08:59:21PM +0100, Andrew Lunn wrote:
> The setup() callback is not used by any in kernel code. Remove it.
> Any new code which requires access to the eeprom can use the NVMEM
> API.
> 
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
> Acked-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>

Acked-by: Wolfram Sang <wsa@the-dreams.de>


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCHv7 0/7] Convert exiting EEPROM drivers to NVMEM
  2016-02-26 19:59 [PATCHv7 0/7] Convert exiting EEPROM drivers to NVMEM Andrew Lunn
                   ` (6 preceding siblings ...)
  2016-02-26 19:59 ` [PATCHv7 7/7] misc: at24: replace memory_accessor with nvmem_device_read Andrew Lunn
@ 2016-03-02  0:56 ` Greg KH
  2016-03-06 12:06   ` Wolfram Sang
  7 siblings, 1 reply; 19+ messages in thread
From: Greg KH @ 2016-03-02  0:56 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: srinivas.kandagatla, maxime.ripard, wsa, broonie, vz,
	linux-kernel, pantelis.antoniou, bgolaszewski

On Fri, Feb 26, 2016 at 08:59:17PM +0100, Andrew Lunn wrote:
> This patch set converts the old EEPROM drivers in driver/misc/eeprom to
> use the NVMEM framework. These drivers export there content in /sys as
> read only to root, since the EEPROM may contain sensitive information.
> So the first patch adds a flag so the NVMEM framework will create its
> file in /sys as root read only.
> 
> To keep backwards compatibility with these older drivers, the contents
> of the EEPROM must be exports in sysfs in a file called eeprom in the
> devices node in sys, where as the NVMEM places them under class/nvmem.
> So add this optional backwards compatible to the framework, again
> using a flag.
> 
> Then convert the at24, at25 and 93xx46 by adding regmap support,
> removing each drivers own /sys code and registering with the NVMEM
> framework.
> 
> Lastly, the old memory accessor mechanism has been replaced with the
> nvmem equivalent.

Nice job, all now queue up.

greg k-h

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCHv7 3/7] eeprom: at24: extend driver to plug into the NVMEM framework
  2016-02-26 19:59 ` [PATCHv7 3/7] eeprom: at24: extend driver to plug into the NVMEM framework Andrew Lunn
@ 2016-03-02 21:46   ` Vladimir Zapolskiy
  2016-03-02 21:48     ` Andrew Lunn
  0 siblings, 1 reply; 19+ messages in thread
From: Vladimir Zapolskiy @ 2016-03-02 21:46 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: GregKH, srinivas.kandagatla, maxime.ripard, wsa, broonie,
	linux-kernel, pantelis.antoniou, bgolaszewski

Hi Andrew,

On 26.02.2016 21:59, Andrew Lunn wrote:
> Add a regmap for accessing the EEPROM, and then use that with the
> NVMEM framework. Set the NVMEM config structure to enable backward, so
> that the 'eeprom' file in sys is provided by the framework.
> 
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
> Acked-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
> Tested-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> ---

[snip]

> +static int at24_regmap_read(void *context, const void *reg, size_t reg_size,
> +			    void *val, size_t val_size)
> +{
> +	struct at24_data *at24 = context;
> +	off_t offset = *(u32 *)reg;
> +	int err;
> +
> +	err = at24_read(at24, val, offset, val_size);
> +	if (err)
> +		return err;
> +	return 0;

return at24_read(at24, val, offset, val_size);

Minus 5 LoC.

> +}
> +
> +static int at24_regmap_write(void *context, const void *data, size_t count)
> +{
> +	struct at24_data *at24 = context;
> +	const char *buf;
> +	u32 offset;
> +	size_t len;
> +	int err;
> +
> +	memcpy(&offset, data, sizeof(offset));
> +	buf = (const char *)data + sizeof(offset);
> +	len = count - sizeof(offset);
> +
> +	err = at24_write(at24, buf, offset, len);
> +	if (err)
> +		return err;
> +	return 0;

return at24_write(at24, buf, offset, len);

Minus another 5 LoC.

--
With best wishes,
Vladimir

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCHv7 3/7] eeprom: at24: extend driver to plug into the NVMEM framework
  2016-03-02 21:46   ` Vladimir Zapolskiy
@ 2016-03-02 21:48     ` Andrew Lunn
  2016-03-02 23:03       ` Vladimir Zapolskiy
  0 siblings, 1 reply; 19+ messages in thread
From: Andrew Lunn @ 2016-03-02 21:48 UTC (permalink / raw)
  To: Vladimir Zapolskiy
  Cc: GregKH, srinivas.kandagatla, maxime.ripard, wsa, broonie,
	linux-kernel, pantelis.antoniou, bgolaszewski

On Wed, Mar 02, 2016 at 11:46:39PM +0200, Vladimir Zapolskiy wrote:
> Hi Andrew,
> 
> On 26.02.2016 21:59, Andrew Lunn wrote:
> > Add a regmap for accessing the EEPROM, and then use that with the
> > NVMEM framework. Set the NVMEM config structure to enable backward, so
> > that the 'eeprom' file in sys is provided by the framework.
> > 
> > Signed-off-by: Andrew Lunn <andrew@lunn.ch>
> > Acked-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
> > Tested-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> > ---
> 
> [snip]
> 
> > +static int at24_regmap_read(void *context, const void *reg, size_t reg_size,
> > +			    void *val, size_t val_size)
> > +{
> > +	struct at24_data *at24 = context;
> > +	off_t offset = *(u32 *)reg;
> > +	int err;
> > +
> > +	err = at24_read(at24, val, offset, val_size);
> > +	if (err)
> > +		return err;
> > +	return 0;
> 
> return at24_read(at24, val, offset, val_size);
> 
> Minus 5 LoC.

And everything breaks :-(

regmap expects either an error code, or 0. Return a positive value and
it is not happy.

   Andrew

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCHv7 5/7] eeprom: at25: extend driver to plug into the NVMEM framework
  2016-02-26 19:59 ` [PATCHv7 5/7] eeprom: at25: extend driver to plug into the NVMEM framework Andrew Lunn
@ 2016-03-02 21:56   ` Vladimir Zapolskiy
  0 siblings, 0 replies; 19+ messages in thread
From: Vladimir Zapolskiy @ 2016-03-02 21:56 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: GregKH, srinivas.kandagatla, maxime.ripard, wsa, broonie,
	linux-kernel, pantelis.antoniou, bgolaszewski

Hi Andrew,

On 26.02.2016 21:59, Andrew Lunn wrote:
> Add a regmap for accessing the EEPROM, and then use that with the
> NVMEM framework. Enable backwards compatibility in the NVMEM config,
> so that the 'eeprom' file in sys is provided by the framework.
> 
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
> Acked-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
> ---

[snip]

>  
> -static ssize_t
> -at25_bin_read(struct file *filp, struct kobject *kobj,
> -	      struct bin_attribute *bin_attr,
> -	      char *buf, loff_t off, size_t count)
> +static int at25_regmap_read(void *context, const void *reg, size_t reg_size,
> +			    void *val, size_t val_size)
>  {
> -	struct device		*dev;
> -	struct at25_data	*at25;
> -
> -	dev = kobj_to_dev(kobj);
> -	at25 = dev_get_drvdata(dev);
> +	struct at25_data *at25 = context;
> +	off_t offset = *(u32 *)reg;
> +	int err;
>  
> -	return at25_ee_read(at25, buf, off, count);
> +	err = at25_ee_read(at25, val, offset, val_size);
> +	if (err)
> +		return err;
> +	return 0;

return at25_ee_read(at25, val, offset, val_size);

>  }
>  

[snip]

>  
> -static ssize_t
> -at25_bin_write(struct file *filp, struct kobject *kobj,
> -	       struct bin_attribute *bin_attr,
> -	       char *buf, loff_t off, size_t count)
> +static int at25_regmap_write(void *context, const void *data, size_t count)
>  {
> -	struct device		*dev;
> -	struct at25_data	*at25;
> +	struct at25_data *at25 = context;
> +	const char *buf;
> +	u32 offset;
> +	size_t len;
> +	int err;
>  
> -	dev = kobj_to_dev(kobj);
> -	at25 = dev_get_drvdata(dev);
> +	memcpy(&offset, data, sizeof(offset));
> +	buf = (const char *)data + sizeof(offset);
> +	len = count - sizeof(offset);
>  
> -	return at25_ee_write(at25, buf, off, count);
> +	err = at25_ee_write(at25, buf, offset, len);
> +	if (err)
> +		return err;
> +	return 0;

return at25_ee_write(at25, buf, offset, len) is shorter.

>  }

--
With best wishes,
Vladimir

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCHv7 6/7] eeprom: 93xx46: extend driver to plug into the NVMEM framework
  2016-02-26 19:59 ` [PATCHv7 6/7] eeprom: 93xx46: " Andrew Lunn
@ 2016-03-02 22:08   ` Vladimir Zapolskiy
  2016-03-02 22:26     ` Andrew Lunn
  0 siblings, 1 reply; 19+ messages in thread
From: Vladimir Zapolskiy @ 2016-03-02 22:08 UTC (permalink / raw)
  To: Andrew Lunn, GregKH
  Cc: srinivas.kandagatla, maxime.ripard, wsa, broonie, linux-kernel,
	pantelis.antoniou, bgolaszewski

Hi Andrew,

On 26.02.2016 21:59, Andrew Lunn wrote:
> Add a regmap for accessing the EEPROM, and then use that with the
> NVMEM framework. Enable backward compatibility in the NVMEM config
> structure, so that the 'eeprom' file in sys is provided by the
> framework.
> 
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
> Acked-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
> ---

[snip]

>  
>  static ssize_t
> -eeprom_93xx46_bin_read(struct file *filp, struct kobject *kobj,
> -		       struct bin_attribute *bin_attr,
> -		       char *buf, loff_t off, size_t count)
> +eeprom_93xx46_read(struct eeprom_93xx46_dev *edev, char *buf,
> +		   unsigned off, size_t count)
>  {
> -	struct eeprom_93xx46_dev *edev;
> -	struct device *dev;
>  	ssize_t ret = 0;
>  
> -	dev = kobj_to_dev(kobj);
> -	edev = dev_get_drvdata(dev);
> +	if (unlikely(off >= edev->size))
> +		return 0;
> +	if ((off + count) > edev->size)
> +		count = edev->size - off;
> +	if (unlikely(!count))
> +		return count;
>  

I'm scratching my head, do you want to kind of revert
the change https://lkml.org/lkml/2015/7/26/89 ? Why?

If you know regmap_config.max_register, then all necessary
boundary checks can be done inside NVMEM core.

>  	mutex_lock(&edev->lock);
>  
> @@ -226,16 +231,17 @@ eeprom_93xx46_write_word(struct eeprom_93xx46_dev *edev,
>  }
>  
>  static ssize_t
> -eeprom_93xx46_bin_write(struct file *filp, struct kobject *kobj,
> -			struct bin_attribute *bin_attr,
> -			char *buf, loff_t off, size_t count)
> +eeprom_93xx46_write(struct eeprom_93xx46_dev *edev, const char *buf,
> +		    loff_t off, size_t count)
>  {
> -	struct eeprom_93xx46_dev *edev;
> -	struct device *dev;
>  	int i, ret, step = 1;
>  
> -	dev = kobj_to_dev(kobj);
> -	edev = dev_get_drvdata(dev);
> +	if (unlikely(off >= edev->size))
> +		return -EFBIG;
> +	if ((off + count) > edev->size)
> +		count = edev->size - off;
> +	if (unlikely(!count))
> +		return count;
>  

See a comment above.

>  	/* only write even number of bytes on 16-bit devices */
>  	if (edev->addrlen == 6) {
> @@ -272,6 +278,49 @@ eeprom_93xx46_bin_write(struct file *filp, struct kobject *kobj,
>  	return ret ? : count;
>  }
>  
> +/*
> + * Provide a regmap interface, which is registered with the NVMEM
> + * framework
> +*/
> +static int eeprom_93xx46_regmap_read(void *context, const void *reg,
> +				     size_t reg_size, void *val,
> +				     size_t val_size)
> +{
> +	struct eeprom_93xx46_dev *eeprom_93xx46 = context;
> +	off_t offset = *(u32 *)reg;
> +	int err;
> +
> +	err = eeprom_93xx46_read(eeprom_93xx46, val, offset, val_size);
> +	if (err)
> +		return err;
> +	return 0;

return eeprom_93xx46_read(eeprom_93xx46, val, offset, val_size);

> +}
> +
> +static int eeprom_93xx46_regmap_write(void *context, const void *data,
> +				      size_t count)
> +{
> +	struct eeprom_93xx46_dev *eeprom_93xx46 = context;
> +	const char *buf;
> +	u32 offset;
> +	size_t len;
> +	int err;
> +
> +	memcpy(&offset, data, sizeof(offset));
> +	buf = (const char *)data + sizeof(offset);
> +	len = count - sizeof(offset);
> +
> +	err = eeprom_93xx46_write(eeprom_93xx46, buf, offset, len);
> +	if (err)
> +		return err;
> +	return 0;

return eeprom_93xx46_write(eeprom_93xx46, buf, offset, len);

> +}
> +


--
With best wishes,
Vladimir

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCHv7 6/7] eeprom: 93xx46: extend driver to plug into the NVMEM framework
  2016-03-02 22:08   ` Vladimir Zapolskiy
@ 2016-03-02 22:26     ` Andrew Lunn
  2016-03-02 23:18       ` Vladimir Zapolskiy
  0 siblings, 1 reply; 19+ messages in thread
From: Andrew Lunn @ 2016-03-02 22:26 UTC (permalink / raw)
  To: Vladimir Zapolskiy
  Cc: GregKH, srinivas.kandagatla, maxime.ripard, wsa, broonie,
	linux-kernel, pantelis.antoniou, bgolaszewski

> >  static ssize_t
> > -eeprom_93xx46_bin_read(struct file *filp, struct kobject *kobj,
> > -		       struct bin_attribute *bin_attr,
> > -		       char *buf, loff_t off, size_t count)
> > +eeprom_93xx46_read(struct eeprom_93xx46_dev *edev, char *buf,
> > +		   unsigned off, size_t count)
> >  {
> > -	struct eeprom_93xx46_dev *edev;
> > -	struct device *dev;
> >  	ssize_t ret = 0;
> >  
> > -	dev = kobj_to_dev(kobj);
> > -	edev = dev_get_drvdata(dev);
> > +	if (unlikely(off >= edev->size))
> > +		return 0;
> > +	if ((off + count) > edev->size)
> > +		count = edev->size - off;
> > +	if (unlikely(!count))
> > +		return count;
> >  
> 
> I'm scratching my head, do you want to kind of revert
> the change https://lkml.org/lkml/2015/7/26/89 ? Why?

Hi Vladimir

I had not noticed you had removed this.
 
> If you know regmap_config.max_register, then all necessary
> boundary checks can be done inside NVMEM core.

You don't have to use NVMEM, you could use the regmap directly. It is
a public API. Also, during implementation, i did manage to get out of
bounds read passed into the drivers and they caused a crash. That
might of been AT24, i don't remember, but verifying is better than
possible crashing.

> > +/*
> > + * Provide a regmap interface, which is registered with the NVMEM
> > + * framework
> > +*/
> > +static int eeprom_93xx46_regmap_read(void *context, const void *reg,
> > +				     size_t reg_size, void *val,
> > +				     size_t val_size)
> > +{
> > +	struct eeprom_93xx46_dev *eeprom_93xx46 = context;
> > +	off_t offset = *(u32 *)reg;
> > +	int err;
> > +
> > +	err = eeprom_93xx46_read(eeprom_93xx46, val, offset, val_size);
> > +	if (err)
> > +		return err;
> > +	return 0;
> 
> return eeprom_93xx46_read(eeprom_93xx46, val, offset, val_size);

As i've said a few times now to a few different people reviewing these
patches, regmap wants either an error code or 0.

	 Andrew

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCHv7 3/7] eeprom: at24: extend driver to plug into the NVMEM framework
  2016-03-02 21:48     ` Andrew Lunn
@ 2016-03-02 23:03       ` Vladimir Zapolskiy
  0 siblings, 0 replies; 19+ messages in thread
From: Vladimir Zapolskiy @ 2016-03-02 23:03 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: GregKH, srinivas.kandagatla, maxime.ripard, wsa, broonie,
	linux-kernel, pantelis.antoniou, bgolaszewski

On 02.03.2016 23:48, Andrew Lunn wrote:
> On Wed, Mar 02, 2016 at 11:46:39PM +0200, Vladimir Zapolskiy wrote:
>> Hi Andrew,
>>
>> On 26.02.2016 21:59, Andrew Lunn wrote:
>>> Add a regmap for accessing the EEPROM, and then use that with the
>>> NVMEM framework. Set the NVMEM config structure to enable backward, so
>>> that the 'eeprom' file in sys is provided by the framework.
>>>
>>> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
>>> Acked-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
>>> Tested-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>>> ---
>>
>> [snip]
>>
>>> +static int at24_regmap_read(void *context, const void *reg, size_t reg_size,
>>> +			    void *val, size_t val_size)
>>> +{
>>> +	struct at24_data *at24 = context;
>>> +	off_t offset = *(u32 *)reg;
>>> +	int err;
>>> +
>>> +	err = at24_read(at24, val, offset, val_size);
>>> +	if (err)
>>> +		return err;
>>> +	return 0;
>>
>> return at24_read(at24, val, offset, val_size);
>>
>> Minus 5 LoC.
> 
> And everything breaks :-(
> 
> regmap expects either an error code, or 0. Return a positive value and
> it is not happy.
> 

Well, do you agree that semantically my proposed change is equal to the
original one?

Let see...

	static int at24_regmap_read() {

		int err;

		err = at24_read(at24, val, offset, val_size);
		if (err)
			return err;
		return 0;
	}

I don't see a check for (err <= 0) returned.

--
With best wishes,
Vladimir

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCHv7 6/7] eeprom: 93xx46: extend driver to plug into the NVMEM framework
  2016-03-02 22:26     ` Andrew Lunn
@ 2016-03-02 23:18       ` Vladimir Zapolskiy
  0 siblings, 0 replies; 19+ messages in thread
From: Vladimir Zapolskiy @ 2016-03-02 23:18 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: GregKH, srinivas.kandagatla, maxime.ripard, wsa, broonie,
	linux-kernel, pantelis.antoniou, bgolaszewski

On 03.03.2016 00:26, Andrew Lunn wrote:
>>>  static ssize_t
>>> -eeprom_93xx46_bin_read(struct file *filp, struct kobject *kobj,
>>> -		       struct bin_attribute *bin_attr,
>>> -		       char *buf, loff_t off, size_t count)
>>> +eeprom_93xx46_read(struct eeprom_93xx46_dev *edev, char *buf,
>>> +		   unsigned off, size_t count)
>>>  {
>>> -	struct eeprom_93xx46_dev *edev;
>>> -	struct device *dev;
>>>  	ssize_t ret = 0;
>>>  
>>> -	dev = kobj_to_dev(kobj);
>>> -	edev = dev_get_drvdata(dev);
>>> +	if (unlikely(off >= edev->size))
>>> +		return 0;
>>> +	if ((off + count) > edev->size)
>>> +		count = edev->size - off;
>>> +	if (unlikely(!count))
>>> +		return count;
>>>  
>>
>> I'm scratching my head, do you want to kind of revert
>> the change https://lkml.org/lkml/2015/7/26/89 ? Why?
> 
> Hi Vladimir
> 
> I had not noticed you had removed this.
>  
>> If you know regmap_config.max_register, then all necessary
>> boundary checks can be done inside NVMEM core.
> 
> You don't have to use NVMEM, you could use the regmap directly. 

No problem, regmap API from drivers/base/regmap/regmap.c contains
all necessary boundary checks as far as I understand.

> It is a public API. Also, during implementation, i did manage to get out of
> bounds read passed into the drivers and they caused a crash. That
> might of been AT24, i don't remember, but verifying is better than
> possible crashing.
> 

IMHO to avoid boilerplate code and/or missed/redundant checks it
might be better to handle this particular kind of problem only
in one common place, for example sysfs binary attribute files do
not need this anymore, probably I should scrutinize the situation
with this transition to NVMEM as well.

If you remember a reproduction scenario for that crash, please let
me know.

At least this changeset must be applied I guess, am I right?
In other words is the code without this changeset safe in connection
to boundary checks, and this is a new discovered issue?

--
With best wishes,
Vladimir

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCHv7 0/7] Convert exiting EEPROM drivers to NVMEM
  2016-03-02  0:56 ` [PATCHv7 0/7] Convert exiting EEPROM drivers to NVMEM Greg KH
@ 2016-03-06 12:06   ` Wolfram Sang
  0 siblings, 0 replies; 19+ messages in thread
From: Wolfram Sang @ 2016-03-06 12:06 UTC (permalink / raw)
  To: Greg KH
  Cc: Andrew Lunn, srinivas.kandagatla, maxime.ripard, broonie, vz,
	linux-kernel, pantelis.antoniou, bgolaszewski

[-- Attachment #1: Type: text/plain, Size: 1491 bytes --]

On Wed, Mar 02, 2016 at 12:56:42AM +0000, Greg KH wrote:
> On Fri, Feb 26, 2016 at 08:59:17PM +0100, Andrew Lunn wrote:
> > This patch set converts the old EEPROM drivers in driver/misc/eeprom to
> > use the NVMEM framework. These drivers export there content in /sys as
> > read only to root, since the EEPROM may contain sensitive information.
> > So the first patch adds a flag so the NVMEM framework will create its
> > file in /sys as root read only.
> > 
> > To keep backwards compatibility with these older drivers, the contents
> > of the EEPROM must be exports in sysfs in a file called eeprom in the
> > devices node in sys, where as the NVMEM places them under class/nvmem.
> > So add this optional backwards compatible to the framework, again
> > using a flag.
> > 
> > Then convert the at24, at25 and 93xx46 by adding regmap support,
> > removing each drivers own /sys code and registering with the NVMEM
> > framework.
> > 
> > Lastly, the old memory accessor mechanism has been replaced with the
> > nvmem equivalent.
> 
> Nice job, all now queue up.

Yes, really. Pity I didn't have the time to review the at24-to-nvmem
changes as much as I hoped for. But it will be good in the end.

I am really thankful that you made the effort to convert this hardly
used memory_accessor thing and convert it into the more widely used
nvmem mechanism. And clean up the unneeded bits afterwards. Always nice
to see such attitude :)

Thanks,

   Wolfram


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2016-03-06 12:06 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-26 19:59 [PATCHv7 0/7] Convert exiting EEPROM drivers to NVMEM Andrew Lunn
2016-02-26 19:59 ` [PATCHv7 1/7] nvmem: Add flag to export NVMEM to root only Andrew Lunn
2016-02-26 19:59 ` [PATCHv7 2/7] nvmem: Add backwards compatibility support for older EEPROM drivers Andrew Lunn
2016-02-26 19:59 ` [PATCHv7 3/7] eeprom: at24: extend driver to plug into the NVMEM framework Andrew Lunn
2016-03-02 21:46   ` Vladimir Zapolskiy
2016-03-02 21:48     ` Andrew Lunn
2016-03-02 23:03       ` Vladimir Zapolskiy
2016-02-26 19:59 ` [PATCHv7 4/7] eeprom: at25: Remove in kernel API for accessing the EEPROM Andrew Lunn
2016-02-28 21:02   ` Wolfram Sang
2016-02-26 19:59 ` [PATCHv7 5/7] eeprom: at25: extend driver to plug into the NVMEM framework Andrew Lunn
2016-03-02 21:56   ` Vladimir Zapolskiy
2016-02-26 19:59 ` [PATCHv7 6/7] eeprom: 93xx46: " Andrew Lunn
2016-03-02 22:08   ` Vladimir Zapolskiy
2016-03-02 22:26     ` Andrew Lunn
2016-03-02 23:18       ` Vladimir Zapolskiy
2016-02-26 19:59 ` [PATCHv7 7/7] misc: at24: replace memory_accessor with nvmem_device_read Andrew Lunn
2016-02-28 21:01   ` Wolfram Sang
2016-03-02  0:56 ` [PATCHv7 0/7] Convert exiting EEPROM drivers to NVMEM Greg KH
2016-03-06 12:06   ` Wolfram Sang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).