Message ID | 49C0B26E.7040201@st.com (mailing list archive) |
---|---|
State | Rejected |
Headers | show |
Hi Francesco, On Wed, Mar 18, 2009 at 5:35 PM, Francesco VIRLINZI <francesco.virlinzi@st.com> wrote: > Hi all > > Ad I said in a previous email the current hibernation suppont has a problem > with > every interrupt line enabled in the previous session by modules. On suspend: kernel/power/disk.c: create_image() calls device_power_down() drivers/base/power/main.c: device_power_down() calls suspend_device_irqs() kernel/irq/pm.c: suspend_device_irqs() calls __disable_irq() kernel/irq/manage.c: __disable_irq() marks with IRQ_SUSPENDED and calls chip->disable() On resume: kernel/power/disk.c: create_image() calls device_power_up() drivers/base/power/main.c: device_power_up() calls resume_device_irqs() kernel/irq/pm.c: resume_device_irqs() calls __enable_irq() kernel/irq/manage.c: __enable_irq() calls check_irq_resend() I suspect you want check_irq_resend() to re-enable the interrupt for you somehow instead of doing it in restore_processor_state(). Does that solve your problem? > The right thing should be add sysdev device to the intc but it requires more > work in the intc design. Yes, upgrading intc to use sysdev for suspend and resume sounds like a good idea. Adding wakeup support so we can do enable_irq_wake() and set_irq_wake() is also needed. On top of that we really need to re-init the entire interrupt controller after coming back from U/R-standby. / magnus -- To unsubscribe from this list: send the line "unsubscribe linux-sh" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
From 8dd0655b55843957a06f6d2297e07322570b647d Mon Sep 17 00:00:00 2001 From: Francesco Virlinzi <francesco.virlinzi@st.com> Date: Wed, 18 Mar 2009 09:25:37 +0100 Subject: [PATCH] sh_irq: Added setup irq line support on hibernation This patch fixes the irq line status after a resume from hibernation. This is required for all the irq line required from every module loaded during the runtime of previous session and not initialized during the system boots. Signed-off-by: Francesco Virlinzi <francesco.virlinzi@st.com> --- arch/sh/kernel/swsusp.c | 25 +++++++++++++++++++++++++ 1 files changed, 25 insertions(+), 0 deletions(-) diff --git a/arch/sh/kernel/swsusp.c b/arch/sh/kernel/swsusp.c index 12b64a0..3f383a2 100644 --- a/arch/sh/kernel/swsusp.c +++ b/arch/sh/kernel/swsusp.c @@ -11,6 +11,8 @@ #include <linux/mm.h> #include <linux/sched.h> #include <linux/suspend.h> +#include <linux/irqflags.h> +#include <linux/irq.h> #include <asm/suspend.h> #include <asm/sections.h> #include <asm/tlbflush.h> @@ -34,5 +36,28 @@ void save_processor_state(void) void restore_processor_state(void) { + int i; + unsigned long flags; + struct irq_desc *desc; + void (*irq_func)(unsigned int irq); + + /* now restore the hw irq setting */ + local_irq_save(flags); + for (i = 0; i < NR_IRQS; ++i) { + desc = &irq_desc[i]; + if (desc->chip != &no_irq_chip && desc->action) { + irq_func = (desc->status & IRQ_DISABLED) ? + desc->chip->disable : desc->chip->enable; + spin_lock(&desc->lock); + desc->chip->startup(i); + irq_func(i); + if (desc->chip->set_wake) + desc->chip->set_wake(i, + ((desc->status & IRQ_WAKEUP) ? 1 : 0)); + spin_unlock(&desc->lock); + } /* if.. */ + } /* for... */ + local_irq_restore(flags); + local_flush_tlb_all(); } -- 1.5.6.6