From: Richard Maina <quic_rmaina@xxxxxxxxxxx> Currently each device receives a dedicated hwspinlock that is not accesible to other device drivers. In order to allow multiple consumers access to the same hwspinlock, introduce a refcount to hwspinlock struct and implement refcounting infrastructure. Signed-off-by: Richard Maina <quic_rmaina@xxxxxxxxxxx> Signed-off-by: Chris Lew <quic_clew@xxxxxxxxxxx> --- drivers/hwspinlock/hwspinlock_core.c | 14 +++++++++----- drivers/hwspinlock/hwspinlock_internal.h | 2 ++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c index 0c0a932c00f3..29b33072ff57 100644 --- a/drivers/hwspinlock/hwspinlock_core.c +++ b/drivers/hwspinlock/hwspinlock_core.c @@ -428,6 +428,7 @@ static int hwspin_lock_register_single(struct hwspinlock *hwlock, int id) int ret; mutex_lock(&hwspinlock_tree_lock); + hwlock->refcnt = 0; ret = radix_tree_insert(&hwspinlock_tree, id, hwlock); if (ret) { @@ -671,6 +672,8 @@ static int __hwspin_lock_request(struct hwspinlock *hwlock) ret = 0; + hwlock->refcnt++; + /* mark hwspinlock as used, should not fail */ tmp = radix_tree_tag_clear(&hwspinlock_tree, hwlock_to_id(hwlock), HWSPINLOCK_UNUSED); @@ -829,12 +832,13 @@ int hwspin_lock_free(struct hwspinlock *hwlock) /* notify the underlying device that power is not needed */ pm_runtime_put(dev); - /* mark this hwspinlock as available */ - tmp = radix_tree_tag_set(&hwspinlock_tree, hwlock_to_id(hwlock), - HWSPINLOCK_UNUSED); + if (--hwlock->refcnt == 0) { + /* mark this hwspinlock as available */ + tmp = radix_tree_tag_set(&hwspinlock_tree, hwlock_to_id(hwlock), HWSPINLOCK_UNUSED); - /* sanity check (this shouldn't happen) */ - WARN_ON(tmp != hwlock); + /* sanity check (this shouldn't happen) */ + WARN_ON(tmp != hwlock); + } module_put(dev->driver->owner); diff --git a/drivers/hwspinlock/hwspinlock_internal.h b/drivers/hwspinlock/hwspinlock_internal.h index 29892767bb7a..12f230b40693 100644 --- a/drivers/hwspinlock/hwspinlock_internal.h +++ b/drivers/hwspinlock/hwspinlock_internal.h @@ -35,11 +35,13 @@ struct hwspinlock_ops { * struct hwspinlock - this struct represents a single hwspinlock instance * @bank: the hwspinlock_device structure which owns this lock * @lock: initialized and used by hwspinlock core + * @refcnt: counter for the number of existing references to the hwspinlock * @priv: private data, owned by the underlying platform-specific hwspinlock drv */ struct hwspinlock { struct hwspinlock_device *bank; spinlock_t lock; + unsigned int refcnt; void *priv; }; -- 2.25.1