xref: /openbmc/linux/include/linux/irq_work.h (revision 64e7f102)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2e360adbeSPeter Zijlstra #ifndef _LINUX_IRQ_WORK_H
3e360adbeSPeter Zijlstra #define _LINUX_IRQ_WORK_H
4e360adbeSPeter Zijlstra 
58c4890d1SPeter Zijlstra #include <linux/smp_types.h>
681097968SSebastian Andrzej Siewior #include <linux/rcuwait.h>
738aaf809SHuang Ying 
8bc6679aeSFrederic Weisbecker /*
9bc6679aeSFrederic Weisbecker  * An entry can be in one of four states:
10bc6679aeSFrederic Weisbecker  *
11bc6679aeSFrederic Weisbecker  * free	     NULL, 0 -> {claimed}       : free to be used
12bc6679aeSFrederic Weisbecker  * claimed   NULL, 3 -> {pending}       : claimed to be enqueued
13bc6679aeSFrederic Weisbecker  * pending   next, 3 -> {busy}          : queued, pending callback
14bc6679aeSFrederic Weisbecker  * busy      NULL, 2 -> {free, claimed} : callback in progress, can be claimed
15bc6679aeSFrederic Weisbecker  */
16bc6679aeSFrederic Weisbecker 
17e360adbeSPeter Zijlstra struct irq_work {
188c4890d1SPeter Zijlstra 	struct __call_single_node node;
19e360adbeSPeter Zijlstra 	void (*func)(struct irq_work *);
2081097968SSebastian Andrzej Siewior 	struct rcuwait irqwait;
21e360adbeSPeter Zijlstra };
22e360adbeSPeter Zijlstra 
237a9f50a0SPeter Zijlstra #define __IRQ_WORK_INIT(_func, _flags) (struct irq_work){	\
247a9f50a0SPeter Zijlstra 	.node = { .u_flags = (_flags), },			\
257a9f50a0SPeter Zijlstra 	.func = (_func),					\
2681097968SSebastian Andrzej Siewior 	.irqwait = __RCUWAIT_INITIALIZER(irqwait),		\
277a9f50a0SPeter Zijlstra }
287a9f50a0SPeter Zijlstra 
297a9f50a0SPeter Zijlstra #define IRQ_WORK_INIT(_func) __IRQ_WORK_INIT(_func, 0)
307a9f50a0SPeter Zijlstra #define IRQ_WORK_INIT_LAZY(_func) __IRQ_WORK_INIT(_func, IRQ_WORK_LAZY)
317a9f50a0SPeter Zijlstra #define IRQ_WORK_INIT_HARD(_func) __IRQ_WORK_INIT(_func, IRQ_WORK_HARD_IRQ)
327a9f50a0SPeter Zijlstra 
337a9f50a0SPeter Zijlstra #define DEFINE_IRQ_WORK(name, _f)				\
347a9f50a0SPeter Zijlstra 	struct irq_work name = IRQ_WORK_INIT(_f)
357a9f50a0SPeter Zijlstra 
36e360adbeSPeter Zijlstra static inline
init_irq_work(struct irq_work * work,void (* func)(struct irq_work *))3738aaf809SHuang Ying void init_irq_work(struct irq_work *work, void (*func)(struct irq_work *))
38e360adbeSPeter Zijlstra {
397a9f50a0SPeter Zijlstra 	*work = IRQ_WORK_INIT(func);
40e360adbeSPeter Zijlstra }
41e360adbeSPeter Zijlstra 
irq_work_is_pending(struct irq_work * work)427a9f50a0SPeter Zijlstra static inline bool irq_work_is_pending(struct irq_work *work)
437a9f50a0SPeter Zijlstra {
447a9f50a0SPeter Zijlstra 	return atomic_read(&work->node.a_flags) & IRQ_WORK_PENDING;
45153bedbaSFrederic Weisbecker }
46153bedbaSFrederic Weisbecker 
irq_work_is_busy(struct irq_work * work)477a9f50a0SPeter Zijlstra static inline bool irq_work_is_busy(struct irq_work *work)
487a9f50a0SPeter Zijlstra {
497a9f50a0SPeter Zijlstra 	return atomic_read(&work->node.a_flags) & IRQ_WORK_BUSY;
507a9f50a0SPeter Zijlstra }
516a02ad66SPeter Zijlstra 
irq_work_is_hard(struct irq_work * work)5209089db7SSebastian Andrzej Siewior static inline bool irq_work_is_hard(struct irq_work *work)
5309089db7SSebastian Andrzej Siewior {
5409089db7SSebastian Andrzej Siewior 	return atomic_read(&work->node.a_flags) & IRQ_WORK_HARD_IRQ;
5509089db7SSebastian Andrzej Siewior }
5609089db7SSebastian Andrzej Siewior 
57cd578abbSPeter Zijlstra bool irq_work_queue(struct irq_work *work);
5847885016SFrederic Weisbecker bool irq_work_queue_on(struct irq_work *work, int cpu);
5947885016SFrederic Weisbecker 
6076a33061SFrederic Weisbecker void irq_work_tick(void);
6138aaf809SHuang Ying void irq_work_sync(struct irq_work *work);
62e360adbeSPeter Zijlstra 
6300b42959SFrederic Weisbecker #ifdef CONFIG_IRQ_WORK
64c5c38ef3SPeter Zijlstra #include <asm/irq_work.h>
65c5c38ef3SPeter Zijlstra 
6671ad00d6SSteven Rostedt void irq_work_run(void);
6700b42959SFrederic Weisbecker bool irq_work_needs_cpu(void);
6825de110dSIngo Molnar void irq_work_single(void *arg);
69*64e7f102SArnd Bergmann 
70*64e7f102SArnd Bergmann void arch_irq_work_raise(void);
71*64e7f102SArnd Bergmann 
7200b42959SFrederic Weisbecker #else
irq_work_needs_cpu(void)73fe8d5261SJames Hogan static inline bool irq_work_needs_cpu(void) { return false; }
irq_work_run(void)7471ad00d6SSteven Rostedt static inline void irq_work_run(void) { }
irq_work_single(void * arg)7525de110dSIngo Molnar static inline void irq_work_single(void *arg) { }
7600b42959SFrederic Weisbecker #endif
7700b42959SFrederic Weisbecker 
78e360adbeSPeter Zijlstra #endif /* _LINUX_IRQ_WORK_H */
79