diff options
Diffstat (limited to 'drivers/hwspinlock/hwspinlock_core.c')
| -rw-r--r-- | drivers/hwspinlock/hwspinlock_core.c | 172 |
1 files changed, 55 insertions, 117 deletions
diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c index fd5f5c5a5244..cc8e952a6772 100644 --- a/drivers/hwspinlock/hwspinlock_core.c +++ b/drivers/hwspinlock/hwspinlock_core.c @@ -84,8 +84,9 @@ static DEFINE_MUTEX(hwspinlock_tree_lock); * should decide between spin_trylock, spin_trylock_irq and * spin_trylock_irqsave. * - * Returns 0 if we successfully locked the hwspinlock or -EBUSY if + * Returns: %0 if we successfully locked the hwspinlock or -EBUSY if * the hwspinlock was already taken. + * * This function will never sleep. */ int __hwspin_trylock(struct hwspinlock *hwlock, int mode, unsigned long *flags) @@ -171,7 +172,7 @@ EXPORT_SYMBOL_GPL(__hwspin_trylock); /** * __hwspin_lock_timeout() - lock an hwspinlock with timeout limit * @hwlock: the hwspinlock to be locked - * @timeout: timeout value in msecs + * @to: timeout value in msecs * @mode: mode which controls whether local interrupts are disabled or not * @flags: a pointer to where the caller's interrupt state will be saved at (if * requested) @@ -199,9 +200,11 @@ EXPORT_SYMBOL_GPL(__hwspin_trylock); * to choose the appropriate @mode of operation, exactly the same way users * should decide between spin_lock, spin_lock_irq and spin_lock_irqsave. * - * Returns 0 when the @hwlock was successfully taken, and an appropriate + * Returns: %0 when the @hwlock was successfully taken, and an appropriate * error code otherwise (most notably -ETIMEDOUT if the @hwlock is still - * busy after @timeout msecs). The function will never sleep. + * busy after @timeout msecs). + * + * The function will never sleep. */ int __hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int to, int mode, unsigned long *flags) @@ -303,14 +306,41 @@ void __hwspin_unlock(struct hwspinlock *hwlock, int mode, unsigned long *flags) EXPORT_SYMBOL_GPL(__hwspin_unlock); /** + * hwspin_lock_bust() - bust a specific hwspinlock + * @hwlock: a previously-acquired hwspinlock which we want to bust + * @id: identifier of the remote lock holder, if applicable + * + * This function will bust a hwspinlock that was previously acquired as + * long as the current owner of the lock matches the id given by the caller. + * + * Context: Process context. + * + * Returns: 0 on success, or -EINVAL if the hwspinlock does not exist, or + * the bust operation fails, and -EOPNOTSUPP if the bust operation is not + * defined for the hwspinlock. + */ +int hwspin_lock_bust(struct hwspinlock *hwlock, unsigned int id) +{ + if (WARN_ON(!hwlock)) + return -EINVAL; + + if (!hwlock->bank->ops->bust) { + pr_err("bust operation not defined\n"); + return -EOPNOTSUPP; + } + + return hwlock->bank->ops->bust(hwlock, id); +} +EXPORT_SYMBOL_GPL(hwspin_lock_bust); + +/** * of_hwspin_lock_simple_xlate - translate hwlock_spec to return a lock id - * @bank: the hwspinlock device bank * @hwlock_spec: hwlock specifier as found in the device tree * * This is a simple translation function, suitable for hwspinlock platform * drivers that only has a lock specifier length of 1. * - * Returns a relative index of the lock within a specified bank on success, + * Returns: a relative index of the lock within a specified bank on success, * or -EINVAL on invalid specifier cell count. */ static inline int @@ -332,9 +362,10 @@ of_hwspin_lock_simple_xlate(const struct of_phandle_args *hwlock_spec) * hwspinlock device, so that it can be requested using the normal * hwspin_lock_request_specific() API. * - * Returns the global lock id number on success, -EPROBE_DEFER if the hwspinlock - * device is not yet registered, -EINVAL on invalid args specifier value or an - * appropriate error as returned from the OF parsing of the DT client node. + * Returns: the global lock id number on success, -EPROBE_DEFER if the + * hwspinlock device is not yet registered, -EINVAL on invalid args + * specifier value or an appropriate error as returned from the OF parsing + * of the DT client node. */ int of_hwspin_lock_get_id(struct device_node *np, int index) { @@ -367,7 +398,7 @@ int of_hwspin_lock_get_id(struct device_node *np, int index) continue; } - if (hwlock->bank->dev->of_node == args.np) { + if (device_match_of_node(hwlock->bank->dev, args.np)) { ret = 0; break; } @@ -399,9 +430,10 @@ EXPORT_SYMBOL_GPL(of_hwspin_lock_get_id); * the hwspinlock device, so that it can be requested using the normal * hwspin_lock_request_specific() API. * - * Returns the global lock id number on success, -EPROBE_DEFER if the hwspinlock - * device is not yet registered, -EINVAL on invalid args specifier value or an - * appropriate error as returned from the OF parsing of the DT client node. + * Returns: the global lock id number on success, -EPROBE_DEFER if the + * hwspinlock device is not yet registered, -EINVAL on invalid args + * specifier value or an appropriate error as returned from the OF parsing + * of the DT client node. */ int of_hwspin_lock_get_id_byname(struct device_node *np, const char *name) { @@ -481,7 +513,7 @@ out: * * Should be called from a process context (might sleep) * - * Returns 0 on success, or an appropriate error code on failure + * 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) @@ -529,7 +561,7 @@ EXPORT_SYMBOL_GPL(hwspin_lock_register); * * Should be called from a process context (might sleep) * - * Returns 0 on success, or an appropriate error code on failure + * Returns: %0 on success, or an appropriate error code on failure */ int hwspin_lock_unregister(struct hwspinlock_device *bank) { @@ -578,7 +610,7 @@ static int devm_hwspin_lock_device_match(struct device *dev, void *res, * * Should be called from a process context (might sleep) * - * Returns 0 on success, or an appropriate error code on failure + * Returns: %0 on success, or an appropriate error code on failure */ int devm_hwspin_lock_unregister(struct device *dev, struct hwspinlock_device *bank) @@ -607,7 +639,7 @@ EXPORT_SYMBOL_GPL(devm_hwspin_lock_unregister); * * Should be called from a process context (might sleep) * - * Returns 0 on success, or an appropriate error code on failure + * Returns: %0 on success, or an appropriate error code on failure */ int devm_hwspin_lock_register(struct device *dev, struct hwspinlock_device *bank, @@ -635,12 +667,13 @@ EXPORT_SYMBOL_GPL(devm_hwspin_lock_register); /** * __hwspin_lock_request() - tag an hwspinlock as used and power it up + * @hwlock: the target hwspinlock * * This is an internal function that prepares an hwspinlock instance * before it is given to the user. The function assumes that * hwspinlock_tree_lock is taken. * - * Returns 0 or positive to indicate success, and a negative value to + * Returns: %0 or positive to indicate success, and a negative value to * indicate an error (with the appropriate error code) */ static int __hwspin_lock_request(struct hwspinlock *hwlock) @@ -677,66 +710,6 @@ static int __hwspin_lock_request(struct hwspinlock *hwlock) } /** - * hwspin_lock_get_id() - retrieve id number of a given hwspinlock - * @hwlock: a valid hwspinlock instance - * - * Returns the id number of a given @hwlock, or -EINVAL if @hwlock is invalid. - */ -int hwspin_lock_get_id(struct hwspinlock *hwlock) -{ - if (!hwlock) { - pr_err("invalid hwlock\n"); - return -EINVAL; - } - - return hwlock_to_id(hwlock); -} -EXPORT_SYMBOL_GPL(hwspin_lock_get_id); - -/** - * hwspin_lock_request() - request an hwspinlock - * - * This function should be called by users of the hwspinlock device, - * in order to dynamically assign them an unused hwspinlock. - * Usually the user of this lock will then have to communicate the lock's id - * to the remote core before it can be used for synchronization (to get the - * id of a given hwlock, use hwspin_lock_get_id()). - * - * Should be called from a process context (might sleep) - * - * Returns the address of the assigned hwspinlock, or NULL on error - */ -struct hwspinlock *hwspin_lock_request(void) -{ - struct hwspinlock *hwlock; - int ret; - - mutex_lock(&hwspinlock_tree_lock); - - /* look for an unused lock */ - ret = radix_tree_gang_lookup_tag(&hwspinlock_tree, (void **)&hwlock, - 0, 1, HWSPINLOCK_UNUSED); - if (ret == 0) { - pr_warn("a free hwspinlock is not available\n"); - hwlock = NULL; - goto out; - } - - /* sanity check that should never fail */ - WARN_ON(ret > 1); - - /* mark as used and power up */ - ret = __hwspin_lock_request(hwlock); - if (ret < 0) - hwlock = NULL; - -out: - mutex_unlock(&hwspinlock_tree_lock); - return hwlock; -} -EXPORT_SYMBOL_GPL(hwspin_lock_request); - -/** * hwspin_lock_request_specific() - request for a specific hwspinlock * @id: index of the specific hwspinlock that is requested * @@ -747,7 +720,7 @@ EXPORT_SYMBOL_GPL(hwspin_lock_request); * * Should be called from a process context (might sleep) * - * Returns the address of the assigned hwspinlock, or NULL on error + * Returns: the address of the assigned hwspinlock, or %NULL on error */ struct hwspinlock *hwspin_lock_request_specific(unsigned int id) { @@ -795,7 +768,7 @@ EXPORT_SYMBOL_GPL(hwspin_lock_request_specific); * * Should be called from a process context (might sleep) * - * Returns 0 on success, or an appropriate error code on failure + * Returns: %0 on success, or an appropriate error code on failure */ int hwspin_lock_free(struct hwspinlock *hwlock) { @@ -865,7 +838,7 @@ static void devm_hwspin_lock_release(struct device *dev, void *res) * * Should be called from a process context (might sleep) * - * Returns 0 on success, or an appropriate error code on failure + * Returns: %0 on success, or an appropriate error code on failure */ int devm_hwspin_lock_free(struct device *dev, struct hwspinlock *hwlock) { @@ -880,40 +853,6 @@ int devm_hwspin_lock_free(struct device *dev, struct hwspinlock *hwlock) EXPORT_SYMBOL_GPL(devm_hwspin_lock_free); /** - * devm_hwspin_lock_request() - request an hwspinlock for a managed device - * @dev: the device to request an hwspinlock - * - * This function should be called by users of the hwspinlock device, - * in order to dynamically assign them an unused hwspinlock. - * Usually the user of this lock will then have to communicate the lock's id - * to the remote core before it can be used for synchronization (to get the - * id of a given hwlock, use hwspin_lock_get_id()). - * - * Should be called from a process context (might sleep) - * - * Returns the address of the assigned hwspinlock, or NULL on error - */ -struct hwspinlock *devm_hwspin_lock_request(struct device *dev) -{ - struct hwspinlock **ptr, *hwlock; - - ptr = devres_alloc(devm_hwspin_lock_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return NULL; - - hwlock = hwspin_lock_request(); - if (hwlock) { - *ptr = hwlock; - devres_add(dev, ptr); - } else { - devres_free(ptr); - } - - return hwlock; -} -EXPORT_SYMBOL_GPL(devm_hwspin_lock_request); - -/** * devm_hwspin_lock_request_specific() - request for a specific hwspinlock for * a managed device * @dev: the device to request the specific hwspinlock @@ -926,7 +865,7 @@ EXPORT_SYMBOL_GPL(devm_hwspin_lock_request); * * Should be called from a process context (might sleep) * - * Returns the address of the assigned hwspinlock, or NULL on error + * Returns: the address of the assigned hwspinlock, or %NULL on error */ struct hwspinlock *devm_hwspin_lock_request_specific(struct device *dev, unsigned int id) @@ -949,6 +888,5 @@ struct hwspinlock *devm_hwspin_lock_request_specific(struct device *dev, } EXPORT_SYMBOL_GPL(devm_hwspin_lock_request_specific); -MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Hardware spinlock interface"); MODULE_AUTHOR("Ohad Ben-Cohen <ohad@wizery.com>"); |
