Back to home page

LXR

 
 

    


0001 Hardware Spinlock Framework
0002 
0003 1. Introduction
0004 
0005 Hardware spinlock modules provide hardware assistance for synchronization
0006 and mutual exclusion between heterogeneous processors and those not operating
0007 under a single, shared operating system.
0008 
0009 For example, OMAP4 has dual Cortex-A9, dual Cortex-M3 and a C64x+ DSP,
0010 each of which is running a different Operating System (the master, A9,
0011 is usually running Linux and the slave processors, the M3 and the DSP,
0012 are running some flavor of RTOS).
0013 
0014 A generic hwspinlock framework allows platform-independent drivers to use
0015 the hwspinlock device in order to access data structures that are shared
0016 between remote processors, that otherwise have no alternative mechanism
0017 to accomplish synchronization and mutual exclusion operations.
0018 
0019 This is necessary, for example, for Inter-processor communications:
0020 on OMAP4, cpu-intensive multimedia tasks are offloaded by the host to the
0021 remote M3 and/or C64x+ slave processors (by an IPC subsystem called Syslink).
0022 
0023 To achieve fast message-based communications, a minimal kernel support
0024 is needed to deliver messages arriving from a remote processor to the
0025 appropriate user process.
0026 
0027 This communication is based on simple data structures that is shared between
0028 the remote processors, and access to it is synchronized using the hwspinlock
0029 module (remote processor directly places new messages in this shared data
0030 structure).
0031 
0032 A common hwspinlock interface makes it possible to have generic, platform-
0033 independent, drivers.
0034 
0035 2. User API
0036 
0037   struct hwspinlock *hwspin_lock_request(void);
0038    - dynamically assign an hwspinlock and return its address, or NULL
0039      in case an unused hwspinlock isn't available. Users of this
0040      API will usually want to communicate the lock's id to the remote core
0041      before it can be used to achieve synchronization.
0042      Should be called from a process context (might sleep).
0043 
0044   struct hwspinlock *hwspin_lock_request_specific(unsigned int id);
0045    - assign a specific hwspinlock id and return its address, or NULL
0046      if that hwspinlock is already in use. Usually board code will
0047      be calling this function in order to reserve specific hwspinlock
0048      ids for predefined purposes.
0049      Should be called from a process context (might sleep).
0050 
0051   int of_hwspin_lock_get_id(struct device_node *np, int index);
0052    - retrieve the global lock id for an OF phandle-based specific lock.
0053      This function provides a means for DT users of a hwspinlock module
0054      to get the global lock id of a specific hwspinlock, so that it can
0055      be requested using the normal hwspin_lock_request_specific() API.
0056      The function returns a lock id number on success, -EPROBE_DEFER if
0057      the hwspinlock device is not yet registered with the core, or other
0058      error values.
0059      Should be called from a process context (might sleep).
0060 
0061   int hwspin_lock_free(struct hwspinlock *hwlock);
0062    - free a previously-assigned hwspinlock; returns 0 on success, or an
0063      appropriate error code on failure (e.g. -EINVAL if the hwspinlock
0064      is already free).
0065      Should be called from a process context (might sleep).
0066 
0067   int hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int timeout);
0068    - lock a previously-assigned hwspinlock with a timeout limit (specified in
0069      msecs). If the hwspinlock is already taken, the function will busy loop
0070      waiting for it to be released, but give up when the timeout elapses.
0071      Upon a successful return from this function, preemption is disabled so
0072      the caller must not sleep, and is advised to release the hwspinlock as
0073      soon as possible, in order to minimize remote cores polling on the
0074      hardware interconnect.
0075      Returns 0 when successful and an appropriate error code otherwise (most
0076      notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs).
0077      The function will never sleep.
0078 
0079   int hwspin_lock_timeout_irq(struct hwspinlock *hwlock, unsigned int timeout);
0080    - lock a previously-assigned hwspinlock with a timeout limit (specified in
0081      msecs). If the hwspinlock is already taken, the function will busy loop
0082      waiting for it to be released, but give up when the timeout elapses.
0083      Upon a successful return from this function, preemption and the local
0084      interrupts are disabled, so the caller must not sleep, and is advised to
0085      release the hwspinlock as soon as possible.
0086      Returns 0 when successful and an appropriate error code otherwise (most
0087      notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs).
0088      The function will never sleep.
0089 
0090   int hwspin_lock_timeout_irqsave(struct hwspinlock *hwlock, unsigned int to,
0091                                                         unsigned long *flags);
0092    - lock a previously-assigned hwspinlock with a timeout limit (specified in
0093      msecs). If the hwspinlock is already taken, the function will busy loop
0094      waiting for it to be released, but give up when the timeout elapses.
0095      Upon a successful return from this function, preemption is disabled,
0096      local interrupts are disabled and their previous state is saved at the
0097      given flags placeholder. The caller must not sleep, and is advised to
0098      release the hwspinlock as soon as possible.
0099      Returns 0 when successful and an appropriate error code otherwise (most
0100      notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs).
0101      The function will never sleep.
0102 
0103   int hwspin_trylock(struct hwspinlock *hwlock);
0104    - attempt to lock a previously-assigned hwspinlock, but immediately fail if
0105      it is already taken.
0106      Upon a successful return from this function, preemption is disabled so
0107      caller must not sleep, and is advised to release the hwspinlock as soon as
0108      possible, in order to minimize remote cores polling on the hardware
0109      interconnect.
0110      Returns 0 on success and an appropriate error code otherwise (most
0111      notably -EBUSY if the hwspinlock was already taken).
0112      The function will never sleep.
0113 
0114   int hwspin_trylock_irq(struct hwspinlock *hwlock);
0115    - attempt to lock a previously-assigned hwspinlock, but immediately fail if
0116      it is already taken.
0117      Upon a successful return from this function, preemption and the local
0118      interrupts are disabled so caller must not sleep, and is advised to
0119      release the hwspinlock as soon as possible.
0120      Returns 0 on success and an appropriate error code otherwise (most
0121      notably -EBUSY if the hwspinlock was already taken).
0122      The function will never sleep.
0123 
0124   int hwspin_trylock_irqsave(struct hwspinlock *hwlock, unsigned long *flags);
0125    - attempt to lock a previously-assigned hwspinlock, but immediately fail if
0126      it is already taken.
0127      Upon a successful return from this function, preemption is disabled,
0128      the local interrupts are disabled and their previous state is saved
0129      at the given flags placeholder. The caller must not sleep, and is advised
0130      to release the hwspinlock as soon as possible.
0131      Returns 0 on success and an appropriate error code otherwise (most
0132      notably -EBUSY if the hwspinlock was already taken).
0133      The function will never sleep.
0134 
0135   void hwspin_unlock(struct hwspinlock *hwlock);
0136    - unlock a previously-locked hwspinlock. Always succeed, and can be called
0137      from any context (the function never sleeps). Note: code should _never_
0138      unlock an hwspinlock which is already unlocked (there is no protection
0139      against this).
0140 
0141   void hwspin_unlock_irq(struct hwspinlock *hwlock);
0142    - unlock a previously-locked hwspinlock and enable local interrupts.
0143      The caller should _never_ unlock an hwspinlock which is already unlocked.
0144      Doing so is considered a bug (there is no protection against this).
0145      Upon a successful return from this function, preemption and local
0146      interrupts are enabled. This function will never sleep.
0147 
0148   void
0149   hwspin_unlock_irqrestore(struct hwspinlock *hwlock, unsigned long *flags);
0150    - unlock a previously-locked hwspinlock.
0151      The caller should _never_ unlock an hwspinlock which is already unlocked.
0152      Doing so is considered a bug (there is no protection against this).
0153      Upon a successful return from this function, preemption is reenabled,
0154      and the state of the local interrupts is restored to the state saved at
0155      the given flags. This function will never sleep.
0156 
0157   int hwspin_lock_get_id(struct hwspinlock *hwlock);
0158    - retrieve id number of a given hwspinlock. This is needed when an
0159      hwspinlock is dynamically assigned: before it can be used to achieve
0160      mutual exclusion with a remote cpu, the id number should be communicated
0161      to the remote task with which we want to synchronize.
0162      Returns the hwspinlock id number, or -EINVAL if hwlock is null.
0163 
0164 3. Typical usage
0165 
0166 #include <linux/hwspinlock.h>
0167 #include <linux/err.h>
0168 
0169 int hwspinlock_example1(void)
0170 {
0171         struct hwspinlock *hwlock;
0172         int ret;
0173 
0174         /* dynamically assign a hwspinlock */
0175         hwlock = hwspin_lock_request();
0176         if (!hwlock)
0177                 ...
0178 
0179         id = hwspin_lock_get_id(hwlock);
0180         /* probably need to communicate id to a remote processor now */
0181 
0182         /* take the lock, spin for 1 sec if it's already taken */
0183         ret = hwspin_lock_timeout(hwlock, 1000);
0184         if (ret)
0185                 ...
0186 
0187         /*
0188          * we took the lock, do our thing now, but do NOT sleep
0189          */
0190 
0191         /* release the lock */
0192         hwspin_unlock(hwlock);
0193 
0194         /* free the lock */
0195         ret = hwspin_lock_free(hwlock);
0196         if (ret)
0197                 ...
0198 
0199         return ret;
0200 }
0201 
0202 int hwspinlock_example2(void)
0203 {
0204         struct hwspinlock *hwlock;
0205         int ret;
0206 
0207         /*
0208          * assign a specific hwspinlock id - this should be called early
0209          * by board init code.
0210          */
0211         hwlock = hwspin_lock_request_specific(PREDEFINED_LOCK_ID);
0212         if (!hwlock)
0213                 ...
0214 
0215         /* try to take it, but don't spin on it */
0216         ret = hwspin_trylock(hwlock);
0217         if (!ret) {
0218                 pr_info("lock is already taken\n");
0219                 return -EBUSY;
0220         }
0221 
0222         /*
0223          * we took the lock, do our thing now, but do NOT sleep
0224          */
0225 
0226         /* release the lock */
0227         hwspin_unlock(hwlock);
0228 
0229         /* free the lock */
0230         ret = hwspin_lock_free(hwlock);
0231         if (ret)
0232                 ...
0233 
0234         return ret;
0235 }
0236 
0237 
0238 4. API for implementors
0239 
0240   int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
0241                 const struct hwspinlock_ops *ops, int base_id, int num_locks);
0242    - to be called from the underlying platform-specific implementation, in
0243      order to register a new hwspinlock device (which is usually a bank of
0244      numerous locks). Should be called from a process context (this function
0245      might sleep).
0246      Returns 0 on success, or appropriate error code on failure.
0247 
0248   int hwspin_lock_unregister(struct hwspinlock_device *bank);
0249    - to be called from the underlying vendor-specific implementation, in order
0250      to unregister an hwspinlock device (which is usually a bank of numerous
0251      locks).
0252      Should be called from a process context (this function might sleep).
0253      Returns the address of hwspinlock on success, or NULL on error (e.g.
0254      if the hwspinlock is still in use).
0255 
0256 5. Important structs
0257 
0258 struct hwspinlock_device is a device which usually contains a bank
0259 of hardware locks. It is registered by the underlying hwspinlock
0260 implementation using the hwspin_lock_register() API.
0261 
0262 /**
0263  * struct hwspinlock_device - a device which usually spans numerous hwspinlocks
0264  * @dev: underlying device, will be used to invoke runtime PM api
0265  * @ops: platform-specific hwspinlock handlers
0266  * @base_id: id index of the first lock in this device
0267  * @num_locks: number of locks in this device
0268  * @lock: dynamically allocated array of 'struct hwspinlock'
0269  */
0270 struct hwspinlock_device {
0271         struct device *dev;
0272         const struct hwspinlock_ops *ops;
0273         int base_id;
0274         int num_locks;
0275         struct hwspinlock lock[0];
0276 };
0277 
0278 struct hwspinlock_device contains an array of hwspinlock structs, each
0279 of which represents a single hardware lock:
0280 
0281 /**
0282  * struct hwspinlock - this struct represents a single hwspinlock instance
0283  * @bank: the hwspinlock_device structure which owns this lock
0284  * @lock: initialized and used by hwspinlock core
0285  * @priv: private data, owned by the underlying platform-specific hwspinlock drv
0286  */
0287 struct hwspinlock {
0288         struct hwspinlock_device *bank;
0289         spinlock_t lock;
0290         void *priv;
0291 };
0292 
0293 When registering a bank of locks, the hwspinlock driver only needs to
0294 set the priv members of the locks. The rest of the members are set and
0295 initialized by the hwspinlock core itself.
0296 
0297 6. Implementation callbacks
0298 
0299 There are three possible callbacks defined in 'struct hwspinlock_ops':
0300 
0301 struct hwspinlock_ops {
0302         int (*trylock)(struct hwspinlock *lock);
0303         void (*unlock)(struct hwspinlock *lock);
0304         void (*relax)(struct hwspinlock *lock);
0305 };
0306 
0307 The first two callbacks are mandatory:
0308 
0309 The ->trylock() callback should make a single attempt to take the lock, and
0310 return 0 on failure and 1 on success. This callback may _not_ sleep.
0311 
0312 The ->unlock() callback releases the lock. It always succeed, and it, too,
0313 may _not_ sleep.
0314 
0315 The ->relax() callback is optional. It is called by hwspinlock core while
0316 spinning on a lock, and can be used by the underlying implementation to force
0317 a delay between two successive invocations of ->trylock(). It may _not_ sleep.