diff options
-rw-r--r-- | arch/mips/cavium-octeon/octeon-irq.c | 1422 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/setup.c | 12 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/smp.c | 39 | ||||
-rw-r--r-- | arch/mips/include/asm/mach-cavium-octeon/irq.h | 243 | ||||
-rw-r--r-- | arch/mips/include/asm/octeon/octeon.h | 2 | ||||
-rw-r--r-- | arch/mips/pci/msi-octeon.c | 20 |
6 files changed, 921 insertions, 817 deletions
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index ce7500cdf5b7..03c081da3df4 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c | |||
@@ -3,10 +3,13 @@ | |||
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (C) 2004-2008, 2009, 2010 Cavium Networks | 6 | * Copyright (C) 2004-2008, 2009, 2010, 2011 Cavium Networks |
7 | */ | 7 | */ |
8 | #include <linux/irq.h> | 8 | |
9 | #include <linux/interrupt.h> | 9 | #include <linux/interrupt.h> |
10 | #include <linux/bitops.h> | ||
11 | #include <linux/percpu.h> | ||
12 | #include <linux/irq.h> | ||
10 | #include <linux/smp.h> | 13 | #include <linux/smp.h> |
11 | 14 | ||
12 | #include <asm/octeon/octeon.h> | 15 | #include <asm/octeon/octeon.h> |
@@ -14,6 +17,47 @@ | |||
14 | static DEFINE_RAW_SPINLOCK(octeon_irq_ciu0_lock); | 17 | static DEFINE_RAW_SPINLOCK(octeon_irq_ciu0_lock); |
15 | static DEFINE_RAW_SPINLOCK(octeon_irq_ciu1_lock); | 18 | static DEFINE_RAW_SPINLOCK(octeon_irq_ciu1_lock); |
16 | 19 | ||
20 | static DEFINE_PER_CPU(unsigned long, octeon_irq_ciu0_en_mirror); | ||
21 | static DEFINE_PER_CPU(unsigned long, octeon_irq_ciu1_en_mirror); | ||
22 | |||
23 | static __read_mostly u8 octeon_irq_ciu_to_irq[8][64]; | ||
24 | |||
25 | union octeon_ciu_chip_data { | ||
26 | void *p; | ||
27 | unsigned long l; | ||
28 | struct { | ||
29 | unsigned int line:6; | ||
30 | unsigned int bit:6; | ||
31 | } s; | ||
32 | }; | ||
33 | |||
34 | struct octeon_core_chip_data { | ||
35 | struct mutex core_irq_mutex; | ||
36 | bool current_en; | ||
37 | bool desired_en; | ||
38 | u8 bit; | ||
39 | }; | ||
40 | |||
41 | #define MIPS_CORE_IRQ_LINES 8 | ||
42 | |||
43 | static struct octeon_core_chip_data octeon_irq_core_chip_data[MIPS_CORE_IRQ_LINES]; | ||
44 | |||
45 | static void __init octeon_irq_set_ciu_mapping(int irq, int line, int bit, | ||
46 | struct irq_chip *chip, | ||
47 | irq_flow_handler_t handler) | ||
48 | { | ||
49 | union octeon_ciu_chip_data cd; | ||
50 | |||
51 | irq_set_chip_and_handler(irq, chip, handler); | ||
52 | |||
53 | cd.l = 0; | ||
54 | cd.s.line = line; | ||
55 | cd.s.bit = bit; | ||
56 | |||
57 | irq_set_chip_data(irq, cd.p); | ||
58 | octeon_irq_ciu_to_irq[line][bit] = irq; | ||
59 | } | ||
60 | |||
17 | static int octeon_coreid_for_cpu(int cpu) | 61 | static int octeon_coreid_for_cpu(int cpu) |
18 | { | 62 | { |
19 | #ifdef CONFIG_SMP | 63 | #ifdef CONFIG_SMP |
@@ -23,9 +67,20 @@ static int octeon_coreid_for_cpu(int cpu) | |||
23 | #endif | 67 | #endif |
24 | } | 68 | } |
25 | 69 | ||
26 | static void octeon_irq_core_ack(unsigned int irq) | 70 | static int octeon_cpu_for_coreid(int coreid) |
71 | { | ||
72 | #ifdef CONFIG_SMP | ||
73 | return cpu_number_map(coreid); | ||
74 | #else | ||
75 | return smp_processor_id(); | ||
76 | #endif | ||
77 | } | ||
78 | |||
79 | static void octeon_irq_core_ack(struct irq_data *data) | ||
27 | { | 80 | { |
28 | unsigned int bit = irq - OCTEON_IRQ_SW0; | 81 | struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data); |
82 | unsigned int bit = cd->bit; | ||
83 | |||
29 | /* | 84 | /* |
30 | * We don't need to disable IRQs to make these atomic since | 85 | * We don't need to disable IRQs to make these atomic since |
31 | * they are already disabled earlier in the low level | 86 | * they are already disabled earlier in the low level |
@@ -37,131 +92,133 @@ static void octeon_irq_core_ack(unsigned int irq) | |||
37 | clear_c0_cause(0x100 << bit); | 92 | clear_c0_cause(0x100 << bit); |
38 | } | 93 | } |
39 | 94 | ||
40 | static void octeon_irq_core_eoi(unsigned int irq) | 95 | static void octeon_irq_core_eoi(struct irq_data *data) |
41 | { | 96 | { |
42 | struct irq_desc *desc = irq_to_desc(irq); | 97 | struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data); |
43 | unsigned int bit = irq - OCTEON_IRQ_SW0; | 98 | |
44 | /* | ||
45 | * If an IRQ is being processed while we are disabling it the | ||
46 | * handler will attempt to unmask the interrupt after it has | ||
47 | * been disabled. | ||
48 | */ | ||
49 | if ((unlikely(desc->status & IRQ_DISABLED))) | ||
50 | return; | ||
51 | /* | 99 | /* |
52 | * We don't need to disable IRQs to make these atomic since | 100 | * We don't need to disable IRQs to make these atomic since |
53 | * they are already disabled earlier in the low level | 101 | * they are already disabled earlier in the low level |
54 | * interrupt code. | 102 | * interrupt code. |
55 | */ | 103 | */ |
56 | set_c0_status(0x100 << bit); | 104 | set_c0_status(0x100 << cd->bit); |
57 | } | 105 | } |
58 | 106 | ||
59 | static void octeon_irq_core_enable(unsigned int irq) | 107 | static void octeon_irq_core_set_enable_local(void *arg) |
60 | { | 108 | { |
61 | unsigned long flags; | 109 | struct irq_data *data = arg; |
62 | unsigned int bit = irq - OCTEON_IRQ_SW0; | 110 | struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data); |
111 | unsigned int mask = 0x100 << cd->bit; | ||
63 | 112 | ||
64 | /* | 113 | /* |
65 | * We need to disable interrupts to make sure our updates are | 114 | * Interrupts are already disabled, so these are atomic. |
66 | * atomic. | ||
67 | */ | 115 | */ |
68 | local_irq_save(flags); | 116 | if (cd->desired_en) |
69 | set_c0_status(0x100 << bit); | 117 | set_c0_status(mask); |
70 | local_irq_restore(flags); | 118 | else |
119 | clear_c0_status(mask); | ||
120 | |||
71 | } | 121 | } |
72 | 122 | ||
73 | static void octeon_irq_core_disable_local(unsigned int irq) | 123 | static void octeon_irq_core_disable(struct irq_data *data) |
74 | { | 124 | { |
75 | unsigned long flags; | 125 | struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data); |
76 | unsigned int bit = irq - OCTEON_IRQ_SW0; | 126 | cd->desired_en = false; |
77 | /* | ||
78 | * We need to disable interrupts to make sure our updates are | ||
79 | * atomic. | ||
80 | */ | ||
81 | local_irq_save(flags); | ||
82 | clear_c0_status(0x100 << bit); | ||
83 | local_irq_restore(flags); | ||
84 | } | 127 | } |
85 | 128 | ||
86 | static void octeon_irq_core_disable(unsigned int irq) | 129 | static void octeon_irq_core_enable(struct irq_data *data) |
87 | { | 130 | { |
88 | #ifdef CONFIG_SMP | 131 | struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data); |
89 | on_each_cpu((void (*)(void *)) octeon_irq_core_disable_local, | 132 | cd->desired_en = true; |
90 | (void *) (long) irq, 1); | ||
91 | #else | ||
92 | octeon_irq_core_disable_local(irq); | ||
93 | #endif | ||
94 | } | 133 | } |
95 | 134 | ||
96 | static struct irq_chip octeon_irq_chip_core = { | 135 | static void octeon_irq_core_bus_lock(struct irq_data *data) |
97 | .name = "Core", | 136 | { |
98 | .enable = octeon_irq_core_enable, | 137 | struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data); |
99 | .disable = octeon_irq_core_disable, | ||
100 | .ack = octeon_irq_core_ack, | ||
101 | .eoi = octeon_irq_core_eoi, | ||
102 | }; | ||
103 | 138 | ||
139 | mutex_lock(&cd->core_irq_mutex); | ||
140 | } | ||
104 | 141 | ||
105 | static void octeon_irq_ciu0_ack(unsigned int irq) | 142 | static void octeon_irq_core_bus_sync_unlock(struct irq_data *data) |
106 | { | 143 | { |
107 | switch (irq) { | 144 | struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data); |
108 | case OCTEON_IRQ_GMX_DRP0: | 145 | |
109 | case OCTEON_IRQ_GMX_DRP1: | 146 | if (cd->desired_en != cd->current_en) { |
110 | case OCTEON_IRQ_IPD_DRP: | 147 | on_each_cpu(octeon_irq_core_set_enable_local, data, 1); |
111 | case OCTEON_IRQ_KEY_ZERO: | 148 | |
112 | case OCTEON_IRQ_TIMER0: | 149 | cd->current_en = cd->desired_en; |
113 | case OCTEON_IRQ_TIMER1: | ||
114 | case OCTEON_IRQ_TIMER2: | ||
115 | case OCTEON_IRQ_TIMER3: | ||
116 | { | ||
117 | int index = cvmx_get_core_num() * 2; | ||
118 | u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); | ||
119 | /* | ||
120 | * CIU timer type interrupts must be acknoleged by | ||
121 | * writing a '1' bit to their sum0 bit. | ||
122 | */ | ||
123 | cvmx_write_csr(CVMX_CIU_INTX_SUM0(index), mask); | ||
124 | break; | ||
125 | } | ||
126 | default: | ||
127 | break; | ||
128 | } | 150 | } |
129 | 151 | ||
130 | /* | 152 | mutex_unlock(&cd->core_irq_mutex); |
131 | * In order to avoid any locking accessing the CIU, we | ||
132 | * acknowledge CIU interrupts by disabling all of them. This | ||
133 | * way we can use a per core register and avoid any out of | ||
134 | * core locking requirements. This has the side affect that | ||
135 | * CIU interrupts can't be processed recursively. | ||
136 | * | ||
137 | * We don't need to disable IRQs to make these atomic since | ||
138 | * they are already disabled earlier in the low level | ||
139 | * interrupt code. | ||
140 | */ | ||
141 | clear_c0_status(0x100 << 2); | ||
142 | } | 153 | } |
143 | 154 | ||
144 | static void octeon_irq_ciu0_eoi(unsigned int irq) | 155 | |
156 | static void octeon_irq_core_cpu_online(struct irq_data *data) | ||
145 | { | 157 | { |
146 | /* | 158 | if (irqd_irq_disabled(data)) |
147 | * Enable all CIU interrupts again. We don't need to disable | 159 | octeon_irq_core_eoi(data); |
148 | * IRQs to make these atomic since they are already disabled | 160 | } |
149 | * earlier in the low level interrupt code. | 161 | |
150 | */ | 162 | static void octeon_irq_core_cpu_offline(struct irq_data *data) |
151 | set_c0_status(0x100 << 2); | 163 | { |
164 | if (irqd_irq_disabled(data)) | ||
165 | octeon_irq_core_ack(data); | ||
152 | } | 166 | } |
153 | 167 | ||
154 | static int next_coreid_for_irq(struct irq_desc *desc) | 168 | static struct irq_chip octeon_irq_chip_core = { |
169 | .name = "Core", | ||
170 | .irq_enable = octeon_irq_core_enable, | ||
171 | .irq_disable = octeon_irq_core_disable, | ||
172 | .irq_ack = octeon_irq_core_ack, | ||
173 | .irq_eoi = octeon_irq_core_eoi, | ||
174 | .irq_bus_lock = octeon_irq_core_bus_lock, | ||
175 | .irq_bus_sync_unlock = octeon_irq_core_bus_sync_unlock, | ||
176 | |||
177 | .irq_cpu_online = octeon_irq_core_cpu_online, | ||
178 | .irq_cpu_offline = octeon_irq_core_cpu_offline, | ||
179 | }; | ||
180 | |||
181 | static void __init octeon_irq_init_core(void) | ||
182 | { | ||
183 | int i; | ||
184 | int irq; | ||
185 | struct octeon_core_chip_data *cd; | ||
186 | |||
187 | for (i = 0; i < MIPS_CORE_IRQ_LINES; i++) { | ||
188 | cd = &octeon_irq_core_chip_data[i]; | ||
189 | cd->current_en = false; | ||
190 | cd->desired_en = false; | ||
191 | cd->bit = i; | ||
192 | mutex_init(&cd->core_irq_mutex); | ||
193 | |||
194 | irq = OCTEON_IRQ_SW0 + i; | ||
195 | switch (irq) { | ||
196 | case OCTEON_IRQ_TIMER: | ||
197 | case OCTEON_IRQ_SW0: | ||
198 | case OCTEON_IRQ_SW1: | ||
199 | case OCTEON_IRQ_5: | ||
200 | case OCTEON_IRQ_PERF: | ||
201 | irq_set_chip_data(irq, cd); | ||
202 | irq_set_chip_and_handler(irq, &octeon_irq_chip_core, | ||
203 | handle_percpu_irq); | ||
204 | break; | ||
205 | default: | ||
206 | break; | ||
207 | } | ||
208 | } | ||
209 | } | ||
210 | |||
211 | static int next_cpu_for_irq(struct irq_data *data) | ||
155 | { | 212 | { |
156 | 213 | ||
157 | #ifdef CONFIG_SMP | 214 | #ifdef CONFIG_SMP |
158 | int coreid; | 215 | int cpu; |
159 | int weight = cpumask_weight(desc->affinity); | 216 | int weight = cpumask_weight(data->affinity); |
160 | 217 | ||
161 | if (weight > 1) { | 218 | if (weight > 1) { |
162 | int cpu = smp_processor_id(); | 219 | cpu = smp_processor_id(); |
163 | for (;;) { | 220 | for (;;) { |
164 | cpu = cpumask_next(cpu, desc->affinity); | 221 | cpu = cpumask_next(cpu, data->affinity); |
165 | if (cpu >= nr_cpu_ids) { | 222 | if (cpu >= nr_cpu_ids) { |
166 | cpu = -1; | 223 | cpu = -1; |
167 | continue; | 224 | continue; |
@@ -169,83 +226,175 @@ static int next_coreid_for_irq(struct irq_desc *desc) | |||
169 | break; | 226 | break; |
170 | } | 227 | } |
171 | } | 228 | } |
172 | coreid = octeon_coreid_for_cpu(cpu); | ||
173 | } else if (weight == 1) { | 229 | } else if (weight == 1) { |
174 | coreid = octeon_coreid_for_cpu(cpumask_first(desc->affinity)); | 230 | cpu = cpumask_first(data->affinity); |
175 | } else { | 231 | } else { |
176 | coreid = cvmx_get_core_num(); | 232 | cpu = smp_processor_id(); |
177 | } | 233 | } |
178 | return coreid; | 234 | return cpu; |
179 | #else | 235 | #else |
180 | return cvmx_get_core_num(); | 236 | return smp_processor_id(); |
181 | #endif | 237 | #endif |
182 | } | 238 | } |
183 | 239 | ||
184 | static void octeon_irq_ciu0_enable(unsigned int irq) | 240 | static void octeon_irq_ciu_enable(struct irq_data *data) |
185 | { | 241 | { |
186 | struct irq_desc *desc = irq_to_desc(irq); | 242 | int cpu = next_cpu_for_irq(data); |
187 | int coreid = next_coreid_for_irq(desc); | 243 | int coreid = octeon_coreid_for_cpu(cpu); |
244 | unsigned long *pen; | ||
188 | unsigned long flags; | 245 | unsigned long flags; |
189 | uint64_t en0; | 246 | union octeon_ciu_chip_data cd; |
190 | int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */ | 247 | |
248 | cd.p = irq_data_get_irq_chip_data(data); | ||
191 | 249 | ||
192 | raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags); | 250 | if (cd.s.line == 0) { |
193 | en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); | 251 | raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags); |
194 | en0 |= 1ull << bit; | 252 | pen = &per_cpu(octeon_irq_ciu0_en_mirror, cpu); |
195 | cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0); | 253 | set_bit(cd.s.bit, pen); |
196 | cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); | 254 | cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), *pen); |
197 | raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags); | 255 | raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags); |
256 | } else { | ||
257 | raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags); | ||
258 | pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu); | ||
259 | set_bit(cd.s.bit, pen); | ||
260 | cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), *pen); | ||
261 | raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags); | ||
262 | } | ||
198 | } | 263 | } |
199 | 264 | ||
200 | static void octeon_irq_ciu0_enable_mbox(unsigned int irq) | 265 | static void octeon_irq_ciu_enable_local(struct irq_data *data) |
266 | { | ||
267 | unsigned long *pen; | ||
268 | unsigned long flags; | ||
269 | union octeon_ciu_chip_data cd; | ||
270 | |||
271 | cd.p = irq_data_get_irq_chip_data(data); | ||
272 | |||
273 | if (cd.s.line == 0) { | ||
274 | raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags); | ||
275 | pen = &__get_cpu_var(octeon_irq_ciu0_en_mirror); | ||
276 | set_bit(cd.s.bit, pen); | ||
277 | cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2), *pen); | ||
278 | raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags); | ||
279 | } else { | ||
280 | raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags); | ||
281 | pen = &__get_cpu_var(octeon_irq_ciu1_en_mirror); | ||
282 | set_bit(cd.s.bit, pen); | ||
283 | cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1), *pen); | ||
284 | raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags); | ||
285 | } | ||
286 | } | ||
287 | |||
288 | static void octeon_irq_ciu_disable_local(struct irq_data *data) | ||
289 | { | ||
290 | unsigned long *pen; | ||
291 | unsigned long flags; | ||
292 | union octeon_ciu_chip_data cd; | ||
293 | |||
294 | cd.p = irq_data_get_irq_chip_data(data); | ||
295 | |||
296 | if (cd.s.line == 0) { | ||
297 | raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags); | ||
298 | pen = &__get_cpu_var(octeon_irq_ciu0_en_mirror); | ||
299 | clear_bit(cd.s.bit, pen); | ||
300 | cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2), *pen); | ||
301 | raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags); | ||
302 | } else { | ||
303 | raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags); | ||
304 | pen = &__get_cpu_var(octeon_irq_ciu1_en_mirror); | ||
305 | clear_bit(cd.s.bit, pen); | ||
306 | cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1), *pen); | ||
307 | raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags); | ||
308 | } | ||
309 | } | ||
310 | |||
311 | static void octeon_irq_ciu_disable_all(struct irq_data *data) | ||
201 | { | 312 | { |
202 | int coreid = cvmx_get_core_num(); | ||
203 | unsigned long flags; | 313 | unsigned long flags; |
204 | uint64_t en0; | 314 | unsigned long *pen; |
205 | int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */ | 315 | int cpu; |
316 | union octeon_ciu_chip_data cd; | ||
317 | |||
318 | wmb(); /* Make sure flag changes arrive before register updates. */ | ||
206 | 319 | ||
207 | raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags); | 320 | cd.p = irq_data_get_irq_chip_data(data); |
208 | en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); | 321 | |
209 | en0 |= 1ull << bit; | 322 | if (cd.s.line == 0) { |
210 | cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0); | 323 | raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags); |
211 | cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); | 324 | for_each_online_cpu(cpu) { |
212 | raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags); | 325 | int coreid = octeon_coreid_for_cpu(cpu); |
326 | pen = &per_cpu(octeon_irq_ciu0_en_mirror, cpu); | ||
327 | clear_bit(cd.s.bit, pen); | ||
328 | cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), *pen); | ||
329 | } | ||
330 | raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags); | ||
331 | } else { | ||
332 | raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags); | ||
333 | for_each_online_cpu(cpu) { | ||
334 | int coreid = octeon_coreid_for_cpu(cpu); | ||
335 | pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu); | ||
336 | clear_bit(cd.s.bit, pen); | ||
337 | cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), *pen); | ||
338 | } | ||
339 | raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags); | ||
340 | } | ||
213 | } | 341 | } |
214 | 342 | ||
215 | static void octeon_irq_ciu0_disable(unsigned int irq) | 343 | static void octeon_irq_ciu_enable_all(struct irq_data *data) |
216 | { | 344 | { |
217 | int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */ | ||
218 | unsigned long flags; | 345 | unsigned long flags; |
219 | uint64_t en0; | 346 | unsigned long *pen; |
220 | int cpu; | 347 | int cpu; |
221 | raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags); | 348 | union octeon_ciu_chip_data cd; |
222 | for_each_online_cpu(cpu) { | 349 | |
223 | int coreid = octeon_coreid_for_cpu(cpu); | 350 | cd.p = irq_data_get_irq_chip_data(data); |
224 | en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); | 351 | |
225 | en0 &= ~(1ull << bit); | 352 | if (cd.s.line == 0) { |
226 | cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0); | 353 | raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags); |
354 | for_each_online_cpu(cpu) { | ||
355 | int coreid = octeon_coreid_for_cpu(cpu); | ||
356 | pen = &per_cpu(octeon_irq_ciu0_en_mirror, cpu); | ||
357 | set_bit(cd.s.bit, pen); | ||
358 | cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), *pen); | ||
359 | } | ||
360 | raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags); | ||
361 | } else { | ||
362 | raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags); | ||
363 | for_each_online_cpu(cpu) { | ||
364 | int coreid = octeon_coreid_for_cpu(cpu); | ||
365 | pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu); | ||
366 | set_bit(cd.s.bit, pen); | ||
367 | cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), *pen); | ||
368 | } | ||
369 | raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags); | ||
227 | } | 370 | } |
228 | /* | ||
229 | * We need to do a read after the last update to make sure all | ||
230 | * of them are done. | ||
231 | */ | ||
232 | cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2)); | ||
233 | raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags); | ||
234 | } | 371 | } |
235 | 372 | ||
236 | /* | 373 | /* |
237 | * Enable the irq on the next core in the affinity set for chips that | 374 | * Enable the irq on the next core in the affinity set for chips that |
238 | * have the EN*_W1{S,C} registers. | 375 | * have the EN*_W1{S,C} registers. |
239 | */ | 376 | */ |
240 | static void octeon_irq_ciu0_enable_v2(unsigned int irq) | 377 | static void octeon_irq_ciu_enable_v2(struct irq_data *data) |
241 | { | 378 | { |
242 | int index; | 379 | u64 mask; |
243 | u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); | 380 | int cpu = next_cpu_for_irq(data); |
244 | struct irq_desc *desc = irq_to_desc(irq); | 381 | union octeon_ciu_chip_data cd; |
245 | 382 | ||
246 | if ((desc->status & IRQ_DISABLED) == 0) { | 383 | cd.p = irq_data_get_irq_chip_data(data); |
247 | index = next_coreid_for_irq(desc) * 2; | 384 | mask = 1ull << (cd.s.bit); |
385 | |||
386 | /* | ||
387 | * Called under the desc lock, so these should never get out | ||
388 | * of sync. | ||
389 | */ | ||
390 | if (cd.s.line == 0) { | ||
391 | int index = octeon_coreid_for_cpu(cpu) * 2; | ||
392 | set_bit(cd.s.bit, &per_cpu(octeon_irq_ciu0_en_mirror, cpu)); | ||
248 | cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask); | 393 | cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask); |
394 | } else { | ||
395 | int index = octeon_coreid_for_cpu(cpu) * 2 + 1; | ||
396 | set_bit(cd.s.bit, &per_cpu(octeon_irq_ciu1_en_mirror, cpu)); | ||
397 | cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask); | ||
249 | } | 398 | } |
250 | } | 399 | } |
251 | 400 | ||
@@ -253,83 +402,180 @@ static void octeon_irq_ciu0_enable_v2(unsigned int irq) | |||
253 | * Enable the irq on the current CPU for chips that | 402 | * Enable the irq on the current CPU for chips that |
254 | * have the EN*_W1{S,C} registers. | 403 | * have the EN*_W1{S,C} registers. |
255 | */ | 404 | */ |
256 | static void octeon_irq_ciu0_enable_mbox_v2(unsigned int irq) | 405 | static void octeon_irq_ciu_enable_local_v2(struct irq_data *data) |
257 | { | 406 | { |
258 | int index; | 407 | u64 mask; |
259 | u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); | 408 | union octeon_ciu_chip_data cd; |
409 | |||
410 | cd.p = irq_data_get_irq_chip_data(data); | ||
411 | mask = 1ull << (cd.s.bit); | ||
260 | 412 | ||
261 | index = cvmx_get_core_num() * 2; | 413 | if (cd.s.line == 0) { |
262 | cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask); | 414 | int index = cvmx_get_core_num() * 2; |
415 | set_bit(cd.s.bit, &__get_cpu_var(octeon_irq_ciu0_en_mirror)); | ||
416 | cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask); | ||
417 | } else { | ||
418 | int index = cvmx_get_core_num() * 2 + 1; | ||
419 | set_bit(cd.s.bit, &__get_cpu_var(octeon_irq_ciu1_en_mirror)); | ||
420 | cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask); | ||
421 | } | ||
422 | } | ||
423 | |||
424 | static void octeon_irq_ciu_disable_local_v2(struct irq_data *data) | ||
425 | { | ||
426 | u64 mask; | ||
427 | union octeon_ciu_chip_data cd; | ||
428 | |||
429 | cd.p = irq_data_get_irq_chip_data(data); | ||
430 | mask = 1ull << (cd.s.bit); | ||
431 | |||
432 | if (cd.s.line == 0) { | ||
433 | int index = cvmx_get_core_num() * 2; | ||
434 | clear_bit(cd.s.bit, &__get_cpu_var(octeon_irq_ciu0_en_mirror)); | ||
435 | cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask); | ||
436 | } else { | ||
437 | int index = cvmx_get_core_num() * 2 + 1; | ||
438 | clear_bit(cd.s.bit, &__get_cpu_var(octeon_irq_ciu1_en_mirror)); | ||
439 | cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask); | ||
440 | } | ||
263 | } | 441 | } |
264 | 442 | ||
265 | /* | 443 | /* |
266 | * Disable the irq on the current core for chips that have the EN*_W1{S,C} | 444 | * Write to the W1C bit in CVMX_CIU_INTX_SUM0 to clear the irq. |
267 | * registers. | ||
268 | */ | 445 | */ |
269 | static void octeon_irq_ciu0_ack_v2(unsigned int irq) | 446 | static void octeon_irq_ciu_ack(struct irq_data *data) |
270 | { | 447 | { |
271 | int index = cvmx_get_core_num() * 2; | 448 | u64 mask; |
272 | u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); | 449 | union octeon_ciu_chip_data cd; |
273 | 450 | ||
274 | switch (irq) { | 451 | cd.p = data->chip_data; |
275 | case OCTEON_IRQ_GMX_DRP0: | 452 | mask = 1ull << (cd.s.bit); |
276 | case OCTEON_IRQ_GMX_DRP1: | 453 | |
277 | case OCTEON_IRQ_IPD_DRP: | 454 | if (cd.s.line == 0) { |
278 | case OCTEON_IRQ_KEY_ZERO: | 455 | int index = cvmx_get_core_num() * 2; |
279 | case OCTEON_IRQ_TIMER0: | ||
280 | case OCTEON_IRQ_TIMER1: | ||
281 | case OCTEON_IRQ_TIMER2: | ||
282 | case OCTEON_IRQ_TIMER3: | ||
283 | /* | ||
284 | * CIU timer type interrupts must be acknoleged by | ||
285 | * writing a '1' bit to their sum0 bit. | ||
286 | */ | ||
287 | cvmx_write_csr(CVMX_CIU_INTX_SUM0(index), mask); | 456 | cvmx_write_csr(CVMX_CIU_INTX_SUM0(index), mask); |
288 | break; | 457 | } else { |
289 | default: | 458 | cvmx_write_csr(CVMX_CIU_INT_SUM1, mask); |
290 | break; | ||
291 | } | 459 | } |
292 | |||
293 | cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask); | ||
294 | } | 460 | } |
295 | 461 | ||
296 | /* | 462 | /* |
297 | * Enable the irq on the current core for chips that have the EN*_W1{S,C} | 463 | * Disable the irq on the all cores for chips that have the EN*_W1{S,C} |
298 | * registers. | 464 | * registers. |
299 | */ | 465 | */ |
300 | static void octeon_irq_ciu0_eoi_mbox_v2(unsigned int irq) | 466 | static void octeon_irq_ciu_disable_all_v2(struct irq_data *data) |
301 | { | 467 | { |
302 | struct irq_desc *desc = irq_to_desc(irq); | 468 | int cpu; |
303 | int index = cvmx_get_core_num() * 2; | 469 | u64 mask; |
304 | u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); | 470 | union octeon_ciu_chip_data cd; |
305 | 471 | ||
306 | if (likely((desc->status & IRQ_DISABLED) == 0)) | 472 | wmb(); /* Make sure flag changes arrive before register updates. */ |
307 | cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask); | 473 | |
474 | cd.p = data->chip_data; | ||
475 | mask = 1ull << (cd.s.bit); | ||
476 | |||
477 | if (cd.s.line == 0) { | ||
478 | for_each_online_cpu(cpu) { | ||
479 | int index = octeon_coreid_for_cpu(cpu) * 2; | ||
480 | clear_bit(cd.s.bit, &per_cpu(octeon_irq_ciu0_en_mirror, cpu)); | ||
481 | cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask); | ||
482 | } | ||
483 | } else { | ||
484 | for_each_online_cpu(cpu) { | ||
485 | int index = octeon_coreid_for_cpu(cpu) * 2 + 1; | ||
486 | clear_bit(cd.s.bit, &per_cpu(octeon_irq_ciu1_en_mirror, cpu)); | ||
487 | cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask); | ||
488 | } | ||
489 | } | ||
308 | } | 490 | } |
309 | 491 | ||
310 | /* | 492 | /* |
311 | * Disable the irq on the all cores for chips that have the EN*_W1{S,C} | 493 | * Enable the irq on the all cores for chips that have the EN*_W1{S,C} |
312 | * registers. | 494 | * registers. |
313 | */ | 495 | */ |
314 | static void octeon_irq_ciu0_disable_all_v2(unsigned int irq) | 496 | static void octeon_irq_ciu_enable_all_v2(struct irq_data *data) |
315 | { | 497 | { |
316 | u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); | ||
317 | int index; | ||
318 | int cpu; | 498 | int cpu; |
319 | for_each_online_cpu(cpu) { | 499 | u64 mask; |
320 | index = octeon_coreid_for_cpu(cpu) * 2; | 500 | union octeon_ciu_chip_data cd; |
321 | cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask); | 501 | |
502 | cd.p = data->chip_data; | ||
503 | mask = 1ull << (cd.s.bit); | ||
504 | |||
505 | if (cd.s.line == 0) { | ||
506 | for_each_online_cpu(cpu) { | ||
507 | int index = octeon_coreid_for_cpu(cpu) * 2; | ||
508 | set_bit(cd.s.bit, &per_cpu(octeon_irq_ciu0_en_mirror, cpu)); | ||
509 | cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask); | ||
510 | } | ||
511 | } else { | ||
512 | for_each_online_cpu(cpu) { | ||
513 | int index = octeon_coreid_for_cpu(cpu) * 2 + 1; | ||
514 | set_bit(cd.s.bit, &per_cpu(octeon_irq_ciu1_en_mirror, cpu)); | ||
515 | cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask); | ||
516 | } | ||
322 | } | 517 | } |
323 | } | 518 | } |
324 | 519 | ||
520 | static void octeon_irq_cpu_online_mbox(struct irq_data *data) | ||
521 | { | ||
522 | if (irqd_irq_disabled(data)) | ||
523 | octeon_irq_ciu_enable_local(data); | ||
524 | } | ||
525 | |||
526 | static void octeon_irq_cpu_online_mbox_v2(struct irq_data *data) | ||
527 | { | ||
528 | if (irqd_irq_disabled(data)) | ||
529 | octeon_irq_ciu_enable_local_v2(data); | ||
530 | } | ||
531 | |||
532 | static void octeon_irq_cpu_offline_mbox(struct irq_data *data) | ||
533 | { | ||
534 | if (irqd_irq_disabled(data)) | ||
535 | octeon_irq_ciu_disable_local(data); | ||
536 | } | ||
537 | |||
538 | static void octeon_irq_cpu_offline_mbox_v2(struct irq_data *data) | ||
539 | { | ||
540 | if (irqd_irq_disabled(data)) | ||
541 | octeon_irq_ciu_disable_local_v2(data); | ||
542 | } | ||
543 | |||
325 | #ifdef CONFIG_SMP | 544 | #ifdef CONFIG_SMP |
326 | static int octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask *dest) | 545 | |
546 | static void octeon_irq_cpu_offline_ciu(struct irq_data *data) | ||
547 | { | ||
548 | int cpu = smp_processor_id(); | ||
549 | cpumask_t new_affinity; | ||
550 | |||
551 | if (!cpumask_test_cpu(cpu, data->affinity)) | ||
552 | return; | ||
553 | |||
554 | if (cpumask_weight(data->affinity) > 1) { | ||
555 | /* | ||
556 | * It has multi CPU affinity, just remove this CPU | ||
557 | * from the affinity set. | ||
558 | */ | ||
559 | cpumask_copy(&new_affinity, data->affinity); | ||
560 | cpumask_clear_cpu(cpu, &new_affinity); | ||
561 | } else { | ||
562 | /* Otherwise, put it on lowest numbered online CPU. */ | ||
563 | cpumask_clear(&new_affinity); | ||
564 | cpumask_set_cpu(cpumask_first(cpu_online_mask), &new_affinity); | ||
565 | } | ||
566 | __irq_set_affinity_locked(data, &new_affinity); | ||
567 | } | ||
568 | |||
569 | static int octeon_irq_ciu_set_affinity(struct irq_data *data, | ||
570 | const struct cpumask *dest, bool force) | ||
327 | { | 571 | { |
328 | int cpu; | 572 | int cpu; |
329 | struct irq_desc *desc = irq_to_desc(irq); | 573 | struct irq_desc *desc = irq_to_desc(data->irq); |
330 | int enable_one = (desc->status & IRQ_DISABLED) == 0; | 574 | int enable_one = (desc->status & IRQ_DISABLED) == 0; |
331 | unsigned long flags; | 575 | unsigned long flags; |
332 | int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */ | 576 | union octeon_ciu_chip_data cd; |
577 | |||
578 | cd.p = data->chip_data; | ||
333 | 579 | ||
334 | /* | 580 | /* |
335 | * For non-v2 CIU, we will allow only single CPU affinity. | 581 | * For non-v2 CIU, we will allow only single CPU affinity. |
@@ -339,26 +585,40 @@ static int octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask * | |||
339 | if (cpumask_weight(dest) != 1) | 585 | if (cpumask_weight(dest) != 1) |
340 | return -EINVAL; | 586 | return -EINVAL; |
341 | 587 | ||
342 | raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags); | 588 | if (desc->status & IRQ_DISABLED) |
343 | for_each_online_cpu(cpu) { | 589 | return 0; |
344 | int coreid = octeon_coreid_for_cpu(cpu); | 590 | |
345 | uint64_t en0 = | 591 | if (cd.s.line == 0) { |
346 | cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); | 592 | raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags); |
347 | if (cpumask_test_cpu(cpu, dest) && enable_one) { | 593 | for_each_online_cpu(cpu) { |
348 | enable_one = 0; | 594 | int coreid = octeon_coreid_for_cpu(cpu); |
349 | en0 |= 1ull << bit; | 595 | unsigned long *pen = &per_cpu(octeon_irq_ciu0_en_mirror, cpu); |
350 | } else { | 596 | |
351 | en0 &= ~(1ull << bit); | 597 | if (cpumask_test_cpu(cpu, dest) && enable_one) { |
598 | enable_one = 0; | ||
599 | set_bit(cd.s.bit, pen); | ||
600 | } else { | ||
601 | clear_bit(cd.s.bit, pen); | ||
602 | } | ||
603 | cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), *pen); | ||
604 | } | ||
605 | raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags); | ||
606 | } else { | ||
607 | raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags); | ||
608 | for_each_online_cpu(cpu) { | ||
609 | int coreid = octeon_coreid_for_cpu(cpu); | ||
610 | unsigned long *pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu); | ||
611 | |||
612 | if (cpumask_test_cpu(cpu, dest) && enable_one) { | ||
613 | enable_one = 0; | ||
614 | set_bit(cd.s.bit, pen); | ||
615 | } else { | ||
616 | clear_bit(cd.s.bit, pen); | ||
617 | } | ||
618 | cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), *pen); | ||
352 | } | 619 | } |
353 | cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0); | 620 | raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags); |
354 | } | 621 | } |
355 | /* | ||
356 | * We need to do a read after the last update to make sure all | ||
357 | * of them are done. | ||
358 | */ | ||
359 | cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2)); | ||
360 | raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags); | ||
361 | |||
362 | return 0; | 622 | return 0; |
363 | } | 623 | } |
364 | 624 | ||
@@ -366,22 +626,47 @@ static int octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask * | |||
366 | * Set affinity for the irq for chips that have the EN*_W1{S,C} | 626 | * Set affinity for the irq for chips that have the EN*_W1{S,C} |
367 | * registers. | 627 | * registers. |
368 | */ | 628 | */ |
369 | static int octeon_irq_ciu0_set_affinity_v2(unsigned int irq, | 629 | static int octeon_irq_ciu_set_affinity_v2(struct irq_data *data, |
370 | const struct cpumask *dest) | 630 | const struct cpumask *dest, |
631 | bool force) | ||
371 | { | 632 | { |
372 | int cpu; | 633 | int cpu; |
373 | int index; | 634 | struct irq_desc *desc = irq_to_desc(data->irq); |
374 | struct irq_desc *desc = irq_to_desc(irq); | ||
375 | int enable_one = (desc->status & IRQ_DISABLED) == 0; | 635 | int enable_one = (desc->status & IRQ_DISABLED) == 0; |
376 | u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); | 636 | u64 mask; |
377 | 637 | union octeon_ciu_chip_data cd; | |
378 | for_each_online_cpu(cpu) { | 638 | |
379 | index = octeon_coreid_for_cpu(cpu) * 2; | 639 | if (desc->status & IRQ_DISABLED) |
380 | if (cpumask_test_cpu(cpu, dest) && enable_one) { | 640 | return 0; |
381 | enable_one = 0; | 641 | |
382 | cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask); | 642 | cd.p = data->chip_data; |
383 | } else { | 643 | mask = 1ull << cd.s.bit; |
384 | cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask); | 644 | |
645 | if (cd.s.line == 0) { | ||
646 | for_each_online_cpu(cpu) { | ||
647 | unsigned long *pen = &per_cpu(octeon_irq_ciu0_en_mirror, cpu); | ||
648 | int index = octeon_coreid_for_cpu(cpu) * 2; | ||
649 | if (cpumask_test_cpu(cpu, dest) && enable_one) { | ||
650 | enable_one = 0; | ||
651 | set_bit(cd.s.bit, pen); | ||
652 | cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask); | ||
653 | } else { | ||
654 | clear_bit(cd.s.bit, pen); | ||
655 | cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask); | ||
656 | } | ||
657 | } | ||
658 | } else { | ||
659 | for_each_online_cpu(cpu) { | ||
660 | unsigned long *pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu); | ||
661 | int index = octeon_coreid_for_cpu(cpu) * 2 + 1; | ||
662 | if (cpumask_test_cpu(cpu, dest) && enable_one) { | ||
663 | enable_one = 0; | ||
664 | set_bit(cd.s.bit, pen); | ||
665 | cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask); | ||
666 | } else { | ||
667 | clear_bit(cd.s.bit, pen); | ||
668 | cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask); | ||
669 | } | ||
385 | } | 670 | } |
386 | } | 671 | } |
387 | return 0; | 672 | return 0; |
@@ -389,80 +674,101 @@ static int octeon_irq_ciu0_set_affinity_v2(unsigned int irq, | |||
389 | #endif | 674 | #endif |
390 | 675 | ||
391 | /* | 676 | /* |
677 | * The v1 CIU code already masks things, so supply a dummy version to | ||
678 | * the core chip code. | ||
679 | */ | ||
680 | static void octeon_irq_dummy_mask(struct irq_data *data) | ||
681 | { | ||
682 | return; | ||
683 | } | ||
684 | |||
685 | /* | ||
392 | * Newer octeon chips have support for lockless CIU operation. | 686 | * Newer octeon chips have support for lockless CIU operation. |
393 | */ | 687 | */ |
394 | static struct irq_chip octeon_irq_chip_ciu0_v2 = { | 688 | static struct irq_chip octeon_irq_chip_ciu_v2 = { |
395 | .name = "CIU0", | 689 | .name = "CIU", |
396 | .enable = octeon_irq_ciu0_enable_v2, | 690 | .irq_enable = octeon_irq_ciu_enable_v2, |
397 | .disable = octeon_irq_ciu0_disable_all_v2, | 691 | .irq_disable = octeon_irq_ciu_disable_all_v2, |
398 | .eoi = octeon_irq_ciu0_enable_v2, | 692 | .irq_mask = octeon_irq_ciu_disable_local_v2, |
693 | .irq_unmask = octeon_irq_ciu_enable_v2, | ||
399 | #ifdef CONFIG_SMP | 694 | #ifdef CONFIG_SMP |
400 | .set_affinity = octeon_irq_ciu0_set_affinity_v2, | 695 | .irq_set_affinity = octeon_irq_ciu_set_affinity_v2, |
696 | .irq_cpu_offline = octeon_irq_cpu_offline_ciu, | ||
401 | #endif | 697 | #endif |
402 | }; | 698 | }; |
403 | 699 | ||
404 | static struct irq_chip octeon_irq_chip_ciu0 = { | 700 | static struct irq_chip octeon_irq_chip_ciu_edge_v2 = { |
405 | .name = "CIU0", | 701 | .name = "CIU-E", |
406 | .enable = octeon_irq_ciu0_enable, | 702 | .irq_enable = octeon_irq_ciu_enable_v2, |
407 | .disable = octeon_irq_ciu0_disable, | 703 | .irq_disable = octeon_irq_ciu_disable_all_v2, |
408 | .eoi = octeon_irq_ciu0_eoi, | 704 | .irq_ack = octeon_irq_ciu_ack, |
705 | .irq_mask = octeon_irq_ciu_disable_local_v2, | ||
706 | .irq_unmask = octeon_irq_ciu_enable_v2, | ||
409 | #ifdef CONFIG_SMP | 707 | #ifdef CONFIG_SMP |
410 | .set_affinity = octeon_irq_ciu0_set_affinity, | 708 | .irq_set_affinity = octeon_irq_ciu_set_affinity_v2, |
709 | .irq_cpu_offline = octeon_irq_cpu_offline_ciu, | ||
411 | #endif | 710 | #endif |
412 | }; | 711 | }; |
413 | 712 | ||
414 | /* The mbox versions don't do any affinity or round-robin. */ | 713 | static struct irq_chip octeon_irq_chip_ciu = { |
415 | static struct irq_chip octeon_irq_chip_ciu0_mbox_v2 = { | 714 | .name = "CIU", |
416 | .name = "CIU0-M", | 715 | .irq_enable = octeon_irq_ciu_enable, |
417 | .enable = octeon_irq_ciu0_enable_mbox_v2, | 716 | .irq_disable = octeon_irq_ciu_disable_all, |
418 | .disable = octeon_irq_ciu0_disable, | 717 | .irq_mask = octeon_irq_dummy_mask, |
419 | .eoi = octeon_irq_ciu0_eoi_mbox_v2, | 718 | #ifdef CONFIG_SMP |
719 | .irq_set_affinity = octeon_irq_ciu_set_affinity, | ||
720 | .irq_cpu_offline = octeon_irq_cpu_offline_ciu, | ||
721 | #endif | ||
420 | }; | 722 | }; |
421 | 723 | ||
422 | static struct irq_chip octeon_irq_chip_ciu0_mbox = { | 724 | static struct irq_chip octeon_irq_chip_ciu_edge = { |
423 | .name = "CIU0-M", | 725 | .name = "CIU-E", |
424 | .enable = octeon_irq_ciu0_enable_mbox, | 726 | .irq_enable = octeon_irq_ciu_enable, |
425 | .disable = octeon_irq_ciu0_disable, | 727 | .irq_disable = octeon_irq_ciu_disable_all, |
426 | .eoi = octeon_irq_ciu0_eoi, | 728 | .irq_mask = octeon_irq_dummy_mask, |
729 | .irq_ack = octeon_irq_ciu_ack, | ||
730 | #ifdef CONFIG_SMP | ||
731 | .irq_set_affinity = octeon_irq_ciu_set_affinity, | ||
732 | .irq_cpu_offline = octeon_irq_cpu_offline_ciu, | ||
733 | #endif | ||
427 | }; | 734 | }; |
428 | 735 | ||
429 | static void octeon_irq_ciu1_ack(unsigned int irq) | 736 | /* The mbox versions don't do any affinity or round-robin. */ |
430 | { | 737 | static struct irq_chip octeon_irq_chip_ciu_mbox_v2 = { |
431 | /* | 738 | .name = "CIU-M", |
432 | * In order to avoid any locking accessing the CIU, we | 739 | .irq_enable = octeon_irq_ciu_enable_all_v2, |
433 | * acknowledge CIU interrupts by disabling all of them. This | 740 | .irq_disable = octeon_irq_ciu_disable_all_v2, |
434 | * way we can use a per core register and avoid any out of | 741 | .irq_ack = octeon_irq_ciu_disable_local_v2, |
435 | * core locking requirements. This has the side affect that | 742 | .irq_eoi = octeon_irq_ciu_enable_local_v2, |
436 | * CIU interrupts can't be processed recursively. We don't | 743 | |
437 | * need to disable IRQs to make these atomic since they are | 744 | .irq_cpu_online = octeon_irq_cpu_online_mbox_v2, |
438 | * already disabled earlier in the low level interrupt code. | 745 | .irq_cpu_offline = octeon_irq_cpu_offline_mbox_v2, |
439 | */ | 746 | }; |
440 | clear_c0_status(0x100 << 3); | ||
441 | } | ||
442 | 747 | ||
443 | static void octeon_irq_ciu1_eoi(unsigned int irq) | 748 | static struct irq_chip octeon_irq_chip_ciu_mbox = { |
444 | { | 749 | .name = "CIU-M", |
445 | /* | 750 | .irq_enable = octeon_irq_ciu_enable_all, |
446 | * Enable all CIU interrupts again. We don't need to disable | 751 | .irq_disable = octeon_irq_ciu_disable_all, |
447 | * IRQs to make these atomic since they are already disabled | ||
448 | * earlier in the low level interrupt code. | ||
449 | */ | ||
450 | set_c0_status(0x100 << 3); | ||
451 | } | ||
452 | 752 | ||
453 | static void octeon_irq_ciu1_enable(unsigned int irq) | 753 | .irq_cpu_online = octeon_irq_cpu_online_mbox, |
754 | .irq_cpu_offline = octeon_irq_cpu_offline_mbox, | ||
755 | }; | ||
756 | |||
757 | /* | ||
758 | * Watchdog interrupts are special. They are associated with a single | ||
759 | * core, so we hardwire the affinity to that core. | ||
760 | */ | ||
761 | static void octeon_irq_ciu_wd_enable(struct irq_data *data) | ||
454 | { | 762 | { |
455 | struct irq_desc *desc = irq_to_desc(irq); | ||
456 | int coreid = next_coreid_for_irq(desc); | ||
457 | unsigned long flags; | 763 | unsigned long flags; |
458 | uint64_t en1; | 764 | unsigned long *pen; |
459 | int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */ | 765 | int coreid = data->irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */ |
766 | int cpu = octeon_cpu_for_coreid(coreid); | ||
460 | 767 | ||
461 | raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags); | 768 | raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags); |
462 | en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); | 769 | pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu); |
463 | en1 |= 1ull << bit; | 770 | set_bit(coreid, pen); |
464 | cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1); | 771 | cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), *pen); |
465 | cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); | ||
466 | raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags); | 772 | raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags); |
467 | } | 773 | } |
468 | 774 | ||
@@ -470,286 +776,281 @@ static void octeon_irq_ciu1_enable(unsigned int irq) | |||
470 | * Watchdog interrupts are special. They are associated with a single | 776 | * Watchdog interrupts are special. They are associated with a single |
471 | * core, so we hardwire the affinity to that core. | 777 | * core, so we hardwire the affinity to that core. |
472 | */ | 778 | */ |
473 | static void octeon_irq_ciu1_wd_enable(unsigned int irq) | 779 | static void octeon_irq_ciu1_wd_enable_v2(struct irq_data *data) |
474 | { | 780 | { |
475 | unsigned long flags; | 781 | int coreid = data->irq - OCTEON_IRQ_WDOG0; |
476 | uint64_t en1; | 782 | int cpu = octeon_cpu_for_coreid(coreid); |
477 | int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */ | ||
478 | int coreid = bit; | ||
479 | 783 | ||
480 | raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags); | 784 | set_bit(coreid, &per_cpu(octeon_irq_ciu1_en_mirror, cpu)); |
481 | en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); | 785 | cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(coreid * 2 + 1), 1ull << coreid); |
482 | en1 |= 1ull << bit; | ||
483 | cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1); | ||
484 | cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); | ||
485 | raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags); | ||
486 | } | 786 | } |
487 | 787 | ||
488 | static void octeon_irq_ciu1_disable(unsigned int irq) | 788 | |
789 | static struct irq_chip octeon_irq_chip_ciu_wd_v2 = { | ||
790 | .name = "CIU-W", | ||
791 | .irq_enable = octeon_irq_ciu1_wd_enable_v2, | ||
792 | .irq_disable = octeon_irq_ciu_disable_all_v2, | ||
793 | .irq_mask = octeon_irq_ciu_disable_local_v2, | ||
794 | .irq_unmask = octeon_irq_ciu_enable_local_v2, | ||
795 | }; | ||
796 | |||
797 | static struct irq_chip octeon_irq_chip_ciu_wd = { | ||
798 | .name = "CIU-W", | ||
799 | .irq_enable = octeon_irq_ciu_wd_enable, | ||
800 | .irq_disable = octeon_irq_ciu_disable_all, | ||
801 | .irq_mask = octeon_irq_dummy_mask, | ||
802 | }; | ||
803 | |||
804 | static void octeon_irq_ip2_v1(void) | ||
489 | { | 805 | { |
490 | int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */ | 806 | const unsigned long core_id = cvmx_get_core_num(); |
491 | unsigned long flags; | 807 | u64 ciu_sum = cvmx_read_csr(CVMX_CIU_INTX_SUM0(core_id * 2)); |
492 | uint64_t en1; | 808 | |
493 | int cpu; | 809 | ciu_sum &= __get_cpu_var(octeon_irq_ciu0_en_mirror); |
494 | raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags); | 810 | clear_c0_status(STATUSF_IP2); |
495 | for_each_online_cpu(cpu) { | 811 | if (likely(ciu_sum)) { |
496 | int coreid = octeon_coreid_for_cpu(cpu); | 812 | int bit = fls64(ciu_sum) - 1; |
497 | en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); | 813 | int irq = octeon_irq_ciu_to_irq[0][bit]; |
498 | en1 &= ~(1ull << bit); | 814 | if (likely(irq)) |
499 | cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1); | 815 | do_IRQ(irq); |
816 | else | ||
817 | spurious_interrupt(); | ||
818 | } else { | ||
819 | spurious_interrupt(); | ||
500 | } | 820 | } |
501 | /* | 821 | set_c0_status(STATUSF_IP2); |
502 | * We need to do a read after the last update to make sure all | ||
503 | * of them are done. | ||
504 | */ | ||
505 | cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1)); | ||
506 | raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags); | ||
507 | } | 822 | } |
508 | 823 | ||
509 | /* | 824 | static void octeon_irq_ip2_v2(void) |
510 | * Enable the irq on the current core for chips that have the EN*_W1{S,C} | ||
511 | * registers. | ||
512 | */ | ||
513 | static void octeon_irq_ciu1_enable_v2(unsigned int irq) | ||
514 | { | 825 | { |
515 | int index; | 826 | const unsigned long core_id = cvmx_get_core_num(); |
516 | u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0); | 827 | u64 ciu_sum = cvmx_read_csr(CVMX_CIU_INTX_SUM0(core_id * 2)); |
517 | struct irq_desc *desc = irq_to_desc(irq); | 828 | |
518 | 829 | ciu_sum &= __get_cpu_var(octeon_irq_ciu0_en_mirror); | |
519 | if ((desc->status & IRQ_DISABLED) == 0) { | 830 | if (likely(ciu_sum)) { |
520 | index = next_coreid_for_irq(desc) * 2 + 1; | 831 | int bit = fls64(ciu_sum) - 1; |
521 | cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask); | 832 | int irq = octeon_irq_ciu_to_irq[0][bit]; |
833 | if (likely(irq)) | ||
834 | do_IRQ(irq); | ||
835 | else | ||
836 | spurious_interrupt(); | ||
837 | } else { | ||
838 | spurious_interrupt(); | ||
522 | } | 839 | } |
523 | } | 840 | } |
524 | 841 | static void octeon_irq_ip3_v1(void) | |
525 | /* | ||
526 | * Watchdog interrupts are special. They are associated with a single | ||
527 | * core, so we hardwire the affinity to that core. | ||
528 | */ | ||
529 | static void octeon_irq_ciu1_wd_enable_v2(unsigned int irq) | ||
530 | { | 842 | { |
531 | int index; | 843 | u64 ciu_sum = cvmx_read_csr(CVMX_CIU_INT_SUM1); |
532 | int coreid = irq - OCTEON_IRQ_WDOG0; | 844 | |
533 | u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0); | 845 | ciu_sum &= __get_cpu_var(octeon_irq_ciu1_en_mirror); |
534 | struct irq_desc *desc = irq_to_desc(irq); | 846 | clear_c0_status(STATUSF_IP3); |
535 | 847 | if (likely(ciu_sum)) { | |
536 | if ((desc->status & IRQ_DISABLED) == 0) { | 848 | int bit = fls64(ciu_sum) - 1; |
537 | index = coreid * 2 + 1; | 849 | int irq = octeon_irq_ciu_to_irq[1][bit]; |
538 | cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask); | 850 | if (likely(irq)) |
851 | do_IRQ(irq); | ||
852 | else | ||
853 | spurious_interrupt(); | ||
854 | } else { | ||
855 | spurious_interrupt(); | ||
539 | } | 856 | } |
857 | set_c0_status(STATUSF_IP3); | ||
540 | } | 858 | } |
541 | 859 | ||
542 | /* | 860 | static void octeon_irq_ip3_v2(void) |
543 | * Disable the irq on the current core for chips that have the EN*_W1{S,C} | ||
544 | * registers. | ||
545 | */ | ||
546 | static void octeon_irq_ciu1_ack_v2(unsigned int irq) | ||
547 | { | 861 | { |
548 | int index = cvmx_get_core_num() * 2 + 1; | 862 | u64 ciu_sum = cvmx_read_csr(CVMX_CIU_INT_SUM1); |
549 | u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0); | 863 | |
550 | 864 | ciu_sum &= __get_cpu_var(octeon_irq_ciu1_en_mirror); | |
551 | cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask); | 865 | if (likely(ciu_sum)) { |
866 | int bit = fls64(ciu_sum) - 1; | ||
867 | int irq = octeon_irq_ciu_to_irq[1][bit]; | ||
868 | if (likely(irq)) | ||
869 | do_IRQ(irq); | ||
870 | else | ||
871 | spurious_interrupt(); | ||
872 | } else { | ||
873 | spurious_interrupt(); | ||
874 | } | ||
552 | } | 875 | } |
553 | 876 | ||
554 | /* | 877 | static void octeon_irq_ip4_mask(void) |
555 | * Disable the irq on the all cores for chips that have the EN*_W1{S,C} | ||
556 | * registers. | ||
557 | */ | ||
558 | static void octeon_irq_ciu1_disable_all_v2(unsigned int irq) | ||
559 | { | 878 | { |
560 | u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0); | 879 | clear_c0_status(STATUSF_IP4); |
561 | int index; | 880 | spurious_interrupt(); |
562 | int cpu; | ||
563 | for_each_online_cpu(cpu) { | ||
564 | index = octeon_coreid_for_cpu(cpu) * 2 + 1; | ||
565 | cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask); | ||
566 | } | ||
567 | } | 881 | } |
568 | 882 | ||
569 | #ifdef CONFIG_SMP | 883 | static void (*octeon_irq_ip2)(void); |
570 | static int octeon_irq_ciu1_set_affinity(unsigned int irq, | 884 | static void (*octeon_irq_ip3)(void); |
571 | const struct cpumask *dest) | 885 | static void (*octeon_irq_ip4)(void); |
572 | { | ||
573 | int cpu; | ||
574 | struct irq_desc *desc = irq_to_desc(irq); | ||
575 | int enable_one = (desc->status & IRQ_DISABLED) == 0; | ||
576 | unsigned long flags; | ||
577 | int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */ | ||
578 | 886 | ||
579 | /* | 887 | void __cpuinitdata (*octeon_irq_setup_secondary)(void); |
580 | * For non-v2 CIU, we will allow only single CPU affinity. | ||
581 | * This removes the need to do locking in the .ack/.eoi | ||
582 | * functions. | ||
583 | */ | ||
584 | if (cpumask_weight(dest) != 1) | ||
585 | return -EINVAL; | ||
586 | 888 | ||
587 | raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags); | 889 | static void __cpuinit octeon_irq_percpu_enable(void) |
588 | for_each_online_cpu(cpu) { | 890 | { |
589 | int coreid = octeon_coreid_for_cpu(cpu); | 891 | irq_cpu_online(); |
590 | uint64_t en1 = | 892 | } |
591 | cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); | 893 | |
592 | if (cpumask_test_cpu(cpu, dest) && enable_one) { | 894 | static void __cpuinit octeon_irq_init_ciu_percpu(void) |
593 | enable_one = 0; | 895 | { |
594 | en1 |= 1ull << bit; | 896 | int coreid = cvmx_get_core_num(); |
595 | } else { | ||
596 | en1 &= ~(1ull << bit); | ||
597 | } | ||
598 | cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1); | ||
599 | } | ||
600 | /* | 897 | /* |
601 | * We need to do a read after the last update to make sure all | 898 | * Disable All CIU Interrupts. The ones we need will be |
602 | * of them are done. | 899 | * enabled later. Read the SUM register so we know the write |
900 | * completed. | ||
603 | */ | 901 | */ |
604 | cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1)); | 902 | cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2)), 0); |
605 | raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags); | 903 | cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2 + 1)), 0); |
606 | 904 | cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2)), 0); | |
607 | return 0; | 905 | cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2 + 1)), 0); |
906 | cvmx_read_csr(CVMX_CIU_INTX_SUM0((coreid * 2))); | ||
608 | } | 907 | } |
609 | 908 | ||
610 | /* | 909 | static void __cpuinit octeon_irq_setup_secondary_ciu(void) |
611 | * Set affinity for the irq for chips that have the EN*_W1{S,C} | ||
612 | * registers. | ||
613 | */ | ||
614 | static int octeon_irq_ciu1_set_affinity_v2(unsigned int irq, | ||
615 | const struct cpumask *dest) | ||
616 | { | 910 | { |
617 | int cpu; | ||
618 | int index; | ||
619 | struct irq_desc *desc = irq_to_desc(irq); | ||
620 | int enable_one = (desc->status & IRQ_DISABLED) == 0; | ||
621 | u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0); | ||
622 | for_each_online_cpu(cpu) { | ||
623 | index = octeon_coreid_for_cpu(cpu) * 2 + 1; | ||
624 | if (cpumask_test_cpu(cpu, dest) && enable_one) { | ||
625 | enable_one = 0; | ||
626 | cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask); | ||
627 | } else { | ||
628 | cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask); | ||
629 | } | ||
630 | } | ||
631 | return 0; | ||
632 | } | ||
633 | #endif | ||
634 | 911 | ||
635 | /* | 912 | __get_cpu_var(octeon_irq_ciu0_en_mirror) = 0; |
636 | * Newer octeon chips have support for lockless CIU operation. | 913 | __get_cpu_var(octeon_irq_ciu1_en_mirror) = 0; |
637 | */ | ||
638 | static struct irq_chip octeon_irq_chip_ciu1_v2 = { | ||
639 | .name = "CIU1", | ||
640 | .enable = octeon_irq_ciu1_enable_v2, | ||
641 | .disable = octeon_irq_ciu1_disable_all_v2, | ||
642 | .eoi = octeon_irq_ciu1_enable_v2, | ||
643 | #ifdef CONFIG_SMP | ||
644 | .set_affinity = octeon_irq_ciu1_set_affinity_v2, | ||
645 | #endif | ||
646 | }; | ||
647 | 914 | ||
648 | static struct irq_chip octeon_irq_chip_ciu1 = { | 915 | octeon_irq_init_ciu_percpu(); |
649 | .name = "CIU1", | 916 | octeon_irq_percpu_enable(); |
650 | .enable = octeon_irq_ciu1_enable, | ||
651 | .disable = octeon_irq_ciu1_disable, | ||
652 | .eoi = octeon_irq_ciu1_eoi, | ||
653 | #ifdef CONFIG_SMP | ||
654 | .set_affinity = octeon_irq_ciu1_set_affinity, | ||
655 | #endif | ||
656 | }; | ||
657 | 917 | ||
658 | static struct irq_chip octeon_irq_chip_ciu1_wd_v2 = { | 918 | /* Enable the CIU lines */ |
659 | .name = "CIU1-W", | 919 | set_c0_status(STATUSF_IP3 | STATUSF_IP2); |
660 | .enable = octeon_irq_ciu1_wd_enable_v2, | 920 | clear_c0_status(STATUSF_IP4); |
661 | .disable = octeon_irq_ciu1_disable_all_v2, | 921 | } |
662 | .eoi = octeon_irq_ciu1_wd_enable_v2, | ||
663 | }; | ||
664 | 922 | ||
665 | static struct irq_chip octeon_irq_chip_ciu1_wd = { | 923 | static void __init octeon_irq_init_ciu(void) |
666 | .name = "CIU1-W", | 924 | { |
667 | .enable = octeon_irq_ciu1_wd_enable, | 925 | unsigned int i; |
668 | .disable = octeon_irq_ciu1_disable, | 926 | struct irq_chip *chip; |
669 | .eoi = octeon_irq_ciu1_eoi, | 927 | struct irq_chip *chip_edge; |
670 | }; | 928 | struct irq_chip *chip_mbox; |
929 | struct irq_chip *chip_wd; | ||
930 | |||
931 | octeon_irq_init_ciu_percpu(); | ||
932 | octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu; | ||
671 | 933 | ||
672 | static void (*octeon_ciu0_ack)(unsigned int); | 934 | if (OCTEON_IS_MODEL(OCTEON_CN58XX_PASS2_X) || |
673 | static void (*octeon_ciu1_ack)(unsigned int); | 935 | OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) || |
936 | OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X) || | ||
937 | OCTEON_IS_MODEL(OCTEON_CN6XXX)) { | ||
938 | octeon_irq_ip2 = octeon_irq_ip2_v2; | ||
939 | octeon_irq_ip3 = octeon_irq_ip3_v2; | ||
940 | chip = &octeon_irq_chip_ciu_v2; | ||
941 | chip_edge = &octeon_irq_chip_ciu_edge_v2; | ||
942 | chip_mbox = &octeon_irq_chip_ciu_mbox_v2; | ||
943 | chip_wd = &octeon_irq_chip_ciu_wd_v2; | ||
944 | } else { | ||
945 | octeon_irq_ip2 = octeon_irq_ip2_v1; | ||
946 | octeon_irq_ip3 = octeon_irq_ip3_v1; | ||
947 | chip = &octeon_irq_chip_ciu; | ||
948 | chip_edge = &octeon_irq_chip_ciu_edge; | ||
949 | chip_mbox = &octeon_irq_chip_ciu_mbox; | ||
950 | chip_wd = &octeon_irq_chip_ciu_wd; | ||
951 | } | ||
952 | octeon_irq_ip4 = octeon_irq_ip4_mask; | ||
953 | |||
954 | /* Mips internal */ | ||
955 | octeon_irq_init_core(); | ||
956 | |||
957 | /* CIU_0 */ | ||
958 | for (i = 0; i < 16; i++) | ||
959 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0, chip, handle_level_irq); | ||
960 | for (i = 0; i < 16; i++) | ||
961 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GPIO0, 0, i + 16, chip, handle_level_irq); | ||
962 | |||
963 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq); | ||
964 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq); | ||
965 | |||
966 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART0, 0, 34, chip, handle_level_irq); | ||
967 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART1, 0, 35, chip, handle_level_irq); | ||
968 | |||
969 | for (i = 0; i < 4; i++) | ||
970 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_INT0, 0, i + 36, chip, handle_level_irq); | ||
971 | for (i = 0; i < 4; i++) | ||
972 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_MSI0, 0, i + 40, chip, handle_level_irq); | ||
973 | |||
974 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI, 0, 45, chip, handle_level_irq); | ||
975 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_RML, 0, 46, chip, handle_level_irq); | ||
976 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_TRACE0, 0, 47, chip, handle_level_irq); | ||
977 | |||
978 | for (i = 0; i < 2; i++) | ||
979 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GMX_DRP0, 0, i + 48, chip_edge, handle_edge_irq); | ||
980 | |||
981 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD_DRP, 0, 50, chip_edge, handle_edge_irq); | ||
982 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY_ZERO, 0, 51, chip_edge, handle_edge_irq); | ||
983 | |||
984 | for (i = 0; i < 4; i++) | ||
985 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52, chip_edge, handle_edge_irq); | ||
986 | |||
987 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56, chip, handle_level_irq); | ||
988 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_PCM, 0, 57, chip, handle_level_irq); | ||
989 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_MPI, 0, 58, chip, handle_level_irq); | ||
990 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI2, 0, 59, chip, handle_level_irq); | ||
991 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_POWIQ, 0, 60, chip, handle_level_irq); | ||
992 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPDPPTHR, 0, 61, chip, handle_level_irq); | ||
993 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII0, 0, 62, chip, handle_level_irq); | ||
994 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63, chip, handle_level_irq); | ||
995 | |||
996 | /* CIU_1 */ | ||
997 | for (i = 0; i < 16; i++) | ||
998 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq); | ||
999 | |||
1000 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART2, 1, 16, chip, handle_level_irq); | ||
1001 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB1, 1, 17, chip, handle_level_irq); | ||
1002 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII1, 1, 18, chip, handle_level_irq); | ||
1003 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_NAND, 1, 19, chip, handle_level_irq); | ||
1004 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_MIO, 1, 20, chip, handle_level_irq); | ||
1005 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_IOB, 1, 21, chip, handle_level_irq); | ||
1006 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_FPA, 1, 22, chip, handle_level_irq); | ||
1007 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_POW, 1, 23, chip, handle_level_irq); | ||
1008 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_L2C, 1, 24, chip, handle_level_irq); | ||
1009 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD, 1, 25, chip, handle_level_irq); | ||
1010 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_PIP, 1, 26, chip, handle_level_irq); | ||
1011 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_PKO, 1, 27, chip, handle_level_irq); | ||
1012 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_ZIP, 1, 28, chip, handle_level_irq); | ||
1013 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_TIM, 1, 29, chip, handle_level_irq); | ||
1014 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_RAD, 1, 30, chip, handle_level_irq); | ||
1015 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY, 1, 31, chip, handle_level_irq); | ||
1016 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFA, 1, 32, chip, handle_level_irq); | ||
1017 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_USBCTL, 1, 33, chip, handle_level_irq); | ||
1018 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_SLI, 1, 34, chip, handle_level_irq); | ||
1019 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_DPI, 1, 35, chip, handle_level_irq); | ||
1020 | |||
1021 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGX0, 1, 36, chip, handle_level_irq); | ||
1022 | |||
1023 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGL, 1, 46, chip, handle_level_irq); | ||
1024 | |||
1025 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_PTP, 1, 47, chip_edge, handle_edge_irq); | ||
1026 | |||
1027 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM0, 1, 48, chip, handle_level_irq); | ||
1028 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM1, 1, 49, chip, handle_level_irq); | ||
1029 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO0, 1, 50, chip, handle_level_irq); | ||
1030 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO1, 1, 51, chip, handle_level_irq); | ||
1031 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_LMC0, 1, 52, chip, handle_level_irq); | ||
1032 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFM, 1, 56, chip, handle_level_irq); | ||
1033 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_RST, 1, 63, chip, handle_level_irq); | ||
1034 | |||
1035 | /* Enable the CIU lines */ | ||
1036 | set_c0_status(STATUSF_IP3 | STATUSF_IP2); | ||
1037 | clear_c0_status(STATUSF_IP4); | ||
1038 | } | ||
674 | 1039 | ||
675 | void __init arch_init_irq(void) | 1040 | void __init arch_init_irq(void) |
676 | { | 1041 | { |
677 | unsigned int irq; | ||
678 | struct irq_chip *chip0; | ||
679 | struct irq_chip *chip0_mbox; | ||
680 | struct irq_chip *chip1; | ||
681 | struct irq_chip *chip1_wd; | ||
682 | |||
683 | #ifdef CONFIG_SMP | 1042 | #ifdef CONFIG_SMP |
684 | /* Set the default affinity to the boot cpu. */ | 1043 | /* Set the default affinity to the boot cpu. */ |
685 | cpumask_clear(irq_default_affinity); | 1044 | cpumask_clear(irq_default_affinity); |
686 | cpumask_set_cpu(smp_processor_id(), irq_default_affinity); | 1045 | cpumask_set_cpu(smp_processor_id(), irq_default_affinity); |
687 | #endif | 1046 | #endif |
688 | 1047 | octeon_irq_init_ciu(); | |
689 | if (NR_IRQS < OCTEON_IRQ_LAST) | ||
690 | pr_err("octeon_irq_init: NR_IRQS is set too low\n"); | ||
691 | |||
692 | if (OCTEON_IS_MODEL(OCTEON_CN58XX_PASS2_X) || | ||
693 | OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) || | ||
694 | OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X)) { | ||
695 | octeon_ciu0_ack = octeon_irq_ciu0_ack_v2; | ||
696 | octeon_ciu1_ack = octeon_irq_ciu1_ack_v2; | ||
697 | chip0 = &octeon_irq_chip_ciu0_v2; | ||
698 | chip0_mbox = &octeon_irq_chip_ciu0_mbox_v2; | ||
699 | chip1 = &octeon_irq_chip_ciu1_v2; | ||
700 | chip1_wd = &octeon_irq_chip_ciu1_wd_v2; | ||
701 | } else { | ||
702 | octeon_ciu0_ack = octeon_irq_ciu0_ack; | ||
703 | octeon_ciu1_ack = octeon_irq_ciu1_ack; | ||
704 | chip0 = &octeon_irq_chip_ciu0; | ||
705 | chip0_mbox = &octeon_irq_chip_ciu0_mbox; | ||
706 | chip1 = &octeon_irq_chip_ciu1; | ||
707 | chip1_wd = &octeon_irq_chip_ciu1_wd; | ||
708 | } | ||
709 | |||
710 | /* 0 - 15 reserved for i8259 master and slave controller. */ | ||
711 | |||
712 | /* 17 - 23 Mips internal */ | ||
713 | for (irq = OCTEON_IRQ_SW0; irq <= OCTEON_IRQ_TIMER; irq++) { | ||
714 | set_irq_chip_and_handler(irq, &octeon_irq_chip_core, | ||
715 | handle_percpu_irq); | ||
716 | } | ||
717 | |||
718 | /* 24 - 87 CIU_INT_SUM0 */ | ||
719 | for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_BOOTDMA; irq++) { | ||
720 | switch (irq) { | ||
721 | case OCTEON_IRQ_MBOX0: | ||
722 | case OCTEON_IRQ_MBOX1: | ||
723 | set_irq_chip_and_handler(irq, chip0_mbox, handle_percpu_irq); | ||
724 | break; | ||
725 | default: | ||
726 | set_irq_chip_and_handler(irq, chip0, handle_fasteoi_irq); | ||
727 | break; | ||
728 | } | ||
729 | } | ||
730 | |||
731 | /* 88 - 151 CIU_INT_SUM1 */ | ||
732 | for (irq = OCTEON_IRQ_WDOG0; irq <= OCTEON_IRQ_WDOG15; irq++) | ||
733 | set_irq_chip_and_handler(irq, chip1_wd, handle_fasteoi_irq); | ||
734 | |||
735 | for (irq = OCTEON_IRQ_UART2; irq <= OCTEON_IRQ_RESERVED151; irq++) | ||
736 | set_irq_chip_and_handler(irq, chip1, handle_fasteoi_irq); | ||
737 | |||
738 | set_c0_status(0x300 << 2); | ||
739 | } | 1048 | } |
740 | 1049 | ||
741 | asmlinkage void plat_irq_dispatch(void) | 1050 | asmlinkage void plat_irq_dispatch(void) |
742 | { | 1051 | { |
743 | const unsigned long core_id = cvmx_get_core_num(); | ||
744 | const uint64_t ciu_sum0_address = CVMX_CIU_INTX_SUM0(core_id * 2); | ||
745 | const uint64_t ciu_en0_address = CVMX_CIU_INTX_EN0(core_id * 2); | ||
746 | const uint64_t ciu_sum1_address = CVMX_CIU_INT_SUM1; | ||
747 | const uint64_t ciu_en1_address = CVMX_CIU_INTX_EN1(core_id * 2 + 1); | ||
748 | unsigned long cop0_cause; | 1052 | unsigned long cop0_cause; |
749 | unsigned long cop0_status; | 1053 | unsigned long cop0_status; |
750 | uint64_t ciu_en; | ||
751 | uint64_t ciu_sum; | ||
752 | unsigned int irq; | ||
753 | 1054 | ||
754 | while (1) { | 1055 | while (1) { |
755 | cop0_cause = read_c0_cause(); | 1056 | cop0_cause = read_c0_cause(); |
@@ -757,33 +1058,16 @@ asmlinkage void plat_irq_dispatch(void) | |||
757 | cop0_cause &= cop0_status; | 1058 | cop0_cause &= cop0_status; |
758 | cop0_cause &= ST0_IM; | 1059 | cop0_cause &= ST0_IM; |
759 | 1060 | ||
760 | if (unlikely(cop0_cause & STATUSF_IP2)) { | 1061 | if (unlikely(cop0_cause & STATUSF_IP2)) |
761 | ciu_sum = cvmx_read_csr(ciu_sum0_address); | 1062 | octeon_irq_ip2(); |
762 | ciu_en = cvmx_read_csr(ciu_en0_address); | 1063 | else if (unlikely(cop0_cause & STATUSF_IP3)) |
763 | ciu_sum &= ciu_en; | 1064 | octeon_irq_ip3(); |
764 | if (likely(ciu_sum)) { | 1065 | else if (unlikely(cop0_cause & STATUSF_IP4)) |
765 | irq = fls64(ciu_sum) + OCTEON_IRQ_WORKQ0 - 1; | 1066 | octeon_irq_ip4(); |
766 | octeon_ciu0_ack(irq); | 1067 | else if (likely(cop0_cause)) |
767 | do_IRQ(irq); | ||
768 | } else { | ||
769 | spurious_interrupt(); | ||
770 | } | ||
771 | } else if (unlikely(cop0_cause & STATUSF_IP3)) { | ||
772 | ciu_sum = cvmx_read_csr(ciu_sum1_address); | ||
773 | ciu_en = cvmx_read_csr(ciu_en1_address); | ||
774 | ciu_sum &= ciu_en; | ||
775 | if (likely(ciu_sum)) { | ||
776 | irq = fls64(ciu_sum) + OCTEON_IRQ_WDOG0 - 1; | ||
777 | octeon_ciu1_ack(irq); | ||
778 | do_IRQ(irq); | ||
779 | } else { | ||
780 | spurious_interrupt(); | ||
781 | } | ||
782 | } else if (likely(cop0_cause)) { | ||
783 | do_IRQ(fls(cop0_cause) - 9 + MIPS_CPU_IRQ_BASE); | 1068 | do_IRQ(fls(cop0_cause) - 9 + MIPS_CPU_IRQ_BASE); |
784 | } else { | 1069 | else |
785 | break; | 1070 | break; |
786 | } | ||
787 | } | 1071 | } |
788 | } | 1072 | } |
789 | 1073 | ||
@@ -791,83 +1075,7 @@ asmlinkage void plat_irq_dispatch(void) | |||
791 | 1075 | ||
792 | void fixup_irqs(void) | 1076 | void fixup_irqs(void) |
793 | { | 1077 | { |
794 | int irq; | 1078 | irq_cpu_offline(); |
795 | struct irq_desc *desc; | ||
796 | cpumask_t new_affinity; | ||
797 | unsigned long flags; | ||
798 | int do_set_affinity; | ||
799 | int cpu; | ||
800 | |||
801 | cpu = smp_processor_id(); | ||
802 | |||
803 | for (irq = OCTEON_IRQ_SW0; irq <= OCTEON_IRQ_TIMER; irq++) | ||
804 | octeon_irq_core_disable_local(irq); | ||
805 | |||
806 | for (irq = OCTEON_IRQ_WORKQ0; irq < OCTEON_IRQ_LAST; irq++) { | ||
807 | desc = irq_to_desc(irq); | ||
808 | switch (irq) { | ||
809 | case OCTEON_IRQ_MBOX0: | ||
810 | case OCTEON_IRQ_MBOX1: | ||
811 | /* The eoi function will disable them on this CPU. */ | ||
812 | desc->chip->eoi(irq); | ||
813 | break; | ||
814 | case OCTEON_IRQ_WDOG0: | ||
815 | case OCTEON_IRQ_WDOG1: | ||
816 | case OCTEON_IRQ_WDOG2: | ||
817 | case OCTEON_IRQ_WDOG3: | ||
818 | case OCTEON_IRQ_WDOG4: | ||
819 | case OCTEON_IRQ_WDOG5: | ||
820 | case OCTEON_IRQ_WDOG6: | ||
821 | case OCTEON_IRQ_WDOG7: | ||
822 | case OCTEON_IRQ_WDOG8: | ||
823 | case OCTEON_IRQ_WDOG9: | ||
824 | case OCTEON_IRQ_WDOG10: | ||
825 | case OCTEON_IRQ_WDOG11: | ||
826 | case OCTEON_IRQ_WDOG12: | ||
827 | case OCTEON_IRQ_WDOG13: | ||
828 | case OCTEON_IRQ_WDOG14: | ||
829 | case OCTEON_IRQ_WDOG15: | ||
830 | /* | ||
831 | * These have special per CPU semantics and | ||
832 | * are handled in the watchdog driver. | ||
833 | */ | ||
834 | break; | ||
835 | default: | ||
836 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
837 | /* | ||
838 | * If this irq has an action, it is in use and | ||
839 | * must be migrated if it has affinity to this | ||
840 | * cpu. | ||
841 | */ | ||
842 | if (desc->action && cpumask_test_cpu(cpu, desc->affinity)) { | ||
843 | if (cpumask_weight(desc->affinity) > 1) { | ||
844 | /* | ||
845 | * It has multi CPU affinity, | ||
846 | * just remove this CPU from | ||
847 | * the affinity set. | ||
848 | */ | ||
849 | cpumask_copy(&new_affinity, desc->affinity); | ||
850 | cpumask_clear_cpu(cpu, &new_affinity); | ||
851 | } else { | ||
852 | /* | ||
853 | * Otherwise, put it on lowest | ||
854 | * numbered online CPU. | ||
855 | */ | ||
856 | cpumask_clear(&new_affinity); | ||
857 | cpumask_set_cpu(cpumask_first(cpu_online_mask), &new_affinity); | ||
858 | } | ||
859 | do_set_affinity = 1; | ||
860 | } else { | ||
861 | do_set_affinity = 0; | ||
862 | } | ||
863 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
864 | |||
865 | if (do_set_affinity) | ||
866 | irq_set_affinity(irq, &new_affinity); | ||
867 | |||
868 | break; | ||
869 | } | ||
870 | } | ||
871 | } | 1079 | } |
872 | 1080 | ||
873 | #endif /* CONFIG_HOTPLUG_CPU */ | 1081 | #endif /* CONFIG_HOTPLUG_CPU */ |
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index b0c3686c96dd..8b139bf4a1b5 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c | |||
@@ -420,7 +420,6 @@ void octeon_user_io_init(void) | |||
420 | void __init prom_init(void) | 420 | void __init prom_init(void) |
421 | { | 421 | { |
422 | struct cvmx_sysinfo *sysinfo; | 422 | struct cvmx_sysinfo *sysinfo; |
423 | const int coreid = cvmx_get_core_num(); | ||
424 | int i; | 423 | int i; |
425 | int argc; | 424 | int argc; |
426 | #ifdef CONFIG_CAVIUM_RESERVE32 | 425 | #ifdef CONFIG_CAVIUM_RESERVE32 |
@@ -537,17 +536,6 @@ void __init prom_init(void) | |||
537 | 536 | ||
538 | octeon_uart = octeon_get_boot_uart(); | 537 | octeon_uart = octeon_get_boot_uart(); |
539 | 538 | ||
540 | /* | ||
541 | * Disable All CIU Interrupts. The ones we need will be | ||
542 | * enabled later. Read the SUM register so we know the write | ||
543 | * completed. | ||
544 | */ | ||
545 | cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2)), 0); | ||
546 | cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2 + 1)), 0); | ||
547 | cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2)), 0); | ||
548 | cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2 + 1)), 0); | ||
549 | cvmx_read_csr(CVMX_CIU_INTX_SUM0((coreid * 2))); | ||
550 | |||
551 | #ifdef CONFIG_SMP | 539 | #ifdef CONFIG_SMP |
552 | octeon_write_lcd("LinuxSMP"); | 540 | octeon_write_lcd("LinuxSMP"); |
553 | #else | 541 | #else |
diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 391cefe556b3..ba78b21cc8d0 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c | |||
@@ -171,41 +171,19 @@ static void octeon_boot_secondary(int cpu, struct task_struct *idle) | |||
171 | * After we've done initial boot, this function is called to allow the | 171 | * After we've done initial boot, this function is called to allow the |
172 | * board code to clean up state, if needed | 172 | * board code to clean up state, if needed |
173 | */ | 173 | */ |
174 | static void octeon_init_secondary(void) | 174 | static void __cpuinit octeon_init_secondary(void) |
175 | { | 175 | { |
176 | const int coreid = cvmx_get_core_num(); | ||
177 | union cvmx_ciu_intx_sum0 interrupt_enable; | ||
178 | unsigned int sr; | 176 | unsigned int sr; |
179 | 177 | ||
180 | #ifdef CONFIG_HOTPLUG_CPU | ||
181 | struct linux_app_boot_info *labi; | ||
182 | |||
183 | labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER); | ||
184 | |||
185 | if (labi->labi_signature != LABI_SIGNATURE) | ||
186 | panic("The bootloader version on this board is incorrect."); | ||
187 | #endif | ||
188 | |||
189 | sr = set_c0_status(ST0_BEV); | 178 | sr = set_c0_status(ST0_BEV); |
190 | write_c0_ebase((u32)ebase); | 179 | write_c0_ebase((u32)ebase); |
191 | write_c0_status(sr); | 180 | write_c0_status(sr); |
192 | 181 | ||
193 | octeon_check_cpu_bist(); | 182 | octeon_check_cpu_bist(); |
194 | octeon_init_cvmcount(); | 183 | octeon_init_cvmcount(); |
195 | /* | 184 | |
196 | pr_info("SMP: CPU%d (CoreId %lu) started\n", cpu, coreid); | 185 | octeon_irq_setup_secondary(); |
197 | */ | 186 | raw_local_irq_enable(); |
198 | /* Enable Mailbox interrupts to this core. These are the only | ||
199 | interrupts allowed on line 3 */ | ||
200 | cvmx_write_csr(CVMX_CIU_MBOX_CLRX(coreid), 0xffffffff); | ||
201 | interrupt_enable.u64 = 0; | ||
202 | interrupt_enable.s.mbox = 0x3; | ||
203 | cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2)), interrupt_enable.u64); | ||
204 | cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2 + 1)), 0); | ||
205 | cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2)), 0); | ||
206 | cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2 + 1)), 0); | ||
207 | /* Enable core interrupt processing for 2,3 and 7 */ | ||
208 | set_c0_status(0x8c01); | ||
209 | } | 187 | } |
210 | 188 | ||
211 | /** | 189 | /** |
@@ -214,6 +192,15 @@ static void octeon_init_secondary(void) | |||
214 | */ | 192 | */ |
215 | void octeon_prepare_cpus(unsigned int max_cpus) | 193 | void octeon_prepare_cpus(unsigned int max_cpus) |
216 | { | 194 | { |
195 | #ifdef CONFIG_HOTPLUG_CPU | ||
196 | struct linux_app_boot_info *labi; | ||
197 | |||
198 | labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER); | ||
199 | |||
200 | if (labi->labi_signature != LABI_SIGNATURE) | ||
201 | panic("The bootloader version on this board is incorrect."); | ||
202 | #endif | ||
203 | |||
217 | cvmx_write_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()), 0xffffffff); | 204 | cvmx_write_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()), 0xffffffff); |
218 | if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt, IRQF_DISABLED, | 205 | if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt, IRQF_DISABLED, |
219 | "mailbox0", mailbox_interrupt)) { | 206 | "mailbox0", mailbox_interrupt)) { |
diff --git a/arch/mips/include/asm/mach-cavium-octeon/irq.h b/arch/mips/include/asm/mach-cavium-octeon/irq.h index 6ddab8aef644..5b05f186e395 100644 --- a/arch/mips/include/asm/mach-cavium-octeon/irq.h +++ b/arch/mips/include/asm/mach-cavium-octeon/irq.h | |||
@@ -11,172 +11,91 @@ | |||
11 | #define NR_IRQS OCTEON_IRQ_LAST | 11 | #define NR_IRQS OCTEON_IRQ_LAST |
12 | #define MIPS_CPU_IRQ_BASE OCTEON_IRQ_SW0 | 12 | #define MIPS_CPU_IRQ_BASE OCTEON_IRQ_SW0 |
13 | 13 | ||
14 | /* 0 - 7 represent the i8259 master */ | 14 | enum octeon_irq { |
15 | #define OCTEON_IRQ_I8259M0 0 | 15 | /* 1 - 8 represent the 8 MIPS standard interrupt sources */ |
16 | #define OCTEON_IRQ_I8259M1 1 | 16 | OCTEON_IRQ_SW0 = 1, |
17 | #define OCTEON_IRQ_I8259M2 2 | 17 | OCTEON_IRQ_SW1, |
18 | #define OCTEON_IRQ_I8259M3 3 | 18 | /* CIU0, CUI2, CIU4 are 3, 4, 5 */ |
19 | #define OCTEON_IRQ_I8259M4 4 | 19 | OCTEON_IRQ_5 = 6, |
20 | #define OCTEON_IRQ_I8259M5 5 | 20 | OCTEON_IRQ_PERF, |
21 | #define OCTEON_IRQ_I8259M6 6 | 21 | OCTEON_IRQ_TIMER, |
22 | #define OCTEON_IRQ_I8259M7 7 | 22 | /* sources in CIU_INTX_EN0 */ |
23 | /* 8 - 15 represent the i8259 slave */ | 23 | OCTEON_IRQ_WORKQ0, |
24 | #define OCTEON_IRQ_I8259S0 8 | 24 | OCTEON_IRQ_GPIO0 = OCTEON_IRQ_WORKQ0 + 16, |
25 | #define OCTEON_IRQ_I8259S1 9 | 25 | OCTEON_IRQ_WDOG0 = OCTEON_IRQ_GPIO0 + 16, |
26 | #define OCTEON_IRQ_I8259S2 10 | 26 | OCTEON_IRQ_WDOG15 = OCTEON_IRQ_WDOG0 + 15, |
27 | #define OCTEON_IRQ_I8259S3 11 | 27 | OCTEON_IRQ_MBOX0 = OCTEON_IRQ_WDOG0 + 16, |
28 | #define OCTEON_IRQ_I8259S4 12 | 28 | OCTEON_IRQ_MBOX1, |
29 | #define OCTEON_IRQ_I8259S5 13 | 29 | OCTEON_IRQ_UART0, |
30 | #define OCTEON_IRQ_I8259S6 14 | 30 | OCTEON_IRQ_UART1, |
31 | #define OCTEON_IRQ_I8259S7 15 | 31 | OCTEON_IRQ_UART2, |
32 | /* 16 - 23 represent the 8 MIPS standard interrupt sources */ | 32 | OCTEON_IRQ_PCI_INT0, |
33 | #define OCTEON_IRQ_SW0 16 | 33 | OCTEON_IRQ_PCI_INT1, |
34 | #define OCTEON_IRQ_SW1 17 | 34 | OCTEON_IRQ_PCI_INT2, |
35 | #define OCTEON_IRQ_CIU0 18 | 35 | OCTEON_IRQ_PCI_INT3, |
36 | #define OCTEON_IRQ_CIU1 19 | 36 | OCTEON_IRQ_PCI_MSI0, |
37 | #define OCTEON_IRQ_CIU4 20 | 37 | OCTEON_IRQ_PCI_MSI1, |
38 | #define OCTEON_IRQ_5 21 | 38 | OCTEON_IRQ_PCI_MSI2, |
39 | #define OCTEON_IRQ_PERF 22 | 39 | OCTEON_IRQ_PCI_MSI3, |
40 | #define OCTEON_IRQ_TIMER 23 | 40 | |
41 | /* 24 - 87 represent the sources in CIU_INTX_EN0 */ | 41 | OCTEON_IRQ_TWSI, |
42 | #define OCTEON_IRQ_WORKQ0 24 | 42 | OCTEON_IRQ_TWSI2, |
43 | #define OCTEON_IRQ_WORKQ1 25 | 43 | OCTEON_IRQ_RML, |
44 | #define OCTEON_IRQ_WORKQ2 26 | 44 | OCTEON_IRQ_TRACE0, |
45 | #define OCTEON_IRQ_WORKQ3 27 | 45 | OCTEON_IRQ_GMX_DRP0 = OCTEON_IRQ_TRACE0 + 4, |
46 | #define OCTEON_IRQ_WORKQ4 28 | 46 | OCTEON_IRQ_IPD_DRP = OCTEON_IRQ_GMX_DRP0 + 5, |
47 | #define OCTEON_IRQ_WORKQ5 29 | 47 | OCTEON_IRQ_KEY_ZERO, |
48 | #define OCTEON_IRQ_WORKQ6 30 | 48 | OCTEON_IRQ_TIMER0, |
49 | #define OCTEON_IRQ_WORKQ7 31 | 49 | OCTEON_IRQ_TIMER1, |
50 | #define OCTEON_IRQ_WORKQ8 32 | 50 | OCTEON_IRQ_TIMER2, |
51 | #define OCTEON_IRQ_WORKQ9 33 | 51 | OCTEON_IRQ_TIMER3, |
52 | #define OCTEON_IRQ_WORKQ10 34 | 52 | OCTEON_IRQ_USB0, |
53 | #define OCTEON_IRQ_WORKQ11 35 | 53 | OCTEON_IRQ_USB1, |
54 | #define OCTEON_IRQ_WORKQ12 36 | 54 | OCTEON_IRQ_PCM, |
55 | #define OCTEON_IRQ_WORKQ13 37 | 55 | OCTEON_IRQ_MPI, |
56 | #define OCTEON_IRQ_WORKQ14 38 | 56 | OCTEON_IRQ_POWIQ, |
57 | #define OCTEON_IRQ_WORKQ15 39 | 57 | OCTEON_IRQ_IPDPPTHR, |
58 | #define OCTEON_IRQ_GPIO0 40 | 58 | OCTEON_IRQ_MII0, |
59 | #define OCTEON_IRQ_GPIO1 41 | 59 | OCTEON_IRQ_MII1, |
60 | #define OCTEON_IRQ_GPIO2 42 | 60 | OCTEON_IRQ_BOOTDMA, |
61 | #define OCTEON_IRQ_GPIO3 43 | 61 | |
62 | #define OCTEON_IRQ_GPIO4 44 | 62 | OCTEON_IRQ_NAND, |
63 | #define OCTEON_IRQ_GPIO5 45 | 63 | OCTEON_IRQ_MIO, /* Summary of MIO_BOOT_ERR */ |
64 | #define OCTEON_IRQ_GPIO6 46 | 64 | OCTEON_IRQ_IOB, /* Summary of IOB_INT_SUM */ |
65 | #define OCTEON_IRQ_GPIO7 47 | 65 | OCTEON_IRQ_FPA, /* Summary of FPA_INT_SUM */ |
66 | #define OCTEON_IRQ_GPIO8 48 | 66 | OCTEON_IRQ_POW, /* Summary of POW_ECC_ERR */ |
67 | #define OCTEON_IRQ_GPIO9 49 | 67 | OCTEON_IRQ_L2C, /* Summary of L2C_INT_STAT */ |
68 | #define OCTEON_IRQ_GPIO10 50 | 68 | OCTEON_IRQ_IPD, /* Summary of IPD_INT_SUM */ |
69 | #define OCTEON_IRQ_GPIO11 51 | 69 | OCTEON_IRQ_PIP, /* Summary of PIP_INT_REG */ |
70 | #define OCTEON_IRQ_GPIO12 52 | 70 | OCTEON_IRQ_PKO, /* Summary of PKO_REG_ERROR */ |
71 | #define OCTEON_IRQ_GPIO13 53 | 71 | OCTEON_IRQ_ZIP, /* Summary of ZIP_ERROR */ |
72 | #define OCTEON_IRQ_GPIO14 54 | 72 | OCTEON_IRQ_TIM, /* Summary of TIM_REG_ERROR */ |
73 | #define OCTEON_IRQ_GPIO15 55 | 73 | OCTEON_IRQ_RAD, /* Summary of RAD_REG_ERROR */ |
74 | #define OCTEON_IRQ_MBOX0 56 | 74 | OCTEON_IRQ_KEY, /* Summary of KEY_INT_SUM */ |
75 | #define OCTEON_IRQ_MBOX1 57 | 75 | OCTEON_IRQ_DFA, /* Summary of DFA */ |
76 | #define OCTEON_IRQ_UART0 58 | 76 | OCTEON_IRQ_USBCTL, /* Summary of USBN0_INT_SUM */ |
77 | #define OCTEON_IRQ_UART1 59 | 77 | OCTEON_IRQ_SLI, /* Summary of SLI_INT_SUM */ |
78 | #define OCTEON_IRQ_PCI_INT0 60 | 78 | OCTEON_IRQ_DPI, /* Summary of DPI_INT_SUM */ |
79 | #define OCTEON_IRQ_PCI_INT1 61 | 79 | OCTEON_IRQ_AGX0, /* Summary of GMX0*+PCS0_INT*_REG */ |
80 | #define OCTEON_IRQ_PCI_INT2 62 | 80 | OCTEON_IRQ_AGL = OCTEON_IRQ_AGX0 + 5, |
81 | #define OCTEON_IRQ_PCI_INT3 63 | 81 | OCTEON_IRQ_PTP, |
82 | #define OCTEON_IRQ_PCI_MSI0 64 | 82 | OCTEON_IRQ_PEM0, |
83 | #define OCTEON_IRQ_PCI_MSI1 65 | 83 | OCTEON_IRQ_PEM1, |
84 | #define OCTEON_IRQ_PCI_MSI2 66 | 84 | OCTEON_IRQ_SRIO0, |
85 | #define OCTEON_IRQ_PCI_MSI3 67 | 85 | OCTEON_IRQ_SRIO1, |
86 | #define OCTEON_IRQ_RESERVED68 68 /* Summary of CIU_INT_SUM1 */ | 86 | OCTEON_IRQ_LMC0, |
87 | #define OCTEON_IRQ_TWSI 69 | 87 | OCTEON_IRQ_DFM = OCTEON_IRQ_LMC0 + 4, /* Summary of DFM */ |
88 | #define OCTEON_IRQ_RML 70 | 88 | OCTEON_IRQ_RST, |
89 | #define OCTEON_IRQ_TRACE 71 | 89 | }; |
90 | #define OCTEON_IRQ_GMX_DRP0 72 | ||
91 | #define OCTEON_IRQ_GMX_DRP1 73 | ||
92 | #define OCTEON_IRQ_IPD_DRP 74 | ||
93 | #define OCTEON_IRQ_KEY_ZERO 75 | ||
94 | #define OCTEON_IRQ_TIMER0 76 | ||
95 | #define OCTEON_IRQ_TIMER1 77 | ||
96 | #define OCTEON_IRQ_TIMER2 78 | ||
97 | #define OCTEON_IRQ_TIMER3 79 | ||
98 | #define OCTEON_IRQ_USB0 80 | ||
99 | #define OCTEON_IRQ_PCM 81 | ||
100 | #define OCTEON_IRQ_MPI 82 | ||
101 | #define OCTEON_IRQ_TWSI2 83 | ||
102 | #define OCTEON_IRQ_POWIQ 84 | ||
103 | #define OCTEON_IRQ_IPDPPTHR 85 | ||
104 | #define OCTEON_IRQ_MII0 86 | ||
105 | #define OCTEON_IRQ_BOOTDMA 87 | ||
106 | /* 88 - 151 represent the sources in CIU_INTX_EN1 */ | ||
107 | #define OCTEON_IRQ_WDOG0 88 | ||
108 | #define OCTEON_IRQ_WDOG1 89 | ||
109 | #define OCTEON_IRQ_WDOG2 90 | ||
110 | #define OCTEON_IRQ_WDOG3 91 | ||
111 | #define OCTEON_IRQ_WDOG4 92 | ||
112 | #define OCTEON_IRQ_WDOG5 93 | ||
113 | #define OCTEON_IRQ_WDOG6 94 | ||
114 | #define OCTEON_IRQ_WDOG7 95 | ||
115 | #define OCTEON_IRQ_WDOG8 96 | ||
116 | #define OCTEON_IRQ_WDOG9 97 | ||
117 | #define OCTEON_IRQ_WDOG10 98 | ||
118 | #define OCTEON_IRQ_WDOG11 99 | ||
119 | #define OCTEON_IRQ_WDOG12 100 | ||
120 | #define OCTEON_IRQ_WDOG13 101 | ||
121 | #define OCTEON_IRQ_WDOG14 102 | ||
122 | #define OCTEON_IRQ_WDOG15 103 | ||
123 | #define OCTEON_IRQ_UART2 104 | ||
124 | #define OCTEON_IRQ_USB1 105 | ||
125 | #define OCTEON_IRQ_MII1 106 | ||
126 | #define OCTEON_IRQ_RESERVED107 107 | ||
127 | #define OCTEON_IRQ_RESERVED108 108 | ||
128 | #define OCTEON_IRQ_RESERVED109 109 | ||
129 | #define OCTEON_IRQ_RESERVED110 110 | ||
130 | #define OCTEON_IRQ_RESERVED111 111 | ||
131 | #define OCTEON_IRQ_RESERVED112 112 | ||
132 | #define OCTEON_IRQ_RESERVED113 113 | ||
133 | #define OCTEON_IRQ_RESERVED114 114 | ||
134 | #define OCTEON_IRQ_RESERVED115 115 | ||
135 | #define OCTEON_IRQ_RESERVED116 116 | ||
136 | #define OCTEON_IRQ_RESERVED117 117 | ||
137 | #define OCTEON_IRQ_RESERVED118 118 | ||
138 | #define OCTEON_IRQ_RESERVED119 119 | ||
139 | #define OCTEON_IRQ_RESERVED120 120 | ||
140 | #define OCTEON_IRQ_RESERVED121 121 | ||
141 | #define OCTEON_IRQ_RESERVED122 122 | ||
142 | #define OCTEON_IRQ_RESERVED123 123 | ||
143 | #define OCTEON_IRQ_RESERVED124 124 | ||
144 | #define OCTEON_IRQ_RESERVED125 125 | ||
145 | #define OCTEON_IRQ_RESERVED126 126 | ||
146 | #define OCTEON_IRQ_RESERVED127 127 | ||
147 | #define OCTEON_IRQ_RESERVED128 128 | ||
148 | #define OCTEON_IRQ_RESERVED129 129 | ||
149 | #define OCTEON_IRQ_RESERVED130 130 | ||
150 | #define OCTEON_IRQ_RESERVED131 131 | ||
151 | #define OCTEON_IRQ_RESERVED132 132 | ||
152 | #define OCTEON_IRQ_RESERVED133 133 | ||
153 | #define OCTEON_IRQ_RESERVED134 134 | ||
154 | #define OCTEON_IRQ_RESERVED135 135 | ||
155 | #define OCTEON_IRQ_RESERVED136 136 | ||
156 | #define OCTEON_IRQ_RESERVED137 137 | ||
157 | #define OCTEON_IRQ_RESERVED138 138 | ||
158 | #define OCTEON_IRQ_RESERVED139 139 | ||
159 | #define OCTEON_IRQ_RESERVED140 140 | ||
160 | #define OCTEON_IRQ_RESERVED141 141 | ||
161 | #define OCTEON_IRQ_RESERVED142 142 | ||
162 | #define OCTEON_IRQ_RESERVED143 143 | ||
163 | #define OCTEON_IRQ_RESERVED144 144 | ||
164 | #define OCTEON_IRQ_RESERVED145 145 | ||
165 | #define OCTEON_IRQ_RESERVED146 146 | ||
166 | #define OCTEON_IRQ_RESERVED147 147 | ||
167 | #define OCTEON_IRQ_RESERVED148 148 | ||
168 | #define OCTEON_IRQ_RESERVED149 149 | ||
169 | #define OCTEON_IRQ_RESERVED150 150 | ||
170 | #define OCTEON_IRQ_RESERVED151 151 | ||
171 | 90 | ||
172 | #ifdef CONFIG_PCI_MSI | 91 | #ifdef CONFIG_PCI_MSI |
173 | /* 152 - 215 represent the MSI interrupts 0-63 */ | 92 | /* 152 - 407 represent the MSI interrupts 0-255 */ |
174 | #define OCTEON_IRQ_MSI_BIT0 152 | 93 | #define OCTEON_IRQ_MSI_BIT0 (OCTEON_IRQ_RST + 1) |
175 | #define OCTEON_IRQ_MSI_LAST (OCTEON_IRQ_MSI_BIT0 + 255) | ||
176 | 94 | ||
177 | #define OCTEON_IRQ_LAST (OCTEON_IRQ_MSI_LAST + 1) | 95 | #define OCTEON_IRQ_MSI_LAST (OCTEON_IRQ_MSI_BIT0 + 255) |
96 | #define OCTEON_IRQ_LAST (OCTEON_IRQ_MSI_LAST + 1) | ||
178 | #else | 97 | #else |
179 | #define OCTEON_IRQ_LAST 152 | 98 | #define OCTEON_IRQ_LAST (OCTEON_IRQ_RST + 1) |
180 | #endif | 99 | #endif |
181 | 100 | ||
182 | #endif | 101 | #endif |
diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h index 6b34afd0d4e7..f72f768cd3a4 100644 --- a/arch/mips/include/asm/octeon/octeon.h +++ b/arch/mips/include/asm/octeon/octeon.h | |||
@@ -257,4 +257,6 @@ extern struct cvmx_bootinfo *octeon_bootinfo; | |||
257 | 257 | ||
258 | extern uint64_t octeon_bootloader_entry_addr; | 258 | extern uint64_t octeon_bootloader_entry_addr; |
259 | 259 | ||
260 | extern void (*octeon_irq_setup_secondary)(void); | ||
261 | |||
260 | #endif /* __ASM_OCTEON_OCTEON_H */ | 262 | #endif /* __ASM_OCTEON_OCTEON_H */ |
diff --git a/arch/mips/pci/msi-octeon.c b/arch/mips/pci/msi-octeon.c index d8080499872a..eebaf5616d26 100644 --- a/arch/mips/pci/msi-octeon.c +++ b/arch/mips/pci/msi-octeon.c | |||
@@ -259,11 +259,11 @@ static DEFINE_RAW_SPINLOCK(octeon_irq_msi_lock); | |||
259 | static u64 msi_rcv_reg[4]; | 259 | static u64 msi_rcv_reg[4]; |
260 | static u64 mis_ena_reg[4]; | 260 | static u64 mis_ena_reg[4]; |
261 | 261 | ||
262 | static void octeon_irq_msi_enable_pcie(unsigned int irq) | 262 | static void octeon_irq_msi_enable_pcie(struct irq_data *data) |
263 | { | 263 | { |
264 | u64 en; | 264 | u64 en; |
265 | unsigned long flags; | 265 | unsigned long flags; |
266 | int msi_number = irq - OCTEON_IRQ_MSI_BIT0; | 266 | int msi_number = data->irq - OCTEON_IRQ_MSI_BIT0; |
267 | int irq_index = msi_number >> 6; | 267 | int irq_index = msi_number >> 6; |
268 | int irq_bit = msi_number & 0x3f; | 268 | int irq_bit = msi_number & 0x3f; |
269 | 269 | ||
@@ -275,11 +275,11 @@ static void octeon_irq_msi_enable_pcie(unsigned int irq) | |||
275 | raw_spin_unlock_irqrestore(&octeon_irq_msi_lock, flags); | 275 | raw_spin_unlock_irqrestore(&octeon_irq_msi_lock, flags); |
276 | } | 276 | } |
277 | 277 | ||
278 | static void octeon_irq_msi_disable_pcie(unsigned int irq) | 278 | static void octeon_irq_msi_disable_pcie(struct irq_data *data) |
279 | { | 279 | { |
280 | u64 en; | 280 | u64 en; |
281 | unsigned long flags; | 281 | unsigned long flags; |
282 | int msi_number = irq - OCTEON_IRQ_MSI_BIT0; | 282 | int msi_number = data->irq - OCTEON_IRQ_MSI_BIT0; |
283 | int irq_index = msi_number >> 6; | 283 | int irq_index = msi_number >> 6; |
284 | int irq_bit = msi_number & 0x3f; | 284 | int irq_bit = msi_number & 0x3f; |
285 | 285 | ||
@@ -293,11 +293,11 @@ static void octeon_irq_msi_disable_pcie(unsigned int irq) | |||
293 | 293 | ||
294 | static struct irq_chip octeon_irq_chip_msi_pcie = { | 294 | static struct irq_chip octeon_irq_chip_msi_pcie = { |
295 | .name = "MSI", | 295 | .name = "MSI", |
296 | .enable = octeon_irq_msi_enable_pcie, | 296 | .irq_enable = octeon_irq_msi_enable_pcie, |
297 | .disable = octeon_irq_msi_disable_pcie, | 297 | .irq_disable = octeon_irq_msi_disable_pcie, |
298 | }; | 298 | }; |
299 | 299 | ||
300 | static void octeon_irq_msi_enable_pci(unsigned int irq) | 300 | static void octeon_irq_msi_enable_pci(struct irq_data *data) |
301 | { | 301 | { |
302 | /* | 302 | /* |
303 | * Octeon PCI doesn't have the ability to mask/unmask MSI | 303 | * Octeon PCI doesn't have the ability to mask/unmask MSI |
@@ -308,15 +308,15 @@ static void octeon_irq_msi_enable_pci(unsigned int irq) | |||
308 | */ | 308 | */ |
309 | } | 309 | } |
310 | 310 | ||
311 | static void octeon_irq_msi_disable_pci(unsigned int irq) | 311 | static void octeon_irq_msi_disable_pci(struct irq_data *data) |
312 | { | 312 | { |
313 | /* See comment in enable */ | 313 | /* See comment in enable */ |
314 | } | 314 | } |
315 | 315 | ||
316 | static struct irq_chip octeon_irq_chip_msi_pci = { | 316 | static struct irq_chip octeon_irq_chip_msi_pci = { |
317 | .name = "MSI", | 317 | .name = "MSI", |
318 | .enable = octeon_irq_msi_enable_pci, | 318 | .irq_enable = octeon_irq_msi_enable_pci, |
319 | .disable = octeon_irq_msi_disable_pci, | 319 | .irq_disable = octeon_irq_msi_disable_pci, |
320 | }; | 320 | }; |
321 | 321 | ||
322 | /* | 322 | /* |