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 <[email protected]> --- 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
