sphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextChinese (Simplified)}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget&/translations/zh_CN/locking/hwspinlockmodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget&/translations/zh_TW/locking/hwspinlockmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget&/translations/it_IT/locking/hwspinlockmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget&/translations/ja_JP/locking/hwspinlockmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget&/translations/ko_KR/locking/hwspinlockmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget&/translations/sp_SP/locking/hwspinlockmodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageEnglishuh1h hh _documenthsourceNlineNubhsection)}(hhh](htitle)}(hHardware Spinlock Frameworkh]hHardware Spinlock Framework}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhh@/var/lib/git/docbuild/linux/Documentation/locking/hwspinlock.rsthKubh)}(hhh](h)}(h Introductionh]h Introduction}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhhhKubh paragraph)}(hHardware spinlock modules provide hardware assistance for synchronization and mutual exclusion between heterogeneous processors and those not operating under a single, shared operating system.h]hHardware spinlock modules provide hardware assistance for synchronization and mutual exclusion between heterogeneous processors and those not operating under a single, shared operating system.}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hFor example, OMAP4 has dual Cortex-A9, dual Cortex-M3 and a C64x+ DSP, each of which is running a different Operating System (the master, A9, is usually running Linux and the slave processors, the M3 and the DSP, are running some flavor of RTOS).h]hFor example, OMAP4 has dual Cortex-A9, dual Cortex-M3 and a C64x+ DSP, each of which is running a different Operating System (the master, A9, is usually running Linux and the slave processors, the M3 and the DSP, are running some flavor of RTOS).}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK hhhhubh)}(hXA generic hwspinlock framework allows platform-independent drivers to use the hwspinlock device in order to access data structures that are shared between remote processors, that otherwise have no alternative mechanism to accomplish synchronization and mutual exclusion operations.h]hXA generic hwspinlock framework allows platform-independent drivers to use the hwspinlock device in order to access data structures that are shared between remote processors, that otherwise have no alternative mechanism to accomplish synchronization and mutual exclusion operations.}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hThis is necessary, for example, for Inter-processor communications: on OMAP4, cpu-intensive multimedia tasks are offloaded by the host to the remote M3 and/or C64x+ slave processors (by an IPC subsystem called Syslink).h]hThis is necessary, for example, for Inter-processor communications: on OMAP4, cpu-intensive multimedia tasks are offloaded by the host to the remote M3 and/or C64x+ slave processors (by an IPC subsystem called Syslink).}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hTo achieve fast message-based communications, a minimal kernel support is needed to deliver messages arriving from a remote processor to the appropriate user process.h]hTo achieve fast message-based communications, a minimal kernel support is needed to deliver messages arriving from a remote processor to the appropriate user process.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hThis communication is based on simple data structures that is shared between the remote processors, and access to it is synchronized using the hwspinlock module (remote processor directly places new messages in this shared data structure).h]hThis communication is based on simple data structures that is shared between the remote processors, and access to it is synchronized using the hwspinlock module (remote processor directly places new messages in this shared data structure).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(h`A common hwspinlock interface makes it possible to have generic, platform- independent, drivers.h]h`A common hwspinlock interface makes it possible to have generic, platform- independent, drivers.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK#hhhhubeh}(h] introductionah ]h"] introductionah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(hUser APIh]hUser API}(hj7hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj4hhhhhK'ubh literal_block)}(hAstruct hwspinlock *hwspin_lock_request_specific(unsigned int id);h]hAstruct hwspinlock *hwspin_lock_request_specific(unsigned int id);}hjGsbah}(h]h ]h"]h$]h&] xml:spacepreserveuh1jEhhhK+hj4hhubh)}(hAssign 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.h]hAssign 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.}(hjWhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK-hj4hhubh)}(h6Should be called from a process context (might sleep).h]h6Should be called from a process context (might sleep).}(hjehhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK2hj4hhubjF)}(h=int of_hwspin_lock_get_id(struct device_node *np, int index);h]h=int of_hwspin_lock_get_id(struct device_node *np, int index);}hjssbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhK6hj4hhubh)}(hX Retrieve the global lock id for an OF phandle-based specific lock. This function provides a means for DT users of a hwspinlock module to get the global lock id of a specific hwspinlock, so that it can be requested using the normal hwspin_lock_request_specific() API.h]hX Retrieve the global lock id for an OF phandle-based specific lock. This function provides a means for DT users of a hwspinlock module to get the global lock id of a specific hwspinlock, so that it can be requested using the normal hwspin_lock_request_specific() API.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK8hj4hhubh)}(hThe function returns a lock id number on success, -EPROBE_DEFER if the hwspinlock device is not yet registered with the core, or other error values.h]hThe function returns a lock id number on success, -EPROBE_DEFER if the hwspinlock device is not yet registered with the core, or other error values.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK=hj4hhubh)}(h6Should be called from a process context (might sleep).h]h6Should be called from a process context (might sleep).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKAhj4hhubjF)}(h0int hwspin_lock_free(struct hwspinlock *hwlock);h]h0int hwspin_lock_free(struct hwspinlock *hwlock);}hjsbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhKEhj4hhubh)}(hFree a previously-assigned hwspinlock; returns 0 on success, or an appropriate error code on failure (e.g. -EINVAL if the hwspinlock is already free).h]hFree a previously-assigned hwspinlock; returns 0 on success, or an appropriate error code on failure (e.g. -EINVAL if the hwspinlock is already free).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKGhj4hhubh)}(h6Should be called from a process context (might sleep).h]h6Should be called from a process context (might sleep).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKKhj4hhubjF)}(hAint hwspin_lock_bust(struct hwspinlock *hwlock, unsigned int id);h]hAint hwspin_lock_bust(struct hwspinlock *hwlock, unsigned int id);}hjsbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhKOhj4hhubh)}(hAfter verifying the owner of the hwspinlock, release a previously acquired hwspinlock; returns 0 on success, or an appropriate error code on failure (e.g. -EOPNOTSUPP if the bust operation is not defined for the specific hwspinlock).h]hAfter verifying the owner of the hwspinlock, release a previously acquired hwspinlock; returns 0 on success, or an appropriate error code on failure (e.g. -EOPNOTSUPP if the bust operation is not defined for the specific hwspinlock).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKQhj4hhubh)}(h6Should be called from a process context (might sleep).h]h6Should be called from a process context (might sleep).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKVhj4hhubjF)}(hIint hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int timeout);h]hIint hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int timeout);}hjsbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhKZhj4hhubh)}(hXLock a previously-assigned hwspinlock with a timeout limit (specified in msecs). If the hwspinlock is already taken, the function will busy loop waiting for it to be released, but give up when the timeout elapses. Upon a successful return from this function, preemption is disabled so the caller must not sleep, and is advised to release the hwspinlock as soon as possible, in order to minimize remote cores polling on the hardware interconnect.h]hXLock a previously-assigned hwspinlock with a timeout limit (specified in msecs). If the hwspinlock is already taken, the function will busy loop waiting for it to be released, but give up when the timeout elapses. Upon a successful return from this function, preemption is disabled so the caller must not sleep, and is advised to release the hwspinlock as soon as possible, in order to minimize remote cores polling on the hardware interconnect.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK\hj4hhubh)}(hReturns 0 when successful and an appropriate error code otherwise (most notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs). The function will never sleep.h]hReturns 0 when successful and an appropriate error code otherwise (most notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs). The function will never sleep.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKdhj4hhubjF)}(hMint hwspin_lock_timeout_irq(struct hwspinlock *hwlock, unsigned int timeout);h]hMint hwspin_lock_timeout_irq(struct hwspinlock *hwlock, unsigned int timeout);}hj)sbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhKjhj4hhubh)}(hXLock a previously-assigned hwspinlock with a timeout limit (specified in msecs). If the hwspinlock is already taken, the function will busy loop waiting for it to be released, but give up when the timeout elapses. Upon a successful return from this function, preemption and the local interrupts are disabled, so the caller must not sleep, and is advised to release the hwspinlock as soon as possible.h]hXLock a previously-assigned hwspinlock with a timeout limit (specified in msecs). If the hwspinlock is already taken, the function will busy loop waiting for it to be released, but give up when the timeout elapses. Upon a successful return from this function, preemption and the local interrupts are disabled, so the caller must not sleep, and is advised to release the hwspinlock as soon as possible.}(hj7hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKlhj4hhubh)}(hReturns 0 when successful and an appropriate error code otherwise (most notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs). The function will never sleep.h]hReturns 0 when successful and an appropriate error code otherwise (most notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs). The function will never sleep.}(hjEhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKshj4hhubjF)}(hint hwspin_lock_timeout_irqsave(struct hwspinlock *hwlock, unsigned int to, unsigned long *flags);h]hint hwspin_lock_timeout_irqsave(struct hwspinlock *hwlock, unsigned int to, unsigned long *flags);}hjSsbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhKyhj4hhubh)}(hXLock a previously-assigned hwspinlock with a timeout limit (specified in msecs). If the hwspinlock is already taken, the function will busy loop waiting for it to be released, but give up when the timeout elapses. Upon a successful return from this function, preemption is disabled, local interrupts are disabled and their previous state is saved at the given flags placeholder. The caller must not sleep, and is advised to release the hwspinlock as soon as possible.h]hXLock a previously-assigned hwspinlock with a timeout limit (specified in msecs). If the hwspinlock is already taken, the function will busy loop waiting for it to be released, but give up when the timeout elapses. Upon a successful return from this function, preemption is disabled, local interrupts are disabled and their previous state is saved at the given flags placeholder. The caller must not sleep, and is advised to release the hwspinlock as soon as possible.}(hjahhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK|hj4hhubh)}(hReturns 0 when successful and an appropriate error code otherwise (most notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs).h]hReturns 0 when successful and an appropriate error code otherwise (most notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs).}(hjohhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubh)}(hThe function will never sleep.h]hThe function will never sleep.}(hj}hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubjF)}(hMint hwspin_lock_timeout_raw(struct hwspinlock *hwlock, unsigned int timeout);h]hMint hwspin_lock_timeout_raw(struct hwspinlock *hwlock, unsigned int timeout);}hjsbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhKhj4hhubh)}(hLock a previously-assigned hwspinlock with a timeout limit (specified in msecs). If the hwspinlock is already taken, the function will busy loop waiting for it to be released, but give up when the timeout elapses.h]hLock a previously-assigned hwspinlock with a timeout limit (specified in msecs). If the hwspinlock is already taken, the function will busy loop waiting for it to be released, but give up when the timeout elapses.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubh)}(hCaution: User must protect the routine of getting hardware lock with mutex or spinlock to avoid dead-lock, that will let user can do some time-consuming or sleepable operations under the hardware lock.h]hCaution: User must protect the routine of getting hardware lock with mutex or spinlock to avoid dead-lock, that will let user can do some time-consuming or sleepable operations under the hardware lock.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubh)}(hReturns 0 when successful and an appropriate error code otherwise (most notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs).h]hReturns 0 when successful and an appropriate error code otherwise (most notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubh)}(hThe function will never sleep.h]hThe function will never sleep.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubjF)}(hNint hwspin_lock_timeout_in_atomic(struct hwspinlock *hwlock, unsigned int to);h]hNint hwspin_lock_timeout_in_atomic(struct hwspinlock *hwlock, unsigned int to);}hjsbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhKhj4hhubh)}(hLock a previously-assigned hwspinlock with a timeout limit (specified in msecs). If the hwspinlock is already taken, the function will busy loop waiting for it to be released, but give up when the timeout elapses.h]hLock a previously-assigned hwspinlock with a timeout limit (specified in msecs). If the hwspinlock is already taken, the function will busy loop waiting for it to be released, but give up when the timeout elapses.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubh)}(hmThis function shall be called only from an atomic context and the timeout value shall not exceed a few msecs.h]hmThis function shall be called only from an atomic context and the timeout value shall not exceed a few msecs.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubh)}(hReturns 0 when successful and an appropriate error code otherwise (most notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs).h]hReturns 0 when successful and an appropriate error code otherwise (most notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubh)}(hThe function will never sleep.h]hThe function will never sleep.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubjF)}(h.int hwspin_trylock(struct hwspinlock *hwlock);h]h.int hwspin_trylock(struct hwspinlock *hwlock);}hjsbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhKhj4hhubh)}(h^Attempt to lock a previously-assigned hwspinlock, but immediately fail if it is already taken.h]h^Attempt to lock a previously-assigned hwspinlock, but immediately fail if it is already taken.}(hj%hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubh)}(hUpon a successful return from this function, preemption is disabled so caller must not sleep, and is advised to release the hwspinlock as soon as possible, in order to minimize remote cores polling on the hardware interconnect.h]hUpon a successful return from this function, preemption is disabled so caller must not sleep, and is advised to release the hwspinlock as soon as possible, in order to minimize remote cores polling on the hardware interconnect.}(hj3hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubh)}(hReturns 0 on success and an appropriate error code otherwise (most notably -EBUSY if the hwspinlock was already taken). The function will never sleep.h]hReturns 0 on success and an appropriate error code otherwise (most notably -EBUSY if the hwspinlock was already taken). The function will never sleep.}(hjAhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubjF)}(h2int hwspin_trylock_irq(struct hwspinlock *hwlock);h]h2int hwspin_trylock_irq(struct hwspinlock *hwlock);}hjOsbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhKhj4hhubh)}(h^Attempt to lock a previously-assigned hwspinlock, but immediately fail if it is already taken.h]h^Attempt to lock a previously-assigned hwspinlock, but immediately fail if it is already taken.}(hj]hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubh)}(hUpon a successful return from this function, preemption and the local interrupts are disabled so caller must not sleep, and is advised to release the hwspinlock as soon as possible.h]hUpon a successful return from this function, preemption and the local interrupts are disabled so caller must not sleep, and is advised to release the hwspinlock as soon as possible.}(hjkhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubh)}(hwReturns 0 on success and an appropriate error code otherwise (most notably -EBUSY if the hwspinlock was already taken).h]hwReturns 0 on success and an appropriate error code otherwise (most notably -EBUSY if the hwspinlock was already taken).}(hjyhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubh)}(hThe function will never sleep.h]hThe function will never sleep.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubjF)}(hLint hwspin_trylock_irqsave(struct hwspinlock *hwlock, unsigned long *flags);h]hLint hwspin_trylock_irqsave(struct hwspinlock *hwlock, unsigned long *flags);}hjsbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhKhj4hhubh)}(h^Attempt to lock a previously-assigned hwspinlock, but immediately fail if it is already taken.h]h^Attempt to lock a previously-assigned hwspinlock, but immediately fail if it is already taken.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubh)}(hXUpon a successful return from this function, preemption is disabled, the local interrupts are disabled and their previous state is saved at the given flags placeholder. The caller must not sleep, and is advised to release the hwspinlock as soon as possible.h]hXUpon a successful return from this function, preemption is disabled, the local interrupts are disabled and their previous state is saved at the given flags placeholder. The caller must not sleep, and is advised to release the hwspinlock as soon as possible.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubh)}(hReturns 0 on success and an appropriate error code otherwise (most notably -EBUSY if the hwspinlock was already taken). The function will never sleep.h]hReturns 0 on success and an appropriate error code otherwise (most notably -EBUSY if the hwspinlock was already taken). The function will never sleep.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubjF)}(h2int hwspin_trylock_raw(struct hwspinlock *hwlock);h]h2int hwspin_trylock_raw(struct hwspinlock *hwlock);}hjsbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhKhj4hhubh)}(h^Attempt to lock a previously-assigned hwspinlock, but immediately fail if it is already taken.h]h^Attempt to lock a previously-assigned hwspinlock, but immediately fail if it is already taken.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubh)}(hCaution: User must protect the routine of getting hardware lock with mutex or spinlock to avoid dead-lock, that will let user can do some time-consuming or sleepable operations under the hardware lock.h]hCaution: User must protect the routine of getting hardware lock with mutex or spinlock to avoid dead-lock, that will let user can do some time-consuming or sleepable operations under the hardware lock.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubh)}(hReturns 0 on success and an appropriate error code otherwise (most notably -EBUSY if the hwspinlock was already taken). The function will never sleep.h]hReturns 0 on success and an appropriate error code otherwise (most notably -EBUSY if the hwspinlock was already taken). The function will never sleep.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubjF)}(h8int hwspin_trylock_in_atomic(struct hwspinlock *hwlock);h]h8int hwspin_trylock_in_atomic(struct hwspinlock *hwlock);}hjsbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhKhj4hhubh)}(h^Attempt to lock a previously-assigned hwspinlock, but immediately fail if it is already taken.h]h^Attempt to lock a previously-assigned hwspinlock, but immediately fail if it is already taken.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubh)}(h:This function shall be called only from an atomic context.h]h:This function shall be called only from an atomic context.}(hj!hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubh)}(hReturns 0 on success and an appropriate error code otherwise (most notably -EBUSY if the hwspinlock was already taken). The function will never sleep.h]hReturns 0 on success and an appropriate error code otherwise (most notably -EBUSY if the hwspinlock was already taken). The function will never sleep.}(hj/hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubjF)}(h.void hwspin_unlock(struct hwspinlock *hwlock);h]h.void hwspin_unlock(struct hwspinlock *hwlock);}hj=sbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhKhj4hhubh)}(hvUnlock a previously-locked hwspinlock. Always succeed, and can be called from any context (the function never sleeps).h]hvUnlock a previously-locked hwspinlock. Always succeed, and can be called from any context (the function never sleeps).}(hjKhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4hhubhnote)}(hkcode should **never** unlock an hwspinlock which is already unlocked (there is no protection against this).h]h)}(hkcode should **never** unlock an hwspinlock which is already unlocked (there is no protection against this).h](h code should }(hj_hhhNhNubhstrong)}(h **never**h]hnever}(hjihhhNhNubah}(h]h ]h"]h$]h&]uh1jghj_ubhV unlock an hwspinlock which is already unlocked (there is no protection against this).}(hj_hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhj[ubah}(h]h ]h"]h$]h&]uh1jYhj4hhhhhNubjF)}(h2void hwspin_unlock_irq(struct hwspinlock *hwlock);h]h2void hwspin_unlock_irq(struct hwspinlock *hwlock);}hjsbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhMhj4hhubh)}(hUnlock a previously-locked hwspinlock and enable local interrupts. The caller should **never** unlock an hwspinlock which is already unlocked.h](hUUnlock a previously-locked hwspinlock and enable local interrupts. The caller should }(hjhhhNhNubjh)}(h **never**h]hnever}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jghjubh0 unlock an hwspinlock which is already unlocked.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhj4hhubh)}(hDoing so is considered a bug (there is no protection against this). Upon a successful return from this function, preemption and local interrupts are enabled. This function will never sleep.h]hDoing so is considered a bug (there is no protection against this). Upon a successful return from this function, preemption and local interrupts are enabled. This function will never sleep.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM hj4hhubjF)}(hOvoid hwspin_unlock_irqrestore(struct hwspinlock *hwlock, unsigned long *flags);h]hOvoid hwspin_unlock_irqrestore(struct hwspinlock *hwlock, unsigned long *flags);}hjsbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhMhj4hhubh)}(h&Unlock a previously-locked hwspinlock.h]h&Unlock a previously-locked hwspinlock.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj4hhubh)}(hXNThe caller should **never** unlock an hwspinlock which is already unlocked. Doing so is considered a bug (there is no protection against this). Upon a successful return from this function, preemption is reenabled, and the state of the local interrupts is restored to the state saved at the given flags. This function will never sleep.h](hThe caller should }(hjhhhNhNubjh)}(h **never**h]hnever}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jghjubhX3 unlock an hwspinlock which is already unlocked. Doing so is considered a bug (there is no protection against this). Upon a successful return from this function, preemption is reenabled, and the state of the local interrupts is restored to the state saved at the given flags. This function will never sleep.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhj4hhubjF)}(h2void hwspin_unlock_raw(struct hwspinlock *hwlock);h]h2void hwspin_unlock_raw(struct hwspinlock *hwlock);}hjsbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhMhj4hhubh)}(h&Unlock a previously-locked hwspinlock.h]h&Unlock a previously-locked hwspinlock.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM hj4hhubh)}(hThe caller should **never** unlock an hwspinlock which is already unlocked. Doing so is considered a bug (there is no protection against this). This function will never sleep.h](hThe caller should }(hjhhhNhNubjh)}(h **never**h]hnever}(hj#hhhNhNubah}(h]h ]h"]h$]h&]uh1jghjubh unlock an hwspinlock which is already unlocked. Doing so is considered a bug (there is no protection against this). This function will never sleep.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhM"hj4hhubjF)}(h8void hwspin_unlock_in_atomic(struct hwspinlock *hwlock);h]h8void hwspin_unlock_in_atomic(struct hwspinlock *hwlock);}hj;sbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhM(hj4hhubh)}(h&Unlock a previously-locked hwspinlock.h]h&Unlock a previously-locked hwspinlock.}(hjIhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM*hj4hhubh)}(hThe caller should **never** unlock an hwspinlock which is already unlocked. Doing so is considered a bug (there is no protection against this). This function will never sleep.h](hThe caller should }(hjWhhhNhNubjh)}(h **never**h]hnever}(hj_hhhNhNubah}(h]h ]h"]h$]h&]uh1jghjWubh unlock an hwspinlock which is already unlocked. Doing so is considered a bug (there is no protection against this). This function will never sleep.}(hjWhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhM,hj4hhubeh}(h]user-apiah ]h"]user apiah$]h&]uh1hhhhhhhhK'ubh)}(hhh](h)}(h Typical usageh]h Typical usage}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhM1ubjF)}(hXR#include #include int hwspinlock_example(void) { struct hwspinlock *hwlock; int ret; /* * assign a specific hwspinlock id - this should be called early * by board init code. */ hwlock = hwspin_lock_request_specific(PREDEFINED_LOCK_ID); if (!hwlock) ... /* try to take it, but don't spin on it */ ret = hwspin_trylock(hwlock); if (!ret) { pr_info("lock is already taken\n"); return -EBUSY; } /* * we took the lock, do our thing now, but do NOT sleep */ /* release the lock */ hwspin_unlock(hwlock); /* free the lock */ ret = hwspin_lock_free(hwlock); if (ret) ... return ret; }h]hXR#include #include int hwspinlock_example(void) { struct hwspinlock *hwlock; int ret; /* * assign a specific hwspinlock id - this should be called early * by board init code. */ hwlock = hwspin_lock_request_specific(PREDEFINED_LOCK_ID); if (!hwlock) ... /* try to take it, but don't spin on it */ ret = hwspin_trylock(hwlock); if (!ret) { pr_info("lock is already taken\n"); return -EBUSY; } /* * we took the lock, do our thing now, but do NOT sleep */ /* release the lock */ hwspin_unlock(hwlock); /* free the lock */ ret = hwspin_lock_free(hwlock); if (ret) ... return ret; }}hjsbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhM5hjhhubeh}(h] typical-usageah ]h"] typical usageah$]h&]uh1hhhhhhhhM1ubh)}(hhh](h)}(hAPI for implementorsh]hAPI for implementors}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhM]ubjF)}(hint hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev, const struct hwspinlock_ops *ops, int base_id, int num_locks);h]hint hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev, const struct hwspinlock_ops *ops, int base_id, int num_locks);}hjsbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhMahjhhubh)}(hTo be called from the underlying platform-specific implementation, in 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).h]hTo be called from the underlying platform-specific implementation, in 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).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMdhjhhubh)}(h;Returns 0 on success, or appropriate error code on failure.h]h;Returns 0 on success, or appropriate error code on failure.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMihjhhubjF)}(h;int hwspin_lock_unregister(struct hwspinlock_device *bank);h]h;int hwspin_lock_unregister(struct hwspinlock_device *bank);}hjsbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhMmhjhhubh)}(hTo be called from the underlying vendor-specific implementation, in order to unregister an hwspinlock device (which is usually a bank of numerous locks).h]hTo be called from the underlying vendor-specific implementation, in order to unregister an hwspinlock device (which is usually a bank of numerous locks).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMohjhhubh)}(hDShould be called from a process context (this function might sleep).h]hDShould be called from a process context (this function might sleep).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMshjhhubh)}(hhReturns the address of hwspinlock on success, or NULL on error (e.g. if the hwspinlock is still in use).h]hhReturns the address of hwspinlock on success, or NULL on error (e.g. if the hwspinlock is still in use).}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMuhjhhubeh}(h]api-for-implementorsah ]h"]api for implementorsah$]h&]uh1hhhhhhhhM]ubh)}(hhh](h)}(hImportant structsh]hImportant structs}(hj$hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj!hhhhhMyubh)}(hstruct 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.h]hstruct 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.}(hj2hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM{hj!hhubjF)}(hX/** * 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_device { struct device *dev; const struct hwspinlock_ops *ops; int base_id; int num_locks; struct hwspinlock lock[0]; };h]hX/** * 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_device { struct device *dev; const struct hwspinlock_ops *ops; int base_id; int num_locks; struct hwspinlock lock[0]; };}hj@sbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhMhj!hhubh)}(hsstruct hwspinlock_device contains an array of hwspinlock structs, each of which represents a single hardware lock::h]hrstruct hwspinlock_device contains an array of hwspinlock structs, each of which represents a single hardware lock:}(hjNhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj!hhubjF)}(hX{/** * 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; void *priv; };h]hX{/** * 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; void *priv; };}hj\sbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhMhj!hhubh)}(hWhen 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.h]hWhen 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.}(hjjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj!hhubeh}(h]important-structsah ]h"]important structsah$]h&]uh1hhhhhhhhMyubh)}(hhh](h)}(hImplementation callbacksh]hImplementation callbacks}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhMubh)}(hGThere are three possible callbacks defined in 'struct hwspinlock_ops'::h]hJThere are three possible callbacks defined in ‘struct hwspinlock_ops’:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubjF)}(hstruct hwspinlock_ops { int (*trylock)(struct hwspinlock *lock); void (*unlock)(struct hwspinlock *lock); void (*relax)(struct hwspinlock *lock); };h]hstruct hwspinlock_ops { int (*trylock)(struct hwspinlock *lock); void (*unlock)(struct hwspinlock *lock); void (*relax)(struct hwspinlock *lock); };}hjsbah}(h]h ]h"]h$]h&]jUjVuh1jEhhhMhjhhubh)}(h&The first two callbacks are mandatory:h]h&The first two callbacks are mandatory:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hThe ->trylock() callback should make a single attempt to take the lock, and return 0 on failure and 1 on success. This callback may **not** sleep.h](hThe ->trylock() callback should make a single attempt to take the lock, and return 0 on failure and 1 on success. This callback may }(hjhhhNhNubjh)}(h**not**h]hnot}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jghjubh sleep.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(h]The ->unlock() callback releases the lock. It always succeed, and it, too, may **not** sleep.h](hOThe ->unlock() callback releases the lock. It always succeed, and it, too, may }(hjhhhNhNubjh)}(h**not**h]hnot}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jghjubh sleep.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hThe ->relax() callback is optional. It is called by hwspinlock core while spinning on a lock, and can be used by the underlying implementation to force a delay between two successive invocations of ->trylock(). It may **not** sleep.h](hThe ->relax() callback is optional. It is called by hwspinlock core while spinning on a lock, and can be used by the underlying implementation to force a delay between two successive invocations of ->trylock(). It may }(hjhhhNhNubjh)}(h**not**h]hnot}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jghjubh sleep.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjhhubeh}(h]implementation-callbacksah ]h"]implementation callbacksah$]h&]uh1hhhhhhhhMubeh}(h]hardware-spinlock-frameworkah ]h"]hardware spinlock frameworkah$]h&]uh1hhhhhhhhKubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(hN generatorN datestampN source_linkN source_urlN toc_backlinksentryfootnote_backlinksK sectnum_xformKstrip_commentsNstrip_elements_with_classesN strip_classesN report_levelK halt_levelKexit_status_levelKdebugNwarning_streamN tracebackinput_encoding utf-8-siginput_encoding_error_handlerstrictoutput_encodingutf-8output_encoding_error_handlerjNerror_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourceh _destinationN _config_files]7/var/lib/git/docbuild/linux/Documentation/docutils.confafile_insertion_enabled raw_enabledKline_length_limitM'pep_referencesN pep_base_urlhttps://peps.python.org/pep_file_url_templatepep-%04drfc_referencesN rfc_base_url&https://datatracker.ietf.org/doc/html/ tab_widthKtrim_footnote_reference_spacesyntax_highlightlong smart_quotessmartquotes_locales]character_level_inline_markupdoctitle_xform docinfo_xformKsectsubtitle_xform image_loadinglinkembed_stylesheetcloak_email_addressessection_self_linkenvNubreporterNindirect_targets]substitution_defs}substitution_names}refnames}refids}nameids}(j(j%j1j.j|jyjjjjj}jzj ju nametypes}(j(j1j|jjj}j uh}(j%hj.hjyj4jjjjjzj!jju footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}Rparse_messages]transform_messages] transformerN include_log] decorationNhhub.