diff options
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/platforms/pseries/setup.c | 5 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/xics.c | 89 |
2 files changed, 51 insertions, 43 deletions
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index d345bfd56bbe..2a0089a2c829 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -114,10 +114,13 @@ static void __init fwnmi_init(void) | |||
114 | 114 | ||
115 | static void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc) | 115 | static void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc) |
116 | { | 116 | { |
117 | struct irq_chip *chip = get_irq_desc_chip(desc); | ||
117 | unsigned int cascade_irq = i8259_irq(); | 118 | unsigned int cascade_irq = i8259_irq(); |
119 | |||
118 | if (cascade_irq != NO_IRQ) | 120 | if (cascade_irq != NO_IRQ) |
119 | generic_handle_irq(cascade_irq); | 121 | generic_handle_irq(cascade_irq); |
120 | desc->chip->eoi(irq); | 122 | |
123 | chip->irq_eoi(&desc->irq_data); | ||
121 | } | 124 | } |
122 | 125 | ||
123 | static void __init pseries_setup_i8259_cascade(void) | 126 | static void __init pseries_setup_i8259_cascade(void) |
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 7b96e5a270ce..01fea46c0335 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
@@ -202,20 +202,20 @@ static int get_irq_server(unsigned int virq, const struct cpumask *cpumask, | |||
202 | #define get_irq_server(virq, cpumask, strict_check) (default_server) | 202 | #define get_irq_server(virq, cpumask, strict_check) (default_server) |
203 | #endif | 203 | #endif |
204 | 204 | ||
205 | static void xics_unmask_irq(unsigned int virq) | 205 | static void xics_unmask_irq(struct irq_data *d) |
206 | { | 206 | { |
207 | unsigned int irq; | 207 | unsigned int irq; |
208 | int call_status; | 208 | int call_status; |
209 | int server; | 209 | int server; |
210 | 210 | ||
211 | pr_devel("xics: unmask virq %d\n", virq); | 211 | pr_devel("xics: unmask virq %d\n", d->irq); |
212 | 212 | ||
213 | irq = (unsigned int)irq_map[virq].hwirq; | 213 | irq = (unsigned int)irq_map[d->irq].hwirq; |
214 | pr_devel(" -> map to hwirq 0x%x\n", irq); | 214 | pr_devel(" -> map to hwirq 0x%x\n", irq); |
215 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) | 215 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) |
216 | return; | 216 | return; |
217 | 217 | ||
218 | server = get_irq_server(virq, irq_to_desc(virq)->affinity, 0); | 218 | server = get_irq_server(d->irq, d->affinity, 0); |
219 | 219 | ||
220 | call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, | 220 | call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, |
221 | DEFAULT_PRIORITY); | 221 | DEFAULT_PRIORITY); |
@@ -235,61 +235,61 @@ static void xics_unmask_irq(unsigned int virq) | |||
235 | } | 235 | } |
236 | } | 236 | } |
237 | 237 | ||
238 | static unsigned int xics_startup(unsigned int virq) | 238 | static unsigned int xics_startup(struct irq_data *d) |
239 | { | 239 | { |
240 | /* | 240 | /* |
241 | * The generic MSI code returns with the interrupt disabled on the | 241 | * The generic MSI code returns with the interrupt disabled on the |
242 | * card, using the MSI mask bits. Firmware doesn't appear to unmask | 242 | * card, using the MSI mask bits. Firmware doesn't appear to unmask |
243 | * at that level, so we do it here by hand. | 243 | * at that level, so we do it here by hand. |
244 | */ | 244 | */ |
245 | if (irq_to_desc(virq)->msi_desc) | 245 | if (d->msi_desc) |
246 | unmask_msi_irq(irq_get_irq_data(virq)); | 246 | unmask_msi_irq(d); |
247 | 247 | ||
248 | /* unmask it */ | 248 | /* unmask it */ |
249 | xics_unmask_irq(virq); | 249 | xics_unmask_irq(d); |
250 | return 0; | 250 | return 0; |
251 | } | 251 | } |
252 | 252 | ||
253 | static void xics_mask_real_irq(unsigned int irq) | 253 | static void xics_mask_real_irq(struct irq_data *d) |
254 | { | 254 | { |
255 | int call_status; | 255 | int call_status; |
256 | 256 | ||
257 | if (irq == XICS_IPI) | 257 | if (d->irq == XICS_IPI) |
258 | return; | 258 | return; |
259 | 259 | ||
260 | call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq); | 260 | call_status = rtas_call(ibm_int_off, 1, 1, NULL, d->irq); |
261 | if (call_status != 0) { | 261 | if (call_status != 0) { |
262 | printk(KERN_ERR "%s: ibm_int_off irq=%u returned %d\n", | 262 | printk(KERN_ERR "%s: ibm_int_off irq=%u returned %d\n", |
263 | __func__, irq, call_status); | 263 | __func__, d->irq, call_status); |
264 | return; | 264 | return; |
265 | } | 265 | } |
266 | 266 | ||
267 | /* Have to set XIVE to 0xff to be able to remove a slot */ | 267 | /* Have to set XIVE to 0xff to be able to remove a slot */ |
268 | call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, | 268 | call_status = rtas_call(ibm_set_xive, 3, 1, NULL, d->irq, |
269 | default_server, 0xff); | 269 | default_server, 0xff); |
270 | if (call_status != 0) { | 270 | if (call_status != 0) { |
271 | printk(KERN_ERR "%s: ibm_set_xive(0xff) irq=%u returned %d\n", | 271 | printk(KERN_ERR "%s: ibm_set_xive(0xff) irq=%u returned %d\n", |
272 | __func__, irq, call_status); | 272 | __func__, d->irq, call_status); |
273 | return; | 273 | return; |
274 | } | 274 | } |
275 | } | 275 | } |
276 | 276 | ||
277 | static void xics_mask_irq(unsigned int virq) | 277 | static void xics_mask_irq(struct irq_data *d) |
278 | { | 278 | { |
279 | unsigned int irq; | 279 | unsigned int irq; |
280 | 280 | ||
281 | pr_devel("xics: mask virq %d\n", virq); | 281 | pr_devel("xics: mask virq %d\n", d->irq); |
282 | 282 | ||
283 | irq = (unsigned int)irq_map[virq].hwirq; | 283 | irq = (unsigned int)irq_map[d->irq].hwirq; |
284 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) | 284 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) |
285 | return; | 285 | return; |
286 | xics_mask_real_irq(irq); | 286 | xics_mask_real_irq(d); |
287 | } | 287 | } |
288 | 288 | ||
289 | static void xics_mask_unknown_vec(unsigned int vec) | 289 | static void xics_mask_unknown_vec(unsigned int vec) |
290 | { | 290 | { |
291 | printk(KERN_ERR "Interrupt %u (real) is invalid, disabling it.\n", vec); | 291 | printk(KERN_ERR "Interrupt %u (real) is invalid, disabling it.\n", vec); |
292 | xics_mask_real_irq(vec); | 292 | xics_mask_real_irq(irq_get_irq_data(vec)); |
293 | } | 293 | } |
294 | 294 | ||
295 | static inline unsigned int xics_xirr_vector(unsigned int xirr) | 295 | static inline unsigned int xics_xirr_vector(unsigned int xirr) |
@@ -371,30 +371,31 @@ static unsigned char pop_cppr(void) | |||
371 | return os_cppr->stack[--os_cppr->index]; | 371 | return os_cppr->stack[--os_cppr->index]; |
372 | } | 372 | } |
373 | 373 | ||
374 | static void xics_eoi_direct(unsigned int virq) | 374 | static void xics_eoi_direct(struct irq_data *d) |
375 | { | 375 | { |
376 | unsigned int irq = (unsigned int)irq_map[virq].hwirq; | 376 | unsigned int irq = (unsigned int)irq_map[d->irq].hwirq; |
377 | 377 | ||
378 | iosync(); | 378 | iosync(); |
379 | direct_xirr_info_set((pop_cppr() << 24) | irq); | 379 | direct_xirr_info_set((pop_cppr() << 24) | irq); |
380 | } | 380 | } |
381 | 381 | ||
382 | static void xics_eoi_lpar(unsigned int virq) | 382 | static void xics_eoi_lpar(struct irq_data *d) |
383 | { | 383 | { |
384 | unsigned int irq = (unsigned int)irq_map[virq].hwirq; | 384 | unsigned int irq = (unsigned int)irq_map[d->irq].hwirq; |
385 | 385 | ||
386 | iosync(); | 386 | iosync(); |
387 | lpar_xirr_info_set((pop_cppr() << 24) | irq); | 387 | lpar_xirr_info_set((pop_cppr() << 24) | irq); |
388 | } | 388 | } |
389 | 389 | ||
390 | static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask) | 390 | static int |
391 | xics_set_affinity(struct irq_data *d, const struct cpumask *cpumask, bool force) | ||
391 | { | 392 | { |
392 | unsigned int irq; | 393 | unsigned int irq; |
393 | int status; | 394 | int status; |
394 | int xics_status[2]; | 395 | int xics_status[2]; |
395 | int irq_server; | 396 | int irq_server; |
396 | 397 | ||
397 | irq = (unsigned int)irq_map[virq].hwirq; | 398 | irq = (unsigned int)irq_map[d->irq].hwirq; |
398 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) | 399 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) |
399 | return -1; | 400 | return -1; |
400 | 401 | ||
@@ -406,13 +407,13 @@ static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask) | |||
406 | return -1; | 407 | return -1; |
407 | } | 408 | } |
408 | 409 | ||
409 | irq_server = get_irq_server(virq, cpumask, 1); | 410 | irq_server = get_irq_server(d->irq, cpumask, 1); |
410 | if (irq_server == -1) { | 411 | if (irq_server == -1) { |
411 | char cpulist[128]; | 412 | char cpulist[128]; |
412 | cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask); | 413 | cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask); |
413 | printk(KERN_WARNING | 414 | printk(KERN_WARNING |
414 | "%s: No online cpus in the mask %s for irq %d\n", | 415 | "%s: No online cpus in the mask %s for irq %d\n", |
415 | __func__, cpulist, virq); | 416 | __func__, cpulist, d->irq); |
416 | return -1; | 417 | return -1; |
417 | } | 418 | } |
418 | 419 | ||
@@ -430,20 +431,20 @@ static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask) | |||
430 | 431 | ||
431 | static struct irq_chip xics_pic_direct = { | 432 | static struct irq_chip xics_pic_direct = { |
432 | .name = "XICS", | 433 | .name = "XICS", |
433 | .startup = xics_startup, | 434 | .irq_startup = xics_startup, |
434 | .mask = xics_mask_irq, | 435 | .irq_mask = xics_mask_irq, |
435 | .unmask = xics_unmask_irq, | 436 | .irq_unmask = xics_unmask_irq, |
436 | .eoi = xics_eoi_direct, | 437 | .irq_eoi = xics_eoi_direct, |
437 | .set_affinity = xics_set_affinity | 438 | .irq_set_affinity = xics_set_affinity |
438 | }; | 439 | }; |
439 | 440 | ||
440 | static struct irq_chip xics_pic_lpar = { | 441 | static struct irq_chip xics_pic_lpar = { |
441 | .name = "XICS", | 442 | .name = "XICS", |
442 | .startup = xics_startup, | 443 | .irq_startup = xics_startup, |
443 | .mask = xics_mask_irq, | 444 | .irq_mask = xics_mask_irq, |
444 | .unmask = xics_unmask_irq, | 445 | .irq_unmask = xics_unmask_irq, |
445 | .eoi = xics_eoi_lpar, | 446 | .irq_eoi = xics_eoi_lpar, |
446 | .set_affinity = xics_set_affinity | 447 | .irq_set_affinity = xics_set_affinity |
447 | }; | 448 | }; |
448 | 449 | ||
449 | 450 | ||
@@ -890,6 +891,7 @@ void xics_migrate_irqs_away(void) | |||
890 | 891 | ||
891 | for_each_irq(virq) { | 892 | for_each_irq(virq) { |
892 | struct irq_desc *desc; | 893 | struct irq_desc *desc; |
894 | struct irq_chip *chip; | ||
893 | int xics_status[2]; | 895 | int xics_status[2]; |
894 | int status; | 896 | int status; |
895 | unsigned long flags; | 897 | unsigned long flags; |
@@ -903,12 +905,15 @@ void xics_migrate_irqs_away(void) | |||
903 | /* We need to get IPIs still. */ | 905 | /* We need to get IPIs still. */ |
904 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) | 906 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) |
905 | continue; | 907 | continue; |
908 | |||
906 | desc = irq_to_desc(virq); | 909 | desc = irq_to_desc(virq); |
907 | 910 | ||
908 | /* We only need to migrate enabled IRQS */ | 911 | /* We only need to migrate enabled IRQS */ |
909 | if (desc == NULL || desc->chip == NULL | 912 | if (desc == NULL || desc->action == NULL) |
910 | || desc->action == NULL | 913 | continue; |
911 | || desc->chip->set_affinity == NULL) | 914 | |
915 | chip = get_irq_desc_chip(desc); | ||
916 | if (chip == NULL || chip->irq_set_affinity == NULL) | ||
912 | continue; | 917 | continue; |
913 | 918 | ||
914 | raw_spin_lock_irqsave(&desc->lock, flags); | 919 | raw_spin_lock_irqsave(&desc->lock, flags); |
@@ -934,8 +939,8 @@ void xics_migrate_irqs_away(void) | |||
934 | virq, cpu); | 939 | virq, cpu); |
935 | 940 | ||
936 | /* Reset affinity to all cpus */ | 941 | /* Reset affinity to all cpus */ |
937 | cpumask_setall(irq_to_desc(virq)->affinity); | 942 | cpumask_setall(desc->irq_data.affinity); |
938 | desc->chip->set_affinity(virq, cpu_all_mask); | 943 | chip->irq_set_affinity(&desc->irq_data, cpu_all_mask, true); |
939 | unlock: | 944 | unlock: |
940 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 945 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
941 | } | 946 | } |