Ejemplo n.º 1
0
/**
 * 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;
}
Ejemplo n.º 2
0
/**
 * hwspin_lock_request_specific() - request for a specific hwspinlock
 * @id: index of the specific hwspinlock that is requested
 *
 * This function should be called by users of the hwspinlock module,
 * in order to assign them a specific hwspinlock.
 * Usually early board code will be calling this function in order to
 * reserve specific hwspinlock ids for predefined purposes.
 *
 * 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_specific(unsigned int id)
{
	struct hwspinlock *hwlock;
	int ret;

	mutex_lock(&hwspinlock_tree_lock);

	/* make sure this hwspinlock exists */
	hwlock = radix_tree_lookup(&hwspinlock_tree, id);
	if (!hwlock) {
		pr_warn("hwspinlock %u does not exist\n", id);
		goto out;
	}

	/* sanity check (this shouldn't happen) */
	WARN_ON(hwlock_to_id(hwlock) != id);

	/* make sure this hwspinlock is unused */
	ret = radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
	if (ret == 0) {
		pr_warn("hwspinlock %u is already in use\n", id);
		hwlock = NULL;
		goto out;
	}

	/* mark as used and power up */
	ret = __hwspin_lock_request(hwlock);
	if (ret < 0)
		hwlock = NULL;

out:
	mutex_unlock(&hwspinlock_tree_lock);
	return hwlock;
}
Ejemplo n.º 3
0
/**
 * hwspin_lock_request() - request an hwspinlock
 * @lock_type: User to decide to use mutex or spinlocks
 * 1 to use mutex & 0 to use spinlock. If mutex is used, hwspinlock APIs can
 * be called from context that sleeps but cannot be called from interrupt
 * context. If spinlock is used the APIs can be called from any context but
 * the calling context cannot sleep.
 *
 * 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(enum lock_type l)
{
	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;
	} else {
		if (l == USE_MUTEX_LOCK)
			mutex_init(&hwlock->sw_l.mlock);
		else
			spin_lock_init(&hwlock->sw_l.slock);

		hwlock->tlock = l;
	}

out:
	mutex_unlock(&hwspinlock_tree_lock);
	return hwlock;
}