Commit b96fc541 authored by Michael Auchter's avatar Michael Auchter Committed by Greg Kroah-Hartman
Browse files

nvmem: ensure sysfs writes handle write-protect pin



Commit 2a127da4 ("nvmem: add support for the write-protect pin")
added support for handling write-protect pins to the nvmem core, and
Commit 1c89074b ("eeprom: at24: remove the write-protect pin support")
retrofitted the at24 driver to use this support.

These changes broke write() on the nvmem sysfs attribute for eeproms
which utilize a write-protect pin, as the write callback invokes the
nvmem device's reg_write callback directly which no longer handles
changing the state of the write-protect pin.

Change the read and write callbacks for the sysfs attribute to invoke
nvmme_reg_read/nvmem_reg_write helpers which handle this, rather than
calling reg_read/reg_write directly.

Fixes: 2a127da4 ("nvmem: add support for the write-protect pin")
Signed-off-by: default avatarMichael Auchter <michael.auchter@ni.com>
Signed-off-by: default avatarSrinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20200511145042.31223-3-srinivas.kandagatla@linaro.org


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0e2abffd
Loading
Loading
Loading
Loading
+26 −26
Original line number Diff line number Diff line
@@ -66,6 +66,30 @@ static LIST_HEAD(nvmem_lookup_list);

static BLOCKING_NOTIFIER_HEAD(nvmem_notifier);

static int nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset,
			  void *val, size_t bytes)
{
	if (nvmem->reg_read)
		return nvmem->reg_read(nvmem->priv, offset, val, bytes);

	return -EINVAL;
}

static int nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset,
			   void *val, size_t bytes)
{
	int ret;

	if (nvmem->reg_write) {
		gpiod_set_value_cansleep(nvmem->wp_gpio, 0);
		ret = nvmem->reg_write(nvmem->priv, offset, val, bytes);
		gpiod_set_value_cansleep(nvmem->wp_gpio, 1);
		return ret;
	}

	return -EINVAL;
}

#ifdef CONFIG_NVMEM_SYSFS
static const char * const nvmem_type_str[] = {
	[NVMEM_TYPE_UNKNOWN] = "Unknown",
@@ -122,7 +146,7 @@ static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
	if (!nvmem->reg_read)
		return -EPERM;

	rc = nvmem->reg_read(nvmem->priv, pos, buf, count);
	rc = nvmem_reg_read(nvmem, pos, buf, count);

	if (rc)
		return rc;
@@ -159,7 +183,7 @@ static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
	if (!nvmem->reg_write)
		return -EPERM;

	rc = nvmem->reg_write(nvmem->priv, pos, buf, count);
	rc = nvmem_reg_write(nvmem, pos, buf, count);

	if (rc)
		return rc;
@@ -287,30 +311,6 @@ static void nvmem_sysfs_remove_compat(struct nvmem_device *nvmem,

#endif /* CONFIG_NVMEM_SYSFS */

static int nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset,
			  void *val, size_t bytes)
{
	if (nvmem->reg_read)
		return nvmem->reg_read(nvmem->priv, offset, val, bytes);

	return -EINVAL;
}

static int nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset,
			   void *val, size_t bytes)
{
	int ret;

	if (nvmem->reg_write) {
		gpiod_set_value_cansleep(nvmem->wp_gpio, 0);
		ret = nvmem->reg_write(nvmem->priv, offset, val, bytes);
		gpiod_set_value_cansleep(nvmem->wp_gpio, 1);
		return ret;
	}

	return -EINVAL;
}

static void nvmem_release(struct device *dev)
{
	struct nvmem_device *nvmem = to_nvmem_device(dev);