lkml.org 
[lkml]   [2000]   [Sep]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Subject[PATCH] APM updates for 2.2.18pre4
Date
From
Hi Alan,

This is a backport of relevent changes to the 2.3 APM driver. It
also includes the previous patch I sent you today.

This patch does:
- Remove CONFIG_APM_SUSPEND_BOUNCE. The bounce ignore
interval is now configurable.
- Disable interrupts while we are suspended.
- Notify drivers on critical suspend.
- remove zero initialisations.
- general resync with 2.3/4 driver.

It also (as a side effect) makes 2.2.18pre4 boot - if you enable
APM support :-)).

Cheers,
Stephen
--
Stephen Rothwell, Open Source Researcher, Linuxcare, Inc.
+61-2-62628990 tel, +61-2-62628991 fax
sfr@linuxcare.com, http://www.linuxcare.com/
Linuxcare. Support for the revolution.

diff -ruN 2.2.18pre4/arch/i386/config.in 2.2.18pre4-APM.1/arch/i386/config.in
--- 2.2.18pre4/arch/i386/config.in Mon Sep 11 10:17:09 2000
+++ 2.2.18pre4-APM.1/arch/i386/config.in Mon Sep 11 16:22:50 2000
@@ -111,7 +111,6 @@
bool ' Enable PM at boot time' CONFIG_APM_DO_ENABLE
bool ' Make CPU Idle calls when idle' CONFIG_APM_CPU_IDLE
bool ' Enable console blanking using APM' CONFIG_APM_DISPLAY_BLANK
- 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
bool ' Use real mode APM BIOS call to power off' CONFIG_APM_REAL_MODE_POWER_OFF
diff -ruN 2.2.18pre4/arch/i386/kernel/apm.c 2.2.18pre4-APM.1/arch/i386/kernel/apm.c
--- 2.2.18pre4/arch/i386/kernel/apm.c Mon Sep 11 10:17:09 2000
+++ 2.2.18pre4-APM.1/arch/i386/kernel/apm.c Mon Sep 11 16:19:47 2000
@@ -36,6 +36,7 @@
* Oct 1999, Version 1.10
* Nov 1999, Version 1.11
* Jan 2000, Version 1.12
+ * Feb 2000, Version 1.13
*
* History:
* 0.6b: first version in official kernel, Linux 1.3.46
@@ -55,7 +56,7 @@
* The new replacment for it is, but Linux doesn't yet support this.
* Alan Cox Linux 2.1.55
* 1.3: Set up a valid data descriptor 0x40 for buggy BIOS's
- * 1.4: Upgraded to support APM 1.2. Integrated ThinkPad suspend patch by
+ * 1.4: Upgraded to support APM 1.2. Integrated ThinkPad suspend patch by
* Dean Gaudet <dgaudet@arctic.org>.
* C. Scott Ananian <cananian@alumni.princeton.edu> Linux 2.1.87
* 1.5: Fix segment register reloading (in case of bad segments saved
@@ -127,8 +128,13 @@
* scripts that check for it before doing power off
* work (Jim Avera <jima@hal.com>).
* 1.13: Fix the Thinkpad (again) :-( (CONFIG_APM_IGNORE_MULTIPLE_SUSPENDS
- * is now the way life works).
+ * is now the way life works).
* Fix thinko in suspend() (wrong return).
+ * Notify drivers on critical suspend.
+ * Disable interrupts while we are suspended (Andy Henroid
+ * <andy_henroid@yahoo.com> fixed by sfr).
+ * Remove CONFIG_APM_SUSPEND_BOUNCE. The bounce ignore
+ * interval is now configurable.
*
* APM 1.1 Reference:
*
@@ -170,10 +176,6 @@
#include <asm/desc.h>
#include <asm/softirq.h>

-/* 2.2-2.3 Compatability defines */
-#define __setup(x, y)
-#define module_init(x)
-
EXPORT_SYMBOL(apm_register_callback);
EXPORT_SYMBOL(apm_unregister_callback);

@@ -199,9 +201,12 @@
* See Documentation/Config.help for the configuration options.
*
* Various options can be changed at boot time as follows:
+ * (We allow underscores for compatibility with the modules code)
* apm=on/off enable/disable APM
* [no-]debug log some debugging messages
- * [no-]power-off power off on shutdown
+ * [no-]power[-_]off power off on shutdown
+ * bounce[-_]interval ignore suspend bounces for this many
+ * ticks
*/

/* KNOWN PROBLEM MACHINES:
@@ -245,8 +250,8 @@

/*
* Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend.
- * This patched by Chad Miller <cmiller@surfsouth.com>, orig code by David
- * Chen <chen@ctpa04.mit.edu>
+ * This patched by Chad Miller <cmiller@surfsouth.com>, original code by
+ * David Chen <chen@ctpa04.mit.edu>
*/
#undef INIT_TIMER_AFTER_SUSPEND

@@ -262,10 +267,9 @@
#define APM_CHECK_TIMEOUT (HZ)

/*
- * If CONFIG_APM_IGNORE_SUSPEND_BOUNCE is defined then
- * ignore suspend events for this amount of time after a resume
+ * Ignore suspend events for this amount of time after a resume
*/
-#define BOUNCE_INTERVAL (3 * HZ)
+#define DEFAULT_BOUNCE_INTERVAL (3 * HZ)

/*
* Save a segment register away
@@ -309,25 +313,27 @@
unsigned short segment;
} apm_bios_entry;
#ifdef CONFIG_APM_CPU_IDLE
-static int clock_slowed = 0;
+static int clock_slowed;
#endif
-static int suspends_pending = 0;
-static int standbys_pending = 0;
-static int waiting_for_resume = 0;
+static int suspends_pending;
+static int standbys_pending;
+static int waiting_for_resume;
+static int ignore_normal_resume;
+static int bounce_interval = DEFAULT_BOUNCE_INTERVAL;

#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;
+static int got_clock_diff;
#endif
-static int debug = 0;
-static int apm_disabled = 0;
+static int debug;
+static int apm_disabled;
#ifdef CONFIG_SMP
-static int power_off_enabled = 0;
+static int power_off;
#else
-static int power_off_enabled = 1;
+static int power_off = 1;
#endif

static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
@@ -407,7 +413,7 @@
#ifndef CONFIG_APM_ALLOW_INTS
# define APM_DO_CLI __cli()
#else
-# define APM_DO_CLI
+# define APM_DO_CLI __sti()
#endif
#ifdef APM_ZERO_SEGS
# define APM_DECL_SEGS \
@@ -622,7 +628,7 @@
* This may be called on an SMP machine.
*/
#ifdef CONFIG_SMP
- /* Many bioses don't like being called from CPU != 0 */
+ /* Some bioses don't like being called from CPU != 0 */
while (cpu_number_map[smp_processor_id()] != 0) {
kernel_thread(apm_magic, NULL,
CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD);
@@ -636,6 +642,7 @@
#endif
}

+#ifdef CONFIG_APM_DO_ENABLE
static int apm_enable_power_management(int enable)
{
u32 eax;
@@ -651,6 +658,7 @@
apm_bios_info.flags |= APM_BIOS_DISABLED;
return APM_SUCCESS;
}
+#endif

static int apm_get_power_status(u_short *status, u_short *bat, u_short *life)
{
@@ -873,12 +881,35 @@
#endif
}

+static int send_event(apm_event_t event, apm_event_t undo)
+{
+ callback_list_t * call;
+ callback_list_t * fix;
+
+ for (call = callback_list; call != NULL; call = call->next) {
+ if (call->callback(event) && undo) {
+ for (fix = callback_list; fix != call; fix = fix->next)
+ fix->callback(undo);
+ if (event == APM_CRITICAL_SUSPEND) {
+ printk(KERN_CRIT "apm: Critical suspend was vetoed, expect armageddon\n" );
+ return 0;
+ }
+ if (apm_bios_info.version > 0x100)
+ apm_set_power_state(APM_STATE_REJECT);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
static int suspend(void)
{
int err;
struct apm_user *as;

get_time_diff();
+ cli();
err = apm_set_power_state(APM_STATE_SUSPEND);
reinit_timer();
set_time();
@@ -886,10 +917,14 @@
err = APM_SUCCESS;
if (err != APM_SUCCESS)
apm_error("suspend", err);
+ send_event(APM_NORMAL_RESUME, 0);
+ sti();
+ queue_event(APM_NORMAL_RESUME, NULL);
for (as = user_list; as != NULL; as = as->next) {
as->suspend_wait = 0;
as->suspend_result = ((err == APM_SUCCESS) ? 0 : -EIO);
}
+ ignore_normal_resume = 1;
wake_up_interruptible(&apm_suspend_waitqueue);
return err;
}
@@ -910,7 +945,7 @@
apm_event_t event;
apm_eventinfo_t info;

- static int notified = 0;
+ static int notified;

/* we don't use the eventinfo */
error = apm_get_event(&event, &info);
@@ -923,33 +958,11 @@
return 0;
}

-static int send_event(apm_event_t event, apm_event_t undo,
- struct apm_user *sender)
-{
- callback_list_t * call;
- callback_list_t * fix;
-
- for (call = callback_list; call != NULL; call = call->next) {
- if (call->callback(event) && undo) {
- for (fix = callback_list; fix != call; fix = fix->next)
- fix->callback(undo);
- if (apm_bios_info.version > 0x100)
- apm_set_power_state(APM_STATE_REJECT);
- return 0;
- }
- }
-
- queue_event(event, sender);
- return 1;
-}
-
static void check_events(void)
{
apm_event_t event;
-#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
- static unsigned long last_resume = 0;
- static int ignore_bounce = 0;
-#endif
+ static unsigned long last_resume;
+ static int ignore_bounce;

while ((event = get_event()) != 0) {
if (debug) {
@@ -960,15 +973,17 @@
printk(KERN_DEBUG "apm: received unknown "
"event 0x%02x\n", event);
}
-#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
if (ignore_bounce
- && ((jiffies - last_resume) > BOUNCE_INTERVAL))
+ && ((jiffies - last_resume) > bounce_interval))
ignore_bounce = 0;
-#endif
+ if (ignore_normal_resume && (event != APM_NORMAL_RESUME))
+ ignore_normal_resume = 0;
+
switch (event) {
case APM_SYS_STANDBY:
case APM_USER_STANDBY:
- if (send_event(event, APM_STANDBY_RESUME, NULL)) {
+ if (send_event(event, APM_STANDBY_RESUME)) {
+ queue_event(event, NULL);
if (standbys_pending <= 0)
standby();
}
@@ -981,10 +996,11 @@
break;
#endif
case APM_SYS_SUSPEND:
-#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
- if (ignore_bounce)
+ if (ignore_bounce) {
+ if (apm_bios_info.version > 0x100)
+ apm_set_power_state(APM_STATE_REJECT);
break;
-#endif
+ }
/*
* If we are already processing a SUSPEND,
* then further SUSPEND events from the BIOS
@@ -995,7 +1011,8 @@
*/
if (waiting_for_resume)
return;
- if (send_event(event, APM_NORMAL_RESUME, NULL)) {
+ if (send_event(event, APM_NORMAL_RESUME)) {
+ queue_event(event, NULL);
waiting_for_resume = 1;
if (suspends_pending <= 0)
(void) suspend();
@@ -1006,18 +1023,21 @@
case APM_CRITICAL_RESUME:
case APM_STANDBY_RESUME:
waiting_for_resume = 0;
-#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
last_resume = jiffies;
ignore_bounce = 1;
-#endif
- set_time();
- send_event(event, 0, NULL);
+ if ((event != APM_NORMAL_RESUME)
+ || (ignore_normal_resume == 0)) {
+ set_time();
+ send_event(event, 0);
+ queue_event(event, NULL);
+ }
break;

case APM_CAPABILITY_CHANGE:
case APM_LOW_BATTERY:
case APM_POWER_STATUS_CHANGE:
- send_event(event, 0, NULL);
+ send_event(event, 0);
+ queue_event(event, NULL);
break;

case APM_UPDATE_TIME:
@@ -1025,6 +1045,11 @@
break;

case APM_CRITICAL_SUSPEND:
+ send_event(event, 0);
+ /*
+ * We can only hope it worked - we are not allowed
+ * to reject a critical suspend.
+ */
(void) suspend();
break;
}
@@ -1084,7 +1109,7 @@
schedule();
goto repeat;
}
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
remove_wait_queue(&apm_waitqueue, &wait);
}
i = count;
@@ -1146,8 +1171,10 @@
as->standbys_read--;
as->standbys_pending--;
standbys_pending--;
- } else if (!send_event(APM_USER_STANDBY, APM_STANDBY_RESUME, as))
+ } else if (!send_event(APM_USER_STANDBY, APM_STANDBY_RESUME))
return -EAGAIN;
+ else
+ queue_event(APM_USER_STANDBY, as);
if (standbys_pending <= 0)
standby();
break;
@@ -1156,8 +1183,10 @@
as->suspends_read--;
as->suspends_pending--;
suspends_pending--;
- } else if (!send_event(APM_USER_SUSPEND, APM_NORMAL_RESUME, as))
+ } else if (!send_event(APM_USER_SUSPEND, APM_NORMAL_RESUME))
return -EAGAIN;
+ else
+ queue_event(APM_USER_SUSPEND, as);
if (suspends_pending <= 0) {
if (suspend() != APM_SUCCESS)
return -EIO;
@@ -1171,7 +1200,7 @@
break;
schedule();
}
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
remove_wait_queue(&apm_suspend_waitqueue, &wait);
return as->suspend_result;
}
@@ -1417,7 +1446,7 @@
}

/* Install our power off handler.. */
- if (power_off_enabled)
+ if (power_off)
acpi_power_off = apm_power_off;
#ifdef CONFIG_MAGIC_SYSRQ
sysrq_power_off = apm_power_off;
@@ -1430,7 +1459,7 @@
return 0;
}

-void __init apm_setup(char *str, int *dummy)
+static int __init apm_setup(char *str)
{
int invert;

@@ -1444,12 +1473,17 @@
str += 3;
if (strncmp(str, "debug", 5) == 0)
debug = !invert;
- if (strncmp(str, "power-off", 9) == 0)
- power_off_enabled = !invert;
+ if ((strncmp(str, "power-off", 9) == 0) ||
+ (strncmp(str, "power_off", 9) == 0))
+ power_off = !invert;
+ if ((strncmp(str, "bounce-interval=", 16) == 0) ||
+ (strncmp(str, "bounce_interval=", 16) == 0))
+ bounce_interval = simple_strtol(str + 16, NULL, 0);
str = strchr(str, ',');
if (str != NULL)
str += strspn(str, ", \t");
}
+ return 1;
}

__setup("apm=", apm_setup);
@@ -1464,17 +1498,16 @@

static struct miscdevice apm_device = {
APM_MINOR_DEV,
- "apm",
+ "apm_bios",
&apm_bios_fops
};

-#define APM_INIT_ERROR_RETURN return

-void __init apm_init(void)
+static int __init apm_init(void)
{
if (apm_bios_info.version == 0) {
printk(KERN_INFO "apm: BIOS not found.\n");
- APM_INIT_ERROR_RETURN;
+ return -ENODEV;
}
printk(KERN_INFO
"apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n",
@@ -1484,7 +1517,7 @@
driver_version);
if ((apm_bios_info.flags & APM_32_BIT_SUPPORT) == 0) {
printk(KERN_INFO "apm: no 32 bit BIOS support\n");
- APM_INIT_ERROR_RETURN;
+ return -ENODEV;
}

/*
@@ -1513,11 +1546,11 @@

if (apm_disabled) {
printk(KERN_NOTICE "apm: disabled on user request.\n");
- APM_INIT_ERROR_RETURN;
+ return -ENODEV;
}
- if ((smp_num_cpus > 1) && !power_off_enabled) {
+ if ((smp_num_cpus > 1) && !power_off) {
printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
- APM_INIT_ERROR_RETURN;
+ return -ENODEV;
}

/*
@@ -1560,12 +1593,12 @@

apm(0);

- create_proc_info_entry("apm", 0, 0, apm_get_info);
+ create_proc_info_entry("apm", 0, NULL, apm_get_info);

if (smp_num_cpus > 1) {
printk(KERN_NOTICE
"apm: disabled - APM is not SMP safe (power off active).\n");
- APM_INIT_ERROR_RETURN;
+ return 0;
}

init_timer(&apm_timer);
@@ -1578,6 +1611,7 @@
#ifdef CONFIG_APM_CPU_IDLE
acpi_idle = apm_cpu_idle;
#endif
+ return 0;
}

module_init(apm_init)
diff -ruN 2.2.18pre4/drivers/char/misc.c 2.2.18pre4-APM.1/drivers/char/misc.c
--- 2.2.18pre4/drivers/char/misc.c Sun Sep 10 17:05:16 2000
+++ 2.2.18pre4-APM.1/drivers/char/misc.c Mon Sep 11 12:26:39 2000
@@ -43,9 +43,6 @@
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/init.h>
-#ifdef CONFIG_APM
-#include <linux/apm_bios.h>
-#endif

#include <linux/tty.h>
#include <linux/selection.h>
@@ -240,9 +237,6 @@
#endif
#ifdef CONFIG_DTLK
dtlk_init();
-#endif
-#ifdef CONFIG_APM
- apm_init();
#endif
#ifdef CONFIG_H8
h8_init();
diff -ruN 2.2.18pre4/include/linux/apm_bios.h 2.2.18pre4-APM.1/include/linux/apm_bios.h
--- 2.2.18pre4/include/linux/apm_bios.h Thu May 4 10:16:51 2000
+++ 2.2.18pre4-APM.1/include/linux/apm_bios.h Mon Sep 11 12:26:12 2000
@@ -95,9 +95,6 @@
*/
extern struct apm_bios_info apm_bios_info;

-extern void apm_init(void);
-extern void apm_setup(char *, int *);
-
extern int apm_register_callback(int (*callback)(apm_event_t));
extern void apm_unregister_callback(int (*callback)(apm_event_t));

diff -ruN 2.2.18pre4/init/main.c 2.2.18pre4-APM.1/init/main.c
--- 2.2.18pre4/init/main.c Mon Sep 11 10:17:48 2000
+++ 2.2.18pre4-APM.1/init/main.c Mon Sep 11 12:31:17 2000
@@ -43,10 +43,6 @@
# include <asm/mtrr.h>
#endif

-#ifdef CONFIG_APM
-#include <linux/apm_bios.h>
-#endif
-
#ifdef CONFIG_DASD
#include <asm/dasd.h>
#endif
@@ -1095,9 +1091,6 @@
#endif
#ifdef CONFIG_PARIDE_PG
{ "pg.", pg_setup },
-#endif
-#ifdef CONFIG_APM
- { "apm=", apm_setup },
#endif
#ifdef CONFIG_N2
{ "n2=", n2_setup },
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/
\
 
 \ /
  Last update: 2005-03-22 12:38    [W:0.033 / U:0.740 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site