Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/ohad/hwspinlock

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ohad/hwspinlock:
  hwspinlock: add MAINTAINERS entries
  hwspinlock/omap: omap_hwspinlock_remove should be __devexit
  hwspinlock/u8500: add hwspinlock driver
  hwspinlock/core: register a bank of hwspinlocks in a single API call
  hwspinlock/core: remove stubs for register/unregister
  hwspinlock/core: use a mutex to protect the radix tree
  hwspinlock/core/omap: fix id issues on multiple hwspinlock devices
  hwspinlock/omap: simplify allocation scheme
  hwspinlock/core: simplify 'owner' handling
  hwspinlock/core: simplify Kconfig

Fix up trivial conflicts (addition of omap_hwspinlock_pdata, removal of
omap_spinlock_latency) in arch/arm/mach-omap2/hwspinlock.c

Also, do an "evil merge" to fix a compile error in omap_hsmmc.c which
for some reason was reported in the same email thread as the "please
pull hwspinlock changes".
  • Loading branch information
torvalds committed Nov 3, 2011
2 parents 30307c6 + 8b37fcf commit 3f8ddb0
Show file tree
Hide file tree
Showing 11 changed files with 516 additions and 226 deletions.
74 changes: 44 additions & 30 deletions Documentation/hwspinlock.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,20 @@ independent, drivers.
in case an unused hwspinlock isn't available. Users of this
API will usually want to communicate the lock's id to the remote core
before it can be used to achieve synchronization.
Can be called from an atomic context (this function will not sleep) but
not from within interrupt context.
Should be called from a process context (might sleep).

struct hwspinlock *hwspin_lock_request_specific(unsigned int id);
- assign a specific hwspinlock id and return its address, or NULL
if that hwspinlock is already in use. Usually board code will
be calling this function in order to reserve specific hwspinlock
ids for predefined purposes.
Can be called from an atomic context (this function will not sleep) but
not from within interrupt context.
Should be called from a process context (might sleep).

int hwspin_lock_free(struct hwspinlock *hwlock);
- free a previously-assigned hwspinlock; returns 0 on success, or an
appropriate error code on failure (e.g. -EINVAL if the hwspinlock
is already free).
Can be called from an atomic context (this function will not sleep) but
not from within interrupt context.
Should be called from a process context (might sleep).

int hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int timeout);
- lock a previously-assigned hwspinlock with a timeout limit (specified in
Expand Down Expand Up @@ -230,45 +227,62 @@ int hwspinlock_example2(void)

4. API for implementors

int hwspin_lock_register(struct hwspinlock *hwlock);
int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
const struct hwspinlock_ops *ops, int base_id, int num_locks);
- to be called from the underlying platform-specific implementation, in
order to register a new hwspinlock instance. Can be called from an atomic
context (this function will not sleep) but not from within interrupt
context. Returns 0 on success, or appropriate error code on failure.
order to register a new hwspinlock device (which is usually a bank of
numerous locks). Should be called from a process context (this function
might sleep).
Returns 0 on success, or appropriate error code on failure.

struct hwspinlock *hwspin_lock_unregister(unsigned int id);
int hwspin_lock_unregister(struct hwspinlock_device *bank);
- to be called from the underlying vendor-specific implementation, in order
to unregister an existing (and unused) hwspinlock instance.
Can be called from an atomic context (will not sleep) but not from
within interrupt context.
to unregister an hwspinlock device (which is usually a bank of numerous
locks).
Should be called from a process context (this function might sleep).
Returns the address of hwspinlock on success, or NULL on error (e.g.
if the hwspinlock is sill in use).

5. struct hwspinlock
5. Important structs

This struct represents an hwspinlock instance. It is registered by the
underlying hwspinlock implementation using the hwspin_lock_register() API.
struct hwspinlock_device is a device which usually contains a bank
of hardware locks. It is registered by the underlying hwspinlock
implementation using the hwspin_lock_register() API.

/**
* struct hwspinlock - vendor-specific hwspinlock implementation
*
* @dev: underlying device, will be used with runtime PM api
* @ops: vendor-specific hwspinlock handlers
* @id: a global, unique, system-wide, index of the lock.
* @lock: initialized and used by hwspinlock core
* @owner: underlying implementation module, used to maintain module ref count
* struct hwspinlock_device - a device which usually spans numerous hwspinlocks
* @dev: underlying device, will be used to invoke runtime PM api
* @ops: platform-specific hwspinlock handlers
* @base_id: id index of the first lock in this device
* @num_locks: number of locks in this device
* @lock: dynamically allocated array of 'struct hwspinlock'
*/
struct hwspinlock {
struct hwspinlock_device {
struct device *dev;
const struct hwspinlock_ops *ops;
int id;
int base_id;
int num_locks;
struct hwspinlock lock[0];
};

struct hwspinlock_device contains an array of hwspinlock structs, each
of which represents a single hardware lock:

/**
* struct hwspinlock - this struct represents a single hwspinlock instance
* @bank: the hwspinlock_device structure which owns this lock
* @lock: initialized and used by hwspinlock core
* @priv: private data, owned by the underlying platform-specific hwspinlock drv
*/
struct hwspinlock {
struct hwspinlock_device *bank;
spinlock_t lock;
struct module *owner;
void *priv;
};

The underlying implementation is responsible to assign the dev, ops, id and
owner members. The lock member, OTOH, is initialized and used by the hwspinlock
core.
When registering a bank of locks, the hwspinlock driver only needs to
set the priv members of the locks. The rest of the members are set and
initialized by the hwspinlock core itself.

6. Implementation callbacks

Expand Down
14 changes: 14 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -3018,6 +3018,13 @@ F: Documentation/hw_random.txt
F: drivers/char/hw_random/
F: include/linux/hw_random.h

HARDWARE SPINLOCK CORE
M: Ohad Ben-Cohen <[email protected]>
S: Maintained
F: Documentation/hwspinlock.txt
F: drivers/hwspinlock/hwspinlock_*
F: include/linux/hwspinlock.h

HARMONY SOUND DRIVER
M: Kyle McMartin <[email protected]>
L: [email protected]
Expand Down Expand Up @@ -4714,6 +4721,13 @@ S: Maintained
F: drivers/video/omap2/
F: Documentation/arm/OMAP/DSS

OMAP HARDWARE SPINLOCK SUPPORT
M: Ohad Ben-Cohen <[email protected]>
L: [email protected]
S: Maintained
F: drivers/hwspinlock/omap_hwspinlock.c
F: arch/arm/mach-omap2/hwspinlock.c

OMAP MMC SUPPORT
M: Jarkko Lavinen <[email protected]>
L: [email protected]
Expand Down
9 changes: 8 additions & 1 deletion arch/arm/mach-omap2/hwspinlock.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/hwspinlock.h>

#include <plat/omap_hwmod.h>
#include <plat/omap_device.h>

static struct hwspinlock_pdata omap_hwspinlock_pdata __initdata = {
.base_id = 0,
};

int __init hwspinlocks_init(void)
{
int retval = 0;
Expand All @@ -40,7 +45,9 @@ int __init hwspinlocks_init(void)
if (oh == NULL)
return -EINVAL;

pdev = omap_device_build(dev_name, 0, oh, NULL, 0, NULL, 0, false);
pdev = omap_device_build(dev_name, 0, oh, &omap_hwspinlock_pdata,
sizeof(struct hwspinlock_pdata),
NULL, 0, false);
if (IS_ERR(pdev)) {
pr_err("Can't build omap_device for %s:%s\n", dev_name,
oh_name);
Expand Down
27 changes: 18 additions & 9 deletions drivers/hwspinlock/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,31 @@
# Generic HWSPINLOCK framework
#

# HWSPINLOCK always gets selected by whoever wants it.
config HWSPINLOCK
tristate "Generic Hardware Spinlock framework"
depends on ARCH_OMAP4
help
Say y here to support the generic hardware spinlock framework.
You only need to enable this if you have hardware spinlock module
on your system (usually only relevant if your system has remote slave
coprocessors).
tristate

If unsure, say N.
menu "Hardware Spinlock drivers"

config HWSPINLOCK_OMAP
tristate "OMAP Hardware Spinlock device"
depends on HWSPINLOCK && ARCH_OMAP4
depends on ARCH_OMAP4
select HWSPINLOCK
help
Say y here to support the OMAP Hardware Spinlock device (firstly
introduced in OMAP4).

If unsure, say N.

config HSEM_U8500
tristate "STE Hardware Semaphore functionality"
depends on ARCH_U8500
select HWSPINLOCK
help
Say y here to support the STE Hardware Semaphore functionality, which
provides a synchronisation mechanism for the various processor on the
SoC.

If unsure, say N.

endmenu
1 change: 1 addition & 0 deletions drivers/hwspinlock/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@

obj-$(CONFIG_HWSPINLOCK) += hwspinlock_core.o
obj-$(CONFIG_HWSPINLOCK_OMAP) += omap_hwspinlock.o
obj-$(CONFIG_HSEM_U8500) += u8500_hsem.o
Loading

0 comments on commit 3f8ddb0

Please sign in to comment.