From a46b68439d05c3a6b9575bd60ebaa07d584e8245 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Thu, 8 Apr 2004 17:46:51 +0000 Subject: bitkeeper revision 1.858 (4075900bvZ22M6mUE2F3Vk8eDozqtw) Add support for suspend/resume to new evtchn-IRQ binding mechanism. --- xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c | 63 ++++++++++++++++++++++++ xenolinux-2.4.25-sparse/arch/xen/kernel/setup.c | 4 ++ xenolinux-2.4.25-sparse/include/asm-xen/irq.h | 3 ++ 3 files changed, 70 insertions(+) diff --git a/xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c b/xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c index a9c8991fb9..4f933057c2 100644 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c +++ b/xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c @@ -353,6 +353,69 @@ static struct irqaction misdirect_action = { NULL }; +void irq_suspend(void) +{ + evtchn_op_t op; + int virq, irq, evtchn; + + /* Unbind VIRQs from event channels. */ + for ( virq = 0; virq < NR_VIRQS; virq++ ) + { + if ( (irq = virq_to_irq[virq]) == -1 ) + continue; + evtchn = irq_to_evtchn[irq]; + + /* Inform Xen that we are unbinding. */ + op.cmd = EVTCHNOP_close; + op.u.close.dom = DOMID_SELF; + op.u.close.port = evtchn; + if ( HYPERVISOR_event_channel_op(&op) != 0 ) + panic("Failed to unbind virtual IRQ %d\n", virq); + + /* Mark the event channel as unused in our table. */ + evtchn_to_irq[evtchn] = -1; + irq_to_evtchn[irq] = -1; + } + + /* + * We should now be unbound from all event channels. Stale bindings to + * PIRQs and/or inter-domain event channels will cause us to barf here. + */ + for ( evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++ ) + if ( evtchn_to_irq[evtchn] != -1 ) + panic("Suspend attempted while bound to evtchn %d.\n", evtchn); +} + + +void irq_resume(void) +{ + evtchn_op_t op; + int virq, irq, evtchn; + + for ( evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++ ) + mask_evtchn(evtchn); /* New event-channel space is not 'live' yet. */ + + for ( virq = 0; virq < NR_VIRQS; virq++ ) + { + if ( (irq = virq_to_irq[virq]) == -1 ) + continue; + + /* Get a new binding from Xen. */ + op.cmd = EVTCHNOP_bind_virq; + op.u.bind_virq.virq = virq; + if ( HYPERVISOR_event_channel_op(&op) != 0 ) + panic("Failed to bind virtual IRQ %d\n", virq); + evtchn = op.u.bind_virq.port; + + /* Record the new mapping. */ + evtchn_to_irq[evtchn] = irq; + irq_to_evtchn[irq] = evtchn; + + /* Ready for use. */ + unmask_evtchn(evtchn); + } +} + void __init init_IRQ(void) { int i; diff --git a/xenolinux-2.4.25-sparse/arch/xen/kernel/setup.c b/xenolinux-2.4.25-sparse/arch/xen/kernel/setup.c index 36faf53832..be7cc61efe 100644 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/setup.c +++ b/xenolinux-2.4.25-sparse/arch/xen/kernel/setup.c @@ -1190,6 +1190,8 @@ static void stop_task(void *unused) ctrl_if_suspend(); + irq_suspend(); + HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page; clear_fixmap(FIX_SHARED_INFO); @@ -1203,6 +1205,8 @@ static void stop_task(void *unused) HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO); memset(empty_zero_page, 0, PAGE_SIZE); + irq_resume(); + ctrl_if_resume(); time_resume(); diff --git a/xenolinux-2.4.25-sparse/include/asm-xen/irq.h b/xenolinux-2.4.25-sparse/include/asm-xen/irq.h index a05b99640e..668195e9ca 100644 --- a/xenolinux-2.4.25-sparse/include/asm-xen/irq.h +++ b/xenolinux-2.4.25-sparse/include/asm-xen/irq.h @@ -53,4 +53,7 @@ extern void disable_irq(unsigned int); extern void disable_irq_nosync(unsigned int); extern void enable_irq(unsigned int); +extern void irq_suspend(void); +extern void irq_resume(void); + #endif /* _ASM_IRQ_H */ -- cgit v1.2.3