@@ -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);
@@ -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);
};
/**
@@ -120,7 +120,7 @@ static int omap_hwspinlock_probe(struct platform_device *pdev)
bank->lock[i].priv = io_base + LOCK_BASE_OFFSET + sizeof(u32) * i;
return devm_hwspin_lock_register(&pdev->dev, bank, &omap_hwspinlock_ops,
- base_id, num_locks);
+ base_id, num_locks, NULL);
}
static const struct of_device_id omap_hwspinlock_of_match[] = {
@@ -236,7 +236,7 @@ static int qcom_hwspinlock_probe(struct platform_device *pdev)
}
return devm_hwspin_lock_register(&pdev->dev, bank, &qcom_hwspinlock_ops,
- 0, QCOM_MUTEX_NUM_LOCKS);
+ 0, QCOM_MUTEX_NUM_LOCKS, NULL);
}
static struct platform_driver qcom_hwspinlock_driver = {
@@ -132,7 +132,7 @@ static int sprd_hwspinlock_probe(struct platform_device *pdev)
return devm_hwspin_lock_register(&pdev->dev, &sprd_hwlock->bank,
&sprd_hwspinlock_ops, 0,
- SPRD_HWLOCKS_NUM);
+ SPRD_HWLOCKS_NUM, NULL);
}
static const struct of_device_id sprd_hwspinlock_of_match[] = {
@@ -110,7 +110,7 @@ static int stm32_hwspinlock_probe(struct platform_device *pdev)
hw->bank.lock[i].priv = io_base + i * sizeof(u32);
ret = devm_hwspin_lock_register(dev, &hw->bank, &stm32_hwspinlock_ops,
- 0, STM32_MUTEX_NUM_LOCKS);
+ 0, STM32_MUTEX_NUM_LOCKS, NULL);
if (ret)
dev_err(dev, "Failed to register hwspinlock\n");
@@ -180,7 +180,7 @@ static int sun6i_hwspinlock_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, priv);
return devm_hwspin_lock_register(&pdev->dev, priv->bank, &sun6i_hwspinlock_ops,
- SPINLOCK_BASE_ID, priv->nlocks);
+ SPINLOCK_BASE_ID, priv->nlocks, NULL);
bank_fail:
clk_disable_unprepare(priv->ahb_clk);
@@ -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 */