[RFC PATCH v2 02/13] hwspinlock: add callback to fill private data of a hwspinlock
Wolfram Sang
wsa+renesas at sang-engineering.com
Sun Feb 15 14:54:42 PST 2026
To hide internal core structures from providers, a callback is added to
the ops which allows to set the 'priv' field of a hwspinlock. It is
called when a hwspinlock device is registered and, thus, iterated over
all locks. The register-functions are also extended to pass a data
pointer to this callback, so it can do necessary calculations for the
priv field of each hwspinlock. Providers are converted separately
because these changes need dedicated reviews.
Signed-off-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
---
drivers/hwspinlock/hwspinlock_core.c | 19 +++++++++++++++----
drivers/hwspinlock/hwspinlock_internal.h | 19 +++++++++++--------
include/linux/hwspinlock.h | 4 ++--
3 files changed, 28 insertions(+), 14 deletions(-)
diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c
index 2c9eceba7fe8..afe1e7ce2829 100644
--- a/drivers/hwspinlock/hwspinlock_core.c
+++ b/drivers/hwspinlock/hwspinlock_core.c
@@ -507,6 +507,7 @@ static struct hwspinlock *hwspin_lock_unregister_single(unsigned int id)
* @ops: hwspinlock handlers for this device
* @base_id: id of the first hardware spinlock in this bank
* @num_locks: number of hwspinlocks provided by this device
+ * @init_data: additional data passed on to the init_priv callback
*
* This function should be called from the underlying platform-specific
* implementation, to register a new hwspinlock device instance.
@@ -516,10 +517,11 @@ static struct hwspinlock *hwspin_lock_unregister_single(unsigned int id)
* Returns: %0 on success, or an appropriate error code on failure
*/
int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
- const struct hwspinlock_ops *ops, int base_id, int num_locks)
+ const struct hwspinlock_ops *ops, int base_id, int num_locks,
+ void *init_data)
{
struct hwspinlock *hwlock;
- int ret = 0, i;
+ int ret, i;
if (!bank || !ops || !dev || !num_locks || !ops->trylock ||
!ops->unlock) {
@@ -538,6 +540,14 @@ int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
spin_lock_init(&hwlock->lock);
hwlock->bank = bank;
+ if (ops->init_priv) {
+ hwlock->priv = ops->init_priv(i, init_data);
+ if (IS_ERR(hwlock->priv)) {
+ ret = PTR_ERR(hwlock->priv);
+ goto reg_failed;
+ }
+ }
+
ret = hwspin_lock_register_single(hwlock, base_id + i);
if (ret)
goto reg_failed;
@@ -633,6 +643,7 @@ EXPORT_SYMBOL_GPL(devm_hwspin_lock_unregister);
* @ops: hwspinlock handlers for this device
* @base_id: id of the first hardware spinlock in this bank
* @num_locks: number of hwspinlocks provided by this device
+ * @init_data: additional data passed on to the init_priv callback
*
* This function should be called from the underlying platform-specific
* implementation, to register a new hwspinlock device instance.
@@ -644,7 +655,7 @@ EXPORT_SYMBOL_GPL(devm_hwspin_lock_unregister);
int devm_hwspin_lock_register(struct device *dev,
struct hwspinlock_device *bank,
const struct hwspinlock_ops *ops,
- int base_id, int num_locks)
+ int base_id, int num_locks, void *init_data)
{
struct hwspinlock_device **ptr;
int ret;
@@ -653,7 +664,7 @@ int devm_hwspin_lock_register(struct device *dev,
if (!ptr)
return -ENOMEM;
- ret = hwspin_lock_register(bank, dev, ops, base_id, num_locks);
+ ret = hwspin_lock_register(bank, dev, ops, base_id, num_locks, init_data);
if (!ret) {
*ptr = bank;
devres_add(dev, ptr);
diff --git a/drivers/hwspinlock/hwspinlock_internal.h b/drivers/hwspinlock/hwspinlock_internal.h
index f298fc0ee5ad..3c835d96bf86 100644
--- a/drivers/hwspinlock/hwspinlock_internal.h
+++ b/drivers/hwspinlock/hwspinlock_internal.h
@@ -18,20 +18,23 @@ struct hwspinlock_device;
/**
* struct hwspinlock_ops - platform-specific hwspinlock handlers
*
- * @trylock: make a single attempt to take the lock. returns 0 on
- * failure and true on success. may _not_ sleep.
- * @unlock: release the lock. always succeed. may _not_ sleep.
- * @bust: optional, platform-specific bust handler, called by hwspinlock
- * core to bust a specific lock.
- * @relax: optional, platform-specific relax handler, called by hwspinlock
- * core while spinning on a lock, between two successive
- * invocations of @trylock. may _not_ sleep.
+ * @trylock: make a single attempt to take the lock. returns 0 on
+ * failure and true on success. may _not_ sleep.
+ * @unlock: release the lock. always succeed. may _not_ sleep.
+ * @bust: optional, platform-specific bust handler, called by hwspinlock
+ * core to bust a specific lock.
+ * @relax: optional, platform-specific relax handler, called by hwspinlock
+ * core while spinning on a lock, between two successive
+ * invocations of @trylock. may _not_ sleep.
+ * @init_priv: optional, callback used when registering the hwspinlock device.
+ * Its return value will be used to fill the per-lock 'priv' data.
*/
struct hwspinlock_ops {
int (*trylock)(struct hwspinlock *lock);
void (*unlock)(struct hwspinlock *lock);
int (*bust)(struct hwspinlock *lock, unsigned int id);
void (*relax)(struct hwspinlock *lock);
+ void *(*init_priv)(int local_id, void *init_data);
};
/**
diff --git a/include/linux/hwspinlock.h b/include/linux/hwspinlock.h
index dffa1dff7289..094a6d0d39d6 100644
--- a/include/linux/hwspinlock.h
+++ b/include/linux/hwspinlock.h
@@ -30,7 +30,7 @@ struct hwspinlock_ops;
void *hwspin_lock_get_priv(struct hwspinlock *hwlock);
struct device *hwspin_lock_get_dev(struct hwspinlock *hwlock);
int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
- const struct hwspinlock_ops *ops, int base_id, int num_locks);
+ const struct hwspinlock_ops *ops, int base_id, int num_locks, void *init_data);
int hwspin_lock_unregister(struct hwspinlock_device *bank);
struct hwspinlock *hwspin_lock_request_specific(unsigned int id);
int hwspin_lock_free(struct hwspinlock *hwlock);
@@ -49,7 +49,7 @@ int devm_hwspin_lock_unregister(struct device *dev,
int devm_hwspin_lock_register(struct device *dev,
struct hwspinlock_device *bank,
const struct hwspinlock_ops *ops,
- int base_id, int num_locks);
+ int base_id, int num_locks, void *init_data);
#else /* !CONFIG_HWSPINLOCK */
--
2.51.0
More information about the linux-arm-kernel
mailing list