aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/ps3/interrupt.c
diff options
context:
space:
mode:
authorGeoff Levand <geoffrey.levand@am.sony.com>2007-06-15 17:19:32 -0400
committerPaul Mackerras <paulus@samba.org>2007-06-28 05:16:37 -0400
commit9263e85aa9e9d341ef238fffc040f586674d1709 (patch)
tree51054ba00b9283f8c70125b87968a9bf3274a7f8 /arch/powerpc/platforms/ps3/interrupt.c
parent83bb643d0714b0006ab99dbd195ec51b55a97f4e (diff)
[POWERPC] PS3: Kexec support
Fixup the core platform parts needed for kexec to work on the PS3. - Setup ps3_hpte_clear correctly. - Mask interrupts on irq removal. - Release all hypervisor resources. - Create new routine ps3_shutdown_IRQ() Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/ps3/interrupt.c')
-rw-r--r--arch/powerpc/platforms/ps3/interrupt.c68
1 files changed, 53 insertions, 15 deletions
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
index 2a0a422cea14..462eacc55c97 100644
--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -220,6 +220,8 @@ int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
220 goto fail_set; 220 goto fail_set;
221 } 221 }
222 222
223 ps3_chip_mask(*virq);
224
223 return result; 225 return result;
224 226
225fail_set: 227fail_set:
@@ -311,6 +313,8 @@ int ps3_irq_plug_destroy(unsigned int virq)
311 pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__, 313 pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__,
312 pd->node, pd->cpu, virq); 314 pd->node, pd->cpu, virq);
313 315
316 ps3_chip_mask(virq);
317
314 result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq); 318 result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq);
315 319
316 if (result) 320 if (result)
@@ -368,7 +372,9 @@ int ps3_event_receive_port_destroy(unsigned int virq)
368{ 372{
369 int result; 373 int result;
370 374
371 pr_debug(" -> %s:%d virq: %u\n", __func__, __LINE__, virq); 375 pr_debug(" -> %s:%d virq %u\n", __func__, __LINE__, virq);
376
377 ps3_chip_mask(virq);
372 378
373 result = lv1_destruct_event_receive_port(virq_to_hw(virq)); 379 result = lv1_destruct_event_receive_port(virq_to_hw(virq));
374 380
@@ -376,17 +382,14 @@ int ps3_event_receive_port_destroy(unsigned int virq)
376 pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n", 382 pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n",
377 __func__, __LINE__, ps3_result(result)); 383 __func__, __LINE__, ps3_result(result));
378 384
379 /* lv1_destruct_event_receive_port() destroys the IRQ plug, 385 /*
380 * so don't call ps3_irq_plug_destroy() here. 386 * Don't call ps3_virq_destroy() here since ps3_smp_cleanup_cpu()
387 * calls from interrupt context (smp_call_function) when kexecing.
381 */ 388 */
382 389
383 result = ps3_virq_destroy(virq);
384 BUG_ON(result);
385
386 pr_debug(" <- %s:%d\n", __func__, __LINE__); 390 pr_debug(" <- %s:%d\n", __func__, __LINE__);
387 return result; 391 return result;
388} 392}
389EXPORT_SYMBOL_GPL(ps3_event_receive_port_destroy);
390 393
391int ps3_send_event_locally(unsigned int virq) 394int ps3_send_event_locally(unsigned int virq)
392{ 395{
@@ -458,6 +461,14 @@ int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did,
458 result = ps3_event_receive_port_destroy(virq); 461 result = ps3_event_receive_port_destroy(virq);
459 BUG_ON(result); 462 BUG_ON(result);
460 463
464 /*
465 * ps3_event_receive_port_destroy() destroys the IRQ plug,
466 * so don't call ps3_irq_plug_destroy() here.
467 */
468
469 result = ps3_virq_destroy(virq);
470 BUG_ON(result);
471
461 pr_debug(" <- %s:%d\n", __func__, __LINE__); 472 pr_debug(" <- %s:%d\n", __func__, __LINE__);
462 return result; 473 return result;
463} 474}
@@ -498,16 +509,24 @@ EXPORT_SYMBOL_GPL(ps3_io_irq_setup);
498int ps3_io_irq_destroy(unsigned int virq) 509int ps3_io_irq_destroy(unsigned int virq)
499{ 510{
500 int result; 511 int result;
512 unsigned long outlet = virq_to_hw(virq);
501 513
502 result = lv1_destruct_io_irq_outlet(virq_to_hw(virq)); 514 ps3_chip_mask(virq);
503 515
504 if (result) 516 /*
505 pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n", 517 * lv1_destruct_io_irq_outlet() will destroy the IRQ plug,
506 __func__, __LINE__, ps3_result(result)); 518 * so call ps3_irq_plug_destroy() first.
519 */
507 520
508 result = ps3_irq_plug_destroy(virq); 521 result = ps3_irq_plug_destroy(virq);
509 BUG_ON(result); 522 BUG_ON(result);
510 523
524 result = lv1_destruct_io_irq_outlet(outlet);
525
526 if (result)
527 pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n",
528 __func__, __LINE__, ps3_result(result));
529
511 return result; 530 return result;
512} 531}
513EXPORT_SYMBOL_GPL(ps3_io_irq_destroy); 532EXPORT_SYMBOL_GPL(ps3_io_irq_destroy);
@@ -552,6 +571,7 @@ int ps3_vuart_irq_destroy(unsigned int virq)
552{ 571{
553 int result; 572 int result;
554 573
574 ps3_chip_mask(virq);
555 result = lv1_deconfigure_virtual_uart_irq(); 575 result = lv1_deconfigure_virtual_uart_irq();
556 576
557 if (result) { 577 if (result) {
@@ -600,9 +620,14 @@ int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id,
600 620
601int ps3_spe_irq_destroy(unsigned int virq) 621int ps3_spe_irq_destroy(unsigned int virq)
602{ 622{
603 int result = ps3_irq_plug_destroy(virq); 623 int result;
624
625 ps3_chip_mask(virq);
626
627 result = ps3_irq_plug_destroy(virq);
604 BUG_ON(result); 628 BUG_ON(result);
605 return 0; 629
630 return result;
606} 631}
607 632
608 633
@@ -662,7 +687,7 @@ static int ps3_host_map(struct irq_host *h, unsigned int virq,
662 pr_debug("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq, 687 pr_debug("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq,
663 virq); 688 virq);
664 689
665 set_irq_chip_and_handler(virq, &irq_chip, handle_fasteoi_irq); 690 set_irq_chip_and_handler(virq, &ps3_irq_chip, handle_fasteoi_irq);
666 691
667 return 0; 692 return 0;
668} 693}
@@ -682,7 +707,7 @@ void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq)
682 cpu, virq, pd->bmp.ipi_debug_brk_mask); 707 cpu, virq, pd->bmp.ipi_debug_brk_mask);
683} 708}
684 709
685unsigned int ps3_get_irq(void) 710static unsigned int ps3_get_irq(void)
686{ 711{
687 struct ps3_private *pd = &__get_cpu_var(ps3_private); 712 struct ps3_private *pd = &__get_cpu_var(ps3_private);
688 u64 x = (pd->bmp.status & pd->bmp.mask); 713 u64 x = (pd->bmp.status & pd->bmp.mask);
@@ -747,3 +772,16 @@ void __init ps3_init_IRQ(void)
747 772
748 ppc_md.get_irq = ps3_get_irq; 773 ppc_md.get_irq = ps3_get_irq;
749} 774}
775
776void ps3_shutdown_IRQ(int cpu)
777{
778 int result;
779 u64 ppe_id;
780 u64 thread_id = get_hard_smp_processor_id(cpu);
781
782 lv1_get_logical_ppe_id(&ppe_id);
783 result = lv1_configure_irq_state_bitmap(ppe_id, thread_id, 0);
784
785 DBG("%s:%d: lv1_configure_irq_state_bitmap (%lu:%lu/%d) %s\n", __func__,
786 __LINE__, ppe_id, thread_id, cpu, ps3_result(result));
787}