Skip to contentSkip to conversation

FYI: my current swsusp bigdiff

PATCH Pavel Machek 1 participant 1 message Jul 22, 2003

Subsystems (8)
Network drivers ACPI PCI Driver core +4 more subsystems
lore
Share & tools
lore
#0 lore raw

Hi!

Here it is. This is FYI, not to be applied.
Pavel
%patch

drivers/input/serio/i8042.c +1 -4
Index: linux/drivers/input/serio/i8042.c
===================================================================
@@ -432,18 +432,15 @@
  * desired.
  */
 	
-static int __init i8042_controller_init(void)
+int i8042_controller_init(void)
 {
-
 /*
  * Test the i8042. We need to know if it thinks it's working correctly
  * before doing anything else.
  */
 
 	i8042_flush();
-
 	if (i8042_reset) {
-
 		unsigned char param;
 
 		if (i8042_command(&param, I8042_CMD_CTL_TEST)) {
drivers/input/keyboard/atkbd.c +6 -5
Index: linux/drivers/input/keyboard/atkbd.c
===================================================================
@@ -27,7 +27,7 @@
 
 static int atkbd_set = 2;
 #if defined(__i386__) || defined (__x86_64__)
-static int atkbd_reset;
+static int atkbd_reset = 1;
 #else
 static int atkbd_reset = 1;
 #endif
@@ -387,7 +387,7 @@
  * atkbd_probe() probes for an AT keyboard on a serio port.
  */
 
-static int atkbd_probe(struct atkbd *atkbd)
+int atkbd_probe(struct atkbd *atkbd)
 {
 	unsigned char param[2];
 
@@ -476,6 +476,9 @@
 	kfree(atkbd);
 }
 
+struct atkbd *myat;
+
+
 /*
  * atkbd_connect() is called when the serio module finds and interface
  * that isn't handled yet by an appropriate device driver. We check if
@@ -495,6 +498,7 @@
 	if (!(atkbd = kmalloc(sizeof(struct atkbd), GFP_KERNEL)))
 		return;
 
+	myat = atkbd;
 	memset(atkbd, 0, sizeof(struct atkbd));
 
 	if ((serio->type & SERIO_TYPE) == SERIO_8042 && serio->write)
@@ -523,15 +527,12 @@
 	}
 
 	if (atkbd->write) {
-
 		if (atkbd_probe(atkbd)) {
 			serio_close(serio);
 			kfree(atkbd);
 			return;
 		}
-		
 		atkbd->set = atkbd_set_3(atkbd);
-
 	} else {
 		atkbd->set = 2;
 		atkbd->id = 0xab00;
include/linux/serio.h +0 -4
Index: linux/include/linux/serio.h
===================================================================
@@ -18,10 +18,7 @@
 
 #include <linux/list.h>
 
-struct serio;
-
 struct serio {
-
 	void *private;
 	void *driver;
 	char *name;
@@ -45,7 +42,6 @@
 };
 
 struct serio_dev {
-
 	void *private;
 	char *name;
 
drivers/input/power.c +12 -4
Index: linux/drivers/input/power.c
===================================================================
@@ -45,9 +45,7 @@
 static int suspend_button_pushed = 0;
 static void suspend_button_task_handler(void *data)
 {
-        //extern void pm_do_suspend(void);
         udelay(200); /* debounce */
-        //pm_do_suspend();
         suspend_button_pushed = 0;
 }
 
@@ -67,8 +65,6 @@
 			case KEY_SUSPEND:
 				printk("Powering down entire device\n");
 
-				//pm_send_all(PM_SUSPEND, dev);
-
 				if (!suspend_button_pushed) {
                 			suspend_button_pushed = 1;
                         		schedule_work(&suspend_button_task);
@@ -76,6 +72,18 @@
 				break;
 			case KEY_POWER:
 				/* Hum power down the machine. */
+				{
+					char *argv[2] = {NULL, NULL};
+					char *envp[3] = {NULL, NULL, NULL};
+
+					argv[0] = "/sbin/poweroff";
+
+					/* minimal command environment */
+					envp[0] = "HOME=/";
+					envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+	
+					call_usermodehelper(argv[0], argv, envp, 0);
+				}
 				break;
 			default:	
 				return;
drivers/acpi/sleep/main.c +15 -5
Index: linux/drivers/acpi/sleep/main.c
===================================================================
@@ -50,6 +50,18 @@
 	/* enable interrupts once again */
 	ACPI_ENABLE_IRQS();
 
+//	i8042_controller_init();
+	{
+		extern struct atkbd *myat;
+		atkbd_probe(myat);
+	}
+
+//	i8042_controller_init();
+	{
+		extern struct atkbd *myat;
+		atkbd_probe(myat);
+	}
+
 	/* restore device context */
 	device_resume(RESUME_RESTORE_STATE);
 
@@ -69,10 +81,6 @@
  * First, we call to the device driver layer to save device state.
  * Once we have that, we save whatevery processor and kernel state we
  * need to memory.
- * If we're entering S4, we then write the memory image to disk.
- *
- * Only then is it safe for us to power down devices, since we may need
- * the disks and upstream buses to write to.
  */
 acpi_status
 acpi_system_save_state(
@@ -197,7 +205,7 @@
 		break;
 	}
 	local_irq_restore(flags);
-	printk(KERN_CRIT "Back to C!\n");
+	printk(KERN_DEBUG "Back to C!\n");
 
 	return status;
 }
@@ -226,6 +234,7 @@
 	if (state == ACPI_STATE_S4 && !acpi_gbl_FACS->S4bios_f)
 		return AE_ERROR;
 
+	prepare_suspend_console();
 	/*
 	 * TBD: S1 can be done without device_suspend.  Make a CONFIG_XX
 	 * to handle however when S1 failed without device_suspend.
@@ -270,6 +279,7 @@
 	/* reset firmware waking vector */
 	acpi_set_firmware_waking_vector((acpi_physical_address) 0);
 	thaw_processes();
+	restore_console();
 
 	return status;
 }
arch/x86_64/kernel/time.c +20 -5
Index: linux/arch/x86_64/kernel/time.c
===================================================================
@@ -22,7 +22,7 @@
 #include <linux/time.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
-#include <linux/device.h>
+#include <linux/sysdev.h>
 #include <linux/bcd.h>
 #include <asm/pgtable.h>
 #include <asm/vsyscall.h>
@@ -72,7 +72,7 @@
  * timer interrupt has happened already, but vxtime.trigger wasn't updated yet.
  * This is not a problem, because jiffies hasn't updated either. They are bound
  * together by xtime_lock.
-         */
+ */
 
 static inline unsigned int do_gettimeoffset_tsc(void)
 {
@@ -549,7 +549,17 @@
 	return 0;
 }
 
-void __init pit_init(void)
+static struct sysdev_class rtc_sysclass = {
+	set_kset_name("rtc"),
+};
+
+/* XXX this driverfs stuff should probably go elsewhere later -john */
+static struct sys_device device_i8253 = {
+	.id		= 0,
+	.cls	= &rtc_sysclass,
+};
+
+int __init pit_init(void)
 {
 	unsigned long flags;
 
@@ -558,6 +568,11 @@
 	outb_p(LATCH & 0xff, 0x40);	/* LSB */
 	outb_p(LATCH >> 8, 0x40);	/* MSB */
 	spin_unlock_irqrestore(&i8253_lock, flags);
+
+	int error = sysdev_class_register(&rtc_sysclass);
+	if (!error)
+		error = sys_device_register(&device_i8253);
+	return error;
 }
 
 int __init time_setup(char *str)
@@ -601,8 +616,8 @@
 		cpu_khz = hpet_calibrate_tsc();
 		timename = "HPET";
 	} else {
-	pit_init();
-	cpu_khz = pit_calibrate_tsc();
+		pit_init();
+		cpu_khz = pit_calibrate_tsc();
 		timename = "PIT";
 	}
 
arch/i386/kernel/Makefile +2 -1
Index: linux/arch/i386/kernel/Makefile
===================================================================
@@ -24,7 +24,8 @@
 obj-$(CONFIG_X86_MPPARSE)	+= mpparse.o
 obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o nmi.o
 obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o
-obj-$(CONFIG_SOFTWARE_SUSPEND)	+= suspend.o suspend_asm.o
+obj-$(CONFIG_SOFTWARE_SUSPEND)	+= suspend.o
+obj-$(CONFIG_PM)		+= suspend_asm.o
 obj-$(CONFIG_X86_NUMAQ)		+= numaq.o
 obj-$(CONFIG_X86_SUMMIT)	+= summit.o
 obj-$(CONFIG_EDD)             	+= edd.o
arch/i386/kernel/suspend_asm.S +2 -1
Index: linux/arch/i386/kernel/suspend_asm.S
===================================================================
@@ -32,6 +32,7 @@
 saved_context_eflags:
 	.long	0
 
+#ifdef CONFIG_SOFTWARE_SUSPEND
 	.text
 
 ENTRY(do_magic)
@@ -117,4 +118,4 @@
 loop2:
        .quad 0
        .previous
-	
\ No newline at end of file
+#endif
arch/i386/kernel/sysenter.c +0 -2
Index: linux/arch/i386/kernel/sysenter.c
===================================================================
@@ -31,8 +31,6 @@
 	wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
 	wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp1, 0);
 	wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) sysenter_entry, 0);
-
-	printk("Enabling SEP on CPU %d\n", cpu);
 	put_cpu();	
 }
 
drivers/acpi/Kconfig +2 -2
Index: linux/drivers/acpi/Kconfig
===================================================================
@@ -58,8 +58,8 @@
 	default y
 
 config ACPI_SLEEP
-	bool "Sleep States"
-	depends on X86 && ACPI && !ACPI_HT_ONLY && SOFTWARE_SUSPEND
+	bool "Sleep States (EXPERIMENTAL)"
+	depends on X86 && ACPI && !ACPI_HT_ONLY && EXPERIMENTAL
 	---help---
 	  This option adds support for ACPI suspend states. 
 
drivers/base/power.c +0 -6
Index: linux/drivers/base/power.c
===================================================================
@@ -52,8 +52,6 @@
 	struct device * dev;
 	int error = 0;
 
-	printk(KERN_EMERG "Suspending devices\n");
-
 	down_write(&devices_subsys.rwsem);
 	list_for_each_entry_reverse(dev,&devices_subsys.kset.list,kobj.entry) {
 		if (dev->driver && dev->driver->suspend) {
@@ -114,8 +112,6 @@
 		}
 	}
 	up_write(&devices_subsys.rwsem);
-
-	printk(KERN_EMERG "Devices Resumed\n");
 }
 
 /**
@@ -125,8 +121,6 @@
 {
 	struct device * dev;
 	
-	printk(KERN_EMERG "Shutting down devices\n");
-
 	down_write(&devices_subsys.rwsem);
 	list_for_each_entry_reverse(dev,&devices_subsys.kset.list,kobj.entry) {
 		pr_debug("shutting down %s: ",dev->name);
drivers/pcmcia/yenta_socket.c +4 -1
Index: linux/drivers/pcmcia/yenta_socket.c
===================================================================
@@ -899,7 +899,10 @@
 
 static int yenta_dev_suspend (struct pci_dev *dev, u32 state)
 {
-	return pcmcia_socket_dev_suspend(&dev->dev, state, 0);
+	/* FIXME: We should really let devices to act on *all* levels :-(.
+	   If you put something else than SUSPEND_SAVE_STATE,
+	   pcmcia_socket_dev_suspend() will simply do nothing due to its check. */
+	return pcmcia_socket_dev_suspend(&dev->dev, state, SUSPEND_SAVE_STATE);
 }
 
 
include/linux/reboot.h +1 -1
Index: linux/include/linux/reboot.h
===================================================================
@@ -21,7 +21,7 @@
  * CAD_OFF     Ctrl-Alt-Del sequence sends SIGINT to init task.
  * POWER_OFF   Stop OS and remove all power from system, if possible.
  * RESTART2    Restart system using given command string.
- * SW_SUSPEND  Suspend system using Software Suspend if compiled in
+ * SW_SUSPEND  Suspend system using software suspend if compiled in.
  */
 
 #define	LINUX_REBOOT_CMD_RESTART	0x01234567
include/linux/suspend.h +11 -7
Index: linux/include/linux/suspend.h
===================================================================
@@ -55,10 +55,6 @@
 
 extern int register_suspend_notifier(struct notifier_block *);
 extern int unregister_suspend_notifier(struct notifier_block *);
-extern void refrigerator(unsigned long);
-
-extern int freeze_processes(void);
-extern void thaw_processes(void);
 
 extern unsigned int nr_copy_pages __nosavedata;
 extern suspend_pagedir_t *pagedir_nosave __nosavedata;
@@ -76,15 +72,23 @@
 extern void do_suspend_lowlevel_s4bios(int resume);
 
 #else
-static inline void software_suspend(void)
-{
-}
+static inline void software_suspend(void) { }
 #define software_resume()		do { } while(0)
 #define register_suspend_notifier(a)	do { } while(0)
 #define unregister_suspend_notifier(a)	do { } while(0)
+#endif
+
+#ifdef CONFIG_PM
+extern void refrigerator(unsigned long);
+extern int freeze_processes(void);
+extern void thaw_processes(void);
+#else
 #define refrigerator(a)			do { BUG(); } while(0)
 #define freeze_processes()		do { panic("You need CONFIG_SOFTWARE_SUSPEND to do sleeps."); } while(0)
 #define thaw_processes()		do { } while(0)
 #endif
 
+extern int prepare_suspend_console(void);
+extern void restore_console(void);
+
 #endif /* _LINUX_SWSUSP_H */
kernel/Makefile +1 -1
Index: linux/kernel/Makefile
===================================================================
@@ -17,7 +17,7 @@
 obj-$(CONFIG_PM) += pm.o
 obj-$(CONFIG_CPU_FREQ) += cpufreq.o
 obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
-obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o
+obj-$(CONFIG_PM) += suspend.o
 obj-$(CONFIG_COMPAT) += compat.o
 
 ifneq ($(CONFIG_IA64),y)
kernel/suspend.c +74 -81

274 lines not on this page · raw message

arch/i386/kernel/acpi/wakeup.S +5 -0
Index: linux/arch/i386/kernel/acpi/wakeup.S
===================================================================
@@ -43,6 +43,11 @@
 
 	testl	$1, video_flags - wakeup_code
 	jz	1f
+	/* It is miracle that this works:
+	   * PCI may or may not be initialized at this point
+	   * I'm told we should pass device ID to video bios
+	   However it works on some real machines...
+	 */
 	lcall   $0xc000,$3
 	movw	%cs, %ax
 	movw	%ax, %ds					# Bios might have played with that
drivers/net/8139too.c +12 -1
Index: linux/drivers/net/8139too.c
===================================================================
@@ -109,6 +109,7 @@
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/completion.h>
+#include <linux/suspend.h>
 #include <linux/crc32.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -565,6 +566,7 @@
 	void *mmio_addr;
 	int drv_flags;
 	struct pci_dev *pci_dev;
+        u32 pci_state[16];
 	struct net_device_stats stats;
 	unsigned char *rx_ring;
 	unsigned int cur_rx;	/* Index into the Rx buffer of next Rx pkt. */
@@ -1597,6 +1599,8 @@
 		timeout = next_tick;
 		do {
 			timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout);
+			if (current->flags & PF_FREEZE)
+				refrigerator(PF_IOTHREAD);
 		} while (!signal_pending (current) && (timeout > 0));
 
 		if (signal_pending (current)) {
@@ -2566,6 +2570,9 @@
 	tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
 	RTL_W32 (RxMissed, 0);
 
+	pci_save_state (pdev, tp->pci_state);
+	pci_set_power_state (pdev, 3);
+
 	spin_unlock_irqrestore (&tp->lock, flags);
 	return 0;
 }
@@ -2574,11 +2581,15 @@
 static int rtl8139_resume (struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata (pdev);
+	struct rtl8139_private *tp = dev->priv;
 
 	if (!netif_running (dev))
 		return 0;
-	netif_device_attach (dev);
+	pci_set_power_state (pdev, 0);
+	pci_restore_state (pdev, tp->pci_state);
+	rtl8139_init_ring (dev);
 	rtl8139_hw_start (dev);
+	netif_device_attach (dev);
 	return 0;
 }
 
drivers/pci/pci-driver.c +3 -5
Index: linux/drivers/pci/pci-driver.c
===================================================================
@@ -179,11 +179,9 @@
 	struct pci_dev * pci_dev = to_pci_dev(dev);
 
 	if (pci_dev->driver) {
-		/* We may not call PCI drivers resume at
-		   RESUME_POWER_ON because interrupts are not yet
-		   working at that point. Calling resume at
-		   RESUME_RESTORE_STATE seems like solution. */
-		if (level == RESUME_RESTORE_STATE && pci_dev->driver->resume)
+	        if (level == RESUME_POWER_ON && pci_dev->driver->power_on)
+			pci_dev->driver->power_on(pci_dev);
+		else if (level == RESUME_RESTORE_STATE && pci_dev->driver->resume)
 			pci_dev->driver->resume(pci_dev);
 	}
 	return 0;
include/linux/pci.h +1 -0
Index: linux/include/linux/pci.h
===================================================================
@@ -512,6 +512,7 @@
 	void (*remove) (struct pci_dev *dev);	/* Device removed (NULL if not a hot-plug capable driver) */
 	int  (*save_state) (struct pci_dev *dev, u32 state);    /* Save Device Context */
 	int  (*suspend) (struct pci_dev *dev, u32 state);	/* Device suspended */
+	int  (*power_on) (struct pci_dev *dev);	                /* Device power on */
 	int  (*resume) (struct pci_dev *dev);	                /* Device woken up */
 	int  (*enable_wake) (struct pci_dev *dev, u32 state, int enable);   /* Enable wake event */
 

%diffstat

 arch/i386/kernel/Makefile      |    3 
 arch/i386/kernel/acpi/wakeup.S |    5 +
 arch/i386/kernel/suspend_asm.S |    3 
 arch/i386/kernel/sysenter.c    |    2 
 arch/x86_64/kernel/time.c      |   25 +++++-
 drivers/acpi/Kconfig           |    4 -
 drivers/acpi/sleep/main.c      |   20 +++--
 drivers/base/power.c           |    6 -
 drivers/input/keyboard/atkbd.c |   11 +-
 drivers/input/power.c          |   16 +++-
 drivers/input/serio/i8042.c    |    5 -
 drivers/net/8139too.c          |   13 +++
 drivers/pci/pci-driver.c       |    8 --
 drivers/pcmcia/yenta_socket.c  |    5 +
 include/linux/pci.h            |    1 
 include/linux/reboot.h         |    2 
 include/linux/serio.h          |    4 -
 include/linux/suspend.h        |   18 ++--
 kernel/Makefile                |    2 
 kernel/suspend.c               |  155 +++++++++++++++++++----------------------
 20 files changed, 172 insertions(+), 136 deletions(-)
Signature · 2 lines
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]