diff options
author | Karthikeyan Ramasubramanian <kramasub@codeaurora.org> | 2016-01-07 14:02:12 -0700 |
---|---|---|
committer | Rohit Vaswani <rvaswani@codeaurora.org> | 2016-03-01 12:22:27 -0800 |
commit | e51783348ffbc5141f181f6d462bf2f1af19ebfa (patch) | |
tree | 875343418eb084abe6c9cb8c342a6f9d21e51fa7 /include | |
parent | ed8407419be2a1005dbd57aa48b5ab5f9792a26f (diff) |
hwspinlock/msm: Add snapshot of remote_spinlock driver
This snapshot is taken as of msm-3.18 commit e70ad0cd (Promotion of
kernel.lnx.3.18-151201.)
Signed-off-by: Karthikeyan Ramasubramanian <kramasub@codeaurora.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/msm_remote_spinlock.h | 80 | ||||
-rw-r--r-- | include/linux/remote_spinlock.h | 101 |
2 files changed, 181 insertions, 0 deletions
diff --git a/include/linux/msm_remote_spinlock.h b/include/linux/msm_remote_spinlock.h new file mode 100644 index 000000000000..dc8e5912eb4d --- /dev/null +++ b/include/linux/msm_remote_spinlock.h @@ -0,0 +1,80 @@ +/* Copyright (c) 2009, 2011, 2013-2015 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 + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/* + * Part of this this code is based on the standard ARM spinlock + * implementation (asm/spinlock.h) found in the 2.6.29 kernel. + */ + +#ifndef __ASM__ARCH_QC_REMOTE_SPINLOCK_H +#define __ASM__ARCH_QC_REMOTE_SPINLOCK_H + +#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 { + volatile uint32_t lock; +} raw_remote_spinlock_t; + +typedef raw_remote_spinlock_t *_remote_spinlock_t; + +#define remote_spinlock_id_t const char * + +#if defined(CONFIG_REMOTE_SPINLOCK_MSM) +int _remote_spin_lock_init(remote_spinlock_id_t, _remote_spinlock_t *lock); +void _remote_spin_release_all(uint32_t pid); +void _remote_spin_lock(_remote_spinlock_t *lock); +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); +int _remote_spin_get_hw_spinlocks_element(_remote_spinlock_t *lock); +#else +static inline +int _remote_spin_lock_init(remote_spinlock_id_t id, _remote_spinlock_t *lock) +{ + return -EINVAL; +} +static inline void _remote_spin_release_all(uint32_t pid) {} +static inline void _remote_spin_lock(_remote_spinlock_t *lock) {} +static inline void _remote_spin_unlock(_remote_spinlock_t *lock) {} +static inline int _remote_spin_trylock(_remote_spinlock_t *lock) +{ + return -ENODEV; +} +static inline int _remote_spin_release(_remote_spinlock_t *lock, uint32_t pid) +{ + return -ENODEV; +} +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) {} +static inline int _remote_spin_get_hw_spinlocks_element( + _remote_spinlock_t *lock) +{ + return -ENODEV; +} +#endif +#endif /* __ASM__ARCH_QC_REMOTE_SPINLOCK_H */ diff --git a/include/linux/remote_spinlock.h b/include/linux/remote_spinlock.h new file mode 100644 index 000000000000..591c1b24df9c --- /dev/null +++ b/include/linux/remote_spinlock.h @@ -0,0 +1,101 @@ +/* Copyright (c) 2008-2009, 2011, 2013-2015 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 + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#ifndef __LINUX_REMOTE_SPINLOCK_H +#define __LINUX_REMOTE_SPINLOCK_H + +#include <linux/spinlock.h> +#include <linux/msm_remote_spinlock.h> + +/* Grabbing a local spin lock before going for a remote lock has several + * advantages: + * 1. Get calls to preempt enable/disable and IRQ save/restore for free. + * 2. For UP kernel, there is no overhead. + * 3. Reduces the possibility of executing the remote spin lock code. This is + * especially useful when the remote CPUs' mutual exclusion instructions + * don't work with the local CPUs' instructions. In such cases, one has to + * use software based mutex algorithms (e.g. Lamport's bakery algorithm) + * which could get expensive when the no. of contending CPUs is high. + * 4. In the case of software based mutex algorithm the exection time will be + * smaller since the no. of contending CPUs is reduced by having just one + * contender for all the local CPUs. + * 5. Get most of the spin lock debug features for free. + * 6. The code will continue to work "gracefully" even when the remote spin + * lock code is stubbed out for debug purposes or when there is no remote + * CPU in some board/machine types. + */ +typedef struct { + spinlock_t local; + _remote_spinlock_t remote; +} remote_spinlock_t; + +#define remote_spin_lock_init(lock, id) \ + ({ \ + spin_lock_init(&((lock)->local)); \ + _remote_spin_lock_init(id, &((lock)->remote)); \ + }) +#define remote_spin_lock(lock) \ + do { \ + spin_lock(&((lock)->local)); \ + _remote_spin_lock(&((lock)->remote)); \ + } while (0) +#define remote_spin_unlock(lock) \ + do { \ + _remote_spin_unlock(&((lock)->remote)); \ + spin_unlock(&((lock)->local)); \ + } while (0) +#define remote_spin_lock_irqsave(lock, flags) \ + do { \ + spin_lock_irqsave(&((lock)->local), flags); \ + _remote_spin_lock(&((lock)->remote)); \ + } while (0) +#define remote_spin_unlock_irqrestore(lock, flags) \ + do { \ + _remote_spin_unlock(&((lock)->remote)); \ + spin_unlock_irqrestore(&((lock)->local), flags); \ + } while (0) +#define remote_spin_trylock(lock) \ + ({ \ + spin_trylock(&((lock)->local)) \ + ? _remote_spin_trylock(&((lock)->remote)) \ + ? 1 \ + : ({ spin_unlock(&((lock)->local)); 0; }) \ + : 0; \ + }) +#define remote_spin_trylock_irqsave(lock, flags) \ + ({ \ + spin_trylock_irqsave(&((lock)->local), flags) \ + ? _remote_spin_trylock(&((lock)->remote)) \ + ? 1 \ + : ({ spin_unlock_irqrestore(&((lock)->local), flags); \ + 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) + +#define remote_spin_release_all(pid) \ + _remote_spin_release_all(pid) + +#define remote_spin_owner(lock) \ + _remote_spin_owner(&((lock)->remote)) + +#define remote_spin_get_hw_spinlocks_element(lock) \ + _remote_spin_get_hw_spinlocks_element(&((lock)->remote)) +#endif |