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


Reply via email to