Skip to contentSkip to conversation

SMP support for swsusp, and strange serio/i8042 problems

PATCH Pavel Machek 2 participants 2 messages Jun 2, 2004 – Jun 3, 2004

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

Hi!

Here's experimental (works-for-me-mostly) SMP support for swsusp. While debugging it, I hit strange problem with i8042 driver. If I change #if 0 to #if 1 *and* kernel is CONFIG_SMP, it dies during first schedule(). Ouch.

Why is 8042 marked as system device, btw? Stopping timer for system device is likely useless; first resume is called and only after that interrupts are reenabled.

Pavel

drivers/base/power/shutdown.c +5 -4
@@ -8,6 +8,7 @@
  *
  */
 
+#define DEBUG
 #include <linux/config.h>
 #include <linux/device.h>
 #include <asm/semaphore.h>
@@ -52,14 +53,14 @@
 	struct device * dev;
 	
 	down_write(&devices_subsys.rwsem);
+	printk("Shutting down devices: ");
 	list_for_each_entry_reverse(dev,&devices_subsys.kset.list,kobj.entry) {
-		pr_debug("shutting down %s: ",dev->bus_id);
 		if (dev->driver && dev->driver->shutdown) {
-			pr_debug("Ok\n");
+			printk("%s, ",dev->bus_id);
 			dev->driver->shutdown(dev);
-		} else
-			pr_debug("Ignored.\n");
+		}
 	}
+	printk("ok\n");
 	up_write(&devices_subsys.rwsem);
 
 	sysdev_shutdown();
drivers/base/power/suspend.c +3 -0
@@ -113,10 +113,13 @@
 	int error = 0;
 	struct device * dev;
 
+	printk("Powering down devices: ");
 	list_for_each_entry_reverse(dev,&dpm_off_irq,power.entry) {
+		printk("%s ", dev->bus_id);
 		if ((error = suspend_device(dev,state)))
 			break;
 	} 
+	printk("ok?\n"); 
 	if (error)
 		goto Error;
 	if ((error = sysdev_suspend(state)))
drivers/base/sys.c +8 -8
@@ -302,18 +302,17 @@
 {
 	struct sysdev_class * cls;
 
-	pr_debug("Suspending System Devices\n");
+	printk("Suspending System Devices: ");
 
 	list_for_each_entry_reverse(cls,&system_subsys.kset.list,
 				    kset.kobj.entry) {
 		struct sys_device * sysdev;
 
-		pr_debug("Suspending type '%s':\n",
-			 kobject_name(&cls->kset.kobj));
+		printk("%s: ", kobject_name(&cls->kset.kobj));
 
 		list_for_each_entry(sysdev,&cls->kset.list,kobj.entry) {
 			struct sysdev_driver * drv;
-			pr_debug(" %s\n",kobject_name(&sysdev->kobj));
+			printk(" %s, ",kobject_name(&sysdev->kobj));
 
 			/* Call global drivers first. */
 			list_for_each_entry(drv,&global_drivers,entry) {
@@ -332,6 +331,7 @@
 				cls->suspend(sysdev,state);
 		}
 	}
+	printk("ok\n");
 	return 0;
 }
 
@@ -349,17 +349,16 @@
 {
 	struct sysdev_class * cls;
 
-	pr_debug("Resuming System Devices\n");
+	printk("Resuming System Devices: ");
 
 	list_for_each_entry(cls,&system_subsys.kset.list,kset.kobj.entry) {
 		struct sys_device * sysdev;
 
-		pr_debug("Resuming type '%s':\n",
-			 kobject_name(&cls->kset.kobj));
+		printk("%s: ", kobject_name(&cls->kset.kobj));
 
 		list_for_each_entry(sysdev,&cls->kset.list,kobj.entry) {
 			struct sysdev_driver * drv;
-			pr_debug(" %s\n",kobject_name(&sysdev->kobj));
+			printk(" %s, ",kobject_name(&sysdev->kobj));
 
 			/* First, call the class-specific one */
 			if (cls->resume)
@@ -379,6 +378,7 @@
 
 		}
 	}
+	printk("ok\n");
 	return 0;
 }
 
drivers/input/serio/i8042.c +5 -1
@@ -832,12 +833,13 @@
 		return -1;
 	}
 
+#if 0
 	if (i8042_mux_present)
 		if (i8042_enable_mux_mode(&i8042_aux_values, NULL) ||
 		    i8042_enable_mux_ports(&i8042_aux_values)) {
 			printk(KERN_WARNING "i8042: failed to resume active multiplexor, mouse won't work.\n");
 		}
-
+#endif
 /*
  * Reconnect anything that was connected to the ports.
  */
@@ -845,12 +847,15 @@
 	if (i8042_kbd_values.exists && i8042_activate_port(&i8042_kbd_port) == 0)
 		serio_reconnect(&i8042_kbd_port);
 
+#if 0
 	if (i8042_aux_values.exists && i8042_activate_port(&i8042_aux_port) == 0)
 		serio_reconnect(&i8042_aux_port);
 
 	for (i = 0; i < 4; i++)
 		if (i8042_mux_values[i].exists && i8042_activate_port(i8042_mux_port + i) == 0)
 			serio_reconnect(i8042_mux_port + i);
+#endif
+
 /*
  * Restart timer (for polling "stuck" data)
  */
include/linux/suspend.h +8 -0
@@ -81,6 +81,14 @@
 }
 #endif	/* CONFIG_PM */
 
+#ifdef CONFIG_SMP
+extern void smp_freeze(void);
+extern void smp_restart(void);
+#else
+static inline void smp_freeze(void) {}
+static inline void smp_restart(void) {}
+#endif
+
 asmlinkage void do_magic(int is_resume);
 asmlinkage void do_magic_resume_1(void);
 asmlinkage void do_magic_resume_2(void);
kernel/power/Makefile +1 -0
@@ -1,4 +1,5 @@
 obj-y				:= main.o process.o console.o pm.o
+obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o
 obj-$(CONFIG_PM_DISK)		+= disk.o pmdisk.o
 
kernel/power/console.c +1 -0
@@ -7,6 +7,7 @@
 #include <linux/vt_kern.h>
 #include <linux/kbd_kern.h>
 #include <linux/console.h>
+#include <linux/delay.h>
 #include "power.h"
 
 static int new_loglevel = 10;
kernel/power/smp.c +65 -0

66 lines not on this page · raw message

kernel/power/swsusp.c +16 -4
@@ -851,8 +851,11 @@
 
 		free_some_memory();
 		
-		/* Save state of all device drivers, and stop them. */		   
-		if ((res = device_suspend(4))==0)
+		mdelay(1000);
+		smp_freeze();
+		/* Save state of all device drivers, and stop them. */
+		printk("Suspending devices... ");
+		if ((res = device_suspend(4))==0) {
 			/* If stopping device drivers worked, we proceed basically into
 			 * suspend_save_image.
 			 *
@@ -862,8 +865,16 @@
 			 * unsuspends all device drivers, and writes memory to disk
 			 * using normal kernel mechanism.
 			 */
+			printk("ok\n");
+#if 1
 			do_magic(0);
+#else
+			device_resume();
+#endif
+		}
 		thaw_processes();
+		printk("Processes thawed\n");
+		smp_restart();
 	} else
 		res = -EBUSY;
 	software_suspend_enabled = 1;
@@ -1187,8 +1198,7 @@
 static int __init software_resume(void)
 {
 	if (num_online_cpus() > 1) {
-		printk(KERN_WARNING "Software Suspend has malfunctioning SMP support. Disabled :(\n");	
-		return -EINVAL;
+		printk(KERN_WARNING "SMP support is very experimental.\n");	
 	}
 	/* We enable the possibility of machine suspend */
 	software_suspend_enabled = 1;
@@ -1215,6 +1225,8 @@
 	printk( "resuming from %s\n", resume_file);
 	if (read_suspend_image(resume_file, 0))
 		goto read_failure;
+	mdelay(1000);
+	smp_freeze();
 	device_suspend(4);
 	do_magic(1);
 	panic("This never returns");
Signature · 1 line
934a471f20d6580d5aad759bf0d97ddc
#1 lore raw
Quoted 1 line · Pavel Machek

Why is 8042 marked as system device, btw?

What should it be? Seems to be a good classification for a KBC...

Quoted 4 lines

Stopping timer for system
device is likely useless; first resume is called and only after that interrupts are reenabled.

The same routine is used for new and old (APM) style resume where running timer may prevent system from suspending.

Signature · 1 line
Dmitry