This source file includes following definitions.
- ioei_find_event
- ioei_interrupt
- ioei_init
1
2
3
4
5
6 #include <linux/errno.h>
7 #include <linux/slab.h>
8 #include <linux/export.h>
9 #include <linux/irq.h>
10 #include <linux/interrupt.h>
11 #include <linux/of.h>
12 #include <linux/list.h>
13 #include <linux/notifier.h>
14
15 #include <asm/machdep.h>
16 #include <asm/rtas.h>
17 #include <asm/irq.h>
18 #include <asm/io_event_irq.h>
19
20 #include "pseries.h"
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 ATOMIC_NOTIFIER_HEAD(pseries_ioei_notifier_list);
58 EXPORT_SYMBOL_GPL(pseries_ioei_notifier_list);
59
60 static int ioei_check_exception_token;
61
62 static char ioei_rtas_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned;
63
64
65
66
67
68
69
70
71 static struct pseries_io_event * ioei_find_event(struct rtas_error_log *elog)
72 {
73 struct pseries_errorlog *sect;
74
75
76
77
78
79
80
81 if (unlikely(rtas_error_type(elog) != RTAS_TYPE_IO)) {
82 printk_once(KERN_WARNING"io_event_irq: Unexpected event type %d",
83 rtas_error_type(elog));
84 return NULL;
85 }
86
87 sect = get_pseries_errorlog(elog, PSERIES_ELOG_SECT_ID_IO_EVENT);
88 if (unlikely(!sect)) {
89 printk_once(KERN_WARNING "io_event_irq: RTAS extended event "
90 "log does not contain an IO Event section. "
91 "Could be a bug in system firmware!\n");
92 return NULL;
93 }
94 return (struct pseries_io_event *) §->data;
95 }
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117 static irqreturn_t ioei_interrupt(int irq, void *dev_id)
118 {
119 struct pseries_io_event *event;
120 int rtas_rc;
121
122 for (;;) {
123 rtas_rc = rtas_call(ioei_check_exception_token, 6, 1, NULL,
124 RTAS_VECTOR_EXTERNAL_INTERRUPT,
125 virq_to_hw(irq),
126 RTAS_IO_EVENTS, 1 ,
127 __pa(ioei_rtas_buf),
128 RTAS_DATA_BUF_SIZE);
129 if (rtas_rc != 0)
130 break;
131
132 event = ioei_find_event((struct rtas_error_log *)ioei_rtas_buf);
133 if (!event)
134 continue;
135
136 atomic_notifier_call_chain(&pseries_ioei_notifier_list,
137 0, event);
138 }
139 return IRQ_HANDLED;
140 }
141
142 static int __init ioei_init(void)
143 {
144 struct device_node *np;
145
146 ioei_check_exception_token = rtas_token("check-exception");
147 if (ioei_check_exception_token == RTAS_UNKNOWN_SERVICE)
148 return -ENODEV;
149
150 np = of_find_node_by_path("/event-sources/ibm,io-events");
151 if (np) {
152 request_event_sources_irqs(np, ioei_interrupt, "IO_EVENT");
153 pr_info("IBM I/O event interrupts enabled\n");
154 of_node_put(np);
155 } else {
156 return -ENODEV;
157 }
158 return 0;
159 }
160 machine_subsys_initcall(pseries, ioei_init);
161