Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6b7a4237 authored by Bartosz Golaszewski's avatar Bartosz Golaszewski Committed by Gerrit - the friendly Code Review server
Browse files

nvmem: use kref



Use kref for reference counting. Use an approach similar to the one
seen in the common clock subsystem: don't actually destroy the nvmem
device until the last user puts it. This way we can get rid of the
users check from nvmem_unregister().

Change-Id: I3b8d40ed78304942e43091bd6916a058c1e3dbc4
Signed-off-by: default avatarBartosz Golaszewski <bgolaszewski@baylibre.com>
Signed-off-by: default avatarSrinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Git-commit: c1de7f43bd84271e438a4f2dadc4ba9a353baaea
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git


Signed-off-by: default avatarGaurav Kohli <gkohli@codeaurora.org>
parent 577b57fe
Loading
Loading
Loading
Loading
+22 −22
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/fs.h>
#include <linux/idr.h>
#include <linux/init.h>
#include <linux/kref.h>
#include <linux/module.h>
#include <linux/nvmem-consumer.h>
#include <linux/nvmem-provider.h>
@@ -32,7 +33,7 @@ struct nvmem_device {
	int			stride;
	int			word_size;
	int			id;
	int			users;
	struct kref		refcnt;
	size_t			size;
	bool			read_only;
	int			flags;
@@ -464,6 +465,8 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
		return ERR_PTR(rval);
	}

	kref_init(&nvmem->refcnt);

	nvmem->id = rval;
	nvmem->owner = config->owner;
	if (!nvmem->owner && config->dev->driver)
@@ -533,6 +536,20 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
}
EXPORT_SYMBOL_GPL(nvmem_register);

static void nvmem_device_release(struct kref *kref)
{
	struct nvmem_device *nvmem;

	nvmem = container_of(kref, struct nvmem_device, refcnt);

	if (nvmem->flags & FLAG_COMPAT)
		device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);

	nvmem_device_remove_all_cells(nvmem);
	device_del(&nvmem->dev);
	put_device(&nvmem->dev);
}

/**
 * nvmem_unregister() - Unregister previously registered nvmem device
 *
@@ -542,19 +559,7 @@ EXPORT_SYMBOL_GPL(nvmem_register);
 */
int nvmem_unregister(struct nvmem_device *nvmem)
{
	mutex_lock(&nvmem_mutex);
	if (nvmem->users) {
		mutex_unlock(&nvmem_mutex);
		return -EBUSY;
	}
	mutex_unlock(&nvmem_mutex);

	if (nvmem->flags & FLAG_COMPAT)
		device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);

	nvmem_device_remove_all_cells(nvmem);
	device_del(&nvmem->dev);
	put_device(&nvmem->dev);
	kref_put(&nvmem->refcnt, nvmem_device_release);

	return 0;
}
@@ -649,7 +654,6 @@ static struct nvmem_device *__nvmem_device_get(struct device_node *np,
		}
	}

	nvmem->users++;
	mutex_unlock(&nvmem_mutex);

	if (!try_module_get(nvmem->owner)) {
@@ -657,22 +661,18 @@ static struct nvmem_device *__nvmem_device_get(struct device_node *np,
			"could not increase module refcount for cell %s\n",
			nvmem->name);

		mutex_lock(&nvmem_mutex);
		nvmem->users--;
		mutex_unlock(&nvmem_mutex);

		return ERR_PTR(-EINVAL);
	}

	kref_get(&nvmem->refcnt);

	return nvmem;
}

static void __nvmem_device_put(struct nvmem_device *nvmem)
{
	module_put(nvmem->owner);
	mutex_lock(&nvmem_mutex);
	nvmem->users--;
	mutex_unlock(&nvmem_mutex);
	kref_put(&nvmem->refcnt, nvmem_device_release);
}

static struct nvmem_device *nvmem_find(const char *name)