lkml.org 
[lkml]   [1999]   [Jun]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
SubjectNew APM patch
Date
From
Hi all,

I have finally got some time to APM updates again so here goes.
This first one is against 2.2.10 -pre2 but should patch cleanly
against 2.2.9 and 2.3.X. It does the following:
- Reset time across standby. (this is apparently
needed by some systems.)
- Allow more inititialisation on SMP systems - hopefully
this will allow them to power down.
- Remove CONFIG_APM_POWER_OFF and make it boot time
configurable (default on).
- Make debug only a boot time parameter (remove APM_DEBUG).
- Try to blank all devices on any error.
and some cleanups.

Please try it out (as I don;t have the problems fixed, I cannot
test these changes.

In case it get mangled by the mailing list, the patch is also
available from my web page (see below) - as will its updates.

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

diff -ru linux-2.2.10-pre2/Documentation/Configure.help linux-2.2.10-pre2-APM/Documentation/Configure.help
--- linux-2.2.10-pre2/Documentation/Configure.help Sun Jun 6 17:33:36 1999
+++ linux-2.2.10-pre2-APM/Documentation/Configure.help Sun Jun 6 16:07:40 1999
@@ -8722,9 +8722,15 @@
APM is a BIOS specification for saving power using several different
techniques. This is mostly useful for battery powered laptops with
APM compliant BIOSes. If you say Y here, the system time will be
- reset after a USER RESUME operation, the /proc/apm device will
- provide battery status information, and user-space programs will
- receive notification of APM "events" (e.g., battery status change).
+ reset after a RESUME operation, the /proc/apm device will provide
+ battery status information, and user-space programs will receive
+ notification of APM "events" (e.g., battery status change).
+
+ If you select "Y" here, you can disable actual use of the APM
+ BIOS by passing the "apm=off" option to the kernel at boot time.
+
+ Note that the APM support is almost completely disabled for
+ machines with more than one CPU.

Supporting software is available; for more information, read the
Battery Powered Linux mini-HOWTO, available via FTP (user:
@@ -8737,9 +8743,7 @@
This driver does not support the TI 4000M TravelMate and the ACER
486/DX4/75 because they don't have compliant BIOSes. Many "green"
desktop machines also don't have compliant BIOSes, and this driver
- will cause those machines to panic during the boot phase (typically,
- these machines are using a data segment of 0040, which is reserved
- for the Linux kernel).
+ may cause those machines to panic during the boot phase.

If you are running Linux on a laptop, you may also want to read the
Linux Laptop home page on the WWW at
@@ -8815,18 +8819,6 @@
option doesn't work for all laptops -- it might not turn off your
backlight at all, or it might print a lot of errors to the console,
especially if you are using gpm.
-
-Power off on shutdown
-CONFIG_APM_POWER_OFF
- Enable the ability to power off the computer after the Linux kernel
- is halted. You will need software (e.g., a suitable version of the
- halt(8) command ("man 8 halt")) to cause the computer to power down.
- Recent versions of the sysvinit package available from
- ftp://metalab.unc.edu/pub/Linux/system/daemons/init/ (user:
- anonymous) contain support for this ("halt -p" shuts down Linux and
- powers off the computer, if executed from runlevel 0). As with the
- other APM options, this option may not work reliably with some APM
- BIOS implementations.

Ignore multiple suspend/standby events
CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
diff -ru linux-2.2.10-pre2/arch/i386/config.in linux-2.2.10-pre2-APM/arch/i386/config.in
--- linux-2.2.10-pre2/arch/i386/config.in Sat May 15 17:45:58 1999
+++ linux-2.2.10-pre2-APM/arch/i386/config.in Sun Jun 6 17:31:27 1999
@@ -105,7 +105,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 ' 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
diff -ru linux-2.2.10-pre2/arch/i386/kernel/apm.c linux-2.2.10-pre2-APM/arch/i386/kernel/apm.c
--- linux-2.2.10-pre2/arch/i386/kernel/apm.c Fri Jan 15 17:57:25 1999
+++ linux-2.2.10-pre2-APM/arch/i386/kernel/apm.c Sun Jun 6 16:38:45 1999
@@ -1,6 +1,6 @@
/* -*- linux-c -*-
* APM BIOS driver for Linux
- * Copyright 1994-1998 Stephen Rothwell
+ * Copyright 1994-1999 Stephen Rothwell
* (Stephen.Rothwell@canb.auug.org.au)
* Development of this driver was funded by NEC Australia P/L
* and NEC Corporation
@@ -33,6 +33,7 @@
* Nov 1998, Version 1.7
* Jan 1999, Version 1.8
* Jan 1999, Version 1.9
+ * Jun 1999, Version 1.10
*
* History:
* 0.6b: first version in official kernel, Linux 1.3.46
@@ -90,6 +91,12 @@
* Use CONFIG_SMP instead of __SMP__
* Ignore BOUNCES for three seconds.
* Stephen Rothwell
+ * 1.10: Reset time across standby.
+ * Allow more inititialisation on SMP.
+ * Remove CONFIG_APM_POWER_OFF and make it boot time
+ * configurable (default on).
+ * Make debug only a boot time parameter (remove APM_DEBUG).
+ * Try to blank all devices on any error.
*
* APM 1.1 Reference:
*
@@ -144,51 +151,14 @@
*/
#define APM_MINOR_DEV 134

-/* Configurable options:
- *
- * CONFIG_APM_IGNORE_USER_SUSPEND: define to ignore USER SUSPEND requests.
- * This is necessary on the NEC Versa M series, which generates these when
- * resuming from SYSTEM SUSPEND. However, enabling this on other laptops
- * will cause the laptop to generate a CRITICAL SUSPEND when an appropriate
- * USER SUSPEND is ignored -- this may prevent the APM driver from updating
- * the system time on a RESUME.
- *
- * CONFIG_APM_DO_ENABLE: enable APM features at boot time. From page 36 of
- * the specification: "When disabled, the APM BIOS does not automatically
- * power manage devices, enter the Standby State, enter the Suspend State,
- * or take power saving steps in response to CPU Idle calls." This driver
- * will make CPU Idle calls when Linux is idle (unless this feature is
- * turned off -- see below). This should always save battery power, but
- * more complicated APM features will be dependent on your BIOS
- * implementation. You may need to turn this option off if your computer
- * hangs at boot time when using APM support, or if it beeps continuously
- * instead of suspending. Turn this off if you have a NEC UltraLite Versa
- * 33/C or a Toshiba T400CDT. This is off by default since most machines
- * do fine without this feature.
- *
- * CONFIG_APM_CPU_IDLE: enable calls to APM CPU Idle/CPU Busy inside the
- * idle loop. On some machines, this can activate improved power savings,
- * such as a slowed CPU clock rate, when the machine is idle. These idle
- * call is made after the idle loop has run for some length of time (e.g.,
- * 333 mS). On some machines, this will cause a hang at boot time or
- * whenever the CPU becomes idle.
- *
- * CONFIG_APM_DISPLAY_BLANK: enable console blanking using the APM. Some
- * laptops can use this to turn of the LCD backlight when the VC screen
- * blanker blanks the screen. Note that this is only used by the VC screen
- * blanker, and probably won't turn off the backlight when using X11. Some
- * problems have been reported when using this option with gpm (if you'd
- * like to debug this, please do so).
- *
- * CONFIG_APM_IGNORE_MULTIPLE_SUSPEND: The IBM TP560 bios seems to insist
- * on returning multiple suspend/standby events whenever one occurs. We
- * really only need one at a time, so just ignore any beyond the first.
- * This is probably safe on most laptops.
- *
- * If you are debugging the APM support for your laptop, note that code for
- * all of these options is contained in this file, so you can #define or
- * #undef these on the next line to avoid recompiling the whole kernel.
+/*
+ * See Documentation/Config.help for the configuration options.
*
+ * Various options can be changed at boot time as follows:
+ * apm=on/off enable/disable APM
+ * [no-]debug log some debugging messages
+ * [no-]power-off power off on shutdown
+ * [no-]smp-power-off allow power off even for SMP
*/

/* KNOWN PROBLEM MACHINES:
@@ -207,11 +177,6 @@
*/

/*
- * Define to have debug messages.
- */
-#undef APM_DEBUG
-
-/*
* Define to always call the APM BIOS busy routine even if the clock was
* not slowed by the idle routine.
*/
@@ -266,27 +231,6 @@
__asm__ __volatile__("movl %%" #seg ",%0" : "=m" (where))

/*
- * Forward declarations
- */
-static void suspend(void);
-static void standby(void);
-static void set_time(void);
-
-static void check_events(void);
-static void do_apm_timer(unsigned long);
-
-static int do_open(struct inode *, struct file *);
-static int do_release(struct inode *, struct file *);
-static ssize_t do_read(struct file *, char *, size_t , loff_t *);
-static unsigned int do_poll(struct file *, poll_table *);
-static int do_ioctl(struct inode *, struct file *, u_int, u_long);
-
-static int apm_get_info(char *, char **, off_t, int, int);
-
-extern int apm_register_callback(int (*)(apm_event_t));
-extern void apm_unregister_callback(int (*)(apm_event_t));
-
-/*
* Local variables
*/
static asmlinkage struct {
@@ -313,15 +257,15 @@
#endif
static int debug = 0;
static int apm_disabled = 0;
+static int power_off_enabled = 1;

static struct wait_queue * process_list = NULL;
static struct apm_bios_struct * user_list = NULL;

static struct timer_list apm_timer;

-static char driver_version[] = "1.9"; /* no spaces */
+static char driver_version[] = "1.10"; /* no spaces */

-#ifdef APM_DEBUG
static char * apm_event_name[] = {
"system standby",
"system suspend",
@@ -338,28 +282,6 @@
};
#define NR_APM_EVENT_NAME \
(sizeof(apm_event_name) / sizeof(apm_event_name[0]))
-#endif
-
-static struct file_operations apm_bios_fops = {
- NULL, /* lseek */
- do_read,
- NULL, /* write */
- NULL, /* readdir */
- do_poll,
- do_ioctl,
- NULL, /* mmap */
- do_open,
- NULL, /* flush */
- do_release,
- NULL, /* fsync */
- NULL /* fasync */
-};
-
-static struct miscdevice apm_device = {
- APM_MINOR_DEV,
- "apm",
- &apm_bios_fops
-};

typedef struct callback_list_t {
int (* callback)(apm_event_t);
@@ -502,7 +424,7 @@
return error;
}

-static int apm_driver_version(u_short *val)
+static int __init apm_driver_version(u_short *val)
{
u32 eax;

@@ -543,7 +465,7 @@
return set_power_state(0x0001, state);
}

-void apm_power_off(void)
+void apm_power_off(int force)
{
/*
* smp_hack == 2 means that we would have enabled APM support
@@ -553,7 +475,8 @@
* they are doing because they booted with the smp-power-off
* kernel option.
*/
- if (apm_enabled || (smp_hack == 2))
+ if ((apm_enabled || (smp_hack == 2))
+ && (power_off_enabled || force))
(void) apm_set_power_state(APM_STATE_OFF);
}

@@ -565,7 +488,7 @@

/* Blank the first display device */
error = set_power_state(0x0100, state);
- if (error == APM_BAD_DEVICE)
+ if (error != APM_SUCCESS)
/* try to blank them all instead */
error = set_power_state(0x01ff, state);
return error;
@@ -733,10 +656,8 @@
if (as->event_head == as->event_tail) {
static int notified;

- if (notified == 0) {
+ if (notified++ == 0)
printk(KERN_ERR "apm: an event queue overflowed\n");
- notified = 1;
- }
as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
}
as->events[as->event_head] = event;
@@ -764,21 +685,19 @@
{
unsigned long flags;

- if (!got_clock_diff) /* Don't know time zone, can't set clock */
- return;
-
- save_flags(flags);
- cli();
- CURRENT_TIME = get_cmos_time() + clock_cmos_diff;
- restore_flags(flags);
+ if (got_clock_diff) { /* Must know time zone in order to set clock */
+ save_flags(flags);
+ cli();
+ CURRENT_TIME = get_cmos_time() + clock_cmos_diff;
+ restore_flags(flags);
+ }
}

-static void suspend(void)
+static void get_time_diff(void)
{
+#ifndef CONFIG_APM_RTC_IS_GMT
unsigned long flags;
- int err;

-#ifndef CONFIG_APM_RTC_IS_GMT
/*
* Estimate time zone so that set_time can update the clock
*/
@@ -789,7 +708,14 @@
got_clock_diff = 1;
restore_flags(flags);
#endif
+}
+
+static void suspend(void)
+{
+ unsigned long flags;
+ int err;

+ get_time_diff();
err = apm_set_power_state(APM_STATE_SUSPEND);
if (err)
apm_error("suspend", err);
@@ -812,9 +738,11 @@
{
int err;

+ get_time_diff();
err = apm_set_power_state(APM_STATE_STANDBY);
if (err)
apm_error("standby", err);
+ set_time(); /* should not be necessary ... */
}

static apm_event_t get_event(void)
@@ -864,14 +792,14 @@
#endif

while ((event = get_event()) != 0) {
-#ifdef APM_DEBUG
- if (event <= NR_APM_EVENT_NAME)
- printk(KERN_DEBUG "apm: received %s notify\n",
- apm_event_name[event - 1]);
- else
- printk(KERN_DEBUG "apm: received unknown "
- "event 0x%02x\n", event);
-#endif
+ if (debug) {
+ if (event <= NR_APM_EVENT_NAME)
+ printk(KERN_DEBUG "apm: received %s notify\n",
+ apm_event_name[event - 1]);
+ else
+ 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))
@@ -1277,6 +1205,8 @@
str += 3;
if (strncmp(str, "debug", 5) == 0)
debug = !invert;
+ if (strncmp(str, "power-off", 9) == 0)
+ power_off_enabled = !invert;
if (strncmp(str, "smp-power-off", 13) == 0)
smp_hack = !invert;
str = strchr(str, ',');
@@ -1285,6 +1215,27 @@
}
}

+static struct file_operations apm_bios_fops = {
+ NULL, /* lseek */
+ do_read,
+ NULL, /* write */
+ NULL, /* readdir */
+ do_poll,
+ do_ioctl,
+ NULL, /* mmap */
+ do_open,
+ NULL, /* flush */
+ do_release,
+ NULL, /* fsync */
+ NULL /* fasync */
+};
+
+static struct miscdevice apm_device = {
+ APM_MINOR_DEV,
+ "apm",
+ &apm_bios_fops
+};
+
void __init apm_bios_init(void)
{
unsigned short bx;
@@ -1378,14 +1329,6 @@
(apm_bios_info.dseg_len - 1) & 0xffff);
}
#endif
-#ifdef CONFIG_SMP
- if (smp_num_cpus > 1) {
- printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
- if (smp_hack)
- smp_hack = 2;
- return;
- }
-#endif
if (apm_bios_info.version > 0x100) {
/*
* We only support BIOSs up to version 1.2
@@ -1459,6 +1402,14 @@
if (apm_engage_power_management(0x0001) == APM_SUCCESS)
apm_bios_info.flags &= ~APM_BIOS_DISENGAGED;
}
+#ifdef CONFIG_SMP
+ if (smp_num_cpus > 1) {
+ printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
+ if (smp_hack)
+ smp_hack = 2;
+ return;
+ }
+#endif

init_timer(&apm_timer);
apm_timer.function = do_apm_timer;
diff -ru linux-2.2.10-pre2/arch/i386/kernel/process.c linux-2.2.10-pre2-APM/arch/i386/kernel/process.c
--- linux-2.2.10-pre2/arch/i386/kernel/process.c Sat May 15 17:46:06 1999
+++ linux-2.2.10-pre2-APM/arch/i386/kernel/process.c Sun Jun 6 15:50:42 1999
@@ -31,7 +31,7 @@
#include <linux/smp.h>
#include <linux/reboot.h>
#include <linux/init.h>
-#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
+#if defined(CONFIG_APM)
#include <linux/apm_bios.h>
#endif

@@ -52,11 +52,6 @@

asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");

-#ifdef CONFIG_APM
-extern int apm_do_idle(void);
-extern void apm_do_busy(void);
-#endif
-
static int hlt_counter=0;

#define HARD_IDLE_TIMEOUT (HZ / 3)
@@ -386,8 +381,8 @@

void machine_power_off(void)
{
-#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
- apm_power_off();
+#if defined(CONFIG_APM)
+ apm_power_off(0);
#endif
}

diff -ru linux-2.2.10-pre2/arch/m68k/kernel/process.c linux-2.2.10-pre2-APM/arch/m68k/kernel/process.c
--- linux-2.2.10-pre2/arch/m68k/kernel/process.c Sat May 15 17:46:06 1999
+++ linux-2.2.10-pre2-APM/arch/m68k/kernel/process.c Sun Jun 6 15:51:12 1999
@@ -87,9 +87,6 @@

void machine_power_off(void)
{
-#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
- apm_set_power_state(APM_STATE_OFF);
-#endif
}

void show_regs(struct pt_regs * regs)
diff -ru linux-2.2.10-pre2/drivers/char/sysrq.c linux-2.2.10-pre2-APM/drivers/char/sysrq.c
--- linux-2.2.10-pre2/drivers/char/sysrq.c Thu Nov 26 12:25:17 1998
+++ linux-2.2.10-pre2-APM/drivers/char/sysrq.c Sun Jun 6 15:55:34 1999
@@ -21,13 +21,12 @@
#include <linux/kbd_kern.h>
#include <linux/quotaops.h>
#include <linux/smp_lock.h>
-
-#include <asm/ptrace.h>
-
#ifdef CONFIG_APM
#include <linux/apm_bios.h>
#endif

+#include <asm/ptrace.h>
+
extern void wakeup_bdflush(int);
extern void reset_vc(unsigned int);
extern int console_loglevel;
@@ -85,7 +84,7 @@
#ifdef CONFIG_APM
case 'o': /* O -- power off */
printk("Power off\n");
- apm_power_off();
+ apm_power_off(1);
break;
#endif
case 's': /* S -- emergency sync */
diff -ru linux-2.2.10-pre2/include/linux/apm_bios.h linux-2.2.10-pre2-APM/include/linux/apm_bios.h
--- linux-2.2.10-pre2/include/linux/apm_bios.h Sun Nov 29 12:18:54 1998
+++ linux-2.2.10-pre2-APM/include/linux/apm_bios.h Sun Jun 6 15:44:33 1999
@@ -3,7 +3,7 @@

/*
* Include file for the interface to an APM BIOS
- * Copyright 1994-1998 Stephen Rothwell (Stephen.Rothwell@canb.auug.org.au)
+ * Copyright 1994-1999 Stephen Rothwell (Stephen.Rothwell@canb.auug.org.au)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -82,7 +82,10 @@
extern int apm_register_callback(int (*callback)(apm_event_t));
extern void apm_unregister_callback(int (*callback)(apm_event_t));

-extern void apm_power_off(void);
+extern int apm_do_idle(void);
+extern void apm_do_busy(void);
+
+extern void apm_power_off(int);
extern int apm_display_blank(void);
extern int apm_display_unblank(void);

@@ -112,7 +115,7 @@
#define APM_USER_STANDBY 0x0009
#define APM_USER_SUSPEND 0x000a
#define APM_STANDBY_RESUME 0x000b
-#define APM_CAPABILITY_CHANGE 0x000c
+#define APM_CAPABILITY_CHANGE 0x000c

/*
* Error codes
@@ -128,7 +131,7 @@
#define APM_BAD_DEVICE 0x09
#define APM_BAD_PARAM 0x0a
#define APM_NOT_ENGAGED 0x0b
-#define APM_BAD_FUNCTION 0x0c
+#define APM_BAD_FUNCTION 0x0c
#define APM_RESUME_DISABLED 0x0d
#define APM_BAD_STATE 0x60
#define APM_NO_EVENTS 0x80
-
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/

\
 
 \ /
  Last update: 2005-03-22 13:52    [W:0.025 / U:1.212 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site