aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorGeoff Levand <geoffrey.levand@am.sony.com>2007-01-26 22:08:02 -0500
committerPaul Mackerras <paulus@samba.org>2007-02-06 22:03:18 -0500
commit407e24a0c78f585c228ec7e1152a9b23e262b200 (patch)
treed79f15b0737222a955bc01277ba5045c04db67d7 /arch
parent9633ac8d172f74b8ee51e0fe85c06eb726039aa8 (diff)
[POWERPC] ps3: smp interrupt fixes
PS3 fixups for interrups on SMP. Fixes the alignment of the interrupt status bitmap, changes the hypervisor interrupt calls to the '_ext' versions that take an explicit processor thread ID. Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/platforms/ps3/interrupt.c60
1 files changed, 29 insertions, 31 deletions
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
index 9c8f3b568a21..7a4ca056dd3a 100644
--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -317,22 +317,23 @@ struct ps3_bmp {
317 unsigned long unused_1[3]; 317 unsigned long unused_1[3];
318 unsigned long mask; 318 unsigned long mask;
319 unsigned long unused_2[3]; 319 unsigned long unused_2[3];
320 } __attribute__ ((packed)); 320 } __attribute__ ((aligned (64)));
321
321 spinlock_t lock; 322 spinlock_t lock;
322 unsigned long ipi_debug_brk_mask; 323 unsigned long ipi_debug_brk_mask;
323}; 324};
324 325
325/** 326/**
326 * struct ps3_private - a per cpu data structure 327 * struct ps3_private - a per cpu data structure
327 * @node: HV node id 328 * @bmp: ps3_bmp structure
328 * @cpu: HV thread id 329 * @node: HV logical_ppe_id
329 * @bmp: an HV ps3_bmp structure 330 * @cpu: HV thread_id
330 */ 331 */
331 332
332struct ps3_private { 333struct ps3_private {
334 struct ps3_bmp bmp;
333 unsigned long node; 335 unsigned long node;
334 unsigned int cpu; 336 unsigned int cpu;
335 struct ps3_bmp bmp;
336}; 337};
337 338
338#if defined(DEBUG) 339#if defined(DEBUG)
@@ -389,9 +390,8 @@ static void ps3_chip_mask(unsigned int virq)
389 390
390 spin_lock_irqsave(&pd->bmp.lock, flags); 391 spin_lock_irqsave(&pd->bmp.lock, flags);
391 pd->bmp.mask &= ~(0x8000000000000000UL >> virq); 392 pd->bmp.mask &= ~(0x8000000000000000UL >> virq);
392 spin_unlock_irqrestore(&pd->bmp.lock, flags);
393
394 lv1_did_update_interrupt_mask(pd->node, pd->cpu); 393 lv1_did_update_interrupt_mask(pd->node, pd->cpu);
394 spin_unlock_irqrestore(&pd->bmp.lock, flags);
395} 395}
396 396
397static void ps3_chip_unmask(unsigned int virq) 397static void ps3_chip_unmask(unsigned int virq)
@@ -406,14 +406,14 @@ static void ps3_chip_unmask(unsigned int virq)
406 406
407 spin_lock_irqsave(&pd->bmp.lock, flags); 407 spin_lock_irqsave(&pd->bmp.lock, flags);
408 pd->bmp.mask |= (0x8000000000000000UL >> virq); 408 pd->bmp.mask |= (0x8000000000000000UL >> virq);
409 spin_unlock_irqrestore(&pd->bmp.lock, flags);
410
411 lv1_did_update_interrupt_mask(pd->node, pd->cpu); 409 lv1_did_update_interrupt_mask(pd->node, pd->cpu);
410 spin_unlock_irqrestore(&pd->bmp.lock, flags);
412} 411}
413 412
414static void ps3_chip_eoi(unsigned int virq) 413static void ps3_chip_eoi(unsigned int virq)
415{ 414{
416 lv1_end_of_interrupt(virq); 415 const struct ps3_private *pd = get_irq_chip_data(virq);
416 lv1_end_of_interrupt_ext(pd->node, pd->cpu, virq);
417} 417}
418 418
419static struct irq_chip irq_chip = { 419static struct irq_chip irq_chip = {
@@ -426,10 +426,12 @@ static struct irq_chip irq_chip = {
426static void ps3_host_unmap(struct irq_host *h, unsigned int virq) 426static void ps3_host_unmap(struct irq_host *h, unsigned int virq)
427{ 427{
428 int result; 428 int result;
429 const struct ps3_private *pd = get_irq_chip_data(virq);
429 430
430 pr_debug("%s:%d: virq %d\n", __func__, __LINE__, virq); 431 pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__,
432 pd->node, pd->cpu, virq);
431 433
432 lv1_disconnect_irq_plug(virq); 434 lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq);
433 435
434 result = set_irq_chip_data(virq, NULL); 436 result = set_irq_chip_data(virq, NULL);
435 BUG_ON(result); 437 BUG_ON(result);
@@ -441,31 +443,26 @@ static int ps3_host_map(struct irq_host *h, unsigned int virq,
441 irq_hw_number_t hwirq) 443 irq_hw_number_t hwirq)
442{ 444{
443 int result; 445 int result;
444 unsigned int cpu; 446 struct ps3_private *pd = &__get_cpu_var(ps3_private);
445 447
446 pr_debug(" -> %s:%d\n", __func__, __LINE__); 448 pr_debug("%s:%d: node %lu, cpu %d, hwirq %lu => virq %u\n", __func__,
447 pr_debug("%s:%d: hwirq %lu => virq %u\n", __func__, __LINE__, hwirq, 449 __LINE__, pd->node, pd->cpu, hwirq, virq);
448 virq);
449 450
450 /* bind this virq to a cpu */ 451 /* Binds this virq to pd->cpu (current cpu) */
451 452
452 preempt_disable(); 453 result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, virq, hwirq, 0);
453 cpu = smp_processor_id();
454 result = lv1_connect_irq_plug(virq, hwirq);
455 preempt_enable();
456 454
457 if (result) { 455 if (result) {
458 pr_info("%s:%d: lv1_connect_irq_plug failed:" 456 pr_info("%s:%d: lv1_connect_irq_plug_ext failed:"
459 " %s\n", __func__, __LINE__, ps3_result(result)); 457 " %s\n", __func__, __LINE__, ps3_result(result));
460 return -EPERM; 458 return -EPERM;
461 } 459 }
462 460
463 result = set_irq_chip_data(virq, &per_cpu(ps3_private, cpu)); 461 result = set_irq_chip_data(virq, pd);
464 BUG_ON(result); 462 BUG_ON(result);
465 463
466 set_irq_chip_and_handler(virq, &irq_chip, handle_fasteoi_irq); 464 set_irq_chip_and_handler(virq, &irq_chip, handle_fasteoi_irq);
467 465
468 pr_debug(" <- %s:%d\n", __func__, __LINE__);
469 return result; 466 return result;
470} 467}
471 468
@@ -544,12 +541,9 @@ unsigned int ps3_get_irq(void)
544void __init ps3_init_IRQ(void) 541void __init ps3_init_IRQ(void)
545{ 542{
546 int result; 543 int result;
547 unsigned long node;
548 unsigned cpu; 544 unsigned cpu;
549 struct irq_host *host; 545 struct irq_host *host;
550 546
551 lv1_get_logical_ppe_id(&node);
552
553 host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, &ps3_host_ops, 547 host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, &ps3_host_ops,
554 PS3_INVALID_OUTLET); 548 PS3_INVALID_OUTLET);
555 irq_set_default_host(host); 549 irq_set_default_host(host);
@@ -558,12 +552,16 @@ void __init ps3_init_IRQ(void)
558 for_each_possible_cpu(cpu) { 552 for_each_possible_cpu(cpu) {
559 struct ps3_private *pd = &per_cpu(ps3_private, cpu); 553 struct ps3_private *pd = &per_cpu(ps3_private, cpu);
560 554
561 pd->node = node; 555 lv1_get_logical_ppe_id(&pd->node);
562 pd->cpu = cpu; 556 pd->cpu = get_hard_smp_processor_id(cpu);
563 spin_lock_init(&pd->bmp.lock); 557 spin_lock_init(&pd->bmp.lock);
564 558
565 result = lv1_configure_irq_state_bitmap(node, cpu, 559 pr_debug("%s:%d: node %lu, cpu %d, bmp %lxh\n", __func__,
566 ps3_mm_phys_to_lpar(__pa(&pd->bmp.status))); 560 __LINE__, pd->node, pd->cpu,
561 ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
562
563 result = lv1_configure_irq_state_bitmap(pd->node, pd->cpu,
564 ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
567 565
568 if (result) 566 if (result)
569 pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:" 567 pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:"