cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hwspinlock_core.c (27891B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Hardware spinlock framework
      4 *
      5 * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
      6 *
      7 * Contact: Ohad Ben-Cohen <ohad@wizery.com>
      8 */
      9
     10#define pr_fmt(fmt)    "%s: " fmt, __func__
     11
     12#include <linux/delay.h>
     13#include <linux/kernel.h>
     14#include <linux/module.h>
     15#include <linux/spinlock.h>
     16#include <linux/types.h>
     17#include <linux/err.h>
     18#include <linux/jiffies.h>
     19#include <linux/radix-tree.h>
     20#include <linux/hwspinlock.h>
     21#include <linux/pm_runtime.h>
     22#include <linux/mutex.h>
     23#include <linux/of.h>
     24
     25#include "hwspinlock_internal.h"
     26
     27/* retry delay used in atomic context */
     28#define HWSPINLOCK_RETRY_DELAY_US	100
     29
     30/* radix tree tags */
     31#define HWSPINLOCK_UNUSED	(0) /* tags an hwspinlock as unused */
     32
     33/*
     34 * A radix tree is used to maintain the available hwspinlock instances.
     35 * The tree associates hwspinlock pointers with their integer key id,
     36 * and provides easy-to-use API which makes the hwspinlock core code simple
     37 * and easy to read.
     38 *
     39 * Radix trees are quick on lookups, and reasonably efficient in terms of
     40 * storage, especially with high density usages such as this framework
     41 * requires (a continuous range of integer keys, beginning with zero, is
     42 * used as the ID's of the hwspinlock instances).
     43 *
     44 * The radix tree API supports tagging items in the tree, which this
     45 * framework uses to mark unused hwspinlock instances (see the
     46 * HWSPINLOCK_UNUSED tag above). As a result, the process of querying the
     47 * tree, looking for an unused hwspinlock instance, is now reduced to a
     48 * single radix tree API call.
     49 */
     50static RADIX_TREE(hwspinlock_tree, GFP_KERNEL);
     51
     52/*
     53 * Synchronization of access to the tree is achieved using this mutex,
     54 * as the radix-tree API requires that users provide all synchronisation.
     55 * A mutex is needed because we're using non-atomic radix tree allocations.
     56 */
     57static DEFINE_MUTEX(hwspinlock_tree_lock);
     58
     59
     60/**
     61 * __hwspin_trylock() - attempt to lock a specific hwspinlock
     62 * @hwlock: an hwspinlock which we want to trylock
     63 * @mode: controls whether local interrupts are disabled or not
     64 * @flags: a pointer where the caller's interrupt state will be saved at (if
     65 *         requested)
     66 *
     67 * This function attempts to lock an hwspinlock, and will immediately
     68 * fail if the hwspinlock is already taken.
     69 *
     70 * Caution: If the mode is HWLOCK_RAW, that means user must protect the routine
     71 * of getting hardware lock with mutex or spinlock. Since in some scenarios,
     72 * user need some time-consuming or sleepable operations under the hardware
     73 * lock, they need one sleepable lock (like mutex) to protect the operations.
     74 *
     75 * If the mode is neither HWLOCK_IN_ATOMIC nor HWLOCK_RAW, upon a successful
     76 * return from this function, preemption (and possibly interrupts) is disabled,
     77 * so the caller must not sleep, and is advised to release the hwspinlock as
     78 * soon as possible. This is required in order to minimize remote cores polling
     79 * on the hardware interconnect.
     80 *
     81 * The user decides whether local interrupts are disabled or not, and if yes,
     82 * whether he wants their previous state to be saved. It is up to the user
     83 * to choose the appropriate @mode of operation, exactly the same way users
     84 * should decide between spin_trylock, spin_trylock_irq and
     85 * spin_trylock_irqsave.
     86 *
     87 * Returns 0 if we successfully locked the hwspinlock or -EBUSY if
     88 * the hwspinlock was already taken.
     89 * This function will never sleep.
     90 */
     91int __hwspin_trylock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
     92{
     93	int ret;
     94
     95	if (WARN_ON(!hwlock || (!flags && mode == HWLOCK_IRQSTATE)))
     96		return -EINVAL;
     97
     98	/*
     99	 * This spin_lock{_irq, _irqsave} serves three purposes:
    100	 *
    101	 * 1. Disable preemption, in order to minimize the period of time
    102	 *    in which the hwspinlock is taken. This is important in order
    103	 *    to minimize the possible polling on the hardware interconnect
    104	 *    by a remote user of this lock.
    105	 * 2. Make the hwspinlock SMP-safe (so we can take it from
    106	 *    additional contexts on the local host).
    107	 * 3. Ensure that in_atomic/might_sleep checks catch potential
    108	 *    problems with hwspinlock usage (e.g. scheduler checks like
    109	 *    'scheduling while atomic' etc.)
    110	 */
    111	switch (mode) {
    112	case HWLOCK_IRQSTATE:
    113		ret = spin_trylock_irqsave(&hwlock->lock, *flags);
    114		break;
    115	case HWLOCK_IRQ:
    116		ret = spin_trylock_irq(&hwlock->lock);
    117		break;
    118	case HWLOCK_RAW:
    119	case HWLOCK_IN_ATOMIC:
    120		ret = 1;
    121		break;
    122	default:
    123		ret = spin_trylock(&hwlock->lock);
    124		break;
    125	}
    126
    127	/* is lock already taken by another context on the local cpu ? */
    128	if (!ret)
    129		return -EBUSY;
    130
    131	/* try to take the hwspinlock device */
    132	ret = hwlock->bank->ops->trylock(hwlock);
    133
    134	/* if hwlock is already taken, undo spin_trylock_* and exit */
    135	if (!ret) {
    136		switch (mode) {
    137		case HWLOCK_IRQSTATE:
    138			spin_unlock_irqrestore(&hwlock->lock, *flags);
    139			break;
    140		case HWLOCK_IRQ:
    141			spin_unlock_irq(&hwlock->lock);
    142			break;
    143		case HWLOCK_RAW:
    144		case HWLOCK_IN_ATOMIC:
    145			/* Nothing to do */
    146			break;
    147		default:
    148			spin_unlock(&hwlock->lock);
    149			break;
    150		}
    151
    152		return -EBUSY;
    153	}
    154
    155	/*
    156	 * We can be sure the other core's memory operations
    157	 * are observable to us only _after_ we successfully take
    158	 * the hwspinlock, and we must make sure that subsequent memory
    159	 * operations (both reads and writes) will not be reordered before
    160	 * we actually took the hwspinlock.
    161	 *
    162	 * Note: the implicit memory barrier of the spinlock above is too
    163	 * early, so we need this additional explicit memory barrier.
    164	 */
    165	mb();
    166
    167	return 0;
    168}
    169EXPORT_SYMBOL_GPL(__hwspin_trylock);
    170
    171/**
    172 * __hwspin_lock_timeout() - lock an hwspinlock with timeout limit
    173 * @hwlock: the hwspinlock to be locked
    174 * @timeout: timeout value in msecs
    175 * @mode: mode which controls whether local interrupts are disabled or not
    176 * @flags: a pointer to where the caller's interrupt state will be saved at (if
    177 *         requested)
    178 *
    179 * This function locks the given @hwlock. If the @hwlock
    180 * is already taken, the function will busy loop waiting for it to
    181 * be released, but give up after @timeout msecs have elapsed.
    182 *
    183 * Caution: If the mode is HWLOCK_RAW, that means user must protect the routine
    184 * of getting hardware lock with mutex or spinlock. Since in some scenarios,
    185 * user need some time-consuming or sleepable operations under the hardware
    186 * lock, they need one sleepable lock (like mutex) to protect the operations.
    187 *
    188 * If the mode is HWLOCK_IN_ATOMIC (called from an atomic context) the timeout
    189 * is handled with busy-waiting delays, hence shall not exceed few msecs.
    190 *
    191 * If the mode is neither HWLOCK_IN_ATOMIC nor HWLOCK_RAW, upon a successful
    192 * return from this function, preemption (and possibly interrupts) is disabled,
    193 * so the caller must not sleep, and is advised to release the hwspinlock as
    194 * soon as possible. This is required in order to minimize remote cores polling
    195 * on the hardware interconnect.
    196 *
    197 * The user decides whether local interrupts are disabled or not, and if yes,
    198 * whether he wants their previous state to be saved. It is up to the user
    199 * to choose the appropriate @mode of operation, exactly the same way users
    200 * should decide between spin_lock, spin_lock_irq and spin_lock_irqsave.
    201 *
    202 * Returns 0 when the @hwlock was successfully taken, and an appropriate
    203 * error code otherwise (most notably -ETIMEDOUT if the @hwlock is still
    204 * busy after @timeout msecs). The function will never sleep.
    205 */
    206int __hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int to,
    207					int mode, unsigned long *flags)
    208{
    209	int ret;
    210	unsigned long expire, atomic_delay = 0;
    211
    212	expire = msecs_to_jiffies(to) + jiffies;
    213
    214	for (;;) {
    215		/* Try to take the hwspinlock */
    216		ret = __hwspin_trylock(hwlock, mode, flags);
    217		if (ret != -EBUSY)
    218			break;
    219
    220		/*
    221		 * The lock is already taken, let's check if the user wants
    222		 * us to try again
    223		 */
    224		if (mode == HWLOCK_IN_ATOMIC) {
    225			udelay(HWSPINLOCK_RETRY_DELAY_US);
    226			atomic_delay += HWSPINLOCK_RETRY_DELAY_US;
    227			if (atomic_delay > to * 1000)
    228				return -ETIMEDOUT;
    229		} else {
    230			if (time_is_before_eq_jiffies(expire))
    231				return -ETIMEDOUT;
    232		}
    233
    234		/*
    235		 * Allow platform-specific relax handlers to prevent
    236		 * hogging the interconnect (no sleeping, though)
    237		 */
    238		if (hwlock->bank->ops->relax)
    239			hwlock->bank->ops->relax(hwlock);
    240	}
    241
    242	return ret;
    243}
    244EXPORT_SYMBOL_GPL(__hwspin_lock_timeout);
    245
    246/**
    247 * __hwspin_unlock() - unlock a specific hwspinlock
    248 * @hwlock: a previously-acquired hwspinlock which we want to unlock
    249 * @mode: controls whether local interrupts needs to be restored or not
    250 * @flags: previous caller's interrupt state to restore (if requested)
    251 *
    252 * This function will unlock a specific hwspinlock, enable preemption and
    253 * (possibly) enable interrupts or restore their previous state.
    254 * @hwlock must be already locked before calling this function: it is a bug
    255 * to call unlock on a @hwlock that is already unlocked.
    256 *
    257 * The user decides whether local interrupts should be enabled or not, and
    258 * if yes, whether he wants their previous state to be restored. It is up
    259 * to the user to choose the appropriate @mode of operation, exactly the
    260 * same way users decide between spin_unlock, spin_unlock_irq and
    261 * spin_unlock_irqrestore.
    262 *
    263 * The function will never sleep.
    264 */
    265void __hwspin_unlock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
    266{
    267	if (WARN_ON(!hwlock || (!flags && mode == HWLOCK_IRQSTATE)))
    268		return;
    269
    270	/*
    271	 * We must make sure that memory operations (both reads and writes),
    272	 * done before unlocking the hwspinlock, will not be reordered
    273	 * after the lock is released.
    274	 *
    275	 * That's the purpose of this explicit memory barrier.
    276	 *
    277	 * Note: the memory barrier induced by the spin_unlock below is too
    278	 * late; the other core is going to access memory soon after it will
    279	 * take the hwspinlock, and by then we want to be sure our memory
    280	 * operations are already observable.
    281	 */
    282	mb();
    283
    284	hwlock->bank->ops->unlock(hwlock);
    285
    286	/* Undo the spin_trylock{_irq, _irqsave} called while locking */
    287	switch (mode) {
    288	case HWLOCK_IRQSTATE:
    289		spin_unlock_irqrestore(&hwlock->lock, *flags);
    290		break;
    291	case HWLOCK_IRQ:
    292		spin_unlock_irq(&hwlock->lock);
    293		break;
    294	case HWLOCK_RAW:
    295	case HWLOCK_IN_ATOMIC:
    296		/* Nothing to do */
    297		break;
    298	default:
    299		spin_unlock(&hwlock->lock);
    300		break;
    301	}
    302}
    303EXPORT_SYMBOL_GPL(__hwspin_unlock);
    304
    305/**
    306 * of_hwspin_lock_simple_xlate - translate hwlock_spec to return a lock id
    307 * @bank: the hwspinlock device bank
    308 * @hwlock_spec: hwlock specifier as found in the device tree
    309 *
    310 * This is a simple translation function, suitable for hwspinlock platform
    311 * drivers that only has a lock specifier length of 1.
    312 *
    313 * Returns a relative index of the lock within a specified bank on success,
    314 * or -EINVAL on invalid specifier cell count.
    315 */
    316static inline int
    317of_hwspin_lock_simple_xlate(const struct of_phandle_args *hwlock_spec)
    318{
    319	if (WARN_ON(hwlock_spec->args_count != 1))
    320		return -EINVAL;
    321
    322	return hwlock_spec->args[0];
    323}
    324
    325/**
    326 * of_hwspin_lock_get_id() - get lock id for an OF phandle-based specific lock
    327 * @np: device node from which to request the specific hwlock
    328 * @index: index of the hwlock in the list of values
    329 *
    330 * This function provides a means for DT users of the hwspinlock module to
    331 * get the global lock id of a specific hwspinlock using the phandle of the
    332 * hwspinlock device, so that it can be requested using the normal
    333 * hwspin_lock_request_specific() API.
    334 *
    335 * Returns the global lock id number on success, -EPROBE_DEFER if the hwspinlock
    336 * device is not yet registered, -EINVAL on invalid args specifier value or an
    337 * appropriate error as returned from the OF parsing of the DT client node.
    338 */
    339int of_hwspin_lock_get_id(struct device_node *np, int index)
    340{
    341	struct of_phandle_args args;
    342	struct hwspinlock *hwlock;
    343	struct radix_tree_iter iter;
    344	void **slot;
    345	int id;
    346	int ret;
    347
    348	ret = of_parse_phandle_with_args(np, "hwlocks", "#hwlock-cells", index,
    349					 &args);
    350	if (ret)
    351		return ret;
    352
    353	if (!of_device_is_available(args.np)) {
    354		ret = -ENOENT;
    355		goto out;
    356	}
    357
    358	/* Find the hwspinlock device: we need its base_id */
    359	ret = -EPROBE_DEFER;
    360	rcu_read_lock();
    361	radix_tree_for_each_slot(slot, &hwspinlock_tree, &iter, 0) {
    362		hwlock = radix_tree_deref_slot(slot);
    363		if (unlikely(!hwlock))
    364			continue;
    365		if (radix_tree_deref_retry(hwlock)) {
    366			slot = radix_tree_iter_retry(&iter);
    367			continue;
    368		}
    369
    370		if (hwlock->bank->dev->of_node == args.np) {
    371			ret = 0;
    372			break;
    373		}
    374	}
    375	rcu_read_unlock();
    376	if (ret < 0)
    377		goto out;
    378
    379	id = of_hwspin_lock_simple_xlate(&args);
    380	if (id < 0 || id >= hwlock->bank->num_locks) {
    381		ret = -EINVAL;
    382		goto out;
    383	}
    384	id += hwlock->bank->base_id;
    385
    386out:
    387	of_node_put(args.np);
    388	return ret ? ret : id;
    389}
    390EXPORT_SYMBOL_GPL(of_hwspin_lock_get_id);
    391
    392/**
    393 * of_hwspin_lock_get_id_byname() - get lock id for an specified hwlock name
    394 * @np: device node from which to request the specific hwlock
    395 * @name: hwlock name
    396 *
    397 * This function provides a means for DT users of the hwspinlock module to
    398 * get the global lock id of a specific hwspinlock using the specified name of
    399 * the hwspinlock device, so that it can be requested using the normal
    400 * hwspin_lock_request_specific() API.
    401 *
    402 * Returns the global lock id number on success, -EPROBE_DEFER if the hwspinlock
    403 * device is not yet registered, -EINVAL on invalid args specifier value or an
    404 * appropriate error as returned from the OF parsing of the DT client node.
    405 */
    406int of_hwspin_lock_get_id_byname(struct device_node *np, const char *name)
    407{
    408	int index;
    409
    410	if (!name)
    411		return -EINVAL;
    412
    413	index = of_property_match_string(np, "hwlock-names", name);
    414	if (index < 0)
    415		return index;
    416
    417	return of_hwspin_lock_get_id(np, index);
    418}
    419EXPORT_SYMBOL_GPL(of_hwspin_lock_get_id_byname);
    420
    421static int hwspin_lock_register_single(struct hwspinlock *hwlock, int id)
    422{
    423	struct hwspinlock *tmp;
    424	int ret;
    425
    426	mutex_lock(&hwspinlock_tree_lock);
    427
    428	ret = radix_tree_insert(&hwspinlock_tree, id, hwlock);
    429	if (ret) {
    430		if (ret == -EEXIST)
    431			pr_err("hwspinlock id %d already exists!\n", id);
    432		goto out;
    433	}
    434
    435	/* mark this hwspinlock as available */
    436	tmp = radix_tree_tag_set(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
    437
    438	/* self-sanity check which should never fail */
    439	WARN_ON(tmp != hwlock);
    440
    441out:
    442	mutex_unlock(&hwspinlock_tree_lock);
    443	return 0;
    444}
    445
    446static struct hwspinlock *hwspin_lock_unregister_single(unsigned int id)
    447{
    448	struct hwspinlock *hwlock = NULL;
    449	int ret;
    450
    451	mutex_lock(&hwspinlock_tree_lock);
    452
    453	/* make sure the hwspinlock is not in use (tag is set) */
    454	ret = radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
    455	if (ret == 0) {
    456		pr_err("hwspinlock %d still in use (or not present)\n", id);
    457		goto out;
    458	}
    459
    460	hwlock = radix_tree_delete(&hwspinlock_tree, id);
    461	if (!hwlock) {
    462		pr_err("failed to delete hwspinlock %d\n", id);
    463		goto out;
    464	}
    465
    466out:
    467	mutex_unlock(&hwspinlock_tree_lock);
    468	return hwlock;
    469}
    470
    471/**
    472 * hwspin_lock_register() - register a new hw spinlock device
    473 * @bank: the hwspinlock device, which usually provides numerous hw locks
    474 * @dev: the backing device
    475 * @ops: hwspinlock handlers for this device
    476 * @base_id: id of the first hardware spinlock in this bank
    477 * @num_locks: number of hwspinlocks provided by this device
    478 *
    479 * This function should be called from the underlying platform-specific
    480 * implementation, to register a new hwspinlock device instance.
    481 *
    482 * Should be called from a process context (might sleep)
    483 *
    484 * Returns 0 on success, or an appropriate error code on failure
    485 */
    486int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
    487		const struct hwspinlock_ops *ops, int base_id, int num_locks)
    488{
    489	struct hwspinlock *hwlock;
    490	int ret = 0, i;
    491
    492	if (!bank || !ops || !dev || !num_locks || !ops->trylock ||
    493							!ops->unlock) {
    494		pr_err("invalid parameters\n");
    495		return -EINVAL;
    496	}
    497
    498	bank->dev = dev;
    499	bank->ops = ops;
    500	bank->base_id = base_id;
    501	bank->num_locks = num_locks;
    502
    503	for (i = 0; i < num_locks; i++) {
    504		hwlock = &bank->lock[i];
    505
    506		spin_lock_init(&hwlock->lock);
    507		hwlock->bank = bank;
    508
    509		ret = hwspin_lock_register_single(hwlock, base_id + i);
    510		if (ret)
    511			goto reg_failed;
    512	}
    513
    514	return 0;
    515
    516reg_failed:
    517	while (--i >= 0)
    518		hwspin_lock_unregister_single(base_id + i);
    519	return ret;
    520}
    521EXPORT_SYMBOL_GPL(hwspin_lock_register);
    522
    523/**
    524 * hwspin_lock_unregister() - unregister an hw spinlock device
    525 * @bank: the hwspinlock device, which usually provides numerous hw locks
    526 *
    527 * This function should be called from the underlying platform-specific
    528 * implementation, to unregister an existing (and unused) hwspinlock.
    529 *
    530 * Should be called from a process context (might sleep)
    531 *
    532 * Returns 0 on success, or an appropriate error code on failure
    533 */
    534int hwspin_lock_unregister(struct hwspinlock_device *bank)
    535{
    536	struct hwspinlock *hwlock, *tmp;
    537	int i;
    538
    539	for (i = 0; i < bank->num_locks; i++) {
    540		hwlock = &bank->lock[i];
    541
    542		tmp = hwspin_lock_unregister_single(bank->base_id + i);
    543		if (!tmp)
    544			return -EBUSY;
    545
    546		/* self-sanity check that should never fail */
    547		WARN_ON(tmp != hwlock);
    548	}
    549
    550	return 0;
    551}
    552EXPORT_SYMBOL_GPL(hwspin_lock_unregister);
    553
    554static void devm_hwspin_lock_unreg(struct device *dev, void *res)
    555{
    556	hwspin_lock_unregister(*(struct hwspinlock_device **)res);
    557}
    558
    559static int devm_hwspin_lock_device_match(struct device *dev, void *res,
    560					 void *data)
    561{
    562	struct hwspinlock_device **bank = res;
    563
    564	if (WARN_ON(!bank || !*bank))
    565		return 0;
    566
    567	return *bank == data;
    568}
    569
    570/**
    571 * devm_hwspin_lock_unregister() - unregister an hw spinlock device for
    572 *				   a managed device
    573 * @dev: the backing device
    574 * @bank: the hwspinlock device, which usually provides numerous hw locks
    575 *
    576 * This function should be called from the underlying platform-specific
    577 * implementation, to unregister an existing (and unused) hwspinlock.
    578 *
    579 * Should be called from a process context (might sleep)
    580 *
    581 * Returns 0 on success, or an appropriate error code on failure
    582 */
    583int devm_hwspin_lock_unregister(struct device *dev,
    584				struct hwspinlock_device *bank)
    585{
    586	int ret;
    587
    588	ret = devres_release(dev, devm_hwspin_lock_unreg,
    589			     devm_hwspin_lock_device_match, bank);
    590	WARN_ON(ret);
    591
    592	return ret;
    593}
    594EXPORT_SYMBOL_GPL(devm_hwspin_lock_unregister);
    595
    596/**
    597 * devm_hwspin_lock_register() - register a new hw spinlock device for
    598 *				 a managed device
    599 * @dev: the backing device
    600 * @bank: the hwspinlock device, which usually provides numerous hw locks
    601 * @ops: hwspinlock handlers for this device
    602 * @base_id: id of the first hardware spinlock in this bank
    603 * @num_locks: number of hwspinlocks provided by this device
    604 *
    605 * This function should be called from the underlying platform-specific
    606 * implementation, to register a new hwspinlock device instance.
    607 *
    608 * Should be called from a process context (might sleep)
    609 *
    610 * Returns 0 on success, or an appropriate error code on failure
    611 */
    612int devm_hwspin_lock_register(struct device *dev,
    613			      struct hwspinlock_device *bank,
    614			      const struct hwspinlock_ops *ops,
    615			      int base_id, int num_locks)
    616{
    617	struct hwspinlock_device **ptr;
    618	int ret;
    619
    620	ptr = devres_alloc(devm_hwspin_lock_unreg, sizeof(*ptr), GFP_KERNEL);
    621	if (!ptr)
    622		return -ENOMEM;
    623
    624	ret = hwspin_lock_register(bank, dev, ops, base_id, num_locks);
    625	if (!ret) {
    626		*ptr = bank;
    627		devres_add(dev, ptr);
    628	} else {
    629		devres_free(ptr);
    630	}
    631
    632	return ret;
    633}
    634EXPORT_SYMBOL_GPL(devm_hwspin_lock_register);
    635
    636/**
    637 * __hwspin_lock_request() - tag an hwspinlock as used and power it up
    638 *
    639 * This is an internal function that prepares an hwspinlock instance
    640 * before it is given to the user. The function assumes that
    641 * hwspinlock_tree_lock is taken.
    642 *
    643 * Returns 0 or positive to indicate success, and a negative value to
    644 * indicate an error (with the appropriate error code)
    645 */
    646static int __hwspin_lock_request(struct hwspinlock *hwlock)
    647{
    648	struct device *dev = hwlock->bank->dev;
    649	struct hwspinlock *tmp;
    650	int ret;
    651
    652	/* prevent underlying implementation from being removed */
    653	if (!try_module_get(dev->driver->owner)) {
    654		dev_err(dev, "%s: can't get owner\n", __func__);
    655		return -EINVAL;
    656	}
    657
    658	/* notify PM core that power is now needed */
    659	ret = pm_runtime_get_sync(dev);
    660	if (ret < 0 && ret != -EACCES) {
    661		dev_err(dev, "%s: can't power on device\n", __func__);
    662		pm_runtime_put_noidle(dev);
    663		module_put(dev->driver->owner);
    664		return ret;
    665	}
    666
    667	ret = 0;
    668
    669	/* mark hwspinlock as used, should not fail */
    670	tmp = radix_tree_tag_clear(&hwspinlock_tree, hwlock_to_id(hwlock),
    671							HWSPINLOCK_UNUSED);
    672
    673	/* self-sanity check that should never fail */
    674	WARN_ON(tmp != hwlock);
    675
    676	return ret;
    677}
    678
    679/**
    680 * hwspin_lock_get_id() - retrieve id number of a given hwspinlock
    681 * @hwlock: a valid hwspinlock instance
    682 *
    683 * Returns the id number of a given @hwlock, or -EINVAL if @hwlock is invalid.
    684 */
    685int hwspin_lock_get_id(struct hwspinlock *hwlock)
    686{
    687	if (!hwlock) {
    688		pr_err("invalid hwlock\n");
    689		return -EINVAL;
    690	}
    691
    692	return hwlock_to_id(hwlock);
    693}
    694EXPORT_SYMBOL_GPL(hwspin_lock_get_id);
    695
    696/**
    697 * hwspin_lock_request() - request an hwspinlock
    698 *
    699 * This function should be called by users of the hwspinlock device,
    700 * in order to dynamically assign them an unused hwspinlock.
    701 * Usually the user of this lock will then have to communicate the lock's id
    702 * to the remote core before it can be used for synchronization (to get the
    703 * id of a given hwlock, use hwspin_lock_get_id()).
    704 *
    705 * Should be called from a process context (might sleep)
    706 *
    707 * Returns the address of the assigned hwspinlock, or NULL on error
    708 */
    709struct hwspinlock *hwspin_lock_request(void)
    710{
    711	struct hwspinlock *hwlock;
    712	int ret;
    713
    714	mutex_lock(&hwspinlock_tree_lock);
    715
    716	/* look for an unused lock */
    717	ret = radix_tree_gang_lookup_tag(&hwspinlock_tree, (void **)&hwlock,
    718						0, 1, HWSPINLOCK_UNUSED);
    719	if (ret == 0) {
    720		pr_warn("a free hwspinlock is not available\n");
    721		hwlock = NULL;
    722		goto out;
    723	}
    724
    725	/* sanity check that should never fail */
    726	WARN_ON(ret > 1);
    727
    728	/* mark as used and power up */
    729	ret = __hwspin_lock_request(hwlock);
    730	if (ret < 0)
    731		hwlock = NULL;
    732
    733out:
    734	mutex_unlock(&hwspinlock_tree_lock);
    735	return hwlock;
    736}
    737EXPORT_SYMBOL_GPL(hwspin_lock_request);
    738
    739/**
    740 * hwspin_lock_request_specific() - request for a specific hwspinlock
    741 * @id: index of the specific hwspinlock that is requested
    742 *
    743 * This function should be called by users of the hwspinlock module,
    744 * in order to assign them a specific hwspinlock.
    745 * Usually early board code will be calling this function in order to
    746 * reserve specific hwspinlock ids for predefined purposes.
    747 *
    748 * Should be called from a process context (might sleep)
    749 *
    750 * Returns the address of the assigned hwspinlock, or NULL on error
    751 */
    752struct hwspinlock *hwspin_lock_request_specific(unsigned int id)
    753{
    754	struct hwspinlock *hwlock;
    755	int ret;
    756
    757	mutex_lock(&hwspinlock_tree_lock);
    758
    759	/* make sure this hwspinlock exists */
    760	hwlock = radix_tree_lookup(&hwspinlock_tree, id);
    761	if (!hwlock) {
    762		pr_warn("hwspinlock %u does not exist\n", id);
    763		goto out;
    764	}
    765
    766	/* sanity check (this shouldn't happen) */
    767	WARN_ON(hwlock_to_id(hwlock) != id);
    768
    769	/* make sure this hwspinlock is unused */
    770	ret = radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
    771	if (ret == 0) {
    772		pr_warn("hwspinlock %u is already in use\n", id);
    773		hwlock = NULL;
    774		goto out;
    775	}
    776
    777	/* mark as used and power up */
    778	ret = __hwspin_lock_request(hwlock);
    779	if (ret < 0)
    780		hwlock = NULL;
    781
    782out:
    783	mutex_unlock(&hwspinlock_tree_lock);
    784	return hwlock;
    785}
    786EXPORT_SYMBOL_GPL(hwspin_lock_request_specific);
    787
    788/**
    789 * hwspin_lock_free() - free a specific hwspinlock
    790 * @hwlock: the specific hwspinlock to free
    791 *
    792 * This function mark @hwlock as free again.
    793 * Should only be called with an @hwlock that was retrieved from
    794 * an earlier call to hwspin_lock_request{_specific}.
    795 *
    796 * Should be called from a process context (might sleep)
    797 *
    798 * Returns 0 on success, or an appropriate error code on failure
    799 */
    800int hwspin_lock_free(struct hwspinlock *hwlock)
    801{
    802	struct device *dev;
    803	struct hwspinlock *tmp;
    804	int ret;
    805
    806	if (!hwlock) {
    807		pr_err("invalid hwlock\n");
    808		return -EINVAL;
    809	}
    810
    811	dev = hwlock->bank->dev;
    812	mutex_lock(&hwspinlock_tree_lock);
    813
    814	/* make sure the hwspinlock is used */
    815	ret = radix_tree_tag_get(&hwspinlock_tree, hwlock_to_id(hwlock),
    816							HWSPINLOCK_UNUSED);
    817	if (ret == 1) {
    818		dev_err(dev, "%s: hwlock is already free\n", __func__);
    819		dump_stack();
    820		ret = -EINVAL;
    821		goto out;
    822	}
    823
    824	/* notify the underlying device that power is not needed */
    825	pm_runtime_put(dev);
    826
    827	/* mark this hwspinlock as available */
    828	tmp = radix_tree_tag_set(&hwspinlock_tree, hwlock_to_id(hwlock),
    829							HWSPINLOCK_UNUSED);
    830
    831	/* sanity check (this shouldn't happen) */
    832	WARN_ON(tmp != hwlock);
    833
    834	module_put(dev->driver->owner);
    835
    836out:
    837	mutex_unlock(&hwspinlock_tree_lock);
    838	return ret;
    839}
    840EXPORT_SYMBOL_GPL(hwspin_lock_free);
    841
    842static int devm_hwspin_lock_match(struct device *dev, void *res, void *data)
    843{
    844	struct hwspinlock **hwlock = res;
    845
    846	if (WARN_ON(!hwlock || !*hwlock))
    847		return 0;
    848
    849	return *hwlock == data;
    850}
    851
    852static void devm_hwspin_lock_release(struct device *dev, void *res)
    853{
    854	hwspin_lock_free(*(struct hwspinlock **)res);
    855}
    856
    857/**
    858 * devm_hwspin_lock_free() - free a specific hwspinlock for a managed device
    859 * @dev: the device to free the specific hwspinlock
    860 * @hwlock: the specific hwspinlock to free
    861 *
    862 * This function mark @hwlock as free again.
    863 * Should only be called with an @hwlock that was retrieved from
    864 * an earlier call to hwspin_lock_request{_specific}.
    865 *
    866 * Should be called from a process context (might sleep)
    867 *
    868 * Returns 0 on success, or an appropriate error code on failure
    869 */
    870int devm_hwspin_lock_free(struct device *dev, struct hwspinlock *hwlock)
    871{
    872	int ret;
    873
    874	ret = devres_release(dev, devm_hwspin_lock_release,
    875			     devm_hwspin_lock_match, hwlock);
    876	WARN_ON(ret);
    877
    878	return ret;
    879}
    880EXPORT_SYMBOL_GPL(devm_hwspin_lock_free);
    881
    882/**
    883 * devm_hwspin_lock_request() - request an hwspinlock for a managed device
    884 * @dev: the device to request an hwspinlock
    885 *
    886 * This function should be called by users of the hwspinlock device,
    887 * in order to dynamically assign them an unused hwspinlock.
    888 * Usually the user of this lock will then have to communicate the lock's id
    889 * to the remote core before it can be used for synchronization (to get the
    890 * id of a given hwlock, use hwspin_lock_get_id()).
    891 *
    892 * Should be called from a process context (might sleep)
    893 *
    894 * Returns the address of the assigned hwspinlock, or NULL on error
    895 */
    896struct hwspinlock *devm_hwspin_lock_request(struct device *dev)
    897{
    898	struct hwspinlock **ptr, *hwlock;
    899
    900	ptr = devres_alloc(devm_hwspin_lock_release, sizeof(*ptr), GFP_KERNEL);
    901	if (!ptr)
    902		return NULL;
    903
    904	hwlock = hwspin_lock_request();
    905	if (hwlock) {
    906		*ptr = hwlock;
    907		devres_add(dev, ptr);
    908	} else {
    909		devres_free(ptr);
    910	}
    911
    912	return hwlock;
    913}
    914EXPORT_SYMBOL_GPL(devm_hwspin_lock_request);
    915
    916/**
    917 * devm_hwspin_lock_request_specific() - request for a specific hwspinlock for
    918 *					 a managed device
    919 * @dev: the device to request the specific hwspinlock
    920 * @id: index of the specific hwspinlock that is requested
    921 *
    922 * This function should be called by users of the hwspinlock module,
    923 * in order to assign them a specific hwspinlock.
    924 * Usually early board code will be calling this function in order to
    925 * reserve specific hwspinlock ids for predefined purposes.
    926 *
    927 * Should be called from a process context (might sleep)
    928 *
    929 * Returns the address of the assigned hwspinlock, or NULL on error
    930 */
    931struct hwspinlock *devm_hwspin_lock_request_specific(struct device *dev,
    932						     unsigned int id)
    933{
    934	struct hwspinlock **ptr, *hwlock;
    935
    936	ptr = devres_alloc(devm_hwspin_lock_release, sizeof(*ptr), GFP_KERNEL);
    937	if (!ptr)
    938		return NULL;
    939
    940	hwlock = hwspin_lock_request_specific(id);
    941	if (hwlock) {
    942		*ptr = hwlock;
    943		devres_add(dev, ptr);
    944	} else {
    945		devres_free(ptr);
    946	}
    947
    948	return hwlock;
    949}
    950EXPORT_SYMBOL_GPL(devm_hwspin_lock_request_specific);
    951
    952MODULE_LICENSE("GPL v2");
    953MODULE_DESCRIPTION("Hardware spinlock interface");
    954MODULE_AUTHOR("Ohad Ben-Cohen <ohad@wizery.com>");