SMP support for swsusp, and strange serio/i8042 problems
Subsystems (5)
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
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