diff options
author | Geoff Levand <geoffrey.levand@am.sony.com> | 2007-01-26 22:08:02 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-02-06 22:03:18 -0500 |
commit | 407e24a0c78f585c228ec7e1152a9b23e262b200 (patch) | |
tree | d79f15b0737222a955bc01277ba5045c04db67d7 /arch | |
parent | 9633ac8d172f74b8ee51e0fe85c06eb726039aa8 (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.c | 60 |
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 | ||
332 | struct ps3_private { | 333 | struct 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 | ||
397 | static void ps3_chip_unmask(unsigned int virq) | 397 | static 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 | ||
414 | static void ps3_chip_eoi(unsigned int virq) | 413 | static 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 | ||
419 | static struct irq_chip irq_chip = { | 419 | static struct irq_chip irq_chip = { |
@@ -426,10 +426,12 @@ static struct irq_chip irq_chip = { | |||
426 | static void ps3_host_unmap(struct irq_host *h, unsigned int virq) | 426 | static 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) | |||
544 | void __init ps3_init_IRQ(void) | 541 | void __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:" |