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: Matt Wagantall <mattw@codeaurora.org>
This commit is contained in:
Matt Wagantall
2014-01-31 12:28:43 -08:00
parent 3b337875a5
commit 13739fcc14
3 changed files with 69 additions and 3 deletions
@@ -1,4 +1,5 @@
/* 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. */
struct dek_spinlock {
@@ -48,6 +52,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)
@@ -69,6 +75,9 @@ 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
+53 -1
View File
@@ -1,4 +1,4 @@
/* 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
@@ -81,6 +81,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;
@@ -364,6 +366,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 ------------------------------------------------------ */
@@ -458,6 +481,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;
break;
case AUTO_MODE:
@@ -474,6 +500,10 @@ 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;
break;
}
@@ -517,6 +547,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);
@@ -671,6 +706,23 @@ 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 -------------------------------------------------- */
/* remote mutex implementation ---------------------------------------------- */
+6 -1
View File
@@ -1,4 +1,4 @@
/* 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
@@ -83,6 +83,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)