Gmane
From: Georg C. F. Greve <greve@...>
Subject: Re: acpi-20040715: functional regression on ASUS M2N
Newsgroups: gmane.linux.acpi.devel
Date: 2004-07-27 11:14:23 GMT (4 years, 49 weeks, 9 hours and 37 minutes ago)
Hi all,

okay, I did some more checks on the problems I experienced with
acpi-20040715 on Intel Centrino 855GM notebook ASUS M2N.

Background: As of kernel 2.6.7 suspend to RAM (s3_bios) actually
worked and even with DRI/DRM and AGP compiled in and the X server
running, things are working nicely. 

When restarting from suspend to RAM, I briefly see a yellow "inu" in
the uppermost row for a second, then the screen flickers once and X11
is back.

Only disadvantage: network cards (both wired & ipw2100 wireless) are
dead after suspend to ram, I need a suspend to disk (swsusp2 version
2.0.0.100) to bring them back to life. (referred to as "fine" below)

When upgrading to acpi-20040715 I discovered that resume from suspend
to RAM was broken. Contrary to what I wrote in my previous mail, it
seems that there is the yellow "inu" in the uppermost row and then the
machine is dead. (referred to as "dead" below)

I need a forced poweroff plus "needle-pushed reset button" to bring it
back to life.

Having had some time to let the machine compile in the background, I
narrowed down the code that broke the resume from suspend to RAM on my
machine. Apparently it was the patch that is supposed to fix the
network card problems.

When starting from a patched 2.6.7 with suspend to ram and resume
working fine as described above (=base), I have applied two patches

 (a) acpi-20040715

 (b) Fix ACPI after S3 patch of David Shaohua:
===== arch/i386/kernel/i8259.c 1.30 vs edited =====
--- 1.30/arch/i386/kernel/i8259.c	Thu Apr 22 19:15:40 2004
+++ edited/arch/i386/kernel/i8259.c	Tue Jun 29 15:35:28 2004
@@ -238,14 +238,39 @@
 	}
 }

+static char irq_trigger[2];
+/**
+ * ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ
+ */
+static void restore_ELCR(char *trigger)
+{
+	outb(trigger[0], 0x4d0);
+	outb(trigger[1], 0x4d1);
+}
+
+static void save_ELCR(char *trigger)
+{
+	/* IRQ 0,1,2,8,13 are marked as reserved */
+	trigger[0] = inb(0x4d0) & 0xF8;
+	trigger[1] = inb(0x4d1) & 0xDE;
+}
+
 static int i8259A_resume(struct sys_device *dev)
 {
 	init_8259A(0);
+	restore_ELCR(irq_trigger);
+	return 0;
+}
+
+static int i8259A_suspend(struct sys_device *dev, u32 state)
+{
+	save_ELCR(irq_trigger);
 	return 0;
 }

 static struct sysdev_class i8259_sysdev_class = {
 	set_kset_name("i8259"),
+	.suspend = i8259A_suspend,
 	.resume = i8259A_resume,
 };

===== arch/x86_64/kernel/i8259.c 1.12 vs edited =====
--- 1.12/arch/x86_64/kernel/i8259.c	Wed Apr 21 08:55:12 2004
+++ edited/arch/x86_64/kernel/i8259.c	Tue Jun 29 15:36:08 2004
@@ -318,7 +318,7 @@
 	}
 }

-void __init init_8259A(int auto_eoi)
+void init_8259A(int auto_eoi)
 {
 	unsigned long flags;

@@ -360,6 +360,57 @@

 	spin_unlock_irqrestore(&i8259A_lock, flags);
 }
+
+static char irq_trigger[2];
+/**
+ * ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ
+ */
+static void restore_ELCR(char *trigger)
+{
+	outb(trigger[0], 0x4d0);
+	outb(trigger[1], 0x4d1);
+}
+
+static void save_ELCR(char *trigger)
+{
+	/* IRQ 0,1,2,8,13 are marked as reserved */
+	trigger[0] = inb(0x4d0) & 0xF8;
+	trigger[1] = inb(0x4d1) & 0xDE;
+}
+
+static int i8259A_resume(struct sys_device *dev)
+{
+	init_8259A(0);
+	restore_ELCR(irq_trigger);
+	return 0;
+}
+
+static int i8259A_suspend(struct sys_device *dev, u32 state)
+{
+	save_ELCR(irq_trigger);
+	return 0;
+}
+
+static struct sysdev_class i8259_sysdev_class = {
+	set_kset_name("i8259"),
+	.suspend = i8259A_suspend,
+	.resume = i8259A_resume,
+};
+
+static struct sys_device device_i8259A = {
+	.id	= 0,
+	.cls	= &i8259_sysdev_class,
+};
+
+static int __init i8259A_init_sysfs(void)
+{
+	int error = sysdev_class_register(&i8259_sysdev_class);
+	if (!error)
+		error = sysdev_register(&device_i8259A);
+	return error;
+}
+
+device_initcall(i8259A_init_sysfs);

 /*
  * IRQ2 is cascade interrupt to second interrupt controller
     (from http://bugme.osdl.org/show_bug.cgi?id=2643 )

in the following combinations with the following results:

 base + (a) = dead

 base + (b) = dead

 base + (a) - (b) = fine

So applying the ACPI patch and reverse-applying the (b) patch to it
actually fixes the problem, although the network cards still remain
dead.

Which narrows the problem down to patch (b) as the one breaking
suspend to ram on ASUS M2N. Hope this helps tracking things down.

Regards,
Georg

-- 
Georg C. F. Greve                                       <greve@...>
Free Software Foundation Europe	                 (http://fsfeurope.org)
Brave GNU World	                           (http://brave-gnu-world.org)