Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 84d5e356 authored by Matt Wagantall's avatar Matt Wagantall
Browse files

msm: remote_spinlock: Add support for remote_spin_lock_rlock_id()



remote_spin_lock_rlock_id() and remote_spin_unlock_rlock() are
added to acquire/release a raw remote lock (without a local
spinlock). This is useful when ownership of a lock must transfer
between different execution environments, such as when a lock is
used to guarantee atomicity of a set of actions spread across
different execution environments.

Specifically, these APIs are added to support a new lock which
must be acquired in Linux but released by TrustZone software.

Because no local spinlock is acquired, each thread must use a
different ID so that only one thread can proceed through the
lock at a time.

Support for these new APIs is presently implemented only for
SFPB locks.

Change-Id: Ifc5b1f552090051d2e975107e56e21e22df08924
Signed-off-by: default avatarMatt Wagantall <mattw@codeaurora.org>
parent fdc49c46
Loading
Loading
Loading
Loading
+49 −1
Original line number Diff line number Diff line
/* Copyright (c) 2008-2009, 2011-2013 The Linux Foundation. All rights reserved.
/* Copyright (c) 2008-2009, 2011-2014 The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -33,6 +33,8 @@ struct spinlock_ops {
	int (*trylock)(raw_remote_spinlock_t *lock);
	int (*release)(raw_remote_spinlock_t *lock, uint32_t pid);
	int (*owner)(raw_remote_spinlock_t *lock);
	void (*lock_rlock_id)(raw_remote_spinlock_t *lock, uint32_t tid);
	void (*unlock_rlock)(raw_remote_spinlock_t *lock);
};

static struct spinlock_ops current_ops;
@@ -192,6 +194,27 @@ static void __raw_remote_sfpb_spin_unlock(raw_remote_spinlock_t *lock)
	writel_relaxed(0, lock);
	smp_mb();
}

static void __raw_remote_sfpb_spin_lock_rlock_id(raw_remote_spinlock_t *lock,
						 uint32_t tid)
{
	if (unlikely(!tid)) {
		pr_err("%s: unsupported rlock tid=0\n", __func__);
		BUG();
	}

	do {
		writel_relaxed(tid, lock);
		smp_mb();
	} while (readl_relaxed(lock) != tid);
}

static void __raw_remote_sfpb_spin_unlock_rlock(raw_remote_spinlock_t *lock)
{
	writel_relaxed(0, lock);
	smp_mb();
}

/* end sfpb implementation -------------------------------------------------- */

/* common spinlock API ------------------------------------------------------ */
@@ -265,6 +288,9 @@ static void initialize_ops(void)
		current_ops.trylock = __raw_remote_sfpb_spin_trylock;
		current_ops.release = __raw_remote_gen_spin_release;
		current_ops.owner = __raw_remote_gen_spin_owner;
		current_ops.lock_rlock_id =
				__raw_remote_sfpb_spin_lock_rlock_id;
		current_ops.unlock_rlock = __raw_remote_sfpb_spin_unlock_rlock;
		is_hw_lock_type = 1;
		return;
	}
@@ -302,6 +328,11 @@ static void remote_spin_release_all_locks(uint32_t pid, int count)
	int n;
	 _remote_spinlock_t lock;

	if (pid >= REMOTE_SPINLOCK_NUM_PID) {
		pr_err("%s: Unsupported PID %d\n", __func__, pid);
		return;
	}

	for (n = 0; n < count; ++n) {
		if (remote_spinlock_init_address(n, &lock) == 0)
			_remote_spin_release(&lock, pid);
@@ -418,4 +449,21 @@ int _remote_spin_owner(_remote_spinlock_t *lock)
	return current_ops.owner((raw_remote_spinlock_t *)(*lock));
}
EXPORT_SYMBOL(_remote_spin_owner);

void _remote_spin_lock_rlock_id(_remote_spinlock_t *lock, uint32_t tid)
{
	if (unlikely(!current_ops.lock_rlock_id))
		BUG();
	current_ops.lock_rlock_id((raw_remote_spinlock_t *)(*lock), tid);
}
EXPORT_SYMBOL(_remote_spin_lock_rlock_id);

void _remote_spin_unlock_rlock(_remote_spinlock_t *lock)
{
	if (unlikely(!current_ops.unlock_rlock))
		BUG();
	current_ops.unlock_rlock((raw_remote_spinlock_t *)(*lock));
}
EXPORT_SYMBOL(_remote_spin_unlock_rlock);

/* end common spinlock API -------------------------------------------------- */
+10 −1
Original line number Diff line number Diff line
/* Copyright (c) 2009, 2011, 2013 The Linux Foundation. All rights reserved.
/* Copyright (c) 2009, 2011, 2013-2014 The Linux Foundation.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -22,6 +23,9 @@
#include <linux/io.h>
#include <linux/types.h>

#define REMOTE_SPINLOCK_NUM_PID 128
#define REMOTE_SPINLOCK_TID_START REMOTE_SPINLOCK_NUM_PID

/* Remote spinlock definitions. */

typedef struct {
@@ -40,6 +44,8 @@ void _remote_spin_unlock(_remote_spinlock_t *lock);
int _remote_spin_trylock(_remote_spinlock_t *lock);
int _remote_spin_release(_remote_spinlock_t *lock, uint32_t pid);
int _remote_spin_owner(_remote_spinlock_t *lock);
void _remote_spin_lock_rlock_id(_remote_spinlock_t *lock, uint32_t tid);
void _remote_spin_unlock_rlock(_remote_spinlock_t *lock);
#else
static inline
int _remote_spin_lock_init(remote_spinlock_id_t id, _remote_spinlock_t *lock)
@@ -61,5 +67,8 @@ static inline int _remote_spin_owner(_remote_spinlock_t *lock)
{
	return -ENODEV;
}
static inline void _remote_spin_lock_rlock_id(_remote_spinlock_t *lock,
					      uint32_t tid) {}
static inline void _remote_spin_unlock_rlock(_remote_spinlock_t *lock) {}
#endif
#endif /* __ASM__ARCH_QC_REMOTE_SPINLOCK_H */
+6 −1
Original line number Diff line number Diff line
/* Copyright (c) 2008-2009, 2011, 2013 The Linux Foundation.
/* Copyright (c) 2008-2009, 2011, 2013-2014 The Linux Foundation.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
@@ -81,6 +81,11 @@ typedef struct {
				0; }) \
		: 0; \
	})
#define remote_spin_lock_rlock_id(lock, tid) \
	_remote_spin_lock_rlock_id(&((lock)->remote), tid)

#define remote_spin_unlock_rlock(lock) \
	_remote_spin_unlock_rlock(&((lock)->remote))

#define remote_spin_release(lock, pid) \
	_remote_spin_release(&((lock)->remote), pid)