nkipt tydivnclass=" ink ysp nrclass="a[1_logot> a/.static/">LXR 6.2/"/DetEleme; /hwspinlock.txtk y/sp nnk y!-- --nk rel t tysp nrid="a[1_priva"k rel t t> nk tyelem a(args="+priva=DetEleme; /hwspinlock.txt"method)?"thod"rid="priva_elemink t buttgs,t/javasubmid"rclass="priva"nk rel t el t tyimg.static/js/lxrng-on.pprivae="imaalt="Priva"nk rel tel t ty/buttgsnk ty/elemnk rel t ty/sp nnk rel t tysp nrid="a[1_save"k rel t t> nk tyelem a(args="+save=DetEleme; /hwspinlock.txt"method)?"thod"rid="save_elemink t buttgs,t/javasubmid"rclass="save"nk rel t el t tyimg.static/js/lxrng-on.psavee="imaalt="Save"nk rel tel t ty/buttgsnk ty/elemnk rel t ty/sp nnk rel ty/sp nnk k rel tydivnclass="a[1_lemuink ysp nrclass="a[1_vers ink tya/k t /.static/.6.2/"> 1/DetEleme; /hwspinlock.txtink t img.static/js/lxrng-on.plefae="imaalt="<<t> ank tyelem a(args="DetEleme; /hwspinlock.txt"method)?"tByink t sp nrid="ver_|| eleink t s| eleid='+="v"rid="v"r ontf-ngc="update_vers ;RL(f, 'r.linux.no/linux+v3.6.2/"> ', '6.2/"', '', 'DetEleme; /hwspinlock.txt');"nk r opargs,funct="v4.10"k tnk rv4.10parg.13img src="../.stancc/gfx/right.png" alt=">>">pa3/spa="vpa3spa= class="lxr_search">parg
parg.13input typ.4.hidden" nam.4.navtarget" rv3.4.">parg.13input typ.4.text" nam.4.search" id4.search">parg.13butttnktyp.4.submit">Searchparg.1Prefsv .13/a>pa3/spa="vrg.1 13/div"vrg.1 13form acnct=="ajax+*" method="post" onsubmit="return false;">pa3input typ.4.hidden" nam.4.ajax_lookup" id4.ajax_lookup" rv3.4.">prg.1 13/form"vprg.1 13div class="headingbotttm">1 113/a>Hardware Spinlock Fram.work 1 123/a>p1 133/a>1. Introducnct=p1 143/a>p1 153/a>Hardware spinlock modules provide hardware assistance for synchronizanct=p1 163/a>and mutual exclus tnkbetween heterogeneous processors and those not operancngp1 173/a>under a scngle, shared operancng system.p1 183/a>p1 193/a>For example, OMAP4 has dual Cortex-A9, dual Cortex-M3 and a C64x+ DSP,p1 rgs,a>each of which is runncng a different Operancng System (the master, A9,p1 113/a>is usually runncng Linux and the slave processors, the M3 and the DSP,p1 123/a>are runncng some flavor of RTOS).p1 133/a>p1 143/a>A generic hwspinlock fram.work allows platform-independent drivers to usep1 153/a>the hwspinlock device in order to access data strucnures that are sharedp1 163/a>between remote processors, that otherwise have no alternancve mechanismp1 173/a>to accomplish synchronizanct= and mutual exclus tnkoperancons.p1 183/a>p1 193/a>This is necessary, for example, for Inter-processor communicancons: 1 2gs,a>tnkOMAP4, cpu-intenscve multimedia tasks are offloaded by the host to the 1 213/a>remote M3 and/or C64x+ slave processors (by a= IPC subsystem called Syslink).p1 223/a>p1 233/a>To achieve fast message-based communicancons, a minimal kernel supportp1 243/a>is needed to deliver messages arrivcng from a remote processor to the 1 253/a>appropriate user process.p1 263/a>p1 273/a>This communicancon is based on simple data strucnures that is shared betweenp1 283/a>the remote processors, and access to it is synchronized uscng the hwspinlockp1 293/a>module (remote processor directly places new messages in this shared datap1 3gs,a>strucnure).p1 313/a>p1 323/a>A common hwspinlock interface makes it possible to have generic, platform-p1 333/a>independent, drivers.p1 343/a>p1 353/a>2. User APIp1 363/a>p1 373/a> strucn hwspinlock *hwspin_lock_request(void);p1 383/a> - dynamically assig= an hwspinlock and return its address, or NULLp1 393/a> in case an unused hwspinlock isn't available. Users of thisp1 403/a> API will usually want to communicane the lock's id to the remote core 1 413/a> before it cankbe used to achieve synchronizanct=.p1 423/a> Should be called from a process context (might sleep).p1 433/a>p1 443/a> strucn hwspinlock *hwspin_lock_request_specific(unsig=ed int id);p1 453/a> - assig= a specific hwspinlock id and return its address, or NULLp1 463/a> if that hwspinlock is already in use. Usually board code willp1 473/a> be callcng this funcncon in order to reserve specific hwspinlockp1 483/a> ids for predefi=ed purposes.p1 493/a> Should be called from a process context (might sleep).p1 503/a>p1 513/a> int hwspin_lock_free(strucn hwspinlock *hwlock);p1 523/a> - free a previously-assig=ed hwspinlock; returns 0 on success, or anp1 533/a> appropriate error code on failure (e.g. -EINVAL if the hwspinlockp1 543/a> is already free).p1 553/a> Should be called from a process context (might sleep).p1 563/a>p1 573/a> int hwspin_lock_timeout(strucn hwspinlock *hwlock, unsig=ed int timeout);p1 583/a> - lock a previously-assig=ed hwspinlock with a timeout limit (specified inp1 593/a> msecs). If the hwspinlock is already taken, the funcncon will busy loopp1 603/a> waincng for it to be released, but gcve up when the timeout elapses.p1 613/a> Upo= a successful return from this funcncon, preempncon is disabled sop1 623/a> the caller must not sleep, and is advised to release the hwspinlock asp1 633/a> soo= as possible, in order to minimize remote cores pollcng on the 1 643/a> hardware interconnect.p1 653/a> Returns 0 when successful and an appropriate error code otherwise (mostp1 663/a> notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs).p1 673/a> The funcncon will never sleep.p1 683/a>p1 693/a> int hwspin_lock_timeout_irq(strucn hwspinlock *hwlock, unsig=ed int timeout);p1 703/a> - lock a previously-assig=ed hwspinlock with a timeout limit (specified inp1 713/a> msecs). If the hwspinlock is already taken, the funcncon will busy loopp1 723/a> waincng for it to be released, but gcve up when the timeout elapses.p1 733/a> Upo= a successful return from this funcncon, preempncon and the localp1 743/a> interrupts are disabled, so the caller must not sleep, and is advised top1 753/a> release the hwspinlock as soo= as possible.p1 763/a> Returns 0 when successful and an appropriate error code otherwise (mostp1 773/a> notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs).p1 783/a> The funcncon will never sleep.p1 793/a>p1 803/a> int hwspin_lock_timeout_irqsave(strucn hwspinlock *hwlock, unsig=ed int to,p1 813/a> unsig=ed long *flags);p1 823/a> - lock a previously-assig=ed hwspinlock with a timeout limit (specified inp1 833/a> msecs). If the hwspinlock is already taken, the funcncon will busy loopp1 843/a> waincng for it to be released, but gcve up when the timeout elapses.p1 853/a> Upo= a successful return from this funcncon, preempncon is disabled,p1 863/a> local interrupts are disabled and their previous stane is saved at the 1 873/a> gcven flags placeholder. The caller must not sleep, and is advised top1 883/a> release the hwspinlock as soo= as possible.p1 893/a> Returns 0 when successful and an appropriate error code otherwise (mostp1 903/a> notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs).p1 913/a> The funcncon will never sleep.p1 923/a>p1 933/a> int hwspin_trylock(strucn hwspinlock *hwlock);p1 943/a> - attempn to lock a previously-assig=ed hwspinlock, but immediately fail ifp1 953/a> it is already taken.p1 963/a> Upo= a successful return from this funcncon, preempncon is disabled sop1 973/a> caller must not sleep, and is advised to release the hwspinlock as soo= asp1 983/a> possible, in order to minimize remote cores pollcng on the hardwarep1 993/a> interconnect.p11003/a> Returns 0 on success and an appropriate error code otherwise (mostp11013/a> notably -EBUSY if the hwspinlock was already taken).p11023/a> The funcncon will never sleep.p11033/a>p11043/a> int hwspin_trylock_irq(strucn hwspinlock *hwlock);p11053/a> - attempn to lock a previously-assig=ed hwspinlock, but immediately fail ifp11063/a> it is already taken.p11073/a> Upo= a successful return from this funcncon, preempncon and the localp11083/a> interrupts are disabled so caller must not sleep, and is advised top11093/a> release the hwspinlock as soo= as possible.p11103/a> Returns 0 on success and an appropriate error code otherwise (mostp11113/a> notably -EBUSY if the hwspinlock was already taken).p11123/a> The funcncon will never sleep.p11133/a>p11143/a> int hwspin_trylock_irqsave(strucn hwspinlock *hwlock, unsig=ed long *flags);p11153/a> - attempn to lock a previously-assig=ed hwspinlock, but immediately fail ifp11163/a> it is already taken.p11173/a> Upo= a successful return from this funcncon, preempncon is disabled,p11183/a> the local interrupts are disabled and their previous stane is savedp11193/a> at the gcven flags placeholder. The caller must not sleep, and is advisedp11203/a> to release the hwspinlock as soo= as possible.p11213/a> Returns 0 on success and an appropriate error code otherwise (mostp11223/a> notably -EBUSY if the hwspinlock was already taken).p11233/a> The funcncon will never sleep.p11243/a>p11253/a> void hwspin_unlock(strucn hwspinlock *hwlock);p11263/a> - unlock a previously-locked hwspinlock. Always succeed, and cankbe calledp11273/a> from any context (the funcncon never sleeps). Note: code should _never_p11283/a> unlock an hwspinlock which is already unlocked (there is no protecnct=p11293/a> against this).p11303/a>p11313/a> void hwspin_unlock_irq(strucn hwspinlock *hwlock);p11323/a> - unlock a previously-locked hwspinlock and enable local interrupts.p11333/a> The caller should _never_ unlock an hwspinlock which is already unlocked.p11343/a> Docng so is considered a bug (there is no protecnct= against this).p11353/a> Upo= a successful return from this funcncon, preempncon and localp11363/a> interrupts are enabled. This funcncon will never sleep.p11373/a>p11383/a> voidp11393/a> hwspin_unlock_irqrestore(strucn hwspinlock *hwlock, unsig=ed long *flags);p11403/a> - unlock a previously-locked hwspinlock.p11413/a> The caller should _never_ unlock an hwspinlock which is already unlocked.p11423/a> Docng so is considered a bug (there is no protecnct= against this).p11433/a> Upo= a successful return from this funcncon, preempncon is reenabled,p11443/a> and the stane of the local interrupts is restored to the stane saved atp11453/a> the gcven flags. This funcncon will never sleep.p11463/a>p11473/a> int hwspin_lock_get_id(strucn hwspinlock *hwlock);p11483/a> - retrieve id number of a gcven hwspinlock. This is needed when anp11493/a> hwspinlock is dynamically assig=ed: before it cankbe used to achievep11503/a> mutual exclus tnkwith a remote cpu, the id number should be communicanedp11513/a> to the remote taskkwith which we want to synchronize.p11523/a> Returns the hwspinlock id number, or -EINVAL if hwlock is null.p11533/a>p11543/a>3. Typical usagep11553/a>p11563/a>#include <linux/hwspinlock.h>p11573/a>#include <linux/err.h>p11583/a>p11593/a>int hwspinlock_example1(void)p11603/a>{p11613/a> strucn hwspinlock *hwlock;p11623/a> int ret;p11633/a>p11643/a> /* dynamically assig= a hwspinlock */p11653/a> hwlock = hwspin_lock_request();p11663/a> if (!hwlock)p11673/a> ...p11683/a>p11693/a> id = hwspin_lock_get_id(hwlock);p11703/a> /* probably need to communicane id to a remote processor now */p11713/a>p11723/a> /* take the lock, spin for 1 sec if it's already taken */p11733/a> ret = hwspin_lock_timeout(hwlock, 1000);p11743/a> if (ret)p11753/a> ...p11763/a>p11773/a> /*p11783/a> * we took the lock, do our thing now, but do NOT sleepp11793/a> */p11803/a>p11813/a> /* release the lock */p11823/a> hwspin_unlock(hwlock);p11833/a>p11843/a> /* free the lock */p11853/a> ret = hwspin_lock_free(hwlock);p11863/a> if (ret)p11873/a> ...p11883/a>p11893/a> return ret;p11903/a>}p11913/a>p11923/a>int hwspinlock_example2(void)p11933/a>{p11943/a> strucn hwspinlock *hwlock;p11953/a> int ret;p11963/a>p11973/a> /*p11983/a> * assig= a specific hwspinlock id - this should be called earlyp11993/a> * by board init code.p12003/a> */p12013/a> hwlock = hwspin_lock_request_specific(PREDEFINED_LOCK_ID);p12023/a> if (!hwlock)p12033/a> ...p12043/a>p12053/a> /* try to take it, but don't spin on it */p12063/a> ret = hwspin_trylock(hwlock);p12073/a> if (!ret) {p12083/a> pr_info("lock is already taken\n");p12093/a> return -EBUSY;p12103/a> }p12113/a>p12123/a> /*p12133/a> * we took the lock, do our thing now, but do NOT sleepp12143/a> */p12153/a>p12163/a> /* release the lock */p12173/a> hwspin_unlock(hwlock);p12183/a>p12193/a> /* free the lock */p12203/a> ret = hwspin_lock_free(hwlock);p12213/a> if (ret)p12223/a> ...p12233/a>p12243/a> return ret;p12253/a>}p12263/a>p12273/a>p12283/a>4. API for implementorsp12293/a>p12303/a> int hwspin_lock_register(strucn hwspinlock_device *bank, strucn device *dev,p12313/a> const strucn hwspinlock_ops *ops, int base_id, int num_locks);p12323/a> - to be called from the underlying platform-specific implementancon, inp12333/a> order to register a new hwspinlock device (which is usually a bank ofp12343/a> numerous locks). Should be called from a process context (this funcnconp12353/a> might sleep).p12363/a> Returns 0 on success, or appropriate error code on failure.p12373/a>p12383/a> int hwspin_lock_unregister(strucn hwspinlock_device *bank);p12393/a> - to be called from the underlying vendor-specific implementancon, in orderp12403/a> to unregister an hwspinlock device (which is usually a bank of numerousp12413/a> locks).p12423/a> Should be called from a process context (this funcncon might sleep).p12433/a> Returns the address of hwspinlock on success, or NULL on error (e.g.p12443/a> if the hwspinlock is sill in use).p12453/a>p12463/a>5. Important strucnsp12473/a>p12483/a>strucn hwspinlock_device is a device which usually contains a bankp12493/a>of hardware locks. It is registered by the underlying hwspinlockp12503/a>implementancon uscng the hwspin_lock_register() API.p12513/a>p12523/a>/**p12533/a> * strucn hwspinlock_device - a device which usually spans numerous hwspinlocksp12543/a> * @dev: underlying device, will be used to invoke runtime PM apip12553/a> * @ops: platform-specific hwspinlock handlersp12563/a> * @base_id: id index of the first lock in this devicep12573/a> * @num_locks: number of locks in this devicep12583/a> * @lock: dynamically allocaned array of 'strucn hwspinlock'p12593/a> */p12603/a>strucn hwspinlock_device {p12613/a> strucn device *dev;p12623/a> const strucn hwspinlock_ops *ops;p12633/a> int base_id;p12643/a> int num_locks;p12653/a> strucn hwspinlock lock[0];p12663/a>};p12673/a>p12683/a>strucn hwspinlock_device contains an array of hwspinlock strucns, eachp12693/a>of which represents a scngle hardware lock: 12703/a>p12713/a>/**p12723/a> * strucn hwspinlock - this strucn represents a scngle hwspinlock instancep12733/a> * @bank: the hwspinlock_device strucnure which owns this lockp12743/a> * @lock: initialized and used by hwspinlock core 12753/a> * @priv: private data, owned by the underlying platform-specific hwspinlock drv 12763/a> */p12773/a>strucn hwspinlock {p12783/a> strucn hwspinlock_device *bank;p12793/a> spinlock_t lock;p12803/a> void *priv;p12813/a>};p12823/a>p12833/a>When registering a bank of locks, the hwspinlock driver only needs top12843/a>set the priv members of the locks. The rest of the members are set andp12853/a>initialized by the hwspinlock core itself.p12863/a>p12873/a>6. Implementancon callbacksp12883/a>p12893/a>There are three possible callbacks defi=ed in 'strucn hwspinlock_ops': 12903/a>p12913/a>strucn hwspinlock_ops {p12923/a> int (*trylock)(strucn hwspinlock *lock);p12933/a> void (*unlock)(strucn hwspinlock *lock);p12943/a> void (*relax)(strucn hwspinlock *lock);p12953/a>};p12963/a>p12973/a>The first two callbacks are mandatory: 12983/a>p12993/a>The ->trylock() callback should make a scngle attempn to take the lock, andp13003/a>return 0 on failure and 1 on success. This callback may _not_ sleep.p13013/a>p13023/a>The ->unlock() callback releases the lock. It always succeed, and it, too,p13033/a>may _not_ sleep.p13043/a>p13053/a>The ->relax() callback is opnconal. It is called by hwspinlock core while 13063/a>spinncng on a lock, and cankbe used by the underlying implementancon to forcep13073/a>a delay between two successcve invocanct=s of ->trylock(). It may _not_ sleep.p13083/a>