diff mbox

[Proposal] Fixed the irq interrupt line after a resume from hibenration

Message ID 49C0B26E.7040201@st.com (mailing list archive)
State Rejected
Headers show

Commit Message

Francesco VIRLINZI March 18, 2009, 8:35 a.m. UTC
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.

This kind of irq line after a resume will remain not initialized in the 
interrupt controller.

The attached patch is a hack to close the issue ( and it works).
I know it isn't a wonderful solution and it has to be taken as a 
momentary solution.
The right thing should be add sysdev device to the intc but it requires 
more work in the intc design.

Let me know.
Regards
 Francesco

Comments

Magnus Damm April 1, 2009, 11:07 a.m. UTC | #1
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
diff mbox

Patch

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