[PATCH] APM patch for 2.2.0-pre4

Stephen Rothwell (sfr@canb.auug.org.au)
Tue, 05 Jan 1999 01:41:36 +1100


Hi Linus,

This is the second part of a patch I sent to you for 2.1.131 that
seems top have got lost. It does:
- Add CONFIG_APM_RTC_IS_GMT (Richard Gooch <rgooch@atnf.csiro.au>)
- change APM_NOINTS to CONFIG_APM_ALLOW_INTS (Suggested by many
as it is needed to make the newer Thinkpads suspend without
hanging)
- remove dependency on CONFIG_PROC_FS (since the bits of proc_fs
we need are now always present)
- slight fix to the way CONFIG_APM_IGNORE_SUSPEND_BOUNCE
is implemented

These changes are very minor and the two new config options
are off by default which gives the old behaviour.

Cheers,
Stephen

--
Stephen Rothwell                    Stephen.Rothwell@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

diff -ruN linux-2.2.0-pre4/Documentation/Configure.help linux/Documentation/Configure.help --- linux-2.2.0-pre4/Documentation/Configure.help Tue Jan 5 00:22:03 1999 +++ linux/Documentation/Configure.help Tue Jan 5 01:23:16 1999 @@ -8449,13 +8449,40 @@ Ignore multiple suspend/resume cycles CONFIG_APM_IGNORE_SUSPEND_BOUNCE - This option is necessary on the Dell Inspiron 3200, but should be - safe for all other laptops. When enabled, a system suspend event - that occurs within one second of a resume is ignored. Without this - the Inspiron will shut itself off a few seconds after you open the - lid, requiring you to press the power button to resume it a second - time. + This option is necessary on the Dell Inspiron 3200 and others, but + should be safe for all other laptops. When enabled, a system suspend + event that occurs within one second of a resume is ignored. Without + this the Inspiron will shut itself off a few seconds after you open + the lid, requiring you to press the power button to resume it a + second time. Say Y. + +RTC stores time in GMT +CONFIG_APM_RTC_IS_GMT + This option can be used when your RTC (Real Time Clock aka. Hardware + Clock) stores the time in GMT (Greenwich Mean Time) rather than + localtime. When suspending/resuming, the kernel needs to know what + is stored in the RTC so it can update the system clock (which is + always GMT). Without this option the kernel attempts to measure + the offset between the RTC and the system clock. This means you + can loose one second on each suspend/resume cycle. + Also, on the Dell Inspiron 3200, the hardware slows down the system + even before the kernel can measure the RTC/system clock offset. It + can then take 15 seconds to do this measurement and it can be + incorrect by several seconds. + Say Y if GMT is stored in your RTC. + GMT is usually the best anyway, because you don't have to worry about + daylight savings time changes. The only reason to not use GMT in + your RTC is if you also run a broken OS that doesn't understand GMT. + +Allow interrupts during APM BIOS calls +CONFIG_APM_ALLOW_INTS + Normally we disable external interrupts while we are making calls to + the APM BIOS as a measure to lessen the effects of a badly behaving + BIOS implementation. The BIOS should reeanble interrupts if it + needs to. Unfortunately, some BIOS's do not - especially those in + many of the newer IBM Thinkpads. If you experience hangs when you + suspend, try setting this to Y. Otherwise, say N. Watchdog Timer Support CONFIG_WATCHDOG diff -ruN linux-2.2.0-pre4/arch/i386/config.in linux/arch/i386/config.in --- linux-2.2.0-pre4/arch/i386/config.in Sun Jan 3 02:04:29 1999 +++ linux/arch/i386/config.in Tue Jan 5 01:23:35 1999 @@ -97,6 +97,8 @@ bool ' Power off on shutdown' CONFIG_APM_POWER_OFF bool ' Ignore multiple suspend' CONFIG_APM_IGNORE_MULTIPLE_SUSPEND bool ' Ignore multiple suspend/resume cycles' CONFIG_APM_IGNORE_SUSPEND_BOUNCE + bool ' RTC stores time in GMT' CONFIG_APM_RTC_IS_GMT + bool ' Allow interrupts during APM BIOS calls' CONFIG_APM_ALLOW_INTS fi endmenu diff -ruN linux-2.2.0-pre4/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c --- linux-2.2.0-pre4/arch/i386/kernel/apm.c Thu Dec 3 22:17:09 1998 +++ linux/arch/i386/kernel/apm.c Tue Jan 5 01:19:56 1999 @@ -31,6 +31,7 @@ * Aug 1998, Version 1.5 * Sep 1998, Version 1.6 * Nov 1998, Version 1.7 + * Jan 1999, Version 1.8 * * History: * 0.6b: first version in official kernel, Linux 1.3.46 @@ -72,6 +73,11 @@ * Make boot messages far less verbose by default * Make asm safer * Stephen Rothwell + * 1.8: Add CONFIG_APM_RTC_IS_GMT + * Richard Gooch <rgooch@atnf.csiro.au> + * change APM_NOINTS to CONFIG_APM_ALLOW_INTS + * remove dependency on CONFIG_PROC_FS + * Stephen Rothwell * * APM 1.1 Reference: * @@ -105,10 +111,8 @@ #include <linux/fcntl.h> #include <linux/malloc.h> #include <linux/linkage.h> -#ifdef CONFIG_PROC_FS #include <linux/stat.h> #include <linux/proc_fs.h> -#endif #include <linux/miscdevice.h> #include <linux/apm_bios.h> #include <linux/init.h> @@ -202,13 +206,6 @@ #define ALWAYS_CALL_BUSY /* - * Define to disable interrupts in APM BIOS calls (the CPU Idle BIOS call - * should turn interrupts on before it does a 'hlt'). - * This reportedly needs undefining for the ThinkPad 600. - */ -#define APM_NOINTS - -/* * Define to make the APM BIOS calls zero all data segment registers (so * that an incorrect BIOS implementation will cause a kernel panic if it * tries to write to arbitrary memory). @@ -266,9 +263,7 @@ static unsigned int do_poll(struct file *, poll_table *); static int do_ioctl(struct inode *, struct file *, u_int, u_long); -#ifdef CONFIG_PROC_FS static int apm_get_info(char *, char **, off_t, int, int); -#endif extern int apm_register_callback(int (*)(apm_event_t)); extern void apm_unregister_callback(int (*)(apm_event_t)); @@ -290,8 +285,13 @@ static int waiting_for_resume = 0; #endif +#ifdef CONFIG_APM_RTC_IS_GMT +# define clock_cmos_diff 0 +# define got_clock_diff 1 +#else static long clock_cmos_diff; static int got_clock_diff = 0; +#endif static int debug = 0; static int apm_disabled = 0; @@ -300,7 +300,7 @@ static struct timer_list apm_timer; -static char driver_version[] = "1.7"; /* no spaces */ +static char driver_version[] = "1.8"; /* no spaces */ #ifdef APM_DEBUG static char * apm_event_name[] = { @@ -375,22 +375,22 @@ #define ERROR_COUNT (sizeof(error_table)/sizeof(lookup_t)) /* - * These are the actual BIOS calls. Depending on APM_ZERO_SEGS - * and APM_NOINTS, we are being really paranoid here! Not only are - * interrupts disabled, but all the segment registers (except SS) are - * saved and zeroed this means that if the BIOS tries to reference any - * data without explicitly loading the segment registers, the kernel will - * fault immediately rather than have some unforeseen circumstances for - * the rest of the kernel. And it will be very obvious! :-) Doing this - * depends on CS referring to the same physical memory as DS so that DS - * can be zeroed before the call. Unfortunately, we can't do anything + * These are the actual BIOS calls. Depending on APM_ZERO_SEGS and + * CONFIG_APM_ALLOW_INTS, we are being really paranoid here! Not only + * are interrupts disabled, but all the segment registers (except SS) + * are saved and zeroed this means that if the BIOS tries to reference + * any data without explicitly loading the segment registers, the kernel + * will fault immediately rather than have some unforeseen circumstances + * for the rest of the kernel. And it will be very obvious! :-) Doing + * this depends on CS referring to the same physical memory as DS so that + * DS can be zeroed before the call. Unfortunately, we can't do anything * about the stack segment/pointer. Also, we tell the compiler that * everything could change. * * Also, we KNOW that for the non error case of apm_bios_call, there * is no useful data returned in the low order 8 bits of eax. */ -#ifdef APM_NOINTS +#ifndef CONFIG_APM_ALLOW_INTS # define APM_DO_CLI __cli() #else # define APM_DO_CLI @@ -747,14 +747,17 @@ unsigned long flags; int err; - /* Estimate time zone so that set_time can - update the clock */ +#ifndef CONFIG_APM_RTC_IS_GMT + /* + * Estimate time zone so that set_time can update the clock + */ save_flags(flags); clock_cmos_diff = -get_cmos_time(); cli(); clock_cmos_diff += CURRENT_TIME; got_clock_diff = 1; restore_flags(flags); +#endif err = apm_set_power_state(APM_STATE_SUSPEND); if (err) @@ -826,7 +829,7 @@ apm_event_t event; #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE static unsigned long last_resume = 0; - static int did_resume = 0; + static int ignore_bounce = 0; #endif while ((event = get_event()) != 0) { @@ -838,6 +841,10 @@ printk(KERN_DEBUG "apm: received unknown " "event 0x%02x\n", event); #endif +#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE + if (ignore_bounce && ((jiffies - last_resume) > HZ)) + ignore_bounce = 0; +#endif switch (event) { case APM_SYS_STANDBY: case APM_USER_STANDBY: @@ -859,7 +866,7 @@ #endif case APM_SYS_SUSPEND: #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE - if (did_resume && ((jiffies - last_resume) < HZ)) + if (ignore_bounce) break; #endif #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND @@ -880,7 +887,7 @@ #endif #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE last_resume = jiffies; - did_resume = 1; + ignore_bounce = 1; #endif set_time(); send_event(event, 0, NULL); @@ -1139,7 +1146,6 @@ return 0; } -#ifdef CONFIG_PROC_FS int apm_get_info(char *buf, char **start, off_t fpos, int length, int dummy) { char * p; @@ -1228,7 +1234,6 @@ return p - buf; } -#endif void __init apm_setup(char *str, int *dummy) { @@ -1422,10 +1427,9 @@ apm_timer.expires = APM_CHECK_TIMEOUT + jiffies; add_timer(&apm_timer); -#ifdef CONFIG_PROC_FS ent = create_proc_entry("apm", 0, 0); - ent->get_info = apm_get_info; -#endif + if (ent != NULL) + ent->get_info = apm_get_info; misc_register(&apm_device);

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/