forked from rubenslte/android_kernel_samsung_msm8226
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:
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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 ---------------------------------------------- */
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user