Skip to content

Commit c1de7f4

Browse files
brglgregkh
authored andcommitted
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(). Signed-off-by: Bartosz Golaszewski <[email protected]> Signed-off-by: Srinivas Kandagatla <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent fa72d84 commit c1de7f4

File tree

1 file changed

+22
-22
lines changed

1 file changed

+22
-22
lines changed

drivers/nvmem/core.c

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/fs.h>
2020
#include <linux/idr.h>
2121
#include <linux/init.h>
22+
#include <linux/kref.h>
2223
#include <linux/module.h>
2324
#include <linux/nvmem-consumer.h>
2425
#include <linux/nvmem-provider.h>
@@ -31,7 +32,7 @@ struct nvmem_device {
3132
int stride;
3233
int word_size;
3334
int id;
34-
int users;
35+
struct kref refcnt;
3536
size_t size;
3637
bool read_only;
3738
int flags;
@@ -463,6 +464,8 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
463464
return ERR_PTR(rval);
464465
}
465466

467+
kref_init(&nvmem->refcnt);
468+
466469
nvmem->id = rval;
467470
nvmem->owner = config->owner;
468471
if (!nvmem->owner && config->dev->driver)
@@ -532,6 +535,20 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
532535
}
533536
EXPORT_SYMBOL_GPL(nvmem_register);
534537

538+
static void nvmem_device_release(struct kref *kref)
539+
{
540+
struct nvmem_device *nvmem;
541+
542+
nvmem = container_of(kref, struct nvmem_device, refcnt);
543+
544+
if (nvmem->flags & FLAG_COMPAT)
545+
device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
546+
547+
nvmem_device_remove_all_cells(nvmem);
548+
device_del(&nvmem->dev);
549+
put_device(&nvmem->dev);
550+
}
551+
535552
/**
536553
* nvmem_unregister() - Unregister previously registered nvmem device
537554
*
@@ -541,19 +558,7 @@ EXPORT_SYMBOL_GPL(nvmem_register);
541558
*/
542559
int nvmem_unregister(struct nvmem_device *nvmem)
543560
{
544-
mutex_lock(&nvmem_mutex);
545-
if (nvmem->users) {
546-
mutex_unlock(&nvmem_mutex);
547-
return -EBUSY;
548-
}
549-
mutex_unlock(&nvmem_mutex);
550-
551-
if (nvmem->flags & FLAG_COMPAT)
552-
device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
553-
554-
nvmem_device_remove_all_cells(nvmem);
555-
device_del(&nvmem->dev);
556-
put_device(&nvmem->dev);
561+
kref_put(&nvmem->refcnt, nvmem_device_release);
557562

558563
return 0;
559564
}
@@ -647,30 +652,25 @@ static struct nvmem_device *__nvmem_device_get(struct device_node *np,
647652
}
648653
}
649654

650-
nvmem->users++;
651655
mutex_unlock(&nvmem_mutex);
652656

653657
if (!try_module_get(nvmem->owner)) {
654658
dev_err(&nvmem->dev,
655659
"could not increase module refcount for cell %s\n",
656660
nvmem_dev_name(nvmem));
657661

658-
mutex_lock(&nvmem_mutex);
659-
nvmem->users--;
660-
mutex_unlock(&nvmem_mutex);
661-
662662
return ERR_PTR(-EINVAL);
663663
}
664664

665+
kref_get(&nvmem->refcnt);
666+
665667
return nvmem;
666668
}
667669

668670
static void __nvmem_device_put(struct nvmem_device *nvmem)
669671
{
670672
module_put(nvmem->owner);
671-
mutex_lock(&nvmem_mutex);
672-
nvmem->users--;
673-
mutex_unlock(&nvmem_mutex);
673+
kref_put(&nvmem->refcnt, nvmem_device_release);
674674
}
675675

676676
static struct nvmem_device *nvmem_find(const char *name)

0 commit comments

Comments
 (0)