1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#include <linux/export.h>
29#include <linux/hardirq.h>
30#include <linux/irq.h>
31#include <linux/kernel.h>
32#include <linux/mm.h>
33#include <linux/types.h>
34
35#include <asm/traps.h>
36
37
38
39
40
41static DEFINE_SPINLOCK(kick_handlers_lock);
42static LIST_HEAD(kick_handlers_list);
43
44void kick_register_func(struct kick_irq_handler *kh)
45{
46 unsigned long flags;
47
48 spin_lock_irqsave(&kick_handlers_lock, flags);
49
50 list_add_tail(&kh->list, &kick_handlers_list);
51
52 spin_unlock_irqrestore(&kick_handlers_lock, flags);
53}
54EXPORT_SYMBOL(kick_register_func);
55
56void kick_unregister_func(struct kick_irq_handler *kh)
57{
58 unsigned long flags;
59
60 spin_lock_irqsave(&kick_handlers_lock, flags);
61
62 list_del(&kh->list);
63
64 spin_unlock_irqrestore(&kick_handlers_lock, flags);
65}
66EXPORT_SYMBOL(kick_unregister_func);
67
68TBIRES
69kick_handler(TBIRES State, int SigNum, int Triggers, int Inst, PTBI pTBI)
70{
71 struct pt_regs *old_regs;
72 struct kick_irq_handler *kh;
73 struct list_head *lh;
74 int handled = 0;
75 TBIRES ret;
76
77 head_end(State, ~INTS_OFF_MASK);
78
79
80 if (State.Sig.SaveMask & TBICTX_PRIV_BIT)
81 restart_critical_section(State);
82
83 trace_hardirqs_off();
84
85 old_regs = set_irq_regs((struct pt_regs *)State.Sig.pCtx);
86 irq_enter();
87
88
89
90
91
92 spin_lock(&kick_handlers_lock);
93
94 list_for_each(lh, &kick_handlers_list) {
95 kh = list_entry(lh, struct kick_irq_handler, list);
96
97 ret = kh->func(State, SigNum, Triggers, Inst, pTBI, &handled);
98 if (handled)
99 break;
100 }
101
102 spin_unlock(&kick_handlers_lock);
103
104 WARN_ON(!handled);
105
106 irq_exit();
107 set_irq_regs(old_regs);
108
109 return tail_end(ret);
110}
111