linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] APM: delete APM in Linux-2.6.40
       [not found] ` <20110324154505.934a56a0.sfr@canb.auug.org.au>
@ 2011-03-24  7:39   ` Len Brown
  2011-03-24  8:16     ` [PATCH] x86 APM: delete Linux kernel APM support Len Brown
                       ` (5 more replies)
  0 siblings, 6 replies; 37+ messages in thread
From: Len Brown @ 2011-03-24  7:39 UTC (permalink / raw)
  To: Stephen Rothwell; +Cc: linux-pm, linux-kernel

From: Len Brown <len.brown@intel.com>

Signed-off-by: Len Brown <len.brown@intel.com>
---
 Documentation/feature-removal-schedule.txt |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index b3f35e5..2a03c46 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -619,3 +619,11 @@ Why:	The original implementation of memsw feature enabled by
 Who:	Michal Hocko <mhocko@suse.cz>
 
 ----------------------------
+
+What:	CONFIG_APM
+When:	2.6.40
+Why:	Microsoft deleted APM from Windows as of Vista in in 2006.
+	It now seems more than safe that the latest Linux Kernel be APM-free.
+	The vintage laptops supporting APM are now difficult to find,
+	making it problatic to maintain this code.
+Who:	Len Brown <len.brown@intel.com>
-- 
1.7.4.1.343.ga91df


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH] x86 APM: delete Linux kernel APM support
  2011-03-24  7:39   ` [PATCH] APM: delete APM in Linux-2.6.40 Len Brown
@ 2011-03-24  8:16     ` Len Brown
  2011-03-24  8:31       ` [PATCH] x86 APM: delete Linux kernel APM support (v2) Len Brown
  2011-03-24  8:39       ` [PATCH] x86 APM: delete Linux kernel APM support Ingo Molnar
  2011-03-24  8:18     ` [PATCH] APM: delete APM in Linux-2.6.40 Stephen Rothwell
                       ` (4 subsequent siblings)
  5 siblings, 2 replies; 37+ messages in thread
From: Len Brown @ 2011-03-24  8:16 UTC (permalink / raw)
  To: Stephen Rothwell, x86; +Cc: linux-pm, linux-kernel

From: Len Brown <len.brown@intel.com>

Microsoft was able to delete APM from Windows in 2006
with the release of Windows Vista.  5 years later it seems
quite safe that the latest Linux kernel can also.

The vintage APM laptops have become difficult to find,
making changes in this area difficult to test.

apm_bios.h remains for CONFIG_APM_EMULATION
used by non-x86 architectures.

Signed-off-by: Len Brown <len.brown@intel.com>
---
 Documentation/feature-removal-schedule.txt |    9 -
 MAINTAINERS                                |    8 -
 arch/x86/Kconfig                           |  125 --
 arch/x86/boot/Makefile                     |    1 -
 arch/x86/boot/apm.c                        |   75 -
 arch/x86/boot/main.c                       |    5 -
 arch/x86/include/asm/bootparam.h           |    3 +-
 arch/x86/kernel/Makefile                   |    2 -
 arch/x86/kernel/apm_32.c                   | 2463 ----------------------------
 arch/x86/kernel/process.c                  |    3 -
 arch/x86/kernel/reboot.c                   |    3 -
 arch/x86/kernel/setup.c                    |    4 -
 12 files changed, 1 insertions(+), 2700 deletions(-)
 delete mode 100644 arch/x86/boot/apm.c
 delete mode 100644 arch/x86/kernel/apm_32.c

diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 2a03c46..4b5dfcc 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -618,12 +618,3 @@ Why:	The original implementation of memsw feature enabled by
 	can also cleanup the parameter handling a bit ().
 Who:	Michal Hocko <mhocko@suse.cz>
 
-----------------------------
-
-What:	CONFIG_APM
-When:	2.6.40
-Why:	Microsoft deleted APM from Windows as of Vista in in 2006.
-	It now seems more than safe that the latest Linux Kernel be APM-free.
-	The vintage laptops supporting APM are now difficult to find,
-	making it problatic to maintain this code.
-Who:	Len Brown <len.brown@intel.com>
diff --git a/MAINTAINERS b/MAINTAINERS
index f1bc3dc..a896b39 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -531,14 +531,6 @@ L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:	Maintained
 F:	sound/aoa/
 
-APM DRIVER
-M:	Stephen Rothwell <sfr@canb.auug.org.au>
-L:	linux-laptop@vger.kernel.org
-W:	http://www.canb.auug.org.au/~sfr/
-S:	Supported
-F:	arch/x86/kernel/apm_32.c
-F:	include/linux/apm_bios.h
-
 APPLE BCM5974 MULTITOUCH DRIVER
 M:	Henrik Rydberg <rydberg@euromail.se>
 L:	linux-input@vger.kernel.org
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index d5ed94d..6b4e6b1 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1720,131 +1720,6 @@ source "drivers/acpi/Kconfig"
 
 source "drivers/sfi/Kconfig"
 
-config X86_APM_BOOT
-	def_bool y
-	depends on APM || APM_MODULE
-
-menuconfig APM
-	tristate "APM (Advanced Power Management) BIOS support"
-	depends on X86_32 && PM_SLEEP
-	---help---
-	  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 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.
-
-	  In order to use APM, you will need supporting software. For location
-	  and more information, read <file:Documentation/power/pm.txt> and the
-	  Battery Powered Linux mini-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>.
-
-	  This driver does not spin down disk drives (see the hdparm(8)
-	  manpage ("man 8 hdparm") for that), and it doesn't turn off
-	  VESA-compliant "green" monitors.
-
-	  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
-	  may cause those machines to panic during the boot phase.
-
-	  Generally, if you don't have a battery in your machine, there isn't
-	  much point in using this driver and you should say N. If you get
-	  random kernel OOPSes or reboots that don't seem to be related to
-	  anything, try disabling/enabling this option (or disabling/enabling
-	  APM in your BIOS).
-
-	  Some other things you should try when experiencing seemingly random,
-	  "weird" problems:
-
-	  1) make sure that you have enough swap space and that it is
-	  enabled.
-	  2) pass the "no-hlt" option to the kernel
-	  3) switch on floating point emulation in the kernel and pass
-	  the "no387" option to the kernel
-	  4) pass the "floppy=nodma" option to the kernel
-	  5) pass the "mem=4M" option to the kernel (thereby disabling
-	  all but the first 4 MB of RAM)
-	  6) make sure that the CPU is not over clocked.
-	  7) read the sig11 FAQ at <http://www.bitwizard.nl/sig11/>
-	  8) disable the cache from your BIOS settings
-	  9) install a fan for the video card or exchange video RAM
-	  10) install a better fan for the CPU
-	  11) exchange RAM chips
-	  12) exchange the motherboard.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called apm.
-
-if APM
-
-config APM_IGNORE_USER_SUSPEND
-	bool "Ignore USER SUSPEND"
-	---help---
-	  This option will ignore USER SUSPEND requests. On machines with a
-	  compliant APM BIOS, you want to say N. However, on the NEC Versa M
-	  series notebooks, it is necessary to say Y because of a BIOS bug.
-
-config APM_DO_ENABLE
-	bool "Enable PM at boot time"
-	---help---
-	  Enable APM features at boot time. From page 36 of the APM BIOS
-	  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 "Do CPU IDLE calls", 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
-	bool "Make CPU Idle calls when idle"
-	---help---
-	  Enable calls to APM CPU Idle/CPU Busy inside the kernel's 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 calls
-	  are 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. (On machines with more than one CPU,
-	  this option does nothing.)
-
-config APM_DISPLAY_BLANK
-	bool "Enable console blanking using APM"
-	---help---
-	  Enable console blanking using the APM. Some laptops can use this to
-	  turn off the LCD backlight when the screen blanker of the Linux
-	  virtual console blanks the screen. Note that this is only used by
-	  the virtual console screen blanker, and won't turn off the backlight
-	  when using the X Window system. This also doesn't have anything to
-	  do with your VESA-compliant power-saving monitor. Further, this
-	  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.
-
-config APM_ALLOW_INTS
-	bool "Allow interrupts during APM BIOS calls"
-	---help---
-	  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 reenable interrupts if it
-	  needs to.  Unfortunately, some BIOSes 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.
-
-endif # APM
-
 source "arch/x86/kernel/cpu/cpufreq/Kconfig"
 
 source "drivers/cpuidle/Kconfig"
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index f7cb086..a746cc8 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -30,7 +30,6 @@ setup-y		+= a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o
 setup-y		+= early_serial_console.o edd.o header.o main.o mca.o memory.o
 setup-y		+= pm.o pmjump.o printf.o regs.o string.o tty.o video.o
 setup-y		+= video-mode.o version.o
-setup-$(CONFIG_X86_APM_BOOT) += apm.o
 
 # The link order of the video-*.o modules can matter.  In particular,
 # video-vga.o *must* be listed first, followed by video-vesa.o.
diff --git a/arch/x86/boot/apm.c b/arch/x86/boot/apm.c
deleted file mode 100644
index ee27483..0000000
--- a/arch/x86/boot/apm.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/* -*- linux-c -*- ------------------------------------------------------- *
- *
- *   Copyright (C) 1991, 1992 Linus Torvalds
- *   Copyright 2007 rPath, Inc. - All Rights Reserved
- *   Copyright 2009 Intel Corporation; author H. Peter Anvin
- *
- *   Original APM BIOS checking by Stephen Rothwell, May 1994
- *   (sfr@canb.auug.org.au)
- *
- *   This file is part of the Linux kernel, and is made available under
- *   the terms of the GNU General Public License version 2.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * Get APM BIOS information
- */
-
-#include "boot.h"
-
-int query_apm_bios(void)
-{
-	struct biosregs ireg, oreg;
-
-	/* APM BIOS installation check */
-	initregs(&ireg);
-	ireg.ah = 0x53;
-	intcall(0x15, &ireg, &oreg);
-
-	if (oreg.flags & X86_EFLAGS_CF)
-		return -1;		/* No APM BIOS */
-
-	if (oreg.bx != 0x504d)		/* "PM" signature */
-		return -1;
-
-	if (!(oreg.cx & 0x02))		/* 32 bits supported? */
-		return -1;
-
-	/* Disconnect first, just in case */
-	ireg.al = 0x04;
-	intcall(0x15, &ireg, NULL);
-
-	/* 32-bit connect */
-	ireg.al = 0x03;
-	intcall(0x15, &ireg, &oreg);
-
-	boot_params.apm_bios_info.cseg        = oreg.ax;
-	boot_params.apm_bios_info.offset      = oreg.ebx;
-	boot_params.apm_bios_info.cseg_16     = oreg.cx;
-	boot_params.apm_bios_info.dseg        = oreg.dx;
-	boot_params.apm_bios_info.cseg_len    = oreg.si;
-	boot_params.apm_bios_info.cseg_16_len = oreg.hsi;
-	boot_params.apm_bios_info.dseg_len    = oreg.di;
-
-	if (oreg.flags & X86_EFLAGS_CF)
-		return -1;
-
-	/* Redo the installation check as the 32-bit connect;
-	   some BIOSes return different flags this way... */
-
-	ireg.al = 0x00;
-	intcall(0x15, &ireg, &oreg);
-
-	if ((oreg.eflags & X86_EFLAGS_CF) || oreg.bx != 0x504d) {
-		/* Failure with 32-bit connect, try to disconect and ignore */
-		ireg.al = 0x04;
-		intcall(0x15, &ireg, NULL);
-		return -1;
-	}
-
-	boot_params.apm_bios_info.version = oreg.ax;
-	boot_params.apm_bios_info.flags   = oreg.cx;
-	return 0;
-}
-
diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c
index 40358c8..b6a9743 100644
--- a/arch/x86/boot/main.c
+++ b/arch/x86/boot/main.c
@@ -160,11 +160,6 @@ void main(void)
 	/* Query Intel SpeedStep (IST) information */
 	query_ist();
 
-	/* Query APM information */
-#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
-	query_apm_bios();
-#endif
-
 	/* Query EDD information */
 #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
 	query_edd();
diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h
index c8bfe63..7d8e530 100644
--- a/arch/x86/include/asm/bootparam.h
+++ b/arch/x86/include/asm/bootparam.h
@@ -3,7 +3,6 @@
 
 #include <linux/types.h>
 #include <linux/screen_info.h>
-#include <linux/apm_bios.h>
 #include <linux/edd.h>
 #include <asm/e820.h>
 #include <asm/ist.h>
@@ -92,7 +91,7 @@ struct efi_info {
 /* The so-called "zeropage" */
 struct boot_params {
 	struct screen_info screen_info;			/* 0x000 */
-	struct apm_bios_info apm_bios_info;		/* 0x040 */
+	__u8  _apm_pad[20];				/* 0x040 */
 	__u8  _pad2[4];					/* 0x054 */
 	__u64  tboot_addr;				/* 0x058 */
 	struct ist_info ist_info;			/* 0x060 */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 34244b2..92ef9c9 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -63,8 +63,6 @@ obj-$(CONFIG_MCA)		+= mca_32.o
 obj-$(CONFIG_X86_MSR)		+= msr.o
 obj-$(CONFIG_X86_CPUID)		+= cpuid.o
 obj-$(CONFIG_PCI)		+= early-quirks.o
-apm-y				:= apm_32.o
-obj-$(CONFIG_APM)		+= apm.o
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_SMP)		+= smpboot.o tsc_sync.o
 obj-$(CONFIG_SMP)		+= setup_percpu.o
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
deleted file mode 100644
index 0e4f24c..0000000
--- a/arch/x86/kernel/apm_32.c
+++ /dev/null
@@ -1,2463 +0,0 @@
-/* -*- linux-c -*-
- * APM BIOS driver for Linux
- * Copyright 1994-2001 Stephen Rothwell (sfr@canb.auug.org.au)
- *
- * Initial development of this driver was funded by NEC Australia P/L
- *	and NEC Corporation
- *
- * 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
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * October 1995, Rik Faith (faith@cs.unc.edu):
- *    Minor enhancements and updates (to the patch set) for 1.3.x
- *    Documentation
- * January 1996, Rik Faith (faith@cs.unc.edu):
- *    Make /proc/apm easy to format (bump driver version)
- * March 1996, Rik Faith (faith@cs.unc.edu):
- *    Prohibit APM BIOS calls unless apm_enabled.
- *    (Thanks to Ulrich Windl <Ulrich.Windl@rz.uni-regensburg.de>)
- * April 1996, Stephen Rothwell (sfr@canb.auug.org.au)
- *    Version 1.0 and 1.1
- * May 1996, Version 1.2
- * Feb 1998, Version 1.3
- * Feb 1998, Version 1.4
- * Aug 1998, Version 1.5
- * Sep 1998, Version 1.6
- * Nov 1998, Version 1.7
- * Jan 1999, Version 1.8
- * Jan 1999, Version 1.9
- * Oct 1999, Version 1.10
- * Nov 1999, Version 1.11
- * Jan 2000, Version 1.12
- * Feb 2000, Version 1.13
- * Nov 2000, Version 1.14
- * Oct 2001, Version 1.15
- * Jan 2002, Version 1.16
- * Oct 2002, Version 1.16ac
- *
- * History:
- *    0.6b: first version in official kernel, Linux 1.3.46
- *    0.7: changed /proc/apm format, Linux 1.3.58
- *    0.8: fixed gcc 2.7.[12] compilation problems, Linux 1.3.59
- *    0.9: only call bios if bios is present, Linux 1.3.72
- *    1.0: use fixed device number, consolidate /proc/apm into this file,
- *         Linux 1.3.85
- *    1.1: support user-space standby and suspend, power off after system
- *         halted, Linux 1.3.98
- *    1.2: When resetting RTC after resume, take care so that the time
- *         is only incorrect by 30-60mS (vs. 1S previously) (Gabor J. Toth
- *         <jtoth@princeton.edu>); improve interaction between
- *         screen-blanking and gpm (Stephen Rothwell); Linux 1.99.4
- *    1.2a:Simple change to stop mysterious bug reports with SMP also added
- *	   levels to the printk calls. APM is not defined for SMP machines.
- *         The new replacement 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
- *         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
- *         across BIOS call).
- *         Stephen Rothwell
- *    1.6: Cope with complier/assembler differences.
- *         Only try to turn off the first display device.
- *         Fix OOPS at power off with no APM BIOS by Jan Echternach
- *                   <echter@informatik.uni-rostock.de>
- *         Stephen Rothwell
- *    1.7: Modify driver's cached copy of the disabled/disengaged flags
- *         to reflect current state of APM BIOS.
- *         Chris Rankin <rankinc@bellsouth.net>
- *         Reset interrupt 0 timer to 100Hz after suspend
- *         Chad Miller <cmiller@surfsouth.com>
- *         Add CONFIG_APM_IGNORE_SUSPEND_BOUNCE
- *         Richard Gooch <rgooch@atnf.csiro.au>
- *         Allow boot time disabling of APM
- *         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
- *    1.9: Fix small typo.  <laslo@wodip.opole.pl>
- *         Try to cope with BIOS's that need to have all display
- *         devices blanked and not just the first one.
- *         Ross Paterson <ross@soi.city.ac.uk>
- *         Fix segment limit setting it has always been wrong as
- *         the segments needed to have byte granularity.
- *         Mark a few things __init.
- *         Add hack to allow power off of SMP systems by popular request.
- *         Use CONFIG_SMP instead of __SMP__
- *         Ignore BOUNCES for three seconds.
- *         Stephen Rothwell
- *   1.10: Fix for Thinkpad return code.
- *         Merge 2.2 and 2.3 drivers.
- *         Remove APM dependencies in arch/i386/kernel/process.c
- *         Remove APM dependencies in drivers/char/sysrq.c
- *         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.
- *   1.11: Remove APM dependencies in drivers/char/console.c
- *         Check nr_running to detect if we are idle (from
- *         Borislav Deianov <borislav@lix.polytechnique.fr>)
- *         Fix for bioses that don't zero the top part of the
- *         entrypoint offset (Mario Sitta <sitta@al.unipmn.it>)
- *         (reported by Panos Katsaloulis <teras@writeme.com>).
- *         Real mode power off patch (Walter Hofmann
- *         <Walter.Hofmann@physik.stud.uni-erlangen.de>).
- *   1.12: Remove CONFIG_SMP as the compiler will optimize
- *         the code away anyway (smp_num_cpus == 1 in UP)
- *         noted by Artur Skawina <skawina@geocities.com>.
- *         Make power off under SMP work again.
- *         Fix thinko with initial engaging of BIOS.
- *         Make sure power off only happens on CPU 0
- *         (Paul "Rusty" Russell <rusty@rustcorp.com.au>).
- *         Do error notification to user mode if BIOS calls fail.
- *         Move entrypoint offset fix to ...boot/setup.S
- *         where it belongs (Cosmos <gis88564@cis.nctu.edu.tw>).
- *         Remove smp-power-off. SMP users must now specify
- *         "apm=power-off" on the kernel command line. Suggested
- *         by Jim Avera <jima@hal.com>, modified by Alan Cox
- *         <alan@lxorguk.ukuu.org.uk>.
- *         Register the /proc/apm entry even on SMP so that
- *         scripts that check for it before doing power off
- *         work (Jim Avera <jima@hal.com>).
- *   1.13: Changes for new pm_ interfaces (Andy Henroid
- *         <andy_henroid@yahoo.com>).
- *         Modularize the code.
- *         Fix the Thinkpad (again) :-( (CONFIG_APM_IGNORE_MULTIPLE_SUSPENDS
- *         is now the way life works).
- *         Fix thinko in suspend() (wrong return).
- *         Notify drivers on critical suspend.
- *         Make kapmd absorb more idle time (Pavel Machek <pavel@ucw.cz>
- *         modified by sfr).
- *         Disable interrupts while we are suspended (Andy Henroid
- *         <andy_henroid@yahoo.com> fixed by sfr).
- *         Make power off work on SMP again (Tony Hoyle
- *         <tmh@magenta-logic.com> and <zlatko@iskon.hr>) modified by sfr.
- *         Remove CONFIG_APM_SUSPEND_BOUNCE.  The bounce ignore
- *         interval is now configurable.
- *   1.14: Make connection version persist across module unload/load.
- *         Enable and engage power management earlier.
- *         Disengage power management on module unload.
- *         Changed to use the sysrq-register hack for registering the
- *         power off function called by magic sysrq based upon discussions
- *         in irc://irc.openprojects.net/#kernelnewbies
- *         (Crutcher Dunnavant <crutcher+kernel@datastacks.com>).
- *         Make CONFIG_APM_REAL_MODE_POWER_OFF run time configurable.
- *         (Arjan van de Ven <arjanv@redhat.com>) modified by sfr.
- *         Work around byte swap bug in one of the Vaio's BIOS's
- *         (Marc Boucher <marc@mbsi.ca>).
- *         Exposed the disable flag to dmi so that we can handle known
- *         broken APM (Alan Cox <alan@lxorguk.ukuu.org.uk>).
- *   1.14ac: If the BIOS says "I slowed the CPU down" then don't spin
- *         calling it - instead idle. (Alan Cox <alan@lxorguk.ukuu.org.uk>)
- *         If an APM idle fails log it and idle sensibly
- *   1.15: Don't queue events to clients who open the device O_WRONLY.
- *         Don't expect replies from clients who open the device O_RDONLY.
- *         (Idea from Thomas Hood)
- *         Minor waitqueue cleanups. (John Fremlin <chief@bandits.org>)
- *   1.16: Fix idle calling. (Andreas Steinmetz <ast@domdv.de> et al.)
- *         Notify listeners of standby or suspend events before notifying
- *         drivers. Return EBUSY to ioctl() if suspend is rejected.
- *         (Russell King <rmk@arm.linux.org.uk> and Thomas Hood)
- *         Ignore first resume after we generate our own resume event
- *         after a suspend (Thomas Hood)
- *         Daemonize now gets rid of our controlling terminal (sfr).
- *         CONFIG_APM_CPU_IDLE now just affects the default value of
- *         idle_threshold (sfr).
- *         Change name of kernel apm daemon (as it no longer idles) (sfr).
- *   1.16ac: Fix up SMP support somewhat. You can now force SMP on and we
- *	   make _all_ APM calls on the CPU#0. Fix unsafe sign bug.
- *	   TODO: determine if its "boot CPU" or "CPU0" we want to lock to.
- *
- * APM 1.1 Reference:
- *
- *   Intel Corporation, Microsoft Corporation. Advanced Power Management
- *   (APM) BIOS Interface Specification, Revision 1.1, September 1993.
- *   Intel Order Number 241704-001.  Microsoft Part Number 781-110-X01.
- *
- * [This document is available free from Intel by calling 800.628.8686 (fax
- * 916.356.6100) or 800.548.4725; or from
- * http://www.microsoft.com/whdc/archive/amp_12.mspx  It is also
- * available from Microsoft by calling 206.882.8080.]
- *
- * APM 1.2 Reference:
- *   Intel Corporation, Microsoft Corporation. Advanced Power Management
- *   (APM) BIOS Interface Specification, Revision 1.2, February 1996.
- *
- * [This document is available from Microsoft at:
- *    http://www.microsoft.com/whdc/archive/amp_12.mspx]
- */
-
-#include <linux/module.h>
-
-#include <linux/poll.h>
-#include <linux/types.h>
-#include <linux/stddef.h>
-#include <linux/timer.h>
-#include <linux/fcntl.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/miscdevice.h>
-#include <linux/apm_bios.h>
-#include <linux/init.h>
-#include <linux/time.h>
-#include <linux/sched.h>
-#include <linux/pm.h>
-#include <linux/capability.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/freezer.h>
-#include <linux/smp.h>
-#include <linux/dmi.h>
-#include <linux/suspend.h>
-#include <linux/kthread.h>
-#include <linux/jiffies.h>
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/desc.h>
-#include <asm/i8253.h>
-#include <asm/olpc.h>
-#include <asm/paravirt.h>
-#include <asm/reboot.h>
-
-#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
-extern int (*console_blank_hook)(int);
-#endif
-
-/*
- * The apm_bios device is one of the misc char devices.
- * This is its minor number.
- */
-#define	APM_MINOR_DEV	134
-
-/*
- * 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-]allow[-_]ints		allow interrupts during BIOS calls
- *	    [no-]broken[-_]psr		BIOS has a broken GetPowerStatus call
- *	    [no-]realmode[-_]power[-_]off	switch to real mode before
- *	    					powering off
- *	    [no-]debug			log some debugging messages
- *	    [no-]power[-_]off		power off on shutdown
- *	    [no-]smp			Use apm even on an SMP box
- *	    bounce[-_]interval=<n>	number of ticks to ignore suspend
- *	    				bounces
- *          idle[-_]threshold=<n>       System idle percentage above which to
- *                                      make APM BIOS idle calls. Set it to
- *                                      100 to disable.
- *          idle[-_]period=<n>          Period (in 1/100s of a second) over
- *                                      which the idle percentage is
- *                                      calculated.
- */
-
-/* KNOWN PROBLEM MACHINES:
- *
- * U: TI 4000M TravelMate: BIOS is *NOT* APM compliant
- *                         [Confirmed by TI representative]
- * ?: ACER 486DX4/75: uses dseg 0040, in violation of APM specification
- *                    [Confirmed by BIOS disassembly]
- *                    [This may work now ...]
- * P: Toshiba 1950S: battery life information only gets updated after resume
- * P: Midwest Micro Soundbook Elite DX2/66 monochrome: screen blanking
- * 	broken in BIOS [Reported by Garst R. Reese <reese@isn.net>]
- * ?: AcerNote-950: oops on reading /proc/apm - workaround is a WIP
- * 	Neale Banks <neale@lowendale.com.au> December 2000
- *
- * Legend: U = unusable with APM patches
- *         P = partially usable with APM patches
- */
-
-/*
- * Define as 1 to make the driver always call the APM BIOS busy
- * routine even if the clock was not reported as slowed by the
- * idle routine.  Otherwise, define as 0.
- */
-#define ALWAYS_CALL_BUSY   1
-
-/*
- * 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).
- */
-#define APM_ZERO_SEGS
-
-#include <asm/apm.h>
-
-/*
- * Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend.
- * This patched by Chad Miller <cmiller@surfsouth.com>, original code by
- * David Chen <chen@ctpa04.mit.edu>
- */
-#undef INIT_TIMER_AFTER_SUSPEND
-
-#ifdef INIT_TIMER_AFTER_SUSPEND
-#include <linux/timex.h>
-#include <asm/io.h>
-#include <linux/delay.h>
-#endif
-
-/*
- * Need to poll the APM BIOS every second
- */
-#define APM_CHECK_TIMEOUT	(HZ)
-
-/*
- * Ignore suspend events for this amount of time after a resume
- */
-#define DEFAULT_BOUNCE_INTERVAL	(3 * HZ)
-
-/*
- * Maximum number of events stored
- */
-#define APM_MAX_EVENTS		20
-
-/*
- * The per-file APM data
- */
-struct apm_user {
-	int		magic;
-	struct apm_user *next;
-	unsigned int	suser: 1;
-	unsigned int	writer: 1;
-	unsigned int	reader: 1;
-	unsigned int	suspend_wait: 1;
-	int		suspend_result;
-	int		suspends_pending;
-	int		standbys_pending;
-	int		suspends_read;
-	int		standbys_read;
-	int		event_head;
-	int		event_tail;
-	apm_event_t	events[APM_MAX_EVENTS];
-};
-
-/*
- * The magic number in apm_user
- */
-#define APM_BIOS_MAGIC		0x4101
-
-/*
- * idle percentage above which bios idle calls are done
- */
-#ifdef CONFIG_APM_CPU_IDLE
-#define DEFAULT_IDLE_THRESHOLD	95
-#else
-#define DEFAULT_IDLE_THRESHOLD	100
-#endif
-#define DEFAULT_IDLE_PERIOD	(100 / 3)
-
-/*
- * Local variables
- */
-static struct {
-	unsigned long	offset;
-	unsigned short	segment;
-} apm_bios_entry;
-static int clock_slowed;
-static int idle_threshold __read_mostly = DEFAULT_IDLE_THRESHOLD;
-static int idle_period __read_mostly = DEFAULT_IDLE_PERIOD;
-static int set_pm_idle;
-static int suspends_pending;
-static int standbys_pending;
-static int ignore_sys_suspend;
-static int ignore_normal_resume;
-static int bounce_interval __read_mostly = DEFAULT_BOUNCE_INTERVAL;
-
-static int debug __read_mostly;
-static int smp __read_mostly;
-static int apm_disabled = -1;
-#ifdef CONFIG_SMP
-static int power_off;
-#else
-static int power_off = 1;
-#endif
-static int realmode_power_off;
-#ifdef CONFIG_APM_ALLOW_INTS
-static int allow_ints = 1;
-#else
-static int allow_ints;
-#endif
-static int broken_psr;
-
-static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
-static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
-static struct apm_user *user_list;
-static DEFINE_SPINLOCK(user_list_lock);
-static DEFINE_MUTEX(apm_mutex);
-
-/*
- * Set up a segment that references the real mode segment 0x40
- * that extends up to the end of page zero (that we have reserved).
- * This is for buggy BIOS's that refer to (real mode) segment 0x40
- * even though they are called in protected mode.
- */
-static struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4092,
-			(unsigned long)__va(0x400UL), PAGE_SIZE - 0x400 - 1);
-
-static const char driver_version[] = "1.16ac";	/* no spaces */
-
-static struct task_struct *kapmd_task;
-
-/*
- *	APM event names taken from the APM 1.2 specification. These are
- *	the message codes that the BIOS uses to tell us about events
- */
-static const char * const apm_event_name[] = {
-	"system standby",
-	"system suspend",
-	"normal resume",
-	"critical resume",
-	"low battery",
-	"power status change",
-	"update time",
-	"critical suspend",
-	"user standby",
-	"user suspend",
-	"system standby resume",
-	"capabilities change"
-};
-#define NR_APM_EVENT_NAME ARRAY_SIZE(apm_event_name)
-
-typedef struct lookup_t {
-	int	key;
-	char 	*msg;
-} lookup_t;
-
-/*
- *	The BIOS returns a set of standard error codes in AX when the
- *	carry flag is set.
- */
-
-static const lookup_t error_table[] = {
-/* N/A	{ APM_SUCCESS,		"Operation succeeded" }, */
-	{ APM_DISABLED,		"Power management disabled" },
-	{ APM_CONNECTED,	"Real mode interface already connected" },
-	{ APM_NOT_CONNECTED,	"Interface not connected" },
-	{ APM_16_CONNECTED,	"16 bit interface already connected" },
-/* N/A	{ APM_16_UNSUPPORTED,	"16 bit interface not supported" }, */
-	{ APM_32_CONNECTED,	"32 bit interface already connected" },
-	{ APM_32_UNSUPPORTED,	"32 bit interface not supported" },
-	{ APM_BAD_DEVICE,	"Unrecognized device ID" },
-	{ APM_BAD_PARAM,	"Parameter out of range" },
-	{ APM_NOT_ENGAGED,	"Interface not engaged" },
-	{ APM_BAD_FUNCTION,     "Function not supported" },
-	{ APM_RESUME_DISABLED,	"Resume timer disabled" },
-	{ APM_BAD_STATE,	"Unable to enter requested state" },
-/* N/A	{ APM_NO_EVENTS,	"No events pending" }, */
-	{ APM_NO_ERROR,		"BIOS did not set a return code" },
-	{ APM_NOT_PRESENT,	"No APM present" }
-};
-#define ERROR_COUNT	ARRAY_SIZE(error_table)
-
-/**
- *	apm_error	-	display an APM error
- *	@str: information string
- *	@err: APM BIOS return code
- *
- *	Write a meaningful log entry to the kernel log in the event of
- *	an APM error.  Note that this also handles (negative) kernel errors.
- */
-
-static void apm_error(char *str, int err)
-{
-	int i;
-
-	for (i = 0; i < ERROR_COUNT; i++)
-		if (error_table[i].key == err)
-			break;
-	if (i < ERROR_COUNT)
-		printk(KERN_NOTICE "apm: %s: %s\n", str, error_table[i].msg);
-	else if (err < 0)
-		printk(KERN_NOTICE "apm: %s: linux error code %i\n", str, err);
-	else
-		printk(KERN_NOTICE "apm: %s: unknown error code %#2.2x\n",
-		       str, err);
-}
-
-/*
- * These are the actual BIOS calls.  Depending on APM_ZERO_SEGS and
- * apm_info.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.
- */
-
-static inline unsigned long __apm_irq_save(void)
-{
-	unsigned long flags;
-	local_save_flags(flags);
-	if (apm_info.allow_ints) {
-		if (irqs_disabled_flags(flags))
-			local_irq_enable();
-	} else
-		local_irq_disable();
-
-	return flags;
-}
-
-#define apm_irq_save(flags) \
-	do { flags = __apm_irq_save(); } while (0)
-
-static inline void apm_irq_restore(unsigned long flags)
-{
-	if (irqs_disabled_flags(flags))
-		local_irq_disable();
-	else if (irqs_disabled())
-		local_irq_enable();
-}
-
-#ifdef APM_ZERO_SEGS
-#	define APM_DECL_SEGS \
-		unsigned int saved_fs; unsigned int saved_gs;
-#	define APM_DO_SAVE_SEGS \
-		savesegment(fs, saved_fs); savesegment(gs, saved_gs)
-#	define APM_DO_RESTORE_SEGS \
-		loadsegment(fs, saved_fs); loadsegment(gs, saved_gs)
-#else
-#	define APM_DECL_SEGS
-#	define APM_DO_SAVE_SEGS
-#	define APM_DO_RESTORE_SEGS
-#endif
-
-struct apm_bios_call {
-	u32 func;
-	/* In and out */
-	u32 ebx;
-	u32 ecx;
-	/* Out only */
-	u32 eax;
-	u32 edx;
-	u32 esi;
-
-	/* Error: -ENOMEM, or bits 8-15 of eax */
-	int err;
-};
-
-/**
- *	__apm_bios_call - Make an APM BIOS 32bit call
- *	@_call: pointer to struct apm_bios_call.
- *
- *	Make an APM call using the 32bit protected mode interface. The
- *	caller is responsible for knowing if APM BIOS is configured and
- *	enabled. This call can disable interrupts for a long period of
- *	time on some laptops.  The return value is in AH and the carry
- *	flag is loaded into AL.  If there is an error, then the error
- *	code is returned in AH (bits 8-15 of eax) and this function
- *	returns non-zero.
- *
- *	Note: this makes the call on the current CPU.
- */
-static long __apm_bios_call(void *_call)
-{
-	APM_DECL_SEGS
-	unsigned long		flags;
-	int			cpu;
-	struct desc_struct	save_desc_40;
-	struct desc_struct	*gdt;
-	struct apm_bios_call	*call = _call;
-
-	cpu = get_cpu();
-	BUG_ON(cpu != 0);
-	gdt = get_cpu_gdt_table(cpu);
-	save_desc_40 = gdt[0x40 / 8];
-	gdt[0x40 / 8] = bad_bios_desc;
-
-	apm_irq_save(flags);
-	APM_DO_SAVE_SEGS;
-	apm_bios_call_asm(call->func, call->ebx, call->ecx,
-			  &call->eax, &call->ebx, &call->ecx, &call->edx,
-			  &call->esi);
-	APM_DO_RESTORE_SEGS;
-	apm_irq_restore(flags);
-	gdt[0x40 / 8] = save_desc_40;
-	put_cpu();
-
-	return call->eax & 0xff;
-}
-
-/* Run __apm_bios_call or __apm_bios_call_simple on CPU 0 */
-static int on_cpu0(long (*fn)(void *), struct apm_bios_call *call)
-{
-	int ret;
-
-	/* Don't bother with work_on_cpu in the common case, so we don't
-	 * have to worry about OOM or overhead. */
-	if (get_cpu() == 0) {
-		ret = fn(call);
-		put_cpu();
-	} else {
-		put_cpu();
-		ret = work_on_cpu(0, fn, call);
-	}
-
-	/* work_on_cpu can fail with -ENOMEM */
-	if (ret < 0)
-		call->err = ret;
-	else
-		call->err = (call->eax >> 8) & 0xff;
-
-	return ret;
-}
-
-/**
- *	apm_bios_call	-	Make an APM BIOS 32bit call (on CPU 0)
- *	@call: the apm_bios_call registers.
- *
- *	If there is an error, it is returned in @call.err.
- */
-static int apm_bios_call(struct apm_bios_call *call)
-{
-	return on_cpu0(__apm_bios_call, call);
-}
-
-/**
- *	__apm_bios_call_simple - Make an APM BIOS 32bit call (on CPU 0)
- *	@_call: pointer to struct apm_bios_call.
- *
- *	Make a BIOS call that returns one value only, or just status.
- *	If there is an error, then the error code is returned in AH
- *	(bits 8-15 of eax) and this function returns non-zero (it can
- *	also return -ENOMEM). This is used for simpler BIOS operations.
- *	This call may hold interrupts off for a long time on some laptops.
- *
- *	Note: this makes the call on the current CPU.
- */
-static long __apm_bios_call_simple(void *_call)
-{
-	u8			error;
-	APM_DECL_SEGS
-	unsigned long		flags;
-	int			cpu;
-	struct desc_struct	save_desc_40;
-	struct desc_struct	*gdt;
-	struct apm_bios_call	*call = _call;
-
-	cpu = get_cpu();
-	BUG_ON(cpu != 0);
-	gdt = get_cpu_gdt_table(cpu);
-	save_desc_40 = gdt[0x40 / 8];
-	gdt[0x40 / 8] = bad_bios_desc;
-
-	apm_irq_save(flags);
-	APM_DO_SAVE_SEGS;
-	error = apm_bios_call_simple_asm(call->func, call->ebx, call->ecx,
-					 &call->eax);
-	APM_DO_RESTORE_SEGS;
-	apm_irq_restore(flags);
-	gdt[0x40 / 8] = save_desc_40;
-	put_cpu();
-	return error;
-}
-
-/**
- *	apm_bios_call_simple	-	make a simple APM BIOS 32bit call
- *	@func: APM function to invoke
- *	@ebx_in: EBX register value for BIOS call
- *	@ecx_in: ECX register value for BIOS call
- *	@eax: EAX register on return from the BIOS call
- *	@err: bits
- *
- *	Make a BIOS call that returns one value only, or just status.
- *	If there is an error, then the error code is returned in @err
- *	and this function returns non-zero. This is used for simpler
- *	BIOS operations.  This call may hold interrupts off for a long
- *	time on some laptops.
- */
-static int apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax,
-				int *err)
-{
-	struct apm_bios_call call;
-	int ret;
-
-	call.func = func;
-	call.ebx = ebx_in;
-	call.ecx = ecx_in;
-
-	ret = on_cpu0(__apm_bios_call_simple, &call);
-	*eax = call.eax;
-	*err = call.err;
-	return ret;
-}
-
-/**
- *	apm_driver_version	-	APM driver version
- *	@val:	loaded with the APM version on return
- *
- *	Retrieve the APM version supported by the BIOS. This is only
- *	supported for APM 1.1 or higher. An error indicates APM 1.0 is
- *	probably present.
- *
- *	On entry val should point to a value indicating the APM driver
- *	version with the high byte being the major and the low byte the
- *	minor number both in BCD
- *
- *	On return it will hold the BIOS revision supported in the
- *	same format.
- */
-
-static int apm_driver_version(u_short *val)
-{
-	u32 eax;
-	int err;
-
-	if (apm_bios_call_simple(APM_FUNC_VERSION, 0, *val, &eax, &err))
-		return err;
-	*val = eax;
-	return APM_SUCCESS;
-}
-
-/**
- *	apm_get_event	-	get an APM event from the BIOS
- *	@event: pointer to the event
- *	@info: point to the event information
- *
- *	The APM BIOS provides a polled information for event
- *	reporting. The BIOS expects to be polled at least every second
- *	when events are pending. When a message is found the caller should
- *	poll until no more messages are present.  However, this causes
- *	problems on some laptops where a suspend event notification is
- *	not cleared until it is acknowledged.
- *
- *	Additional information is returned in the info pointer, providing
- *	that APM 1.2 is in use. If no messges are pending the value 0x80
- *	is returned (No power management events pending).
- */
-static int apm_get_event(apm_event_t *event, apm_eventinfo_t *info)
-{
-	struct apm_bios_call call;
-
-	call.func = APM_FUNC_GET_EVENT;
-	call.ebx = call.ecx = 0;
-
-	if (apm_bios_call(&call))
-		return call.err;
-
-	*event = call.ebx;
-	if (apm_info.connection_version < 0x0102)
-		*info = ~0; /* indicate info not valid */
-	else
-		*info = call.ecx;
-	return APM_SUCCESS;
-}
-
-/**
- *	set_power_state	-	set the power management state
- *	@what: which items to transition
- *	@state: state to transition to
- *
- *	Request an APM change of state for one or more system devices. The
- *	processor state must be transitioned last of all. what holds the
- *	class of device in the upper byte and the device number (0xFF for
- *	all) for the object to be transitioned.
- *
- *	The state holds the state to transition to, which may in fact
- *	be an acceptance of a BIOS requested state change.
- */
-
-static int set_power_state(u_short what, u_short state)
-{
-	u32 eax;
-	int err;
-
-	if (apm_bios_call_simple(APM_FUNC_SET_STATE, what, state, &eax, &err))
-		return err;
-	return APM_SUCCESS;
-}
-
-/**
- *	set_system_power_state - set system wide power state
- *	@state: which state to enter
- *
- *	Transition the entire system into a new APM power state.
- */
-
-static int set_system_power_state(u_short state)
-{
-	return set_power_state(APM_DEVICE_ALL, state);
-}
-
-/**
- *	apm_do_idle	-	perform power saving
- *
- *	This function notifies the BIOS that the processor is (in the view
- *	of the OS) idle. It returns -1 in the event that the BIOS refuses
- *	to handle the idle request. On a success the function returns 1
- *	if the BIOS did clock slowing or 0 otherwise.
- */
-
-static int apm_do_idle(void)
-{
-	u32 eax;
-	u8 ret = 0;
-	int idled = 0;
-	int polling;
-	int err = 0;
-
-	polling = !!(current_thread_info()->status & TS_POLLING);
-	if (polling) {
-		current_thread_info()->status &= ~TS_POLLING;
-		/*
-		 * TS_POLLING-cleared state must be visible before we
-		 * test NEED_RESCHED:
-		 */
-		smp_mb();
-	}
-	if (!need_resched()) {
-		idled = 1;
-		ret = apm_bios_call_simple(APM_FUNC_IDLE, 0, 0, &eax, &err);
-	}
-	if (polling)
-		current_thread_info()->status |= TS_POLLING;
-
-	if (!idled)
-		return 0;
-
-	if (ret) {
-		static unsigned long t;
-
-		/* This always fails on some SMP boards running UP kernels.
-		 * Only report the failure the first 5 times.
-		 */
-		if (++t < 5) {
-			printk(KERN_DEBUG "apm_do_idle failed (%d)\n", err);
-			t = jiffies;
-		}
-		return -1;
-	}
-	clock_slowed = (apm_info.bios.flags & APM_IDLE_SLOWS_CLOCK) != 0;
-	return clock_slowed;
-}
-
-/**
- *	apm_do_busy	-	inform the BIOS the CPU is busy
- *
- *	Request that the BIOS brings the CPU back to full performance.
- */
-
-static void apm_do_busy(void)
-{
-	u32 dummy;
-	int err;
-
-	if (clock_slowed || ALWAYS_CALL_BUSY) {
-		(void)apm_bios_call_simple(APM_FUNC_BUSY, 0, 0, &dummy, &err);
-		clock_slowed = 0;
-	}
-}
-
-/*
- * If no process has really been interested in
- * the CPU for some time, we want to call BIOS
- * power management - we probably want
- * to conserve power.
- */
-#define IDLE_CALC_LIMIT	(HZ * 100)
-#define IDLE_LEAKY_MAX	16
-
-static void (*original_pm_idle)(void) __read_mostly;
-
-/**
- * apm_cpu_idle		-	cpu idling for APM capable Linux
- *
- * This is the idling function the kernel executes when APM is available. It
- * tries to do BIOS powermanagement based on the average system idle time.
- * Furthermore it calls the system default idle routine.
- */
-
-static void apm_cpu_idle(void)
-{
-	static int use_apm_idle; /* = 0 */
-	static unsigned int last_jiffies; /* = 0 */
-	static unsigned int last_stime; /* = 0 */
-
-	int apm_idle_done = 0;
-	unsigned int jiffies_since_last_check = jiffies - last_jiffies;
-	unsigned int bucket;
-
-recalc:
-	if (jiffies_since_last_check > IDLE_CALC_LIMIT) {
-		use_apm_idle = 0;
-		last_jiffies = jiffies;
-		last_stime = current->stime;
-	} else if (jiffies_since_last_check > idle_period) {
-		unsigned int idle_percentage;
-
-		idle_percentage = current->stime - last_stime;
-		idle_percentage *= 100;
-		idle_percentage /= jiffies_since_last_check;
-		use_apm_idle = (idle_percentage > idle_threshold);
-		if (apm_info.forbid_idle)
-			use_apm_idle = 0;
-		last_jiffies = jiffies;
-		last_stime = current->stime;
-	}
-
-	bucket = IDLE_LEAKY_MAX;
-
-	while (!need_resched()) {
-		if (use_apm_idle) {
-			unsigned int t;
-
-			t = jiffies;
-			switch (apm_do_idle()) {
-			case 0:
-				apm_idle_done = 1;
-				if (t != jiffies) {
-					if (bucket) {
-						bucket = IDLE_LEAKY_MAX;
-						continue;
-					}
-				} else if (bucket) {
-					bucket--;
-					continue;
-				}
-				break;
-			case 1:
-				apm_idle_done = 1;
-				break;
-			default: /* BIOS refused */
-				break;
-			}
-		}
-		if (original_pm_idle)
-			original_pm_idle();
-		else
-			default_idle();
-		local_irq_disable();
-		jiffies_since_last_check = jiffies - last_jiffies;
-		if (jiffies_since_last_check > idle_period)
-			goto recalc;
-	}
-
-	if (apm_idle_done)
-		apm_do_busy();
-
-	local_irq_enable();
-}
-
-/**
- *	apm_power_off	-	ask the BIOS to power off
- *
- *	Handle the power off sequence. This is the one piece of code we
- *	will execute even on SMP machines. In order to deal with BIOS
- *	bugs we support real mode APM BIOS power off calls. We also make
- *	the SMP call on CPU0 as some systems will only honour this call
- *	on their first cpu.
- */
-
-static void apm_power_off(void)
-{
-	unsigned char po_bios_call[] = {
-		0xb8, 0x00, 0x10,	/* movw  $0x1000,ax  */
-		0x8e, 0xd0,		/* movw  ax,ss       */
-		0xbc, 0x00, 0xf0,	/* movw  $0xf000,sp  */
-		0xb8, 0x07, 0x53,	/* movw  $0x5307,ax  */
-		0xbb, 0x01, 0x00,	/* movw  $0x0001,bx  */
-		0xb9, 0x03, 0x00,	/* movw  $0x0003,cx  */
-		0xcd, 0x15		/* int   $0x15       */
-	};
-
-	/* Some bioses don't like being called from CPU != 0 */
-	if (apm_info.realmode_power_off) {
-		set_cpus_allowed_ptr(current, cpumask_of(0));
-		machine_real_restart(po_bios_call, sizeof(po_bios_call));
-	} else {
-		(void)set_system_power_state(APM_STATE_OFF);
-	}
-}
-
-#ifdef CONFIG_APM_DO_ENABLE
-
-/**
- *	apm_enable_power_management - enable BIOS APM power management
- *	@enable: enable yes/no
- *
- *	Enable or disable the APM BIOS power services.
- */
-
-static int apm_enable_power_management(int enable)
-{
-	u32 eax;
-	int err;
-
-	if ((enable == 0) && (apm_info.bios.flags & APM_BIOS_DISENGAGED))
-		return APM_NOT_ENGAGED;
-	if (apm_bios_call_simple(APM_FUNC_ENABLE_PM, APM_DEVICE_BALL,
-				 enable, &eax, &err))
-		return err;
-	if (enable)
-		apm_info.bios.flags &= ~APM_BIOS_DISABLED;
-	else
-		apm_info.bios.flags |= APM_BIOS_DISABLED;
-	return APM_SUCCESS;
-}
-#endif
-
-/**
- *	apm_get_power_status	-	get current power state
- *	@status: returned status
- *	@bat: battery info
- *	@life: estimated life
- *
- *	Obtain the current power status from the APM BIOS. We return a
- *	status which gives the rough battery status, and current power
- *	source. The bat value returned give an estimate as a percentage
- *	of life and a status value for the battery. The estimated life
- *	if reported is a lifetime in secodnds/minutes at current powwer
- *	consumption.
- */
-
-static int apm_get_power_status(u_short *status, u_short *bat, u_short *life)
-{
-	struct apm_bios_call call;
-
-	call.func = APM_FUNC_GET_STATUS;
-	call.ebx = APM_DEVICE_ALL;
-	call.ecx = 0;
-
-	if (apm_info.get_power_status_broken)
-		return APM_32_UNSUPPORTED;
-	if (apm_bios_call(&call))
-		return call.err;
-	*status = call.ebx;
-	*bat = call.ecx;
-	if (apm_info.get_power_status_swabinminutes) {
-		*life = swab16((u16)call.edx);
-		*life |= 0x8000;
-	} else
-		*life = call.edx;
-	return APM_SUCCESS;
-}
-
-#if 0
-static int apm_get_battery_status(u_short which, u_short *status,
-				  u_short *bat, u_short *life, u_short *nbat)
-{
-	u32 eax;
-	u32 ebx;
-	u32 ecx;
-	u32 edx;
-	u32 esi;
-
-	if (apm_info.connection_version < 0x0102) {
-		/* pretend we only have one battery. */
-		if (which != 1)
-			return APM_BAD_DEVICE;
-		*nbat = 1;
-		return apm_get_power_status(status, bat, life);
-	}
-
-	if (apm_bios_call(APM_FUNC_GET_STATUS, (0x8000 | (which)), 0, &eax,
-			  &ebx, &ecx, &edx, &esi))
-		return (eax >> 8) & 0xff;
-	*status = ebx;
-	*bat = ecx;
-	*life = edx;
-	*nbat = esi;
-	return APM_SUCCESS;
-}
-#endif
-
-/**
- *	apm_engage_power_management	-	enable PM on a device
- *	@device: identity of device
- *	@enable: on/off
- *
- *	Activate or deactive power management on either a specific device
- *	or the entire system (%APM_DEVICE_ALL).
- */
-
-static int apm_engage_power_management(u_short device, int enable)
-{
-	u32 eax;
-	int err;
-
-	if ((enable == 0) && (device == APM_DEVICE_ALL)
-	    && (apm_info.bios.flags & APM_BIOS_DISABLED))
-		return APM_DISABLED;
-	if (apm_bios_call_simple(APM_FUNC_ENGAGE_PM, device, enable,
-				 &eax, &err))
-		return err;
-	if (device == APM_DEVICE_ALL) {
-		if (enable)
-			apm_info.bios.flags &= ~APM_BIOS_DISENGAGED;
-		else
-			apm_info.bios.flags |= APM_BIOS_DISENGAGED;
-	}
-	return APM_SUCCESS;
-}
-
-#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
-
-/**
- *	apm_console_blank	-	blank the display
- *	@blank: on/off
- *
- *	Attempt to blank the console, firstly by blanking just video device
- *	zero, and if that fails (some BIOSes don't support it) then it blanks
- *	all video devices. Typically the BIOS will do laptop backlight and
- *	monitor powerdown for us.
- */
-
-static int apm_console_blank(int blank)
-{
-	int error = APM_NOT_ENGAGED; /* silence gcc */
-	int i;
-	u_short state;
-	static const u_short dev[3] = { 0x100, 0x1FF, 0x101 };
-
-	state = blank ? APM_STATE_STANDBY : APM_STATE_READY;
-
-	for (i = 0; i < ARRAY_SIZE(dev); i++) {
-		error = set_power_state(dev[i], state);
-
-		if ((error == APM_SUCCESS) || (error == APM_NO_ERROR))
-			return 1;
-
-		if (error == APM_NOT_ENGAGED)
-			break;
-	}
-
-	if (error == APM_NOT_ENGAGED) {
-		static int tried;
-		int eng_error;
-		if (tried++ == 0) {
-			eng_error = apm_engage_power_management(APM_DEVICE_ALL, 1);
-			if (eng_error) {
-				apm_error("set display", error);
-				apm_error("engage interface", eng_error);
-				return 0;
-			} else
-				return apm_console_blank(blank);
-		}
-	}
-	apm_error("set display", error);
-	return 0;
-}
-#endif
-
-static int queue_empty(struct apm_user *as)
-{
-	return as->event_head == as->event_tail;
-}
-
-static apm_event_t get_queued_event(struct apm_user *as)
-{
-	if (++as->event_tail >= APM_MAX_EVENTS)
-		as->event_tail = 0;
-	return as->events[as->event_tail];
-}
-
-static void queue_event(apm_event_t event, struct apm_user *sender)
-{
-	struct apm_user *as;
-
-	spin_lock(&user_list_lock);
-	if (user_list == NULL)
-		goto out;
-	for (as = user_list; as != NULL; as = as->next) {
-		if ((as == sender) || (!as->reader))
-			continue;
-		if (++as->event_head >= APM_MAX_EVENTS)
-			as->event_head = 0;
-
-		if (as->event_head == as->event_tail) {
-			static int notified;
-
-			if (notified++ == 0)
-			    printk(KERN_ERR "apm: an event queue overflowed\n");
-			if (++as->event_tail >= APM_MAX_EVENTS)
-				as->event_tail = 0;
-		}
-		as->events[as->event_head] = event;
-		if (!as->suser || !as->writer)
-			continue;
-		switch (event) {
-		case APM_SYS_SUSPEND:
-		case APM_USER_SUSPEND:
-			as->suspends_pending++;
-			suspends_pending++;
-			break;
-
-		case APM_SYS_STANDBY:
-		case APM_USER_STANDBY:
-			as->standbys_pending++;
-			standbys_pending++;
-			break;
-		}
-	}
-	wake_up_interruptible(&apm_waitqueue);
-out:
-	spin_unlock(&user_list_lock);
-}
-
-static void reinit_timer(void)
-{
-#ifdef INIT_TIMER_AFTER_SUSPEND
-	unsigned long flags;
-
-	raw_spin_lock_irqsave(&i8253_lock, flags);
-	/* set the clock to HZ */
-	outb_pit(0x34, PIT_MODE);		/* binary, mode 2, LSB/MSB, ch 0 */
-	udelay(10);
-	outb_pit(LATCH & 0xff, PIT_CH0);	/* LSB */
-	udelay(10);
-	outb_pit(LATCH >> 8, PIT_CH0);	/* MSB */
-	udelay(10);
-	raw_spin_unlock_irqrestore(&i8253_lock, flags);
-#endif
-}
-
-static int suspend(int vetoable)
-{
-	int err;
-	struct apm_user	*as;
-
-	dpm_suspend_start(PMSG_SUSPEND);
-
-	dpm_suspend_noirq(PMSG_SUSPEND);
-
-	local_irq_disable();
-	sysdev_suspend(PMSG_SUSPEND);
-
-	local_irq_enable();
-
-	save_processor_state();
-	err = set_system_power_state(APM_STATE_SUSPEND);
-	ignore_normal_resume = 1;
-	restore_processor_state();
-
-	local_irq_disable();
-	reinit_timer();
-
-	if (err == APM_NO_ERROR)
-		err = APM_SUCCESS;
-	if (err != APM_SUCCESS)
-		apm_error("suspend", err);
-	err = (err == APM_SUCCESS) ? 0 : -EIO;
-
-	sysdev_resume();
-	local_irq_enable();
-
-	dpm_resume_noirq(PMSG_RESUME);
-
-	dpm_resume_end(PMSG_RESUME);
-	queue_event(APM_NORMAL_RESUME, NULL);
-	spin_lock(&user_list_lock);
-	for (as = user_list; as != NULL; as = as->next) {
-		as->suspend_wait = 0;
-		as->suspend_result = err;
-	}
-	spin_unlock(&user_list_lock);
-	wake_up_interruptible(&apm_suspend_waitqueue);
-	return err;
-}
-
-static void standby(void)
-{
-	int err;
-
-	dpm_suspend_noirq(PMSG_SUSPEND);
-
-	local_irq_disable();
-	sysdev_suspend(PMSG_SUSPEND);
-	local_irq_enable();
-
-	err = set_system_power_state(APM_STATE_STANDBY);
-	if ((err != APM_SUCCESS) && (err != APM_NO_ERROR))
-		apm_error("standby", err);
-
-	local_irq_disable();
-	sysdev_resume();
-	local_irq_enable();
-
-	dpm_resume_noirq(PMSG_RESUME);
-}
-
-static apm_event_t get_event(void)
-{
-	int error;
-	apm_event_t event = APM_NO_EVENTS; /* silence gcc */
-	apm_eventinfo_t	info;
-
-	static int notified;
-
-	/* we don't use the eventinfo */
-	error = apm_get_event(&event, &info);
-	if (error == APM_SUCCESS)
-		return event;
-
-	if ((error != APM_NO_EVENTS) && (notified++ == 0))
-		apm_error("get_event", error);
-
-	return 0;
-}
-
-static void check_events(void)
-{
-	apm_event_t event;
-	static unsigned long last_resume;
-	static int ignore_bounce;
-
-	while ((event = get_event()) != 0) {
-		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);
-		}
-		if (ignore_bounce
-		    && (time_after(jiffies, last_resume + bounce_interval)))
-			ignore_bounce = 0;
-
-		switch (event) {
-		case APM_SYS_STANDBY:
-		case APM_USER_STANDBY:
-			queue_event(event, NULL);
-			if (standbys_pending <= 0)
-				standby();
-			break;
-
-		case APM_USER_SUSPEND:
-#ifdef CONFIG_APM_IGNORE_USER_SUSPEND
-			if (apm_info.connection_version > 0x100)
-				set_system_power_state(APM_STATE_REJECT);
-			break;
-#endif
-		case APM_SYS_SUSPEND:
-			if (ignore_bounce) {
-				if (apm_info.connection_version > 0x100)
-					set_system_power_state(APM_STATE_REJECT);
-				break;
-			}
-			/*
-			 * If we are already processing a SUSPEND,
-			 * then further SUSPEND events from the BIOS
-			 * will be ignored.  We also return here to
-			 * cope with the fact that the Thinkpads keep
-			 * sending a SUSPEND event until something else
-			 * happens!
-			 */
-			if (ignore_sys_suspend)
-				return;
-			ignore_sys_suspend = 1;
-			queue_event(event, NULL);
-			if (suspends_pending <= 0)
-				(void) suspend(1);
-			break;
-
-		case APM_NORMAL_RESUME:
-		case APM_CRITICAL_RESUME:
-		case APM_STANDBY_RESUME:
-			ignore_sys_suspend = 0;
-			last_resume = jiffies;
-			ignore_bounce = 1;
-			if ((event != APM_NORMAL_RESUME)
-			    || (ignore_normal_resume == 0)) {
-				dpm_resume_end(PMSG_RESUME);
-				queue_event(event, NULL);
-			}
-			ignore_normal_resume = 0;
-			break;
-
-		case APM_CAPABILITY_CHANGE:
-		case APM_LOW_BATTERY:
-		case APM_POWER_STATUS_CHANGE:
-			queue_event(event, NULL);
-			/* If needed, notify drivers here */
-			break;
-
-		case APM_UPDATE_TIME:
-			break;
-
-		case APM_CRITICAL_SUSPEND:
-			/*
-			 * We are not allowed to reject a critical suspend.
-			 */
-			(void)suspend(0);
-			break;
-		}
-	}
-}
-
-static void apm_event_handler(void)
-{
-	static int pending_count = 4;
-	int err;
-
-	if ((standbys_pending > 0) || (suspends_pending > 0)) {
-		if ((apm_info.connection_version > 0x100) &&
-		    (pending_count-- <= 0)) {
-			pending_count = 4;
-			if (debug)
-				printk(KERN_DEBUG "apm: setting state busy\n");
-			err = set_system_power_state(APM_STATE_BUSY);
-			if (err)
-				apm_error("busy", err);
-		}
-	} else
-		pending_count = 4;
-	check_events();
-}
-
-/*
- * This is the APM thread main loop.
- */
-
-static void apm_mainloop(void)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	add_wait_queue(&apm_waitqueue, &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
-	for (;;) {
-		schedule_timeout(APM_CHECK_TIMEOUT);
-		if (kthread_should_stop())
-			break;
-		/*
-		 * Ok, check all events, check for idle (and mark us sleeping
-		 * so as not to count towards the load average)..
-		 */
-		set_current_state(TASK_INTERRUPTIBLE);
-		apm_event_handler();
-	}
-	remove_wait_queue(&apm_waitqueue, &wait);
-}
-
-static int check_apm_user(struct apm_user *as, const char *func)
-{
-	if (as == NULL || as->magic != APM_BIOS_MAGIC) {
-		printk(KERN_ERR "apm: %s passed bad filp\n", func);
-		return 1;
-	}
-	return 0;
-}
-
-static ssize_t do_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
-{
-	struct apm_user *as;
-	int i;
-	apm_event_t event;
-
-	as = fp->private_data;
-	if (check_apm_user(as, "read"))
-		return -EIO;
-	if ((int)count < sizeof(apm_event_t))
-		return -EINVAL;
-	if ((queue_empty(as)) && (fp->f_flags & O_NONBLOCK))
-		return -EAGAIN;
-	wait_event_interruptible(apm_waitqueue, !queue_empty(as));
-	i = count;
-	while ((i >= sizeof(event)) && !queue_empty(as)) {
-		event = get_queued_event(as);
-		if (copy_to_user(buf, &event, sizeof(event))) {
-			if (i < count)
-				break;
-			return -EFAULT;
-		}
-		switch (event) {
-		case APM_SYS_SUSPEND:
-		case APM_USER_SUSPEND:
-			as->suspends_read++;
-			break;
-
-		case APM_SYS_STANDBY:
-		case APM_USER_STANDBY:
-			as->standbys_read++;
-			break;
-		}
-		buf += sizeof(event);
-		i -= sizeof(event);
-	}
-	if (i < count)
-		return count - i;
-	if (signal_pending(current))
-		return -ERESTARTSYS;
-	return 0;
-}
-
-static unsigned int do_poll(struct file *fp, poll_table *wait)
-{
-	struct apm_user *as;
-
-	as = fp->private_data;
-	if (check_apm_user(as, "poll"))
-		return 0;
-	poll_wait(fp, &apm_waitqueue, wait);
-	if (!queue_empty(as))
-		return POLLIN | POLLRDNORM;
-	return 0;
-}
-
-static long do_ioctl(struct file *filp, u_int cmd, u_long arg)
-{
-	struct apm_user *as;
-	int ret;
-
-	as = filp->private_data;
-	if (check_apm_user(as, "ioctl"))
-		return -EIO;
-	if (!as->suser || !as->writer)
-		return -EPERM;
-	switch (cmd) {
-	case APM_IOC_STANDBY:
-		mutex_lock(&apm_mutex);
-		if (as->standbys_read > 0) {
-			as->standbys_read--;
-			as->standbys_pending--;
-			standbys_pending--;
-		} else
-			queue_event(APM_USER_STANDBY, as);
-		if (standbys_pending <= 0)
-			standby();
-		mutex_unlock(&apm_mutex);
-		break;
-	case APM_IOC_SUSPEND:
-		mutex_lock(&apm_mutex);
-		if (as->suspends_read > 0) {
-			as->suspends_read--;
-			as->suspends_pending--;
-			suspends_pending--;
-		} else
-			queue_event(APM_USER_SUSPEND, as);
-		if (suspends_pending <= 0) {
-			ret = suspend(1);
-			mutex_unlock(&apm_mutex);
-		} else {
-			as->suspend_wait = 1;
-			mutex_unlock(&apm_mutex);
-			wait_event_interruptible(apm_suspend_waitqueue,
-					as->suspend_wait == 0);
-			ret = as->suspend_result;
-		}
-		return ret;
-	default:
-		return -ENOTTY;
-	}
-	return 0;
-}
-
-static int do_release(struct inode *inode, struct file *filp)
-{
-	struct apm_user *as;
-
-	as = filp->private_data;
-	if (check_apm_user(as, "release"))
-		return 0;
-	filp->private_data = NULL;
-	if (as->standbys_pending > 0) {
-		standbys_pending -= as->standbys_pending;
-		if (standbys_pending <= 0)
-			standby();
-	}
-	if (as->suspends_pending > 0) {
-		suspends_pending -= as->suspends_pending;
-		if (suspends_pending <= 0)
-			(void) suspend(1);
-	}
-	spin_lock(&user_list_lock);
-	if (user_list == as)
-		user_list = as->next;
-	else {
-		struct apm_user *as1;
-
-		for (as1 = user_list;
-		     (as1 != NULL) && (as1->next != as);
-		     as1 = as1->next)
-			;
-		if (as1 == NULL)
-			printk(KERN_ERR "apm: filp not in user list\n");
-		else
-			as1->next = as->next;
-	}
-	spin_unlock(&user_list_lock);
-	kfree(as);
-	return 0;
-}
-
-static int do_open(struct inode *inode, struct file *filp)
-{
-	struct apm_user *as;
-
-	as = kmalloc(sizeof(*as), GFP_KERNEL);
-	if (as == NULL) {
-		printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
-		       sizeof(*as));
-		return -ENOMEM;
-	}
-	as->magic = APM_BIOS_MAGIC;
-	as->event_tail = as->event_head = 0;
-	as->suspends_pending = as->standbys_pending = 0;
-	as->suspends_read = as->standbys_read = 0;
-	/*
-	 * XXX - this is a tiny bit broken, when we consider BSD
-	 * process accounting. If the device is opened by root, we
-	 * instantly flag that we used superuser privs. Who knows,
-	 * we might close the device immediately without doing a
-	 * privileged operation -- cevans
-	 */
-	as->suser = capable(CAP_SYS_ADMIN);
-	as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
-	as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
-	spin_lock(&user_list_lock);
-	as->next = user_list;
-	user_list = as;
-	spin_unlock(&user_list_lock);
-	filp->private_data = as;
-	return 0;
-}
-
-static int proc_apm_show(struct seq_file *m, void *v)
-{
-	unsigned short	bx;
-	unsigned short	cx;
-	unsigned short	dx;
-	int		error;
-	unsigned short  ac_line_status = 0xff;
-	unsigned short  battery_status = 0xff;
-	unsigned short  battery_flag   = 0xff;
-	int		percentage     = -1;
-	int             time_units     = -1;
-	char            *units         = "?";
-
-	if ((num_online_cpus() == 1) &&
-	    !(error = apm_get_power_status(&bx, &cx, &dx))) {
-		ac_line_status = (bx >> 8) & 0xff;
-		battery_status = bx & 0xff;
-		if ((cx & 0xff) != 0xff)
-			percentage = cx & 0xff;
-
-		if (apm_info.connection_version > 0x100) {
-			battery_flag = (cx >> 8) & 0xff;
-			if (dx != 0xffff) {
-				units = (dx & 0x8000) ? "min" : "sec";
-				time_units = dx & 0x7fff;
-			}
-		}
-	}
-	/* Arguments, with symbols from linux/apm_bios.h.  Information is
-	   from the Get Power Status (0x0a) call unless otherwise noted.
-
-	   0) Linux driver version (this will change if format changes)
-	   1) APM BIOS Version.  Usually 1.0, 1.1 or 1.2.
-	   2) APM flags from APM Installation Check (0x00):
-	      bit 0: APM_16_BIT_SUPPORT
-	      bit 1: APM_32_BIT_SUPPORT
-	      bit 2: APM_IDLE_SLOWS_CLOCK
-	      bit 3: APM_BIOS_DISABLED
-	      bit 4: APM_BIOS_DISENGAGED
-	   3) AC line status
-	      0x00: Off-line
-	      0x01: On-line
-	      0x02: On backup power (BIOS >= 1.1 only)
-	      0xff: Unknown
-	   4) Battery status
-	      0x00: High
-	      0x01: Low
-	      0x02: Critical
-	      0x03: Charging
-	      0x04: Selected battery not present (BIOS >= 1.2 only)
-	      0xff: Unknown
-	   5) Battery flag
-	      bit 0: High
-	      bit 1: Low
-	      bit 2: Critical
-	      bit 3: Charging
-	      bit 7: No system battery
-	      0xff: Unknown
-	   6) Remaining battery life (percentage of charge):
-	      0-100: valid
-	      -1: Unknown
-	   7) Remaining battery life (time units):
-	      Number of remaining minutes or seconds
-	      -1: Unknown
-	   8) min = minutes; sec = seconds */
-
-	seq_printf(m, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
-		   driver_version,
-		   (apm_info.bios.version >> 8) & 0xff,
-		   apm_info.bios.version & 0xff,
-		   apm_info.bios.flags,
-		   ac_line_status,
-		   battery_status,
-		   battery_flag,
-		   percentage,
-		   time_units,
-		   units);
-	return 0;
-}
-
-static int proc_apm_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, proc_apm_show, NULL);
-}
-
-static const struct file_operations apm_file_ops = {
-	.owner		= THIS_MODULE,
-	.open		= proc_apm_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int apm(void *unused)
-{
-	unsigned short	bx;
-	unsigned short	cx;
-	unsigned short	dx;
-	int		error;
-	char 		*power_stat;
-	char 		*bat_stat;
-
-	/* 2002/08/01 - WT
-	 * This is to avoid random crashes at boot time during initialization
-	 * on SMP systems in case of "apm=power-off" mode. Seen on ASUS A7M266D.
-	 * Some bioses don't like being called from CPU != 0.
-	 * Method suggested by Ingo Molnar.
-	 */
-	set_cpus_allowed_ptr(current, cpumask_of(0));
-	BUG_ON(smp_processor_id() != 0);
-
-	if (apm_info.connection_version == 0) {
-		apm_info.connection_version = apm_info.bios.version;
-		if (apm_info.connection_version > 0x100) {
-			/*
-			 * We only support BIOSs up to version 1.2
-			 */
-			if (apm_info.connection_version > 0x0102)
-				apm_info.connection_version = 0x0102;
-			error = apm_driver_version(&apm_info.connection_version);
-			if (error != APM_SUCCESS) {
-				apm_error("driver version", error);
-				/* Fall back to an APM 1.0 connection. */
-				apm_info.connection_version = 0x100;
-			}
-		}
-	}
-
-	if (debug)
-		printk(KERN_INFO "apm: Connection version %d.%d\n",
-			(apm_info.connection_version >> 8) & 0xff,
-			apm_info.connection_version & 0xff);
-
-#ifdef CONFIG_APM_DO_ENABLE
-	if (apm_info.bios.flags & APM_BIOS_DISABLED) {
-		/*
-		 * This call causes my NEC UltraLite Versa 33/C to hang if it
-		 * is booted with PM disabled but not in the docking station.
-		 * Unfortunate ...
-		 */
-		error = apm_enable_power_management(1);
-		if (error) {
-			apm_error("enable power management", error);
-			return -1;
-		}
-	}
-#endif
-
-	if ((apm_info.bios.flags & APM_BIOS_DISENGAGED)
-	    && (apm_info.connection_version > 0x0100)) {
-		error = apm_engage_power_management(APM_DEVICE_ALL, 1);
-		if (error) {
-			apm_error("engage power management", error);
-			return -1;
-		}
-	}
-
-	if (debug && (num_online_cpus() == 1 || smp)) {
-		error = apm_get_power_status(&bx, &cx, &dx);
-		if (error)
-			printk(KERN_INFO "apm: power status not available\n");
-		else {
-			switch ((bx >> 8) & 0xff) {
-			case 0:
-				power_stat = "off line";
-				break;
-			case 1:
-				power_stat = "on line";
-				break;
-			case 2:
-				power_stat = "on backup power";
-				break;
-			default:
-				power_stat = "unknown";
-				break;
-			}
-			switch (bx & 0xff) {
-			case 0:
-				bat_stat = "high";
-				break;
-			case 1:
-				bat_stat = "low";
-				break;
-			case 2:
-				bat_stat = "critical";
-				break;
-			case 3:
-				bat_stat = "charging";
-				break;
-			default:
-				bat_stat = "unknown";
-				break;
-			}
-			printk(KERN_INFO
-			       "apm: AC %s, battery status %s, battery life ",
-			       power_stat, bat_stat);
-			if ((cx & 0xff) == 0xff)
-				printk("unknown\n");
-			else
-				printk("%d%%\n", cx & 0xff);
-			if (apm_info.connection_version > 0x100) {
-				printk(KERN_INFO
-				       "apm: battery flag 0x%02x, battery life ",
-				       (cx >> 8) & 0xff);
-				if (dx == 0xffff)
-					printk("unknown\n");
-				else
-					printk("%d %s\n", dx & 0x7fff,
-					       (dx & 0x8000) ?
-					       "minutes" : "seconds");
-			}
-		}
-	}
-
-	/* Install our power off handler.. */
-	if (power_off)
-		pm_power_off = apm_power_off;
-
-	if (num_online_cpus() == 1 || smp) {
-#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
-		console_blank_hook = apm_console_blank;
-#endif
-		apm_mainloop();
-#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
-		console_blank_hook = NULL;
-#endif
-	}
-
-	return 0;
-}
-
-#ifndef MODULE
-static int __init apm_setup(char *str)
-{
-	int invert;
-
-	while ((str != NULL) && (*str != '\0')) {
-		if (strncmp(str, "off", 3) == 0)
-			apm_disabled = 1;
-		if (strncmp(str, "on", 2) == 0)
-			apm_disabled = 0;
-		if ((strncmp(str, "bounce-interval=", 16) == 0) ||
-		    (strncmp(str, "bounce_interval=", 16) == 0))
-			bounce_interval = simple_strtol(str + 16, NULL, 0);
-		if ((strncmp(str, "idle-threshold=", 15) == 0) ||
-		    (strncmp(str, "idle_threshold=", 15) == 0))
-			idle_threshold = simple_strtol(str + 15, NULL, 0);
-		if ((strncmp(str, "idle-period=", 12) == 0) ||
-		    (strncmp(str, "idle_period=", 12) == 0))
-			idle_period = simple_strtol(str + 12, NULL, 0);
-		invert = (strncmp(str, "no-", 3) == 0) ||
-			(strncmp(str, "no_", 3) == 0);
-		if (invert)
-			str += 3;
-		if (strncmp(str, "debug", 5) == 0)
-			debug = !invert;
-		if ((strncmp(str, "power-off", 9) == 0) ||
-		    (strncmp(str, "power_off", 9) == 0))
-			power_off = !invert;
-		if (strncmp(str, "smp", 3) == 0) {
-			smp = !invert;
-			idle_threshold = 100;
-		}
-		if ((strncmp(str, "allow-ints", 10) == 0) ||
-		    (strncmp(str, "allow_ints", 10) == 0))
-			apm_info.allow_ints = !invert;
-		if ((strncmp(str, "broken-psr", 10) == 0) ||
-		    (strncmp(str, "broken_psr", 10) == 0))
-			apm_info.get_power_status_broken = !invert;
-		if ((strncmp(str, "realmode-power-off", 18) == 0) ||
-		    (strncmp(str, "realmode_power_off", 18) == 0))
-			apm_info.realmode_power_off = !invert;
-		str = strchr(str, ',');
-		if (str != NULL)
-			str += strspn(str, ", \t");
-	}
-	return 1;
-}
-
-__setup("apm=", apm_setup);
-#endif
-
-static const struct file_operations apm_bios_fops = {
-	.owner		= THIS_MODULE,
-	.read		= do_read,
-	.poll		= do_poll,
-	.unlocked_ioctl	= do_ioctl,
-	.open		= do_open,
-	.release	= do_release,
-	.llseek		= noop_llseek,
-};
-
-static struct miscdevice apm_device = {
-	APM_MINOR_DEV,
-	"apm_bios",
-	&apm_bios_fops
-};
-
-
-/* Simple "print if true" callback */
-static int __init print_if_true(const struct dmi_system_id *d)
-{
-	printk("%s\n", d->ident);
-	return 0;
-}
-
-/*
- * Some Bioses enable the PS/2 mouse (touchpad) at resume, even if it was
- * disabled before the suspend. Linux used to get terribly confused by that.
- */
-static int __init broken_ps2_resume(const struct dmi_system_id *d)
-{
-	printk(KERN_INFO "%s machine detected. Mousepad Resume Bug "
-	       "workaround hopefully not needed.\n", d->ident);
-	return 0;
-}
-
-/* Some bioses have a broken protected mode poweroff and need to use realmode */
-static int __init set_realmode_power_off(const struct dmi_system_id *d)
-{
-	if (apm_info.realmode_power_off == 0) {
-		apm_info.realmode_power_off = 1;
-		printk(KERN_INFO "%s bios detected. "
-		       "Using realmode poweroff only.\n", d->ident);
-	}
-	return 0;
-}
-
-/* Some laptops require interrupts to be enabled during APM calls */
-static int __init set_apm_ints(const struct dmi_system_id *d)
-{
-	if (apm_info.allow_ints == 0) {
-		apm_info.allow_ints = 1;
-		printk(KERN_INFO "%s machine detected. "
-		       "Enabling interrupts during APM calls.\n", d->ident);
-	}
-	return 0;
-}
-
-/* Some APM bioses corrupt memory or just plain do not work */
-static int __init apm_is_horked(const struct dmi_system_id *d)
-{
-	if (apm_info.disabled == 0) {
-		apm_info.disabled = 1;
-		printk(KERN_INFO "%s machine detected. "
-		       "Disabling APM.\n", d->ident);
-	}
-	return 0;
-}
-
-static int __init apm_is_horked_d850md(const struct dmi_system_id *d)
-{
-	if (apm_info.disabled == 0) {
-		apm_info.disabled = 1;
-		printk(KERN_INFO "%s machine detected. "
-		       "Disabling APM.\n", d->ident);
-		printk(KERN_INFO "This bug is fixed in bios P15 which is available for\n");
-		printk(KERN_INFO "download from support.intel.com\n");
-	}
-	return 0;
-}
-
-/* Some APM bioses hang on APM idle calls */
-static int __init apm_likes_to_melt(const struct dmi_system_id *d)
-{
-	if (apm_info.forbid_idle == 0) {
-		apm_info.forbid_idle = 1;
-		printk(KERN_INFO "%s machine detected. "
-		       "Disabling APM idle calls.\n", d->ident);
-	}
-	return 0;
-}
-
-/*
- *  Check for clue free BIOS implementations who use
- *  the following QA technique
- *
- *      [ Write BIOS Code ]<------
- *               |                ^
- *      < Does it Compile >----N--
- *               |Y               ^
- *	< Does it Boot Win98 >-N--
- *               |Y
- *           [Ship It]
- *
- *	Phoenix A04  08/24/2000 is known bad (Dell Inspiron 5000e)
- *	Phoenix A07  09/29/2000 is known good (Dell Inspiron 5000)
- */
-static int __init broken_apm_power(const struct dmi_system_id *d)
-{
-	apm_info.get_power_status_broken = 1;
-	printk(KERN_WARNING "BIOS strings suggest APM bugs, "
-	       "disabling power status reporting.\n");
-	return 0;
-}
-
-/*
- * This bios swaps the APM minute reporting bytes over (Many sony laptops
- * have this problem).
- */
-static int __init swab_apm_power_in_minutes(const struct dmi_system_id *d)
-{
-	apm_info.get_power_status_swabinminutes = 1;
-	printk(KERN_WARNING "BIOS strings suggest APM reports battery life "
-	       "in minutes and wrong byte order.\n");
-	return 0;
-}
-
-static struct dmi_system_id __initdata apm_dmi_table[] = {
-	{
-		print_if_true,
-		KERN_WARNING "IBM T23 - BIOS 1.03b+ and controller firmware 1.02+ may be needed for Linux APM.",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-			DMI_MATCH(DMI_BIOS_VERSION, "1AET38WW (1.01b)"), },
-	},
-	{	/* Handle problems with APM on the C600 */
-		broken_ps2_resume, "Dell Latitude C600",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude C600"), },
-	},
-	{	/* Allow interrupts during suspend on Dell Latitude laptops*/
-		set_apm_ints, "Dell Latitude",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude C510"), }
-	},
-	{	/* APM crashes */
-		apm_is_horked, "Dell Inspiron 2500",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
-			DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "A11"), },
-	},
-	{	/* Allow interrupts during suspend on Dell Inspiron laptops*/
-		set_apm_ints, "Dell Inspiron", {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"), },
-	},
-	{	/* Handle problems with APM on Inspiron 5000e */
-		broken_apm_power, "Dell Inspiron 5000e",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "A04"),
-			DMI_MATCH(DMI_BIOS_DATE, "08/24/2000"), },
-	},
-	{	/* Handle problems with APM on Inspiron 2500 */
-		broken_apm_power, "Dell Inspiron 2500",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "A12"),
-			DMI_MATCH(DMI_BIOS_DATE, "02/04/2002"), },
-	},
-	{	/* APM crashes */
-		apm_is_horked, "Dell Dimension 4100",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "XPS-Z"),
-			DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
-			DMI_MATCH(DMI_BIOS_VERSION, "A11"), },
-	},
-	{	/* Allow interrupts during suspend on Compaq Laptops*/
-		set_apm_ints, "Compaq 12XL125",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Compaq PC"),
-			DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "4.06"), },
-	},
-	{	/* Allow interrupts during APM or the clock goes slow */
-		set_apm_ints, "ASUSTeK",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "L8400K series Notebook PC"), },
-	},
-	{	/* APM blows on shutdown */
-		apm_is_horked, "ABIT KX7-333[R]",
-		{	DMI_MATCH(DMI_BOARD_VENDOR, "ABIT"),
-			DMI_MATCH(DMI_BOARD_NAME, "VT8367-8233A (KX7-333[R])"), },
-	},
-	{	/* APM crashes */
-		apm_is_horked, "Trigem Delhi3",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "TriGem Computer, Inc"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Delhi3"), },
-	},
-	{	/* APM crashes */
-		apm_is_horked, "Fujitsu-Siemens",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "hoenix/FUJITSU SIEMENS"),
-			DMI_MATCH(DMI_BIOS_VERSION, "Version1.01"), },
-	},
-	{	/* APM crashes */
-		apm_is_horked_d850md, "Intel D850MD",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
-			DMI_MATCH(DMI_BIOS_VERSION, "MV85010A.86A.0016.P07.0201251536"), },
-	},
-	{	/* APM crashes */
-		apm_is_horked, "Intel D810EMO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
-			DMI_MATCH(DMI_BIOS_VERSION, "MO81010A.86A.0008.P04.0004170800"), },
-	},
-	{	/* APM crashes */
-		apm_is_horked, "Dell XPS-Z",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
-			DMI_MATCH(DMI_BIOS_VERSION, "A11"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "XPS-Z"), },
-	},
-	{	/* APM crashes */
-		apm_is_horked, "Sharp PC-PJ/AX",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "SHARP"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "PC-PJ/AX"),
-			DMI_MATCH(DMI_BIOS_VENDOR, "SystemSoft"),
-			DMI_MATCH(DMI_BIOS_VERSION, "Version R2.08"), },
-	},
-	{	/* APM crashes */
-		apm_is_horked, "Dell Inspiron 2500",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
-			DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "A11"), },
-	},
-	{	/* APM idle hangs */
-		apm_likes_to_melt, "Jabil AMD",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
-			DMI_MATCH(DMI_BIOS_VERSION, "0AASNP06"), },
-	},
-	{	/* APM idle hangs */
-		apm_likes_to_melt, "AMI Bios",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
-			DMI_MATCH(DMI_BIOS_VERSION, "0AASNP05"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-N505X(DE) */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "R0206H"),
-			DMI_MATCH(DMI_BIOS_DATE, "08/23/99"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-N505VX */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "W2K06H0"),
-			DMI_MATCH(DMI_BIOS_DATE, "02/03/00"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-XG29 */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "R0117A0"),
-			DMI_MATCH(DMI_BIOS_DATE, "04/25/00"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-Z600NE */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "R0121Z1"),
-			DMI_MATCH(DMI_BIOS_DATE, "05/11/00"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-Z600NE */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "WME01Z1"),
-			DMI_MATCH(DMI_BIOS_DATE, "08/11/00"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-Z600LEK(DE) */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "R0206Z3"),
-			DMI_MATCH(DMI_BIOS_DATE, "12/25/00"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-Z505LS */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "R0203D0"),
-			DMI_MATCH(DMI_BIOS_DATE, "05/12/00"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-Z505LS */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "R0203Z3"),
-			DMI_MATCH(DMI_BIOS_DATE, "08/25/00"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-Z505LS (with updated BIOS) */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "R0209Z3"),
-			DMI_MATCH(DMI_BIOS_DATE, "05/12/01"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-F104K */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "R0204K2"),
-			DMI_MATCH(DMI_BIOS_DATE, "08/28/00"), },
-	},
-
-	{	/* Handle problems with APM on Sony Vaio PCG-C1VN/C1VE */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "R0208P1"),
-			DMI_MATCH(DMI_BIOS_DATE, "11/09/00"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-C1VE */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "R0204P1"),
-			DMI_MATCH(DMI_BIOS_DATE, "09/12/00"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-C1VE */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "WXPO1Z3"),
-			DMI_MATCH(DMI_BIOS_DATE, "10/26/01"), },
-	},
-	{	/* broken PM poweroff bios */
-		set_realmode_power_off, "Award Software v4.60 PGMA",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Award Software International, Inc."),
-			DMI_MATCH(DMI_BIOS_VERSION, "4.60 PGMA"),
-			DMI_MATCH(DMI_BIOS_DATE, "134526184"), },
-	},
-
-	/* Generic per vendor APM settings  */
-
-	{	/* Allow interrupts during suspend on IBM laptops */
-		set_apm_ints, "IBM",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "IBM"), },
-	},
-
-	{ }
-};
-
-/*
- * Just start the APM thread. We do NOT want to do APM BIOS
- * calls from anything but the APM thread, if for no other reason
- * than the fact that we don't trust the APM BIOS. This way,
- * most common APM BIOS problems that lead to protection errors
- * etc will have at least some level of being contained...
- *
- * In short, if something bad happens, at least we have a choice
- * of just killing the apm thread..
- */
-static int __init apm_init(void)
-{
-	struct desc_struct *gdt;
-	int err;
-
-	dmi_check_system(apm_dmi_table);
-
-	if (apm_info.bios.version == 0 || paravirt_enabled() || machine_is_olpc()) {
-		printk(KERN_INFO "apm: BIOS not found.\n");
-		return -ENODEV;
-	}
-	printk(KERN_INFO
-	       "apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n",
-	       ((apm_info.bios.version >> 8) & 0xff),
-	       (apm_info.bios.version & 0xff),
-	       apm_info.bios.flags,
-	       driver_version);
-	if ((apm_info.bios.flags & APM_32_BIT_SUPPORT) == 0) {
-		printk(KERN_INFO "apm: no 32 bit BIOS support\n");
-		return -ENODEV;
-	}
-
-	if (allow_ints)
-		apm_info.allow_ints = 1;
-	if (broken_psr)
-		apm_info.get_power_status_broken = 1;
-	if (realmode_power_off)
-		apm_info.realmode_power_off = 1;
-	/* User can override, but default is to trust DMI */
-	if (apm_disabled != -1)
-		apm_info.disabled = apm_disabled;
-
-	/*
-	 * Fix for the Compaq Contura 3/25c which reports BIOS version 0.1
-	 * but is reportedly a 1.0 BIOS.
-	 */
-	if (apm_info.bios.version == 0x001)
-		apm_info.bios.version = 0x100;
-
-	/* BIOS < 1.2 doesn't set cseg_16_len */
-	if (apm_info.bios.version < 0x102)
-		apm_info.bios.cseg_16_len = 0; /* 64k */
-
-	if (debug) {
-		printk(KERN_INFO "apm: entry %x:%x cseg16 %x dseg %x",
-			apm_info.bios.cseg, apm_info.bios.offset,
-			apm_info.bios.cseg_16, apm_info.bios.dseg);
-		if (apm_info.bios.version > 0x100)
-			printk(" cseg len %x, dseg len %x",
-				apm_info.bios.cseg_len,
-				apm_info.bios.dseg_len);
-		if (apm_info.bios.version > 0x101)
-			printk(" cseg16 len %x", apm_info.bios.cseg_16_len);
-		printk("\n");
-	}
-
-	if (apm_info.disabled) {
-		printk(KERN_NOTICE "apm: disabled on user request.\n");
-		return -ENODEV;
-	}
-	if ((num_online_cpus() > 1) && !power_off && !smp) {
-		printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
-		apm_info.disabled = 1;
-		return -ENODEV;
-	}
-	if (pm_flags & PM_ACPI) {
-		printk(KERN_NOTICE "apm: overridden by ACPI.\n");
-		apm_info.disabled = 1;
-		return -ENODEV;
-	}
-	pm_flags |= PM_APM;
-
-	/*
-	 * Set up the long jump entry point to the APM BIOS, which is called
-	 * from inline assembly.
-	 */
-	apm_bios_entry.offset = apm_info.bios.offset;
-	apm_bios_entry.segment = APM_CS;
-
-	/*
-	 * The APM 1.1 BIOS is supposed to provide limit information that it
-	 * recognizes.  Many machines do this correctly, but many others do
-	 * not restrict themselves to their claimed limit.  When this happens,
-	 * they will cause a segmentation violation in the kernel at boot time.
-	 * Most BIOS's, however, will respect a 64k limit, so we use that.
-	 *
-	 * Note we only set APM segments on CPU zero, since we pin the APM
-	 * code to that CPU.
-	 */
-	gdt = get_cpu_gdt_table(0);
-	set_desc_base(&gdt[APM_CS >> 3],
-		 (unsigned long)__va((unsigned long)apm_info.bios.cseg << 4));
-	set_desc_base(&gdt[APM_CS_16 >> 3],
-		 (unsigned long)__va((unsigned long)apm_info.bios.cseg_16 << 4));
-	set_desc_base(&gdt[APM_DS >> 3],
-		 (unsigned long)__va((unsigned long)apm_info.bios.dseg << 4));
-
-	proc_create("apm", 0, NULL, &apm_file_ops);
-
-	kapmd_task = kthread_create(apm, NULL, "kapmd");
-	if (IS_ERR(kapmd_task)) {
-		printk(KERN_ERR "apm: disabled - Unable to start kernel "
-				"thread.\n");
-		err = PTR_ERR(kapmd_task);
-		kapmd_task = NULL;
-		remove_proc_entry("apm", NULL);
-		return err;
-	}
-	wake_up_process(kapmd_task);
-
-	if (num_online_cpus() > 1 && !smp) {
-		printk(KERN_NOTICE
-		       "apm: disabled - APM is not SMP safe (power off active).\n");
-		return 0;
-	}
-
-	/*
-	 * Note we don't actually care if the misc_device cannot be registered.
-	 * this driver can do its job without it, even if userspace can't
-	 * control it.  just log the error
-	 */
-	if (misc_register(&apm_device))
-		printk(KERN_WARNING "apm: Could not register misc device.\n");
-
-	if (HZ != 100)
-		idle_period = (idle_period * HZ) / 100;
-	if (idle_threshold < 100) {
-		original_pm_idle = pm_idle;
-		pm_idle  = apm_cpu_idle;
-		set_pm_idle = 1;
-	}
-
-	return 0;
-}
-
-static void __exit apm_exit(void)
-{
-	int error;
-
-	if (set_pm_idle) {
-		pm_idle = original_pm_idle;
-		/*
-		 * We are about to unload the current idle thread pm callback
-		 * (pm_idle), Wait for all processors to update cached/local
-		 * copies of pm_idle before proceeding.
-		 */
-		cpu_idle_wait();
-	}
-	if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0)
-	    && (apm_info.connection_version > 0x0100)) {
-		error = apm_engage_power_management(APM_DEVICE_ALL, 0);
-		if (error)
-			apm_error("disengage power management", error);
-	}
-	misc_deregister(&apm_device);
-	remove_proc_entry("apm", NULL);
-	if (power_off)
-		pm_power_off = NULL;
-	if (kapmd_task) {
-		kthread_stop(kapmd_task);
-		kapmd_task = NULL;
-	}
-	pm_flags &= ~PM_APM;
-}
-
-module_init(apm_init);
-module_exit(apm_exit);
-
-MODULE_AUTHOR("Stephen Rothwell");
-MODULE_DESCRIPTION("Advanced Power Management");
-MODULE_LICENSE("GPL");
-module_param(debug, bool, 0644);
-MODULE_PARM_DESC(debug, "Enable debug mode");
-module_param(power_off, bool, 0444);
-MODULE_PARM_DESC(power_off, "Enable power off");
-module_param(bounce_interval, int, 0444);
-MODULE_PARM_DESC(bounce_interval,
-		"Set the number of ticks to ignore suspend bounces");
-module_param(allow_ints, bool, 0444);
-MODULE_PARM_DESC(allow_ints, "Allow interrupts during BIOS calls");
-module_param(broken_psr, bool, 0444);
-MODULE_PARM_DESC(broken_psr, "BIOS has a broken GetPowerStatus call");
-module_param(realmode_power_off, bool, 0444);
-MODULE_PARM_DESC(realmode_power_off,
-		"Switch to real mode before powering off");
-module_param(idle_threshold, int, 0444);
-MODULE_PARM_DESC(idle_threshold,
-	"System idle percentage above which to make APM BIOS idle calls");
-module_param(idle_period, int, 0444);
-MODULE_PARM_DESC(idle_period,
-	"Period (in sec/100) over which to caculate the idle percentage");
-module_param(smp, bool, 0444);
-MODULE_PARM_DESC(smp,
-	"Set this to enable APM use on an SMP platform. Use with caution on older systems");
-MODULE_ALIAS_MISCDEV(APM_MINOR_DEV);
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 094d4ac..6808419 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -365,9 +365,6 @@ void default_idle(void)
 	trace_power_end(smp_processor_id());
 	trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
 }
-#ifdef CONFIG_APM_MODULE
-EXPORT_SYMBOL(default_idle);
-#endif
 
 void stop_this_cpu(void *dummy)
 {
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 715037c..60698d3 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -428,9 +428,6 @@ void machine_real_restart(const unsigned char *code, int length)
 				:
 				: "i" ((void *)(0x1000 - sizeof (real_mode_switch) - 100)));
 }
-#ifdef CONFIG_APM_MODULE
-EXPORT_SYMBOL(machine_real_restart);
-#endif
 
 #endif /* CONFIG_X86_32 */
 
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index fab5631..cf9cb87 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -193,9 +193,6 @@ unsigned int machine_id;
 unsigned int machine_submodel_id;
 unsigned int BIOS_revision;
 
-struct apm_info apm_info;
-EXPORT_SYMBOL(apm_info);
-
 #if defined(CONFIG_X86_SPEEDSTEP_SMI) || \
 	defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
 struct ist_info ist_info;
@@ -742,7 +739,6 @@ void __init setup_arch(char **cmdline_p)
 	screen_info = boot_params.screen_info;
 	edid_info = boot_params.edid_info;
 #ifdef CONFIG_X86_32
-	apm_info.bios = boot_params.apm_bios_info;
 	ist_info = boot_params.ist_info;
 	if (boot_params.sys_desc_table.length != 0) {
 		set_mca_bus(boot_params.sys_desc_table.table[3] & 0x2);
-- 
1.7.4.1.343.ga91df



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [PATCH] APM: delete APM in Linux-2.6.40
  2011-03-24  7:39   ` [PATCH] APM: delete APM in Linux-2.6.40 Len Brown
  2011-03-24  8:16     ` [PATCH] x86 APM: delete Linux kernel APM support Len Brown
@ 2011-03-24  8:18     ` Stephen Rothwell
  2011-03-24  8:38     ` Alexander Stein
                       ` (3 subsequent siblings)
  5 siblings, 0 replies; 37+ messages in thread
From: Stephen Rothwell @ 2011-03-24  8:18 UTC (permalink / raw)
  To: Len Brown; +Cc: linux-pm, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 337 bytes --]

On Thu, 24 Mar 2011 03:39:07 -0400 (EDT) Len Brown <lenb@kernel.org> wrote:
>
> From: Len Brown <len.brown@intel.com>
> 
> Signed-off-by: Len Brown <len.brown@intel.com>

Acked-by: Stephen Rothwell <sfr@canb.auug.org.au>

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

[-- Attachment #2: Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH] x86 APM: delete Linux kernel APM support (v2)
  2011-03-24  8:16     ` [PATCH] x86 APM: delete Linux kernel APM support Len Brown
@ 2011-03-24  8:31       ` Len Brown
  2011-03-24 16:01         ` Andi Kleen
  2011-03-24  8:39       ` [PATCH] x86 APM: delete Linux kernel APM support Ingo Molnar
  1 sibling, 1 reply; 37+ messages in thread
From: Len Brown @ 2011-03-24  8:31 UTC (permalink / raw)
  To: Stephen Rothwell, x86; +Cc: linux-pm, linux-kernel

From: Len Brown <len.brown@intel.com>

Microsoft was able to delete APM from Windows in 2006
with the release of Windows Vista.  5 years later it seems
quite safe that the latest Linux kernel can also.

The vintage APM laptops have become difficult to find,
making changes in this area difficult to test.

apm_bios.h remains for CONFIG_APM_EMULATION
used by non-x86 architectures.

Signed-off-by: Len Brown <len.brown@intel.com>
---
v2: also delete pm_flags

 Documentation/feature-removal-schedule.txt |    9 -
 MAINTAINERS                                |    8 -
 arch/x86/Kconfig                           |  125 --
 arch/x86/boot/Makefile                     |    1 -
 arch/x86/boot/apm.c                        |   75 -
 arch/x86/boot/boot.h                       |    3 -
 arch/x86/boot/main.c                       |    5 -
 arch/x86/include/asm/bootparam.h           |    3 +-
 arch/x86/kernel/Makefile                   |    2 -
 arch/x86/kernel/apm_32.c                   | 2463 ----------------------------
 arch/x86/kernel/process.c                  |    3 -
 arch/x86/kernel/reboot.c                   |    3 -
 arch/x86/kernel/setup.c                    |    5 -
 drivers/acpi/bus.c                         |   12 +-
 include/linux/pm.h                         |    9 -
 kernel/power/main.c                        |    3 -
 16 files changed, 3 insertions(+), 2726 deletions(-)
 delete mode 100644 arch/x86/boot/apm.c
 delete mode 100644 arch/x86/kernel/apm_32.c

diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 2a03c46..4b5dfcc 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -618,12 +618,3 @@ Why:	The original implementation of memsw feature enabled by
 	can also cleanup the parameter handling a bit ().
 Who:	Michal Hocko <mhocko@suse.cz>
 
-----------------------------
-
-What:	CONFIG_APM
-When:	2.6.40
-Why:	Microsoft deleted APM from Windows as of Vista in in 2006.
-	It now seems more than safe that the latest Linux Kernel be APM-free.
-	The vintage laptops supporting APM are now difficult to find,
-	making it problatic to maintain this code.
-Who:	Len Brown <len.brown@intel.com>
diff --git a/MAINTAINERS b/MAINTAINERS
index f1bc3dc..a896b39 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -531,14 +531,6 @@ L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:	Maintained
 F:	sound/aoa/
 
-APM DRIVER
-M:	Stephen Rothwell <sfr@canb.auug.org.au>
-L:	linux-laptop@vger.kernel.org
-W:	http://www.canb.auug.org.au/~sfr/
-S:	Supported
-F:	arch/x86/kernel/apm_32.c
-F:	include/linux/apm_bios.h
-
 APPLE BCM5974 MULTITOUCH DRIVER
 M:	Henrik Rydberg <rydberg@euromail.se>
 L:	linux-input@vger.kernel.org
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index d5ed94d..6b4e6b1 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1720,131 +1720,6 @@ source "drivers/acpi/Kconfig"
 
 source "drivers/sfi/Kconfig"
 
-config X86_APM_BOOT
-	def_bool y
-	depends on APM || APM_MODULE
-
-menuconfig APM
-	tristate "APM (Advanced Power Management) BIOS support"
-	depends on X86_32 && PM_SLEEP
-	---help---
-	  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 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.
-
-	  In order to use APM, you will need supporting software. For location
-	  and more information, read <file:Documentation/power/pm.txt> and the
-	  Battery Powered Linux mini-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>.
-
-	  This driver does not spin down disk drives (see the hdparm(8)
-	  manpage ("man 8 hdparm") for that), and it doesn't turn off
-	  VESA-compliant "green" monitors.
-
-	  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
-	  may cause those machines to panic during the boot phase.
-
-	  Generally, if you don't have a battery in your machine, there isn't
-	  much point in using this driver and you should say N. If you get
-	  random kernel OOPSes or reboots that don't seem to be related to
-	  anything, try disabling/enabling this option (or disabling/enabling
-	  APM in your BIOS).
-
-	  Some other things you should try when experiencing seemingly random,
-	  "weird" problems:
-
-	  1) make sure that you have enough swap space and that it is
-	  enabled.
-	  2) pass the "no-hlt" option to the kernel
-	  3) switch on floating point emulation in the kernel and pass
-	  the "no387" option to the kernel
-	  4) pass the "floppy=nodma" option to the kernel
-	  5) pass the "mem=4M" option to the kernel (thereby disabling
-	  all but the first 4 MB of RAM)
-	  6) make sure that the CPU is not over clocked.
-	  7) read the sig11 FAQ at <http://www.bitwizard.nl/sig11/>
-	  8) disable the cache from your BIOS settings
-	  9) install a fan for the video card or exchange video RAM
-	  10) install a better fan for the CPU
-	  11) exchange RAM chips
-	  12) exchange the motherboard.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called apm.
-
-if APM
-
-config APM_IGNORE_USER_SUSPEND
-	bool "Ignore USER SUSPEND"
-	---help---
-	  This option will ignore USER SUSPEND requests. On machines with a
-	  compliant APM BIOS, you want to say N. However, on the NEC Versa M
-	  series notebooks, it is necessary to say Y because of a BIOS bug.
-
-config APM_DO_ENABLE
-	bool "Enable PM at boot time"
-	---help---
-	  Enable APM features at boot time. From page 36 of the APM BIOS
-	  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 "Do CPU IDLE calls", 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
-	bool "Make CPU Idle calls when idle"
-	---help---
-	  Enable calls to APM CPU Idle/CPU Busy inside the kernel's 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 calls
-	  are 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. (On machines with more than one CPU,
-	  this option does nothing.)
-
-config APM_DISPLAY_BLANK
-	bool "Enable console blanking using APM"
-	---help---
-	  Enable console blanking using the APM. Some laptops can use this to
-	  turn off the LCD backlight when the screen blanker of the Linux
-	  virtual console blanks the screen. Note that this is only used by
-	  the virtual console screen blanker, and won't turn off the backlight
-	  when using the X Window system. This also doesn't have anything to
-	  do with your VESA-compliant power-saving monitor. Further, this
-	  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.
-
-config APM_ALLOW_INTS
-	bool "Allow interrupts during APM BIOS calls"
-	---help---
-	  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 reenable interrupts if it
-	  needs to.  Unfortunately, some BIOSes 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.
-
-endif # APM
-
 source "arch/x86/kernel/cpu/cpufreq/Kconfig"
 
 source "drivers/cpuidle/Kconfig"
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index f7cb086..a746cc8 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -30,7 +30,6 @@ setup-y		+= a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o
 setup-y		+= early_serial_console.o edd.o header.o main.o mca.o memory.o
 setup-y		+= pm.o pmjump.o printf.o regs.o string.o tty.o video.o
 setup-y		+= video-mode.o version.o
-setup-$(CONFIG_X86_APM_BOOT) += apm.o
 
 # The link order of the video-*.o modules can matter.  In particular,
 # video-vga.o *must* be listed first, followed by video-vesa.o.
diff --git a/arch/x86/boot/apm.c b/arch/x86/boot/apm.c
deleted file mode 100644
index ee27483..0000000
--- a/arch/x86/boot/apm.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/* -*- linux-c -*- ------------------------------------------------------- *
- *
- *   Copyright (C) 1991, 1992 Linus Torvalds
- *   Copyright 2007 rPath, Inc. - All Rights Reserved
- *   Copyright 2009 Intel Corporation; author H. Peter Anvin
- *
- *   Original APM BIOS checking by Stephen Rothwell, May 1994
- *   (sfr@canb.auug.org.au)
- *
- *   This file is part of the Linux kernel, and is made available under
- *   the terms of the GNU General Public License version 2.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * Get APM BIOS information
- */
-
-#include "boot.h"
-
-int query_apm_bios(void)
-{
-	struct biosregs ireg, oreg;
-
-	/* APM BIOS installation check */
-	initregs(&ireg);
-	ireg.ah = 0x53;
-	intcall(0x15, &ireg, &oreg);
-
-	if (oreg.flags & X86_EFLAGS_CF)
-		return -1;		/* No APM BIOS */
-
-	if (oreg.bx != 0x504d)		/* "PM" signature */
-		return -1;
-
-	if (!(oreg.cx & 0x02))		/* 32 bits supported? */
-		return -1;
-
-	/* Disconnect first, just in case */
-	ireg.al = 0x04;
-	intcall(0x15, &ireg, NULL);
-
-	/* 32-bit connect */
-	ireg.al = 0x03;
-	intcall(0x15, &ireg, &oreg);
-
-	boot_params.apm_bios_info.cseg        = oreg.ax;
-	boot_params.apm_bios_info.offset      = oreg.ebx;
-	boot_params.apm_bios_info.cseg_16     = oreg.cx;
-	boot_params.apm_bios_info.dseg        = oreg.dx;
-	boot_params.apm_bios_info.cseg_len    = oreg.si;
-	boot_params.apm_bios_info.cseg_16_len = oreg.hsi;
-	boot_params.apm_bios_info.dseg_len    = oreg.di;
-
-	if (oreg.flags & X86_EFLAGS_CF)
-		return -1;
-
-	/* Redo the installation check as the 32-bit connect;
-	   some BIOSes return different flags this way... */
-
-	ireg.al = 0x00;
-	intcall(0x15, &ireg, &oreg);
-
-	if ((oreg.eflags & X86_EFLAGS_CF) || oreg.bx != 0x504d) {
-		/* Failure with 32-bit connect, try to disconect and ignore */
-		ireg.al = 0x04;
-		intcall(0x15, &ireg, NULL);
-		return -1;
-	}
-
-	boot_params.apm_bios_info.version = oreg.ax;
-	boot_params.apm_bios_info.flags   = oreg.cx;
-	return 0;
-}
-
diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
index c7093bd..df1ca6d 100644
--- a/arch/x86/boot/boot.h
+++ b/arch/x86/boot/boot.h
@@ -238,9 +238,6 @@ void *memset(void *dst, int c, size_t len);
 /* a20.c */
 int enable_a20(void);
 
-/* apm.c */
-int query_apm_bios(void);
-
 /* bioscall.c */
 struct biosregs {
 	union {
diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c
index 40358c8..b6a9743 100644
--- a/arch/x86/boot/main.c
+++ b/arch/x86/boot/main.c
@@ -160,11 +160,6 @@ void main(void)
 	/* Query Intel SpeedStep (IST) information */
 	query_ist();
 
-	/* Query APM information */
-#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
-	query_apm_bios();
-#endif
-
 	/* Query EDD information */
 #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
 	query_edd();
diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h
index c8bfe63..7d8e530 100644
--- a/arch/x86/include/asm/bootparam.h
+++ b/arch/x86/include/asm/bootparam.h
@@ -3,7 +3,6 @@
 
 #include <linux/types.h>
 #include <linux/screen_info.h>
-#include <linux/apm_bios.h>
 #include <linux/edd.h>
 #include <asm/e820.h>
 #include <asm/ist.h>
@@ -92,7 +91,7 @@ struct efi_info {
 /* The so-called "zeropage" */
 struct boot_params {
 	struct screen_info screen_info;			/* 0x000 */
-	struct apm_bios_info apm_bios_info;		/* 0x040 */
+	__u8  _apm_pad[20];				/* 0x040 */
 	__u8  _pad2[4];					/* 0x054 */
 	__u64  tboot_addr;				/* 0x058 */
 	struct ist_info ist_info;			/* 0x060 */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 34244b2..92ef9c9 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -63,8 +63,6 @@ obj-$(CONFIG_MCA)		+= mca_32.o
 obj-$(CONFIG_X86_MSR)		+= msr.o
 obj-$(CONFIG_X86_CPUID)		+= cpuid.o
 obj-$(CONFIG_PCI)		+= early-quirks.o
-apm-y				:= apm_32.o
-obj-$(CONFIG_APM)		+= apm.o
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_SMP)		+= smpboot.o tsc_sync.o
 obj-$(CONFIG_SMP)		+= setup_percpu.o
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
deleted file mode 100644
index 0e4f24c..0000000
--- a/arch/x86/kernel/apm_32.c
+++ /dev/null
@@ -1,2463 +0,0 @@
-/* -*- linux-c -*-
- * APM BIOS driver for Linux
- * Copyright 1994-2001 Stephen Rothwell (sfr@canb.auug.org.au)
- *
- * Initial development of this driver was funded by NEC Australia P/L
- *	and NEC Corporation
- *
- * 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
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * October 1995, Rik Faith (faith@cs.unc.edu):
- *    Minor enhancements and updates (to the patch set) for 1.3.x
- *    Documentation
- * January 1996, Rik Faith (faith@cs.unc.edu):
- *    Make /proc/apm easy to format (bump driver version)
- * March 1996, Rik Faith (faith@cs.unc.edu):
- *    Prohibit APM BIOS calls unless apm_enabled.
- *    (Thanks to Ulrich Windl <Ulrich.Windl@rz.uni-regensburg.de>)
- * April 1996, Stephen Rothwell (sfr@canb.auug.org.au)
- *    Version 1.0 and 1.1
- * May 1996, Version 1.2
- * Feb 1998, Version 1.3
- * Feb 1998, Version 1.4
- * Aug 1998, Version 1.5
- * Sep 1998, Version 1.6
- * Nov 1998, Version 1.7
- * Jan 1999, Version 1.8
- * Jan 1999, Version 1.9
- * Oct 1999, Version 1.10
- * Nov 1999, Version 1.11
- * Jan 2000, Version 1.12
- * Feb 2000, Version 1.13
- * Nov 2000, Version 1.14
- * Oct 2001, Version 1.15
- * Jan 2002, Version 1.16
- * Oct 2002, Version 1.16ac
- *
- * History:
- *    0.6b: first version in official kernel, Linux 1.3.46
- *    0.7: changed /proc/apm format, Linux 1.3.58
- *    0.8: fixed gcc 2.7.[12] compilation problems, Linux 1.3.59
- *    0.9: only call bios if bios is present, Linux 1.3.72
- *    1.0: use fixed device number, consolidate /proc/apm into this file,
- *         Linux 1.3.85
- *    1.1: support user-space standby and suspend, power off after system
- *         halted, Linux 1.3.98
- *    1.2: When resetting RTC after resume, take care so that the time
- *         is only incorrect by 30-60mS (vs. 1S previously) (Gabor J. Toth
- *         <jtoth@princeton.edu>); improve interaction between
- *         screen-blanking and gpm (Stephen Rothwell); Linux 1.99.4
- *    1.2a:Simple change to stop mysterious bug reports with SMP also added
- *	   levels to the printk calls. APM is not defined for SMP machines.
- *         The new replacement 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
- *         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
- *         across BIOS call).
- *         Stephen Rothwell
- *    1.6: Cope with complier/assembler differences.
- *         Only try to turn off the first display device.
- *         Fix OOPS at power off with no APM BIOS by Jan Echternach
- *                   <echter@informatik.uni-rostock.de>
- *         Stephen Rothwell
- *    1.7: Modify driver's cached copy of the disabled/disengaged flags
- *         to reflect current state of APM BIOS.
- *         Chris Rankin <rankinc@bellsouth.net>
- *         Reset interrupt 0 timer to 100Hz after suspend
- *         Chad Miller <cmiller@surfsouth.com>
- *         Add CONFIG_APM_IGNORE_SUSPEND_BOUNCE
- *         Richard Gooch <rgooch@atnf.csiro.au>
- *         Allow boot time disabling of APM
- *         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
- *    1.9: Fix small typo.  <laslo@wodip.opole.pl>
- *         Try to cope with BIOS's that need to have all display
- *         devices blanked and not just the first one.
- *         Ross Paterson <ross@soi.city.ac.uk>
- *         Fix segment limit setting it has always been wrong as
- *         the segments needed to have byte granularity.
- *         Mark a few things __init.
- *         Add hack to allow power off of SMP systems by popular request.
- *         Use CONFIG_SMP instead of __SMP__
- *         Ignore BOUNCES for three seconds.
- *         Stephen Rothwell
- *   1.10: Fix for Thinkpad return code.
- *         Merge 2.2 and 2.3 drivers.
- *         Remove APM dependencies in arch/i386/kernel/process.c
- *         Remove APM dependencies in drivers/char/sysrq.c
- *         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.
- *   1.11: Remove APM dependencies in drivers/char/console.c
- *         Check nr_running to detect if we are idle (from
- *         Borislav Deianov <borislav@lix.polytechnique.fr>)
- *         Fix for bioses that don't zero the top part of the
- *         entrypoint offset (Mario Sitta <sitta@al.unipmn.it>)
- *         (reported by Panos Katsaloulis <teras@writeme.com>).
- *         Real mode power off patch (Walter Hofmann
- *         <Walter.Hofmann@physik.stud.uni-erlangen.de>).
- *   1.12: Remove CONFIG_SMP as the compiler will optimize
- *         the code away anyway (smp_num_cpus == 1 in UP)
- *         noted by Artur Skawina <skawina@geocities.com>.
- *         Make power off under SMP work again.
- *         Fix thinko with initial engaging of BIOS.
- *         Make sure power off only happens on CPU 0
- *         (Paul "Rusty" Russell <rusty@rustcorp.com.au>).
- *         Do error notification to user mode if BIOS calls fail.
- *         Move entrypoint offset fix to ...boot/setup.S
- *         where it belongs (Cosmos <gis88564@cis.nctu.edu.tw>).
- *         Remove smp-power-off. SMP users must now specify
- *         "apm=power-off" on the kernel command line. Suggested
- *         by Jim Avera <jima@hal.com>, modified by Alan Cox
- *         <alan@lxorguk.ukuu.org.uk>.
- *         Register the /proc/apm entry even on SMP so that
- *         scripts that check for it before doing power off
- *         work (Jim Avera <jima@hal.com>).
- *   1.13: Changes for new pm_ interfaces (Andy Henroid
- *         <andy_henroid@yahoo.com>).
- *         Modularize the code.
- *         Fix the Thinkpad (again) :-( (CONFIG_APM_IGNORE_MULTIPLE_SUSPENDS
- *         is now the way life works).
- *         Fix thinko in suspend() (wrong return).
- *         Notify drivers on critical suspend.
- *         Make kapmd absorb more idle time (Pavel Machek <pavel@ucw.cz>
- *         modified by sfr).
- *         Disable interrupts while we are suspended (Andy Henroid
- *         <andy_henroid@yahoo.com> fixed by sfr).
- *         Make power off work on SMP again (Tony Hoyle
- *         <tmh@magenta-logic.com> and <zlatko@iskon.hr>) modified by sfr.
- *         Remove CONFIG_APM_SUSPEND_BOUNCE.  The bounce ignore
- *         interval is now configurable.
- *   1.14: Make connection version persist across module unload/load.
- *         Enable and engage power management earlier.
- *         Disengage power management on module unload.
- *         Changed to use the sysrq-register hack for registering the
- *         power off function called by magic sysrq based upon discussions
- *         in irc://irc.openprojects.net/#kernelnewbies
- *         (Crutcher Dunnavant <crutcher+kernel@datastacks.com>).
- *         Make CONFIG_APM_REAL_MODE_POWER_OFF run time configurable.
- *         (Arjan van de Ven <arjanv@redhat.com>) modified by sfr.
- *         Work around byte swap bug in one of the Vaio's BIOS's
- *         (Marc Boucher <marc@mbsi.ca>).
- *         Exposed the disable flag to dmi so that we can handle known
- *         broken APM (Alan Cox <alan@lxorguk.ukuu.org.uk>).
- *   1.14ac: If the BIOS says "I slowed the CPU down" then don't spin
- *         calling it - instead idle. (Alan Cox <alan@lxorguk.ukuu.org.uk>)
- *         If an APM idle fails log it and idle sensibly
- *   1.15: Don't queue events to clients who open the device O_WRONLY.
- *         Don't expect replies from clients who open the device O_RDONLY.
- *         (Idea from Thomas Hood)
- *         Minor waitqueue cleanups. (John Fremlin <chief@bandits.org>)
- *   1.16: Fix idle calling. (Andreas Steinmetz <ast@domdv.de> et al.)
- *         Notify listeners of standby or suspend events before notifying
- *         drivers. Return EBUSY to ioctl() if suspend is rejected.
- *         (Russell King <rmk@arm.linux.org.uk> and Thomas Hood)
- *         Ignore first resume after we generate our own resume event
- *         after a suspend (Thomas Hood)
- *         Daemonize now gets rid of our controlling terminal (sfr).
- *         CONFIG_APM_CPU_IDLE now just affects the default value of
- *         idle_threshold (sfr).
- *         Change name of kernel apm daemon (as it no longer idles) (sfr).
- *   1.16ac: Fix up SMP support somewhat. You can now force SMP on and we
- *	   make _all_ APM calls on the CPU#0. Fix unsafe sign bug.
- *	   TODO: determine if its "boot CPU" or "CPU0" we want to lock to.
- *
- * APM 1.1 Reference:
- *
- *   Intel Corporation, Microsoft Corporation. Advanced Power Management
- *   (APM) BIOS Interface Specification, Revision 1.1, September 1993.
- *   Intel Order Number 241704-001.  Microsoft Part Number 781-110-X01.
- *
- * [This document is available free from Intel by calling 800.628.8686 (fax
- * 916.356.6100) or 800.548.4725; or from
- * http://www.microsoft.com/whdc/archive/amp_12.mspx  It is also
- * available from Microsoft by calling 206.882.8080.]
- *
- * APM 1.2 Reference:
- *   Intel Corporation, Microsoft Corporation. Advanced Power Management
- *   (APM) BIOS Interface Specification, Revision 1.2, February 1996.
- *
- * [This document is available from Microsoft at:
- *    http://www.microsoft.com/whdc/archive/amp_12.mspx]
- */
-
-#include <linux/module.h>
-
-#include <linux/poll.h>
-#include <linux/types.h>
-#include <linux/stddef.h>
-#include <linux/timer.h>
-#include <linux/fcntl.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/miscdevice.h>
-#include <linux/apm_bios.h>
-#include <linux/init.h>
-#include <linux/time.h>
-#include <linux/sched.h>
-#include <linux/pm.h>
-#include <linux/capability.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/freezer.h>
-#include <linux/smp.h>
-#include <linux/dmi.h>
-#include <linux/suspend.h>
-#include <linux/kthread.h>
-#include <linux/jiffies.h>
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/desc.h>
-#include <asm/i8253.h>
-#include <asm/olpc.h>
-#include <asm/paravirt.h>
-#include <asm/reboot.h>
-
-#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
-extern int (*console_blank_hook)(int);
-#endif
-
-/*
- * The apm_bios device is one of the misc char devices.
- * This is its minor number.
- */
-#define	APM_MINOR_DEV	134
-
-/*
- * 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-]allow[-_]ints		allow interrupts during BIOS calls
- *	    [no-]broken[-_]psr		BIOS has a broken GetPowerStatus call
- *	    [no-]realmode[-_]power[-_]off	switch to real mode before
- *	    					powering off
- *	    [no-]debug			log some debugging messages
- *	    [no-]power[-_]off		power off on shutdown
- *	    [no-]smp			Use apm even on an SMP box
- *	    bounce[-_]interval=<n>	number of ticks to ignore suspend
- *	    				bounces
- *          idle[-_]threshold=<n>       System idle percentage above which to
- *                                      make APM BIOS idle calls. Set it to
- *                                      100 to disable.
- *          idle[-_]period=<n>          Period (in 1/100s of a second) over
- *                                      which the idle percentage is
- *                                      calculated.
- */
-
-/* KNOWN PROBLEM MACHINES:
- *
- * U: TI 4000M TravelMate: BIOS is *NOT* APM compliant
- *                         [Confirmed by TI representative]
- * ?: ACER 486DX4/75: uses dseg 0040, in violation of APM specification
- *                    [Confirmed by BIOS disassembly]
- *                    [This may work now ...]
- * P: Toshiba 1950S: battery life information only gets updated after resume
- * P: Midwest Micro Soundbook Elite DX2/66 monochrome: screen blanking
- * 	broken in BIOS [Reported by Garst R. Reese <reese@isn.net>]
- * ?: AcerNote-950: oops on reading /proc/apm - workaround is a WIP
- * 	Neale Banks <neale@lowendale.com.au> December 2000
- *
- * Legend: U = unusable with APM patches
- *         P = partially usable with APM patches
- */
-
-/*
- * Define as 1 to make the driver always call the APM BIOS busy
- * routine even if the clock was not reported as slowed by the
- * idle routine.  Otherwise, define as 0.
- */
-#define ALWAYS_CALL_BUSY   1
-
-/*
- * 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).
- */
-#define APM_ZERO_SEGS
-
-#include <asm/apm.h>
-
-/*
- * Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend.
- * This patched by Chad Miller <cmiller@surfsouth.com>, original code by
- * David Chen <chen@ctpa04.mit.edu>
- */
-#undef INIT_TIMER_AFTER_SUSPEND
-
-#ifdef INIT_TIMER_AFTER_SUSPEND
-#include <linux/timex.h>
-#include <asm/io.h>
-#include <linux/delay.h>
-#endif
-
-/*
- * Need to poll the APM BIOS every second
- */
-#define APM_CHECK_TIMEOUT	(HZ)
-
-/*
- * Ignore suspend events for this amount of time after a resume
- */
-#define DEFAULT_BOUNCE_INTERVAL	(3 * HZ)
-
-/*
- * Maximum number of events stored
- */
-#define APM_MAX_EVENTS		20
-
-/*
- * The per-file APM data
- */
-struct apm_user {
-	int		magic;
-	struct apm_user *next;
-	unsigned int	suser: 1;
-	unsigned int	writer: 1;
-	unsigned int	reader: 1;
-	unsigned int	suspend_wait: 1;
-	int		suspend_result;
-	int		suspends_pending;
-	int		standbys_pending;
-	int		suspends_read;
-	int		standbys_read;
-	int		event_head;
-	int		event_tail;
-	apm_event_t	events[APM_MAX_EVENTS];
-};
-
-/*
- * The magic number in apm_user
- */
-#define APM_BIOS_MAGIC		0x4101
-
-/*
- * idle percentage above which bios idle calls are done
- */
-#ifdef CONFIG_APM_CPU_IDLE
-#define DEFAULT_IDLE_THRESHOLD	95
-#else
-#define DEFAULT_IDLE_THRESHOLD	100
-#endif
-#define DEFAULT_IDLE_PERIOD	(100 / 3)
-
-/*
- * Local variables
- */
-static struct {
-	unsigned long	offset;
-	unsigned short	segment;
-} apm_bios_entry;
-static int clock_slowed;
-static int idle_threshold __read_mostly = DEFAULT_IDLE_THRESHOLD;
-static int idle_period __read_mostly = DEFAULT_IDLE_PERIOD;
-static int set_pm_idle;
-static int suspends_pending;
-static int standbys_pending;
-static int ignore_sys_suspend;
-static int ignore_normal_resume;
-static int bounce_interval __read_mostly = DEFAULT_BOUNCE_INTERVAL;
-
-static int debug __read_mostly;
-static int smp __read_mostly;
-static int apm_disabled = -1;
-#ifdef CONFIG_SMP
-static int power_off;
-#else
-static int power_off = 1;
-#endif
-static int realmode_power_off;
-#ifdef CONFIG_APM_ALLOW_INTS
-static int allow_ints = 1;
-#else
-static int allow_ints;
-#endif
-static int broken_psr;
-
-static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
-static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
-static struct apm_user *user_list;
-static DEFINE_SPINLOCK(user_list_lock);
-static DEFINE_MUTEX(apm_mutex);
-
-/*
- * Set up a segment that references the real mode segment 0x40
- * that extends up to the end of page zero (that we have reserved).
- * This is for buggy BIOS's that refer to (real mode) segment 0x40
- * even though they are called in protected mode.
- */
-static struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4092,
-			(unsigned long)__va(0x400UL), PAGE_SIZE - 0x400 - 1);
-
-static const char driver_version[] = "1.16ac";	/* no spaces */
-
-static struct task_struct *kapmd_task;
-
-/*
- *	APM event names taken from the APM 1.2 specification. These are
- *	the message codes that the BIOS uses to tell us about events
- */
-static const char * const apm_event_name[] = {
-	"system standby",
-	"system suspend",
-	"normal resume",
-	"critical resume",
-	"low battery",
-	"power status change",
-	"update time",
-	"critical suspend",
-	"user standby",
-	"user suspend",
-	"system standby resume",
-	"capabilities change"
-};
-#define NR_APM_EVENT_NAME ARRAY_SIZE(apm_event_name)
-
-typedef struct lookup_t {
-	int	key;
-	char 	*msg;
-} lookup_t;
-
-/*
- *	The BIOS returns a set of standard error codes in AX when the
- *	carry flag is set.
- */
-
-static const lookup_t error_table[] = {
-/* N/A	{ APM_SUCCESS,		"Operation succeeded" }, */
-	{ APM_DISABLED,		"Power management disabled" },
-	{ APM_CONNECTED,	"Real mode interface already connected" },
-	{ APM_NOT_CONNECTED,	"Interface not connected" },
-	{ APM_16_CONNECTED,	"16 bit interface already connected" },
-/* N/A	{ APM_16_UNSUPPORTED,	"16 bit interface not supported" }, */
-	{ APM_32_CONNECTED,	"32 bit interface already connected" },
-	{ APM_32_UNSUPPORTED,	"32 bit interface not supported" },
-	{ APM_BAD_DEVICE,	"Unrecognized device ID" },
-	{ APM_BAD_PARAM,	"Parameter out of range" },
-	{ APM_NOT_ENGAGED,	"Interface not engaged" },
-	{ APM_BAD_FUNCTION,     "Function not supported" },
-	{ APM_RESUME_DISABLED,	"Resume timer disabled" },
-	{ APM_BAD_STATE,	"Unable to enter requested state" },
-/* N/A	{ APM_NO_EVENTS,	"No events pending" }, */
-	{ APM_NO_ERROR,		"BIOS did not set a return code" },
-	{ APM_NOT_PRESENT,	"No APM present" }
-};
-#define ERROR_COUNT	ARRAY_SIZE(error_table)
-
-/**
- *	apm_error	-	display an APM error
- *	@str: information string
- *	@err: APM BIOS return code
- *
- *	Write a meaningful log entry to the kernel log in the event of
- *	an APM error.  Note that this also handles (negative) kernel errors.
- */
-
-static void apm_error(char *str, int err)
-{
-	int i;
-
-	for (i = 0; i < ERROR_COUNT; i++)
-		if (error_table[i].key == err)
-			break;
-	if (i < ERROR_COUNT)
-		printk(KERN_NOTICE "apm: %s: %s\n", str, error_table[i].msg);
-	else if (err < 0)
-		printk(KERN_NOTICE "apm: %s: linux error code %i\n", str, err);
-	else
-		printk(KERN_NOTICE "apm: %s: unknown error code %#2.2x\n",
-		       str, err);
-}
-
-/*
- * These are the actual BIOS calls.  Depending on APM_ZERO_SEGS and
- * apm_info.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.
- */
-
-static inline unsigned long __apm_irq_save(void)
-{
-	unsigned long flags;
-	local_save_flags(flags);
-	if (apm_info.allow_ints) {
-		if (irqs_disabled_flags(flags))
-			local_irq_enable();
-	} else
-		local_irq_disable();
-
-	return flags;
-}
-
-#define apm_irq_save(flags) \
-	do { flags = __apm_irq_save(); } while (0)
-
-static inline void apm_irq_restore(unsigned long flags)
-{
-	if (irqs_disabled_flags(flags))
-		local_irq_disable();
-	else if (irqs_disabled())
-		local_irq_enable();
-}
-
-#ifdef APM_ZERO_SEGS
-#	define APM_DECL_SEGS \
-		unsigned int saved_fs; unsigned int saved_gs;
-#	define APM_DO_SAVE_SEGS \
-		savesegment(fs, saved_fs); savesegment(gs, saved_gs)
-#	define APM_DO_RESTORE_SEGS \
-		loadsegment(fs, saved_fs); loadsegment(gs, saved_gs)
-#else
-#	define APM_DECL_SEGS
-#	define APM_DO_SAVE_SEGS
-#	define APM_DO_RESTORE_SEGS
-#endif
-
-struct apm_bios_call {
-	u32 func;
-	/* In and out */
-	u32 ebx;
-	u32 ecx;
-	/* Out only */
-	u32 eax;
-	u32 edx;
-	u32 esi;
-
-	/* Error: -ENOMEM, or bits 8-15 of eax */
-	int err;
-};
-
-/**
- *	__apm_bios_call - Make an APM BIOS 32bit call
- *	@_call: pointer to struct apm_bios_call.
- *
- *	Make an APM call using the 32bit protected mode interface. The
- *	caller is responsible for knowing if APM BIOS is configured and
- *	enabled. This call can disable interrupts for a long period of
- *	time on some laptops.  The return value is in AH and the carry
- *	flag is loaded into AL.  If there is an error, then the error
- *	code is returned in AH (bits 8-15 of eax) and this function
- *	returns non-zero.
- *
- *	Note: this makes the call on the current CPU.
- */
-static long __apm_bios_call(void *_call)
-{
-	APM_DECL_SEGS
-	unsigned long		flags;
-	int			cpu;
-	struct desc_struct	save_desc_40;
-	struct desc_struct	*gdt;
-	struct apm_bios_call	*call = _call;
-
-	cpu = get_cpu();
-	BUG_ON(cpu != 0);
-	gdt = get_cpu_gdt_table(cpu);
-	save_desc_40 = gdt[0x40 / 8];
-	gdt[0x40 / 8] = bad_bios_desc;
-
-	apm_irq_save(flags);
-	APM_DO_SAVE_SEGS;
-	apm_bios_call_asm(call->func, call->ebx, call->ecx,
-			  &call->eax, &call->ebx, &call->ecx, &call->edx,
-			  &call->esi);
-	APM_DO_RESTORE_SEGS;
-	apm_irq_restore(flags);
-	gdt[0x40 / 8] = save_desc_40;
-	put_cpu();
-
-	return call->eax & 0xff;
-}
-
-/* Run __apm_bios_call or __apm_bios_call_simple on CPU 0 */
-static int on_cpu0(long (*fn)(void *), struct apm_bios_call *call)
-{
-	int ret;
-
-	/* Don't bother with work_on_cpu in the common case, so we don't
-	 * have to worry about OOM or overhead. */
-	if (get_cpu() == 0) {
-		ret = fn(call);
-		put_cpu();
-	} else {
-		put_cpu();
-		ret = work_on_cpu(0, fn, call);
-	}
-
-	/* work_on_cpu can fail with -ENOMEM */
-	if (ret < 0)
-		call->err = ret;
-	else
-		call->err = (call->eax >> 8) & 0xff;
-
-	return ret;
-}
-
-/**
- *	apm_bios_call	-	Make an APM BIOS 32bit call (on CPU 0)
- *	@call: the apm_bios_call registers.
- *
- *	If there is an error, it is returned in @call.err.
- */
-static int apm_bios_call(struct apm_bios_call *call)
-{
-	return on_cpu0(__apm_bios_call, call);
-}
-
-/**
- *	__apm_bios_call_simple - Make an APM BIOS 32bit call (on CPU 0)
- *	@_call: pointer to struct apm_bios_call.
- *
- *	Make a BIOS call that returns one value only, or just status.
- *	If there is an error, then the error code is returned in AH
- *	(bits 8-15 of eax) and this function returns non-zero (it can
- *	also return -ENOMEM). This is used for simpler BIOS operations.
- *	This call may hold interrupts off for a long time on some laptops.
- *
- *	Note: this makes the call on the current CPU.
- */
-static long __apm_bios_call_simple(void *_call)
-{
-	u8			error;
-	APM_DECL_SEGS
-	unsigned long		flags;
-	int			cpu;
-	struct desc_struct	save_desc_40;
-	struct desc_struct	*gdt;
-	struct apm_bios_call	*call = _call;
-
-	cpu = get_cpu();
-	BUG_ON(cpu != 0);
-	gdt = get_cpu_gdt_table(cpu);
-	save_desc_40 = gdt[0x40 / 8];
-	gdt[0x40 / 8] = bad_bios_desc;
-
-	apm_irq_save(flags);
-	APM_DO_SAVE_SEGS;
-	error = apm_bios_call_simple_asm(call->func, call->ebx, call->ecx,
-					 &call->eax);
-	APM_DO_RESTORE_SEGS;
-	apm_irq_restore(flags);
-	gdt[0x40 / 8] = save_desc_40;
-	put_cpu();
-	return error;
-}
-
-/**
- *	apm_bios_call_simple	-	make a simple APM BIOS 32bit call
- *	@func: APM function to invoke
- *	@ebx_in: EBX register value for BIOS call
- *	@ecx_in: ECX register value for BIOS call
- *	@eax: EAX register on return from the BIOS call
- *	@err: bits
- *
- *	Make a BIOS call that returns one value only, or just status.
- *	If there is an error, then the error code is returned in @err
- *	and this function returns non-zero. This is used for simpler
- *	BIOS operations.  This call may hold interrupts off for a long
- *	time on some laptops.
- */
-static int apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax,
-				int *err)
-{
-	struct apm_bios_call call;
-	int ret;
-
-	call.func = func;
-	call.ebx = ebx_in;
-	call.ecx = ecx_in;
-
-	ret = on_cpu0(__apm_bios_call_simple, &call);
-	*eax = call.eax;
-	*err = call.err;
-	return ret;
-}
-
-/**
- *	apm_driver_version	-	APM driver version
- *	@val:	loaded with the APM version on return
- *
- *	Retrieve the APM version supported by the BIOS. This is only
- *	supported for APM 1.1 or higher. An error indicates APM 1.0 is
- *	probably present.
- *
- *	On entry val should point to a value indicating the APM driver
- *	version with the high byte being the major and the low byte the
- *	minor number both in BCD
- *
- *	On return it will hold the BIOS revision supported in the
- *	same format.
- */
-
-static int apm_driver_version(u_short *val)
-{
-	u32 eax;
-	int err;
-
-	if (apm_bios_call_simple(APM_FUNC_VERSION, 0, *val, &eax, &err))
-		return err;
-	*val = eax;
-	return APM_SUCCESS;
-}
-
-/**
- *	apm_get_event	-	get an APM event from the BIOS
- *	@event: pointer to the event
- *	@info: point to the event information
- *
- *	The APM BIOS provides a polled information for event
- *	reporting. The BIOS expects to be polled at least every second
- *	when events are pending. When a message is found the caller should
- *	poll until no more messages are present.  However, this causes
- *	problems on some laptops where a suspend event notification is
- *	not cleared until it is acknowledged.
- *
- *	Additional information is returned in the info pointer, providing
- *	that APM 1.2 is in use. If no messges are pending the value 0x80
- *	is returned (No power management events pending).
- */
-static int apm_get_event(apm_event_t *event, apm_eventinfo_t *info)
-{
-	struct apm_bios_call call;
-
-	call.func = APM_FUNC_GET_EVENT;
-	call.ebx = call.ecx = 0;
-
-	if (apm_bios_call(&call))
-		return call.err;
-
-	*event = call.ebx;
-	if (apm_info.connection_version < 0x0102)
-		*info = ~0; /* indicate info not valid */
-	else
-		*info = call.ecx;
-	return APM_SUCCESS;
-}
-
-/**
- *	set_power_state	-	set the power management state
- *	@what: which items to transition
- *	@state: state to transition to
- *
- *	Request an APM change of state for one or more system devices. The
- *	processor state must be transitioned last of all. what holds the
- *	class of device in the upper byte and the device number (0xFF for
- *	all) for the object to be transitioned.
- *
- *	The state holds the state to transition to, which may in fact
- *	be an acceptance of a BIOS requested state change.
- */
-
-static int set_power_state(u_short what, u_short state)
-{
-	u32 eax;
-	int err;
-
-	if (apm_bios_call_simple(APM_FUNC_SET_STATE, what, state, &eax, &err))
-		return err;
-	return APM_SUCCESS;
-}
-
-/**
- *	set_system_power_state - set system wide power state
- *	@state: which state to enter
- *
- *	Transition the entire system into a new APM power state.
- */
-
-static int set_system_power_state(u_short state)
-{
-	return set_power_state(APM_DEVICE_ALL, state);
-}
-
-/**
- *	apm_do_idle	-	perform power saving
- *
- *	This function notifies the BIOS that the processor is (in the view
- *	of the OS) idle. It returns -1 in the event that the BIOS refuses
- *	to handle the idle request. On a success the function returns 1
- *	if the BIOS did clock slowing or 0 otherwise.
- */
-
-static int apm_do_idle(void)
-{
-	u32 eax;
-	u8 ret = 0;
-	int idled = 0;
-	int polling;
-	int err = 0;
-
-	polling = !!(current_thread_info()->status & TS_POLLING);
-	if (polling) {
-		current_thread_info()->status &= ~TS_POLLING;
-		/*
-		 * TS_POLLING-cleared state must be visible before we
-		 * test NEED_RESCHED:
-		 */
-		smp_mb();
-	}
-	if (!need_resched()) {
-		idled = 1;
-		ret = apm_bios_call_simple(APM_FUNC_IDLE, 0, 0, &eax, &err);
-	}
-	if (polling)
-		current_thread_info()->status |= TS_POLLING;
-
-	if (!idled)
-		return 0;
-
-	if (ret) {
-		static unsigned long t;
-
-		/* This always fails on some SMP boards running UP kernels.
-		 * Only report the failure the first 5 times.
-		 */
-		if (++t < 5) {
-			printk(KERN_DEBUG "apm_do_idle failed (%d)\n", err);
-			t = jiffies;
-		}
-		return -1;
-	}
-	clock_slowed = (apm_info.bios.flags & APM_IDLE_SLOWS_CLOCK) != 0;
-	return clock_slowed;
-}
-
-/**
- *	apm_do_busy	-	inform the BIOS the CPU is busy
- *
- *	Request that the BIOS brings the CPU back to full performance.
- */
-
-static void apm_do_busy(void)
-{
-	u32 dummy;
-	int err;
-
-	if (clock_slowed || ALWAYS_CALL_BUSY) {
-		(void)apm_bios_call_simple(APM_FUNC_BUSY, 0, 0, &dummy, &err);
-		clock_slowed = 0;
-	}
-}
-
-/*
- * If no process has really been interested in
- * the CPU for some time, we want to call BIOS
- * power management - we probably want
- * to conserve power.
- */
-#define IDLE_CALC_LIMIT	(HZ * 100)
-#define IDLE_LEAKY_MAX	16
-
-static void (*original_pm_idle)(void) __read_mostly;
-
-/**
- * apm_cpu_idle		-	cpu idling for APM capable Linux
- *
- * This is the idling function the kernel executes when APM is available. It
- * tries to do BIOS powermanagement based on the average system idle time.
- * Furthermore it calls the system default idle routine.
- */
-
-static void apm_cpu_idle(void)
-{
-	static int use_apm_idle; /* = 0 */
-	static unsigned int last_jiffies; /* = 0 */
-	static unsigned int last_stime; /* = 0 */
-
-	int apm_idle_done = 0;
-	unsigned int jiffies_since_last_check = jiffies - last_jiffies;
-	unsigned int bucket;
-
-recalc:
-	if (jiffies_since_last_check > IDLE_CALC_LIMIT) {
-		use_apm_idle = 0;
-		last_jiffies = jiffies;
-		last_stime = current->stime;
-	} else if (jiffies_since_last_check > idle_period) {
-		unsigned int idle_percentage;
-
-		idle_percentage = current->stime - last_stime;
-		idle_percentage *= 100;
-		idle_percentage /= jiffies_since_last_check;
-		use_apm_idle = (idle_percentage > idle_threshold);
-		if (apm_info.forbid_idle)
-			use_apm_idle = 0;
-		last_jiffies = jiffies;
-		last_stime = current->stime;
-	}
-
-	bucket = IDLE_LEAKY_MAX;
-
-	while (!need_resched()) {
-		if (use_apm_idle) {
-			unsigned int t;
-
-			t = jiffies;
-			switch (apm_do_idle()) {
-			case 0:
-				apm_idle_done = 1;
-				if (t != jiffies) {
-					if (bucket) {
-						bucket = IDLE_LEAKY_MAX;
-						continue;
-					}
-				} else if (bucket) {
-					bucket--;
-					continue;
-				}
-				break;
-			case 1:
-				apm_idle_done = 1;
-				break;
-			default: /* BIOS refused */
-				break;
-			}
-		}
-		if (original_pm_idle)
-			original_pm_idle();
-		else
-			default_idle();
-		local_irq_disable();
-		jiffies_since_last_check = jiffies - last_jiffies;
-		if (jiffies_since_last_check > idle_period)
-			goto recalc;
-	}
-
-	if (apm_idle_done)
-		apm_do_busy();
-
-	local_irq_enable();
-}
-
-/**
- *	apm_power_off	-	ask the BIOS to power off
- *
- *	Handle the power off sequence. This is the one piece of code we
- *	will execute even on SMP machines. In order to deal with BIOS
- *	bugs we support real mode APM BIOS power off calls. We also make
- *	the SMP call on CPU0 as some systems will only honour this call
- *	on their first cpu.
- */
-
-static void apm_power_off(void)
-{
-	unsigned char po_bios_call[] = {
-		0xb8, 0x00, 0x10,	/* movw  $0x1000,ax  */
-		0x8e, 0xd0,		/* movw  ax,ss       */
-		0xbc, 0x00, 0xf0,	/* movw  $0xf000,sp  */
-		0xb8, 0x07, 0x53,	/* movw  $0x5307,ax  */
-		0xbb, 0x01, 0x00,	/* movw  $0x0001,bx  */
-		0xb9, 0x03, 0x00,	/* movw  $0x0003,cx  */
-		0xcd, 0x15		/* int   $0x15       */
-	};
-
-	/* Some bioses don't like being called from CPU != 0 */
-	if (apm_info.realmode_power_off) {
-		set_cpus_allowed_ptr(current, cpumask_of(0));
-		machine_real_restart(po_bios_call, sizeof(po_bios_call));
-	} else {
-		(void)set_system_power_state(APM_STATE_OFF);
-	}
-}
-
-#ifdef CONFIG_APM_DO_ENABLE
-
-/**
- *	apm_enable_power_management - enable BIOS APM power management
- *	@enable: enable yes/no
- *
- *	Enable or disable the APM BIOS power services.
- */
-
-static int apm_enable_power_management(int enable)
-{
-	u32 eax;
-	int err;
-
-	if ((enable == 0) && (apm_info.bios.flags & APM_BIOS_DISENGAGED))
-		return APM_NOT_ENGAGED;
-	if (apm_bios_call_simple(APM_FUNC_ENABLE_PM, APM_DEVICE_BALL,
-				 enable, &eax, &err))
-		return err;
-	if (enable)
-		apm_info.bios.flags &= ~APM_BIOS_DISABLED;
-	else
-		apm_info.bios.flags |= APM_BIOS_DISABLED;
-	return APM_SUCCESS;
-}
-#endif
-
-/**
- *	apm_get_power_status	-	get current power state
- *	@status: returned status
- *	@bat: battery info
- *	@life: estimated life
- *
- *	Obtain the current power status from the APM BIOS. We return a
- *	status which gives the rough battery status, and current power
- *	source. The bat value returned give an estimate as a percentage
- *	of life and a status value for the battery. The estimated life
- *	if reported is a lifetime in secodnds/minutes at current powwer
- *	consumption.
- */
-
-static int apm_get_power_status(u_short *status, u_short *bat, u_short *life)
-{
-	struct apm_bios_call call;
-
-	call.func = APM_FUNC_GET_STATUS;
-	call.ebx = APM_DEVICE_ALL;
-	call.ecx = 0;
-
-	if (apm_info.get_power_status_broken)
-		return APM_32_UNSUPPORTED;
-	if (apm_bios_call(&call))
-		return call.err;
-	*status = call.ebx;
-	*bat = call.ecx;
-	if (apm_info.get_power_status_swabinminutes) {
-		*life = swab16((u16)call.edx);
-		*life |= 0x8000;
-	} else
-		*life = call.edx;
-	return APM_SUCCESS;
-}
-
-#if 0
-static int apm_get_battery_status(u_short which, u_short *status,
-				  u_short *bat, u_short *life, u_short *nbat)
-{
-	u32 eax;
-	u32 ebx;
-	u32 ecx;
-	u32 edx;
-	u32 esi;
-
-	if (apm_info.connection_version < 0x0102) {
-		/* pretend we only have one battery. */
-		if (which != 1)
-			return APM_BAD_DEVICE;
-		*nbat = 1;
-		return apm_get_power_status(status, bat, life);
-	}
-
-	if (apm_bios_call(APM_FUNC_GET_STATUS, (0x8000 | (which)), 0, &eax,
-			  &ebx, &ecx, &edx, &esi))
-		return (eax >> 8) & 0xff;
-	*status = ebx;
-	*bat = ecx;
-	*life = edx;
-	*nbat = esi;
-	return APM_SUCCESS;
-}
-#endif
-
-/**
- *	apm_engage_power_management	-	enable PM on a device
- *	@device: identity of device
- *	@enable: on/off
- *
- *	Activate or deactive power management on either a specific device
- *	or the entire system (%APM_DEVICE_ALL).
- */
-
-static int apm_engage_power_management(u_short device, int enable)
-{
-	u32 eax;
-	int err;
-
-	if ((enable == 0) && (device == APM_DEVICE_ALL)
-	    && (apm_info.bios.flags & APM_BIOS_DISABLED))
-		return APM_DISABLED;
-	if (apm_bios_call_simple(APM_FUNC_ENGAGE_PM, device, enable,
-				 &eax, &err))
-		return err;
-	if (device == APM_DEVICE_ALL) {
-		if (enable)
-			apm_info.bios.flags &= ~APM_BIOS_DISENGAGED;
-		else
-			apm_info.bios.flags |= APM_BIOS_DISENGAGED;
-	}
-	return APM_SUCCESS;
-}
-
-#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
-
-/**
- *	apm_console_blank	-	blank the display
- *	@blank: on/off
- *
- *	Attempt to blank the console, firstly by blanking just video device
- *	zero, and if that fails (some BIOSes don't support it) then it blanks
- *	all video devices. Typically the BIOS will do laptop backlight and
- *	monitor powerdown for us.
- */
-
-static int apm_console_blank(int blank)
-{
-	int error = APM_NOT_ENGAGED; /* silence gcc */
-	int i;
-	u_short state;
-	static const u_short dev[3] = { 0x100, 0x1FF, 0x101 };
-
-	state = blank ? APM_STATE_STANDBY : APM_STATE_READY;
-
-	for (i = 0; i < ARRAY_SIZE(dev); i++) {
-		error = set_power_state(dev[i], state);
-
-		if ((error == APM_SUCCESS) || (error == APM_NO_ERROR))
-			return 1;
-
-		if (error == APM_NOT_ENGAGED)
-			break;
-	}
-
-	if (error == APM_NOT_ENGAGED) {
-		static int tried;
-		int eng_error;
-		if (tried++ == 0) {
-			eng_error = apm_engage_power_management(APM_DEVICE_ALL, 1);
-			if (eng_error) {
-				apm_error("set display", error);
-				apm_error("engage interface", eng_error);
-				return 0;
-			} else
-				return apm_console_blank(blank);
-		}
-	}
-	apm_error("set display", error);
-	return 0;
-}
-#endif
-
-static int queue_empty(struct apm_user *as)
-{
-	return as->event_head == as->event_tail;
-}
-
-static apm_event_t get_queued_event(struct apm_user *as)
-{
-	if (++as->event_tail >= APM_MAX_EVENTS)
-		as->event_tail = 0;
-	return as->events[as->event_tail];
-}
-
-static void queue_event(apm_event_t event, struct apm_user *sender)
-{
-	struct apm_user *as;
-
-	spin_lock(&user_list_lock);
-	if (user_list == NULL)
-		goto out;
-	for (as = user_list; as != NULL; as = as->next) {
-		if ((as == sender) || (!as->reader))
-			continue;
-		if (++as->event_head >= APM_MAX_EVENTS)
-			as->event_head = 0;
-
-		if (as->event_head == as->event_tail) {
-			static int notified;
-
-			if (notified++ == 0)
-			    printk(KERN_ERR "apm: an event queue overflowed\n");
-			if (++as->event_tail >= APM_MAX_EVENTS)
-				as->event_tail = 0;
-		}
-		as->events[as->event_head] = event;
-		if (!as->suser || !as->writer)
-			continue;
-		switch (event) {
-		case APM_SYS_SUSPEND:
-		case APM_USER_SUSPEND:
-			as->suspends_pending++;
-			suspends_pending++;
-			break;
-
-		case APM_SYS_STANDBY:
-		case APM_USER_STANDBY:
-			as->standbys_pending++;
-			standbys_pending++;
-			break;
-		}
-	}
-	wake_up_interruptible(&apm_waitqueue);
-out:
-	spin_unlock(&user_list_lock);
-}
-
-static void reinit_timer(void)
-{
-#ifdef INIT_TIMER_AFTER_SUSPEND
-	unsigned long flags;
-
-	raw_spin_lock_irqsave(&i8253_lock, flags);
-	/* set the clock to HZ */
-	outb_pit(0x34, PIT_MODE);		/* binary, mode 2, LSB/MSB, ch 0 */
-	udelay(10);
-	outb_pit(LATCH & 0xff, PIT_CH0);	/* LSB */
-	udelay(10);
-	outb_pit(LATCH >> 8, PIT_CH0);	/* MSB */
-	udelay(10);
-	raw_spin_unlock_irqrestore(&i8253_lock, flags);
-#endif
-}
-
-static int suspend(int vetoable)
-{
-	int err;
-	struct apm_user	*as;
-
-	dpm_suspend_start(PMSG_SUSPEND);
-
-	dpm_suspend_noirq(PMSG_SUSPEND);
-
-	local_irq_disable();
-	sysdev_suspend(PMSG_SUSPEND);
-
-	local_irq_enable();
-
-	save_processor_state();
-	err = set_system_power_state(APM_STATE_SUSPEND);
-	ignore_normal_resume = 1;
-	restore_processor_state();
-
-	local_irq_disable();
-	reinit_timer();
-
-	if (err == APM_NO_ERROR)
-		err = APM_SUCCESS;
-	if (err != APM_SUCCESS)
-		apm_error("suspend", err);
-	err = (err == APM_SUCCESS) ? 0 : -EIO;
-
-	sysdev_resume();
-	local_irq_enable();
-
-	dpm_resume_noirq(PMSG_RESUME);
-
-	dpm_resume_end(PMSG_RESUME);
-	queue_event(APM_NORMAL_RESUME, NULL);
-	spin_lock(&user_list_lock);
-	for (as = user_list; as != NULL; as = as->next) {
-		as->suspend_wait = 0;
-		as->suspend_result = err;
-	}
-	spin_unlock(&user_list_lock);
-	wake_up_interruptible(&apm_suspend_waitqueue);
-	return err;
-}
-
-static void standby(void)
-{
-	int err;
-
-	dpm_suspend_noirq(PMSG_SUSPEND);
-
-	local_irq_disable();
-	sysdev_suspend(PMSG_SUSPEND);
-	local_irq_enable();
-
-	err = set_system_power_state(APM_STATE_STANDBY);
-	if ((err != APM_SUCCESS) && (err != APM_NO_ERROR))
-		apm_error("standby", err);
-
-	local_irq_disable();
-	sysdev_resume();
-	local_irq_enable();
-
-	dpm_resume_noirq(PMSG_RESUME);
-}
-
-static apm_event_t get_event(void)
-{
-	int error;
-	apm_event_t event = APM_NO_EVENTS; /* silence gcc */
-	apm_eventinfo_t	info;
-
-	static int notified;
-
-	/* we don't use the eventinfo */
-	error = apm_get_event(&event, &info);
-	if (error == APM_SUCCESS)
-		return event;
-
-	if ((error != APM_NO_EVENTS) && (notified++ == 0))
-		apm_error("get_event", error);
-
-	return 0;
-}
-
-static void check_events(void)
-{
-	apm_event_t event;
-	static unsigned long last_resume;
-	static int ignore_bounce;
-
-	while ((event = get_event()) != 0) {
-		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);
-		}
-		if (ignore_bounce
-		    && (time_after(jiffies, last_resume + bounce_interval)))
-			ignore_bounce = 0;
-
-		switch (event) {
-		case APM_SYS_STANDBY:
-		case APM_USER_STANDBY:
-			queue_event(event, NULL);
-			if (standbys_pending <= 0)
-				standby();
-			break;
-
-		case APM_USER_SUSPEND:
-#ifdef CONFIG_APM_IGNORE_USER_SUSPEND
-			if (apm_info.connection_version > 0x100)
-				set_system_power_state(APM_STATE_REJECT);
-			break;
-#endif
-		case APM_SYS_SUSPEND:
-			if (ignore_bounce) {
-				if (apm_info.connection_version > 0x100)
-					set_system_power_state(APM_STATE_REJECT);
-				break;
-			}
-			/*
-			 * If we are already processing a SUSPEND,
-			 * then further SUSPEND events from the BIOS
-			 * will be ignored.  We also return here to
-			 * cope with the fact that the Thinkpads keep
-			 * sending a SUSPEND event until something else
-			 * happens!
-			 */
-			if (ignore_sys_suspend)
-				return;
-			ignore_sys_suspend = 1;
-			queue_event(event, NULL);
-			if (suspends_pending <= 0)
-				(void) suspend(1);
-			break;
-
-		case APM_NORMAL_RESUME:
-		case APM_CRITICAL_RESUME:
-		case APM_STANDBY_RESUME:
-			ignore_sys_suspend = 0;
-			last_resume = jiffies;
-			ignore_bounce = 1;
-			if ((event != APM_NORMAL_RESUME)
-			    || (ignore_normal_resume == 0)) {
-				dpm_resume_end(PMSG_RESUME);
-				queue_event(event, NULL);
-			}
-			ignore_normal_resume = 0;
-			break;
-
-		case APM_CAPABILITY_CHANGE:
-		case APM_LOW_BATTERY:
-		case APM_POWER_STATUS_CHANGE:
-			queue_event(event, NULL);
-			/* If needed, notify drivers here */
-			break;
-
-		case APM_UPDATE_TIME:
-			break;
-
-		case APM_CRITICAL_SUSPEND:
-			/*
-			 * We are not allowed to reject a critical suspend.
-			 */
-			(void)suspend(0);
-			break;
-		}
-	}
-}
-
-static void apm_event_handler(void)
-{
-	static int pending_count = 4;
-	int err;
-
-	if ((standbys_pending > 0) || (suspends_pending > 0)) {
-		if ((apm_info.connection_version > 0x100) &&
-		    (pending_count-- <= 0)) {
-			pending_count = 4;
-			if (debug)
-				printk(KERN_DEBUG "apm: setting state busy\n");
-			err = set_system_power_state(APM_STATE_BUSY);
-			if (err)
-				apm_error("busy", err);
-		}
-	} else
-		pending_count = 4;
-	check_events();
-}
-
-/*
- * This is the APM thread main loop.
- */
-
-static void apm_mainloop(void)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	add_wait_queue(&apm_waitqueue, &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
-	for (;;) {
-		schedule_timeout(APM_CHECK_TIMEOUT);
-		if (kthread_should_stop())
-			break;
-		/*
-		 * Ok, check all events, check for idle (and mark us sleeping
-		 * so as not to count towards the load average)..
-		 */
-		set_current_state(TASK_INTERRUPTIBLE);
-		apm_event_handler();
-	}
-	remove_wait_queue(&apm_waitqueue, &wait);
-}
-
-static int check_apm_user(struct apm_user *as, const char *func)
-{
-	if (as == NULL || as->magic != APM_BIOS_MAGIC) {
-		printk(KERN_ERR "apm: %s passed bad filp\n", func);
-		return 1;
-	}
-	return 0;
-}
-
-static ssize_t do_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
-{
-	struct apm_user *as;
-	int i;
-	apm_event_t event;
-
-	as = fp->private_data;
-	if (check_apm_user(as, "read"))
-		return -EIO;
-	if ((int)count < sizeof(apm_event_t))
-		return -EINVAL;
-	if ((queue_empty(as)) && (fp->f_flags & O_NONBLOCK))
-		return -EAGAIN;
-	wait_event_interruptible(apm_waitqueue, !queue_empty(as));
-	i = count;
-	while ((i >= sizeof(event)) && !queue_empty(as)) {
-		event = get_queued_event(as);
-		if (copy_to_user(buf, &event, sizeof(event))) {
-			if (i < count)
-				break;
-			return -EFAULT;
-		}
-		switch (event) {
-		case APM_SYS_SUSPEND:
-		case APM_USER_SUSPEND:
-			as->suspends_read++;
-			break;
-
-		case APM_SYS_STANDBY:
-		case APM_USER_STANDBY:
-			as->standbys_read++;
-			break;
-		}
-		buf += sizeof(event);
-		i -= sizeof(event);
-	}
-	if (i < count)
-		return count - i;
-	if (signal_pending(current))
-		return -ERESTARTSYS;
-	return 0;
-}
-
-static unsigned int do_poll(struct file *fp, poll_table *wait)
-{
-	struct apm_user *as;
-
-	as = fp->private_data;
-	if (check_apm_user(as, "poll"))
-		return 0;
-	poll_wait(fp, &apm_waitqueue, wait);
-	if (!queue_empty(as))
-		return POLLIN | POLLRDNORM;
-	return 0;
-}
-
-static long do_ioctl(struct file *filp, u_int cmd, u_long arg)
-{
-	struct apm_user *as;
-	int ret;
-
-	as = filp->private_data;
-	if (check_apm_user(as, "ioctl"))
-		return -EIO;
-	if (!as->suser || !as->writer)
-		return -EPERM;
-	switch (cmd) {
-	case APM_IOC_STANDBY:
-		mutex_lock(&apm_mutex);
-		if (as->standbys_read > 0) {
-			as->standbys_read--;
-			as->standbys_pending--;
-			standbys_pending--;
-		} else
-			queue_event(APM_USER_STANDBY, as);
-		if (standbys_pending <= 0)
-			standby();
-		mutex_unlock(&apm_mutex);
-		break;
-	case APM_IOC_SUSPEND:
-		mutex_lock(&apm_mutex);
-		if (as->suspends_read > 0) {
-			as->suspends_read--;
-			as->suspends_pending--;
-			suspends_pending--;
-		} else
-			queue_event(APM_USER_SUSPEND, as);
-		if (suspends_pending <= 0) {
-			ret = suspend(1);
-			mutex_unlock(&apm_mutex);
-		} else {
-			as->suspend_wait = 1;
-			mutex_unlock(&apm_mutex);
-			wait_event_interruptible(apm_suspend_waitqueue,
-					as->suspend_wait == 0);
-			ret = as->suspend_result;
-		}
-		return ret;
-	default:
-		return -ENOTTY;
-	}
-	return 0;
-}
-
-static int do_release(struct inode *inode, struct file *filp)
-{
-	struct apm_user *as;
-
-	as = filp->private_data;
-	if (check_apm_user(as, "release"))
-		return 0;
-	filp->private_data = NULL;
-	if (as->standbys_pending > 0) {
-		standbys_pending -= as->standbys_pending;
-		if (standbys_pending <= 0)
-			standby();
-	}
-	if (as->suspends_pending > 0) {
-		suspends_pending -= as->suspends_pending;
-		if (suspends_pending <= 0)
-			(void) suspend(1);
-	}
-	spin_lock(&user_list_lock);
-	if (user_list == as)
-		user_list = as->next;
-	else {
-		struct apm_user *as1;
-
-		for (as1 = user_list;
-		     (as1 != NULL) && (as1->next != as);
-		     as1 = as1->next)
-			;
-		if (as1 == NULL)
-			printk(KERN_ERR "apm: filp not in user list\n");
-		else
-			as1->next = as->next;
-	}
-	spin_unlock(&user_list_lock);
-	kfree(as);
-	return 0;
-}
-
-static int do_open(struct inode *inode, struct file *filp)
-{
-	struct apm_user *as;
-
-	as = kmalloc(sizeof(*as), GFP_KERNEL);
-	if (as == NULL) {
-		printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
-		       sizeof(*as));
-		return -ENOMEM;
-	}
-	as->magic = APM_BIOS_MAGIC;
-	as->event_tail = as->event_head = 0;
-	as->suspends_pending = as->standbys_pending = 0;
-	as->suspends_read = as->standbys_read = 0;
-	/*
-	 * XXX - this is a tiny bit broken, when we consider BSD
-	 * process accounting. If the device is opened by root, we
-	 * instantly flag that we used superuser privs. Who knows,
-	 * we might close the device immediately without doing a
-	 * privileged operation -- cevans
-	 */
-	as->suser = capable(CAP_SYS_ADMIN);
-	as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
-	as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
-	spin_lock(&user_list_lock);
-	as->next = user_list;
-	user_list = as;
-	spin_unlock(&user_list_lock);
-	filp->private_data = as;
-	return 0;
-}
-
-static int proc_apm_show(struct seq_file *m, void *v)
-{
-	unsigned short	bx;
-	unsigned short	cx;
-	unsigned short	dx;
-	int		error;
-	unsigned short  ac_line_status = 0xff;
-	unsigned short  battery_status = 0xff;
-	unsigned short  battery_flag   = 0xff;
-	int		percentage     = -1;
-	int             time_units     = -1;
-	char            *units         = "?";
-
-	if ((num_online_cpus() == 1) &&
-	    !(error = apm_get_power_status(&bx, &cx, &dx))) {
-		ac_line_status = (bx >> 8) & 0xff;
-		battery_status = bx & 0xff;
-		if ((cx & 0xff) != 0xff)
-			percentage = cx & 0xff;
-
-		if (apm_info.connection_version > 0x100) {
-			battery_flag = (cx >> 8) & 0xff;
-			if (dx != 0xffff) {
-				units = (dx & 0x8000) ? "min" : "sec";
-				time_units = dx & 0x7fff;
-			}
-		}
-	}
-	/* Arguments, with symbols from linux/apm_bios.h.  Information is
-	   from the Get Power Status (0x0a) call unless otherwise noted.
-
-	   0) Linux driver version (this will change if format changes)
-	   1) APM BIOS Version.  Usually 1.0, 1.1 or 1.2.
-	   2) APM flags from APM Installation Check (0x00):
-	      bit 0: APM_16_BIT_SUPPORT
-	      bit 1: APM_32_BIT_SUPPORT
-	      bit 2: APM_IDLE_SLOWS_CLOCK
-	      bit 3: APM_BIOS_DISABLED
-	      bit 4: APM_BIOS_DISENGAGED
-	   3) AC line status
-	      0x00: Off-line
-	      0x01: On-line
-	      0x02: On backup power (BIOS >= 1.1 only)
-	      0xff: Unknown
-	   4) Battery status
-	      0x00: High
-	      0x01: Low
-	      0x02: Critical
-	      0x03: Charging
-	      0x04: Selected battery not present (BIOS >= 1.2 only)
-	      0xff: Unknown
-	   5) Battery flag
-	      bit 0: High
-	      bit 1: Low
-	      bit 2: Critical
-	      bit 3: Charging
-	      bit 7: No system battery
-	      0xff: Unknown
-	   6) Remaining battery life (percentage of charge):
-	      0-100: valid
-	      -1: Unknown
-	   7) Remaining battery life (time units):
-	      Number of remaining minutes or seconds
-	      -1: Unknown
-	   8) min = minutes; sec = seconds */
-
-	seq_printf(m, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
-		   driver_version,
-		   (apm_info.bios.version >> 8) & 0xff,
-		   apm_info.bios.version & 0xff,
-		   apm_info.bios.flags,
-		   ac_line_status,
-		   battery_status,
-		   battery_flag,
-		   percentage,
-		   time_units,
-		   units);
-	return 0;
-}
-
-static int proc_apm_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, proc_apm_show, NULL);
-}
-
-static const struct file_operations apm_file_ops = {
-	.owner		= THIS_MODULE,
-	.open		= proc_apm_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int apm(void *unused)
-{
-	unsigned short	bx;
-	unsigned short	cx;
-	unsigned short	dx;
-	int		error;
-	char 		*power_stat;
-	char 		*bat_stat;
-
-	/* 2002/08/01 - WT
-	 * This is to avoid random crashes at boot time during initialization
-	 * on SMP systems in case of "apm=power-off" mode. Seen on ASUS A7M266D.
-	 * Some bioses don't like being called from CPU != 0.
-	 * Method suggested by Ingo Molnar.
-	 */
-	set_cpus_allowed_ptr(current, cpumask_of(0));
-	BUG_ON(smp_processor_id() != 0);
-
-	if (apm_info.connection_version == 0) {
-		apm_info.connection_version = apm_info.bios.version;
-		if (apm_info.connection_version > 0x100) {
-			/*
-			 * We only support BIOSs up to version 1.2
-			 */
-			if (apm_info.connection_version > 0x0102)
-				apm_info.connection_version = 0x0102;
-			error = apm_driver_version(&apm_info.connection_version);
-			if (error != APM_SUCCESS) {
-				apm_error("driver version", error);
-				/* Fall back to an APM 1.0 connection. */
-				apm_info.connection_version = 0x100;
-			}
-		}
-	}
-
-	if (debug)
-		printk(KERN_INFO "apm: Connection version %d.%d\n",
-			(apm_info.connection_version >> 8) & 0xff,
-			apm_info.connection_version & 0xff);
-
-#ifdef CONFIG_APM_DO_ENABLE
-	if (apm_info.bios.flags & APM_BIOS_DISABLED) {
-		/*
-		 * This call causes my NEC UltraLite Versa 33/C to hang if it
-		 * is booted with PM disabled but not in the docking station.
-		 * Unfortunate ...
-		 */
-		error = apm_enable_power_management(1);
-		if (error) {
-			apm_error("enable power management", error);
-			return -1;
-		}
-	}
-#endif
-
-	if ((apm_info.bios.flags & APM_BIOS_DISENGAGED)
-	    && (apm_info.connection_version > 0x0100)) {
-		error = apm_engage_power_management(APM_DEVICE_ALL, 1);
-		if (error) {
-			apm_error("engage power management", error);
-			return -1;
-		}
-	}
-
-	if (debug && (num_online_cpus() == 1 || smp)) {
-		error = apm_get_power_status(&bx, &cx, &dx);
-		if (error)
-			printk(KERN_INFO "apm: power status not available\n");
-		else {
-			switch ((bx >> 8) & 0xff) {
-			case 0:
-				power_stat = "off line";
-				break;
-			case 1:
-				power_stat = "on line";
-				break;
-			case 2:
-				power_stat = "on backup power";
-				break;
-			default:
-				power_stat = "unknown";
-				break;
-			}
-			switch (bx & 0xff) {
-			case 0:
-				bat_stat = "high";
-				break;
-			case 1:
-				bat_stat = "low";
-				break;
-			case 2:
-				bat_stat = "critical";
-				break;
-			case 3:
-				bat_stat = "charging";
-				break;
-			default:
-				bat_stat = "unknown";
-				break;
-			}
-			printk(KERN_INFO
-			       "apm: AC %s, battery status %s, battery life ",
-			       power_stat, bat_stat);
-			if ((cx & 0xff) == 0xff)
-				printk("unknown\n");
-			else
-				printk("%d%%\n", cx & 0xff);
-			if (apm_info.connection_version > 0x100) {
-				printk(KERN_INFO
-				       "apm: battery flag 0x%02x, battery life ",
-				       (cx >> 8) & 0xff);
-				if (dx == 0xffff)
-					printk("unknown\n");
-				else
-					printk("%d %s\n", dx & 0x7fff,
-					       (dx & 0x8000) ?
-					       "minutes" : "seconds");
-			}
-		}
-	}
-
-	/* Install our power off handler.. */
-	if (power_off)
-		pm_power_off = apm_power_off;
-
-	if (num_online_cpus() == 1 || smp) {
-#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
-		console_blank_hook = apm_console_blank;
-#endif
-		apm_mainloop();
-#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
-		console_blank_hook = NULL;
-#endif
-	}
-
-	return 0;
-}
-
-#ifndef MODULE
-static int __init apm_setup(char *str)
-{
-	int invert;
-
-	while ((str != NULL) && (*str != '\0')) {
-		if (strncmp(str, "off", 3) == 0)
-			apm_disabled = 1;
-		if (strncmp(str, "on", 2) == 0)
-			apm_disabled = 0;
-		if ((strncmp(str, "bounce-interval=", 16) == 0) ||
-		    (strncmp(str, "bounce_interval=", 16) == 0))
-			bounce_interval = simple_strtol(str + 16, NULL, 0);
-		if ((strncmp(str, "idle-threshold=", 15) == 0) ||
-		    (strncmp(str, "idle_threshold=", 15) == 0))
-			idle_threshold = simple_strtol(str + 15, NULL, 0);
-		if ((strncmp(str, "idle-period=", 12) == 0) ||
-		    (strncmp(str, "idle_period=", 12) == 0))
-			idle_period = simple_strtol(str + 12, NULL, 0);
-		invert = (strncmp(str, "no-", 3) == 0) ||
-			(strncmp(str, "no_", 3) == 0);
-		if (invert)
-			str += 3;
-		if (strncmp(str, "debug", 5) == 0)
-			debug = !invert;
-		if ((strncmp(str, "power-off", 9) == 0) ||
-		    (strncmp(str, "power_off", 9) == 0))
-			power_off = !invert;
-		if (strncmp(str, "smp", 3) == 0) {
-			smp = !invert;
-			idle_threshold = 100;
-		}
-		if ((strncmp(str, "allow-ints", 10) == 0) ||
-		    (strncmp(str, "allow_ints", 10) == 0))
-			apm_info.allow_ints = !invert;
-		if ((strncmp(str, "broken-psr", 10) == 0) ||
-		    (strncmp(str, "broken_psr", 10) == 0))
-			apm_info.get_power_status_broken = !invert;
-		if ((strncmp(str, "realmode-power-off", 18) == 0) ||
-		    (strncmp(str, "realmode_power_off", 18) == 0))
-			apm_info.realmode_power_off = !invert;
-		str = strchr(str, ',');
-		if (str != NULL)
-			str += strspn(str, ", \t");
-	}
-	return 1;
-}
-
-__setup("apm=", apm_setup);
-#endif
-
-static const struct file_operations apm_bios_fops = {
-	.owner		= THIS_MODULE,
-	.read		= do_read,
-	.poll		= do_poll,
-	.unlocked_ioctl	= do_ioctl,
-	.open		= do_open,
-	.release	= do_release,
-	.llseek		= noop_llseek,
-};
-
-static struct miscdevice apm_device = {
-	APM_MINOR_DEV,
-	"apm_bios",
-	&apm_bios_fops
-};
-
-
-/* Simple "print if true" callback */
-static int __init print_if_true(const struct dmi_system_id *d)
-{
-	printk("%s\n", d->ident);
-	return 0;
-}
-
-/*
- * Some Bioses enable the PS/2 mouse (touchpad) at resume, even if it was
- * disabled before the suspend. Linux used to get terribly confused by that.
- */
-static int __init broken_ps2_resume(const struct dmi_system_id *d)
-{
-	printk(KERN_INFO "%s machine detected. Mousepad Resume Bug "
-	       "workaround hopefully not needed.\n", d->ident);
-	return 0;
-}
-
-/* Some bioses have a broken protected mode poweroff and need to use realmode */
-static int __init set_realmode_power_off(const struct dmi_system_id *d)
-{
-	if (apm_info.realmode_power_off == 0) {
-		apm_info.realmode_power_off = 1;
-		printk(KERN_INFO "%s bios detected. "
-		       "Using realmode poweroff only.\n", d->ident);
-	}
-	return 0;
-}
-
-/* Some laptops require interrupts to be enabled during APM calls */
-static int __init set_apm_ints(const struct dmi_system_id *d)
-{
-	if (apm_info.allow_ints == 0) {
-		apm_info.allow_ints = 1;
-		printk(KERN_INFO "%s machine detected. "
-		       "Enabling interrupts during APM calls.\n", d->ident);
-	}
-	return 0;
-}
-
-/* Some APM bioses corrupt memory or just plain do not work */
-static int __init apm_is_horked(const struct dmi_system_id *d)
-{
-	if (apm_info.disabled == 0) {
-		apm_info.disabled = 1;
-		printk(KERN_INFO "%s machine detected. "
-		       "Disabling APM.\n", d->ident);
-	}
-	return 0;
-}
-
-static int __init apm_is_horked_d850md(const struct dmi_system_id *d)
-{
-	if (apm_info.disabled == 0) {
-		apm_info.disabled = 1;
-		printk(KERN_INFO "%s machine detected. "
-		       "Disabling APM.\n", d->ident);
-		printk(KERN_INFO "This bug is fixed in bios P15 which is available for\n");
-		printk(KERN_INFO "download from support.intel.com\n");
-	}
-	return 0;
-}
-
-/* Some APM bioses hang on APM idle calls */
-static int __init apm_likes_to_melt(const struct dmi_system_id *d)
-{
-	if (apm_info.forbid_idle == 0) {
-		apm_info.forbid_idle = 1;
-		printk(KERN_INFO "%s machine detected. "
-		       "Disabling APM idle calls.\n", d->ident);
-	}
-	return 0;
-}
-
-/*
- *  Check for clue free BIOS implementations who use
- *  the following QA technique
- *
- *      [ Write BIOS Code ]<------
- *               |                ^
- *      < Does it Compile >----N--
- *               |Y               ^
- *	< Does it Boot Win98 >-N--
- *               |Y
- *           [Ship It]
- *
- *	Phoenix A04  08/24/2000 is known bad (Dell Inspiron 5000e)
- *	Phoenix A07  09/29/2000 is known good (Dell Inspiron 5000)
- */
-static int __init broken_apm_power(const struct dmi_system_id *d)
-{
-	apm_info.get_power_status_broken = 1;
-	printk(KERN_WARNING "BIOS strings suggest APM bugs, "
-	       "disabling power status reporting.\n");
-	return 0;
-}
-
-/*
- * This bios swaps the APM minute reporting bytes over (Many sony laptops
- * have this problem).
- */
-static int __init swab_apm_power_in_minutes(const struct dmi_system_id *d)
-{
-	apm_info.get_power_status_swabinminutes = 1;
-	printk(KERN_WARNING "BIOS strings suggest APM reports battery life "
-	       "in minutes and wrong byte order.\n");
-	return 0;
-}
-
-static struct dmi_system_id __initdata apm_dmi_table[] = {
-	{
-		print_if_true,
-		KERN_WARNING "IBM T23 - BIOS 1.03b+ and controller firmware 1.02+ may be needed for Linux APM.",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-			DMI_MATCH(DMI_BIOS_VERSION, "1AET38WW (1.01b)"), },
-	},
-	{	/* Handle problems with APM on the C600 */
-		broken_ps2_resume, "Dell Latitude C600",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude C600"), },
-	},
-	{	/* Allow interrupts during suspend on Dell Latitude laptops*/
-		set_apm_ints, "Dell Latitude",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude C510"), }
-	},
-	{	/* APM crashes */
-		apm_is_horked, "Dell Inspiron 2500",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
-			DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "A11"), },
-	},
-	{	/* Allow interrupts during suspend on Dell Inspiron laptops*/
-		set_apm_ints, "Dell Inspiron", {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"), },
-	},
-	{	/* Handle problems with APM on Inspiron 5000e */
-		broken_apm_power, "Dell Inspiron 5000e",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "A04"),
-			DMI_MATCH(DMI_BIOS_DATE, "08/24/2000"), },
-	},
-	{	/* Handle problems with APM on Inspiron 2500 */
-		broken_apm_power, "Dell Inspiron 2500",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "A12"),
-			DMI_MATCH(DMI_BIOS_DATE, "02/04/2002"), },
-	},
-	{	/* APM crashes */
-		apm_is_horked, "Dell Dimension 4100",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "XPS-Z"),
-			DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
-			DMI_MATCH(DMI_BIOS_VERSION, "A11"), },
-	},
-	{	/* Allow interrupts during suspend on Compaq Laptops*/
-		set_apm_ints, "Compaq 12XL125",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Compaq PC"),
-			DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "4.06"), },
-	},
-	{	/* Allow interrupts during APM or the clock goes slow */
-		set_apm_ints, "ASUSTeK",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "L8400K series Notebook PC"), },
-	},
-	{	/* APM blows on shutdown */
-		apm_is_horked, "ABIT KX7-333[R]",
-		{	DMI_MATCH(DMI_BOARD_VENDOR, "ABIT"),
-			DMI_MATCH(DMI_BOARD_NAME, "VT8367-8233A (KX7-333[R])"), },
-	},
-	{	/* APM crashes */
-		apm_is_horked, "Trigem Delhi3",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "TriGem Computer, Inc"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Delhi3"), },
-	},
-	{	/* APM crashes */
-		apm_is_horked, "Fujitsu-Siemens",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "hoenix/FUJITSU SIEMENS"),
-			DMI_MATCH(DMI_BIOS_VERSION, "Version1.01"), },
-	},
-	{	/* APM crashes */
-		apm_is_horked_d850md, "Intel D850MD",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
-			DMI_MATCH(DMI_BIOS_VERSION, "MV85010A.86A.0016.P07.0201251536"), },
-	},
-	{	/* APM crashes */
-		apm_is_horked, "Intel D810EMO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
-			DMI_MATCH(DMI_BIOS_VERSION, "MO81010A.86A.0008.P04.0004170800"), },
-	},
-	{	/* APM crashes */
-		apm_is_horked, "Dell XPS-Z",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
-			DMI_MATCH(DMI_BIOS_VERSION, "A11"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "XPS-Z"), },
-	},
-	{	/* APM crashes */
-		apm_is_horked, "Sharp PC-PJ/AX",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "SHARP"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "PC-PJ/AX"),
-			DMI_MATCH(DMI_BIOS_VENDOR, "SystemSoft"),
-			DMI_MATCH(DMI_BIOS_VERSION, "Version R2.08"), },
-	},
-	{	/* APM crashes */
-		apm_is_horked, "Dell Inspiron 2500",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
-			DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "A11"), },
-	},
-	{	/* APM idle hangs */
-		apm_likes_to_melt, "Jabil AMD",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
-			DMI_MATCH(DMI_BIOS_VERSION, "0AASNP06"), },
-	},
-	{	/* APM idle hangs */
-		apm_likes_to_melt, "AMI Bios",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
-			DMI_MATCH(DMI_BIOS_VERSION, "0AASNP05"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-N505X(DE) */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "R0206H"),
-			DMI_MATCH(DMI_BIOS_DATE, "08/23/99"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-N505VX */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "W2K06H0"),
-			DMI_MATCH(DMI_BIOS_DATE, "02/03/00"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-XG29 */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "R0117A0"),
-			DMI_MATCH(DMI_BIOS_DATE, "04/25/00"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-Z600NE */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "R0121Z1"),
-			DMI_MATCH(DMI_BIOS_DATE, "05/11/00"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-Z600NE */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "WME01Z1"),
-			DMI_MATCH(DMI_BIOS_DATE, "08/11/00"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-Z600LEK(DE) */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "R0206Z3"),
-			DMI_MATCH(DMI_BIOS_DATE, "12/25/00"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-Z505LS */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "R0203D0"),
-			DMI_MATCH(DMI_BIOS_DATE, "05/12/00"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-Z505LS */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "R0203Z3"),
-			DMI_MATCH(DMI_BIOS_DATE, "08/25/00"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-Z505LS (with updated BIOS) */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "R0209Z3"),
-			DMI_MATCH(DMI_BIOS_DATE, "05/12/01"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-F104K */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "R0204K2"),
-			DMI_MATCH(DMI_BIOS_DATE, "08/28/00"), },
-	},
-
-	{	/* Handle problems with APM on Sony Vaio PCG-C1VN/C1VE */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "R0208P1"),
-			DMI_MATCH(DMI_BIOS_DATE, "11/09/00"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-C1VE */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "R0204P1"),
-			DMI_MATCH(DMI_BIOS_DATE, "09/12/00"), },
-	},
-	{	/* Handle problems with APM on Sony Vaio PCG-C1VE */
-		swab_apm_power_in_minutes, "Sony VAIO",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
-			DMI_MATCH(DMI_BIOS_VERSION, "WXPO1Z3"),
-			DMI_MATCH(DMI_BIOS_DATE, "10/26/01"), },
-	},
-	{	/* broken PM poweroff bios */
-		set_realmode_power_off, "Award Software v4.60 PGMA",
-		{	DMI_MATCH(DMI_BIOS_VENDOR, "Award Software International, Inc."),
-			DMI_MATCH(DMI_BIOS_VERSION, "4.60 PGMA"),
-			DMI_MATCH(DMI_BIOS_DATE, "134526184"), },
-	},
-
-	/* Generic per vendor APM settings  */
-
-	{	/* Allow interrupts during suspend on IBM laptops */
-		set_apm_ints, "IBM",
-		{	DMI_MATCH(DMI_SYS_VENDOR, "IBM"), },
-	},
-
-	{ }
-};
-
-/*
- * Just start the APM thread. We do NOT want to do APM BIOS
- * calls from anything but the APM thread, if for no other reason
- * than the fact that we don't trust the APM BIOS. This way,
- * most common APM BIOS problems that lead to protection errors
- * etc will have at least some level of being contained...
- *
- * In short, if something bad happens, at least we have a choice
- * of just killing the apm thread..
- */
-static int __init apm_init(void)
-{
-	struct desc_struct *gdt;
-	int err;
-
-	dmi_check_system(apm_dmi_table);
-
-	if (apm_info.bios.version == 0 || paravirt_enabled() || machine_is_olpc()) {
-		printk(KERN_INFO "apm: BIOS not found.\n");
-		return -ENODEV;
-	}
-	printk(KERN_INFO
-	       "apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n",
-	       ((apm_info.bios.version >> 8) & 0xff),
-	       (apm_info.bios.version & 0xff),
-	       apm_info.bios.flags,
-	       driver_version);
-	if ((apm_info.bios.flags & APM_32_BIT_SUPPORT) == 0) {
-		printk(KERN_INFO "apm: no 32 bit BIOS support\n");
-		return -ENODEV;
-	}
-
-	if (allow_ints)
-		apm_info.allow_ints = 1;
-	if (broken_psr)
-		apm_info.get_power_status_broken = 1;
-	if (realmode_power_off)
-		apm_info.realmode_power_off = 1;
-	/* User can override, but default is to trust DMI */
-	if (apm_disabled != -1)
-		apm_info.disabled = apm_disabled;
-
-	/*
-	 * Fix for the Compaq Contura 3/25c which reports BIOS version 0.1
-	 * but is reportedly a 1.0 BIOS.
-	 */
-	if (apm_info.bios.version == 0x001)
-		apm_info.bios.version = 0x100;
-
-	/* BIOS < 1.2 doesn't set cseg_16_len */
-	if (apm_info.bios.version < 0x102)
-		apm_info.bios.cseg_16_len = 0; /* 64k */
-
-	if (debug) {
-		printk(KERN_INFO "apm: entry %x:%x cseg16 %x dseg %x",
-			apm_info.bios.cseg, apm_info.bios.offset,
-			apm_info.bios.cseg_16, apm_info.bios.dseg);
-		if (apm_info.bios.version > 0x100)
-			printk(" cseg len %x, dseg len %x",
-				apm_info.bios.cseg_len,
-				apm_info.bios.dseg_len);
-		if (apm_info.bios.version > 0x101)
-			printk(" cseg16 len %x", apm_info.bios.cseg_16_len);
-		printk("\n");
-	}
-
-	if (apm_info.disabled) {
-		printk(KERN_NOTICE "apm: disabled on user request.\n");
-		return -ENODEV;
-	}
-	if ((num_online_cpus() > 1) && !power_off && !smp) {
-		printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
-		apm_info.disabled = 1;
-		return -ENODEV;
-	}
-	if (pm_flags & PM_ACPI) {
-		printk(KERN_NOTICE "apm: overridden by ACPI.\n");
-		apm_info.disabled = 1;
-		return -ENODEV;
-	}
-	pm_flags |= PM_APM;
-
-	/*
-	 * Set up the long jump entry point to the APM BIOS, which is called
-	 * from inline assembly.
-	 */
-	apm_bios_entry.offset = apm_info.bios.offset;
-	apm_bios_entry.segment = APM_CS;
-
-	/*
-	 * The APM 1.1 BIOS is supposed to provide limit information that it
-	 * recognizes.  Many machines do this correctly, but many others do
-	 * not restrict themselves to their claimed limit.  When this happens,
-	 * they will cause a segmentation violation in the kernel at boot time.
-	 * Most BIOS's, however, will respect a 64k limit, so we use that.
-	 *
-	 * Note we only set APM segments on CPU zero, since we pin the APM
-	 * code to that CPU.
-	 */
-	gdt = get_cpu_gdt_table(0);
-	set_desc_base(&gdt[APM_CS >> 3],
-		 (unsigned long)__va((unsigned long)apm_info.bios.cseg << 4));
-	set_desc_base(&gdt[APM_CS_16 >> 3],
-		 (unsigned long)__va((unsigned long)apm_info.bios.cseg_16 << 4));
-	set_desc_base(&gdt[APM_DS >> 3],
-		 (unsigned long)__va((unsigned long)apm_info.bios.dseg << 4));
-
-	proc_create("apm", 0, NULL, &apm_file_ops);
-
-	kapmd_task = kthread_create(apm, NULL, "kapmd");
-	if (IS_ERR(kapmd_task)) {
-		printk(KERN_ERR "apm: disabled - Unable to start kernel "
-				"thread.\n");
-		err = PTR_ERR(kapmd_task);
-		kapmd_task = NULL;
-		remove_proc_entry("apm", NULL);
-		return err;
-	}
-	wake_up_process(kapmd_task);
-
-	if (num_online_cpus() > 1 && !smp) {
-		printk(KERN_NOTICE
-		       "apm: disabled - APM is not SMP safe (power off active).\n");
-		return 0;
-	}
-
-	/*
-	 * Note we don't actually care if the misc_device cannot be registered.
-	 * this driver can do its job without it, even if userspace can't
-	 * control it.  just log the error
-	 */
-	if (misc_register(&apm_device))
-		printk(KERN_WARNING "apm: Could not register misc device.\n");
-
-	if (HZ != 100)
-		idle_period = (idle_period * HZ) / 100;
-	if (idle_threshold < 100) {
-		original_pm_idle = pm_idle;
-		pm_idle  = apm_cpu_idle;
-		set_pm_idle = 1;
-	}
-
-	return 0;
-}
-
-static void __exit apm_exit(void)
-{
-	int error;
-
-	if (set_pm_idle) {
-		pm_idle = original_pm_idle;
-		/*
-		 * We are about to unload the current idle thread pm callback
-		 * (pm_idle), Wait for all processors to update cached/local
-		 * copies of pm_idle before proceeding.
-		 */
-		cpu_idle_wait();
-	}
-	if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0)
-	    && (apm_info.connection_version > 0x0100)) {
-		error = apm_engage_power_management(APM_DEVICE_ALL, 0);
-		if (error)
-			apm_error("disengage power management", error);
-	}
-	misc_deregister(&apm_device);
-	remove_proc_entry("apm", NULL);
-	if (power_off)
-		pm_power_off = NULL;
-	if (kapmd_task) {
-		kthread_stop(kapmd_task);
-		kapmd_task = NULL;
-	}
-	pm_flags &= ~PM_APM;
-}
-
-module_init(apm_init);
-module_exit(apm_exit);
-
-MODULE_AUTHOR("Stephen Rothwell");
-MODULE_DESCRIPTION("Advanced Power Management");
-MODULE_LICENSE("GPL");
-module_param(debug, bool, 0644);
-MODULE_PARM_DESC(debug, "Enable debug mode");
-module_param(power_off, bool, 0444);
-MODULE_PARM_DESC(power_off, "Enable power off");
-module_param(bounce_interval, int, 0444);
-MODULE_PARM_DESC(bounce_interval,
-		"Set the number of ticks to ignore suspend bounces");
-module_param(allow_ints, bool, 0444);
-MODULE_PARM_DESC(allow_ints, "Allow interrupts during BIOS calls");
-module_param(broken_psr, bool, 0444);
-MODULE_PARM_DESC(broken_psr, "BIOS has a broken GetPowerStatus call");
-module_param(realmode_power_off, bool, 0444);
-MODULE_PARM_DESC(realmode_power_off,
-		"Switch to real mode before powering off");
-module_param(idle_threshold, int, 0444);
-MODULE_PARM_DESC(idle_threshold,
-	"System idle percentage above which to make APM BIOS idle calls");
-module_param(idle_period, int, 0444);
-MODULE_PARM_DESC(idle_period,
-	"Period (in sec/100) over which to caculate the idle percentage");
-module_param(smp, bool, 0444);
-MODULE_PARM_DESC(smp,
-	"Set this to enable APM use on an SMP platform. Use with caution on older systems");
-MODULE_ALIAS_MISCDEV(APM_MINOR_DEV);
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 094d4ac..6808419 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -365,9 +365,6 @@ void default_idle(void)
 	trace_power_end(smp_processor_id());
 	trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
 }
-#ifdef CONFIG_APM_MODULE
-EXPORT_SYMBOL(default_idle);
-#endif
 
 void stop_this_cpu(void *dummy)
 {
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 715037c..60698d3 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -428,9 +428,6 @@ void machine_real_restart(const unsigned char *code, int length)
 				:
 				: "i" ((void *)(0x1000 - sizeof (real_mode_switch) - 100)));
 }
-#ifdef CONFIG_APM_MODULE
-EXPORT_SYMBOL(machine_real_restart);
-#endif
 
 #endif /* CONFIG_X86_32 */
 
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index fab5631..76aaaf8 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -28,7 +28,6 @@
 #include <linux/ioport.h>
 #include <linux/acpi.h>
 #include <linux/sfi.h>
-#include <linux/apm_bios.h>
 #include <linux/initrd.h>
 #include <linux/bootmem.h>
 #include <linux/memblock.h>
@@ -193,9 +192,6 @@ unsigned int machine_id;
 unsigned int machine_submodel_id;
 unsigned int BIOS_revision;
 
-struct apm_info apm_info;
-EXPORT_SYMBOL(apm_info);
-
 #if defined(CONFIG_X86_SPEEDSTEP_SMI) || \
 	defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
 struct ist_info ist_info;
@@ -742,7 +738,6 @@ void __init setup_arch(char **cmdline_p)
 	screen_info = boot_params.screen_info;
 	edid_info = boot_params.edid_info;
 #ifdef CONFIG_X86_32
-	apm_info.bios = boot_params.apm_bios_info;
 	ist_info = boot_params.ist_info;
 	if (boot_params.sys_desc_table.length != 0) {
 		set_mca_bus(boot_params.sys_desc_table.table[3] & 0x2);
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 7ced61f..c974656 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -1023,17 +1023,9 @@ static int __init acpi_init(void)
 	init_acpi_device_notify();
 	result = acpi_bus_init();
 
-	if (!result) {
+	if (!result)
 		pci_mmcfg_late_init();
-		if (!(pm_flags & PM_APM))
-			pm_flags |= PM_ACPI;
-		else {
-			printk(KERN_INFO PREFIX
-			       "APM is already active, exiting\n");
-			disable_acpi();
-			result = -ENODEV;
-		}
-	} else
+	else
 		disable_acpi();
 
 	if (acpi_disabled)
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 21415cc..ccd92b3 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -565,15 +565,6 @@ enum dpm_order {
 	DPM_ORDER_DEV_LAST,
 };
 
-/*
- * Global Power Management flags
- * Used to keep APM and ACPI from both being active
- */
-extern unsigned int	pm_flags;
-
-#define PM_APM	1
-#define PM_ACPI	2
-
 extern int pm_generic_suspend(struct device *dev);
 extern int pm_generic_resume(struct device *dev);
 extern int pm_generic_freeze(struct device *dev);
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 7018530..8eaba5f 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -17,9 +17,6 @@
 
 DEFINE_MUTEX(pm_mutex);
 
-unsigned int pm_flags;
-EXPORT_SYMBOL(pm_flags);
-
 #ifdef CONFIG_PM_SLEEP
 
 /* Routines for PM-transition notifications */
-- 
1.7.4.1.343.ga91df



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [PATCH] APM: delete APM in Linux-2.6.40
  2011-03-24  7:39   ` [PATCH] APM: delete APM in Linux-2.6.40 Len Brown
  2011-03-24  8:16     ` [PATCH] x86 APM: delete Linux kernel APM support Len Brown
  2011-03-24  8:18     ` [PATCH] APM: delete APM in Linux-2.6.40 Stephen Rothwell
@ 2011-03-24  8:38     ` Alexander Stein
  2011-03-24 10:21     ` Henrique de Moraes Holschuh
                       ` (2 subsequent siblings)
  5 siblings, 0 replies; 37+ messages in thread
From: Alexander Stein @ 2011-03-24  8:38 UTC (permalink / raw)
  To: Len Brown; +Cc: Stephen Rothwell, linux-pm, linux-kernel

On Thursday 24 March 2011, 08:39:07 Len Brown wrote:
> From: Len Brown <len.brown@intel.com>
> 
> Signed-off-by: Len Brown <len.brown@intel.com>
> ---
>  Documentation/feature-removal-schedule.txt |    8 ++++++++
>  1 files changed, 8 insertions(+), 0 deletions(-)
> 
> diff --git a/Documentation/feature-removal-schedule.txt
> b/Documentation/feature-removal-schedule.txt index b3f35e5..2a03c46 100644
> --- a/Documentation/feature-removal-schedule.txt
> +++ b/Documentation/feature-removal-schedule.txt
> @@ -619,3 +619,11 @@ Why:	The original implementation of memsw feature
> enabled by Who:	Michal Hocko <mhocko@suse.cz>
> 
>  ----------------------------
> +
> +What:	CONFIG_APM
> +When:	2.6.40
> +Why:	Microsoft deleted APM from Windows as of Vista in in 2006.

Minor nitpick: 'in' is doubled.

Alexander

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] x86 APM: delete Linux kernel APM support
  2011-03-24  8:16     ` [PATCH] x86 APM: delete Linux kernel APM support Len Brown
  2011-03-24  8:31       ` [PATCH] x86 APM: delete Linux kernel APM support (v2) Len Brown
@ 2011-03-24  8:39       ` Ingo Molnar
  2011-03-24 23:49         ` Len Brown
  1 sibling, 1 reply; 37+ messages in thread
From: Ingo Molnar @ 2011-03-24  8:39 UTC (permalink / raw)
  To: Len Brown
  Cc: Stephen Rothwell, x86, linux-pm, linux-kernel, Linus Torvalds,
	Thomas Gleixner, H. Peter Anvin, Andrew Morton


* Len Brown <lenb@kernel.org> wrote:

> From: Len Brown <len.brown@intel.com>
> 
> Microsoft was able to delete APM from Windows in 2006
> with the release of Windows Vista. [...]

Does Windows XP still support it?

> [...]  5 years later it seems quite safe that the latest Linux kernel can 
> also.
> 
> The vintage APM laptops have become difficult to find,
> making changes in this area difficult to test.
> 
> apm_bios.h remains for CONFIG_APM_EMULATION
> used by non-x86 architectures.

Dunno. This bit:

> --- a/Documentation/feature-removal-schedule.txt
> +++ b/Documentation/feature-removal-schedule.txt
> @@ -618,12 +618,3 @@ Why:	The original implementation of memsw feature enabled by
>  	can also cleanup the parameter handling a bit ().
>  Who:	Michal Hocko <mhocko@suse.cz>
>  
> -----------------------------
> -
> -What:	CONFIG_APM
> -When:	2.6.40
> -Why:	Microsoft deleted APM from Windows as of Vista in in 2006.
> -	It now seems more than safe that the latest Linux Kernel be APM-free.
> -	The vintage laptops supporting APM are now difficult to find,
> -	making it problatic to maintain this code.
> -Who:	Len Brown <len.brown@intel.com>

Is weird as there's no such CONFIG_APM entry upstream, and never was. Which 
tree is this entry included in?

While i'm not a fan of APM at all, this removal is a tad fast IMHO.

Beyond the lack of a upstream-visible feature-removal-schedule entry, we still 
have an Arcnet driver which hardware was obsoleted by Ethernet in the late 80s, 
and we still have i486 support and those are *much* older than APM.

If you look at the diffstat:

>  Documentation/feature-removal-schedule.txt |    9 -
>  MAINTAINERS                                |    8 -
>  arch/x86/Kconfig                           |  125 --
>  arch/x86/boot/Makefile                     |    1 -
>  arch/x86/boot/apm.c                        |   75 -
>  arch/x86/boot/main.c                       |    5 -
>  arch/x86/include/asm/bootparam.h           |    3 +-
>  arch/x86/kernel/Makefile                   |    2 -
>  arch/x86/kernel/apm_32.c                   | 2463 ----------------------------
>  arch/x86/kernel/process.c                  |    3 -
>  arch/x86/kernel/reboot.c                   |    3 -
>  arch/x86/kernel/setup.c                    |    4 -
>  12 files changed, 1 insertions(+), 2700 deletions(-)

You see that the kernel implementation is nicely modularized and its 
cross-section to the rest of arch/x86/ is minimal. To arch/x86/ it's little 
more than an obscure driver.

Thus from a maintenance POV APM has not been much of a drag on the x86 
maintainer side. Sure, we do not test it, but that's the case with most of the 
obsolete drivers in the kernel.

The principle is that as long as there's no ongoing drag, the cost of carrying 
obsolete drivers is minimal - and the unknown cost of screwing someone in a big 
way by removing hardware support is hard to measure reliably. So we are 
cautious and err on the side of supporting too much hardware.

Removal could be prepared by:

 - moving CONFIG_APM to under CONFIG_EXPERT though, and keep it there for a few 
   releases, and see whether anyone complains

 - we could emit a WARN() with a "APM support will be obsoleted, please report 
   this if you depend on this feature" text or so, and see what happens for a 
   couple of releases.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] APM: delete APM in Linux-2.6.40
  2011-03-24  7:39   ` [PATCH] APM: delete APM in Linux-2.6.40 Len Brown
                       ` (2 preceding siblings ...)
  2011-03-24  8:38     ` Alexander Stein
@ 2011-03-24 10:21     ` Henrique de Moraes Holschuh
  2011-03-24 23:05       ` Len Brown
  2011-03-24 12:15     ` Ondrej Zary
  2011-04-02 21:40     ` Yuhong Bao
  5 siblings, 1 reply; 37+ messages in thread
From: Henrique de Moraes Holschuh @ 2011-03-24 10:21 UTC (permalink / raw)
  To: Len Brown; +Cc: Stephen Rothwell, linux-pm, linux-kernel

On Thu, 24 Mar 2011, Len Brown wrote:
> +What:	CONFIG_APM
> +When:	2.6.40
> +Why:	Microsoft deleted APM from Windows as of Vista in in 2006.
> +	It now seems more than safe that the latest Linux Kernel be APM-free.
> +	The vintage laptops supporting APM are now difficult to find,
> +	making it problatic to maintain this code.
> +Who:	Len Brown <len.brown@intel.com>

People with a ThinkPad T23, T30 will really not appreciate this, and it
should not be too difficult to recruit some as testers.

Do you want me to try to recruit testers?  These boxes should still work for
about 5 more years, give or take.  IBM *really* knew how to build stuff back
then...

If no testers show up, then the removal would be well justified.

-- 
  "One disk to rule them all, One disk to find them. One disk to bring
  them all and in the darkness grind them. In the Land of Redmond
  where the shadows lie." -- The Silicon Valley Tarot
  Henrique Holschuh

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] APM: delete APM in Linux-2.6.40
  2011-03-24  7:39   ` [PATCH] APM: delete APM in Linux-2.6.40 Len Brown
                       ` (3 preceding siblings ...)
  2011-03-24 10:21     ` Henrique de Moraes Holschuh
@ 2011-03-24 12:15     ` Ondrej Zary
  2011-03-24 23:29       ` Len Brown
  2011-04-02 21:40     ` Yuhong Bao
  5 siblings, 1 reply; 37+ messages in thread
From: Ondrej Zary @ 2011-03-24 12:15 UTC (permalink / raw)
  To: Len Brown; +Cc: Stephen Rothwell, linux-pm, linux-kernel

On Thursday 24 March 2011, Len Brown wrote:
> From: Len Brown <len.brown@intel.com>
>
> Signed-off-by: Len Brown <len.brown@intel.com>
> ---
>  Documentation/feature-removal-schedule.txt |    8 ++++++++
>  1 files changed, 8 insertions(+), 0 deletions(-)
>
> diff --git a/Documentation/feature-removal-schedule.txt
> b/Documentation/feature-removal-schedule.txt index b3f35e5..2a03c46 100644
> --- a/Documentation/feature-removal-schedule.txt
> +++ b/Documentation/feature-removal-schedule.txt
> @@ -619,3 +619,11 @@ Why:	The original implementation of memsw feature
> enabled by Who:	Michal Hocko <mhocko@suse.cz>
>
>  ----------------------------
> +
> +What:	CONFIG_APM
> +When:	2.6.40
> +Why:	Microsoft deleted APM from Windows as of Vista in in 2006.
> +	It now seems more than safe that the latest Linux Kernel be APM-free.
> +	The vintage laptops supporting APM are now difficult to find,
> +	making it problatic to maintain this code.
> +Who:	Len Brown <len.brown@intel.com>

Please don't turn Linux into second Windows. If you don't want APM in the 
kernel, just don't compile it. There are many people using older systems with 
APM - and most of them wouldn't oppose to this removal as they don't even 
know about it.

-- 
Ondrej Zary

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] x86 APM: delete Linux kernel APM support (v2)
  2011-03-24  8:31       ` [PATCH] x86 APM: delete Linux kernel APM support (v2) Len Brown
@ 2011-03-24 16:01         ` Andi Kleen
  0 siblings, 0 replies; 37+ messages in thread
From: Andi Kleen @ 2011-03-24 16:01 UTC (permalink / raw)
  To: Len Brown; +Cc: Stephen Rothwell, x86, linux-pm, linux-kernel

Len Brown <lenb@kernel.org> writes:

> Microsoft was able to delete APM from Windows in 2006
> with the release of Windows Vista.  5 years later it seems
> quite safe that the latest Linux kernel can also.
>
> The vintage APM laptops have become difficult to find,
> making changes in this area difficult to test.

One other use-case even on non laptops was powering off the system.
I know my desktops used to need that.

Would it make sense to retain that path? 

-Andi
-- 
ak@linux.intel.com -- Speaking for myself only

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] APM: delete APM in Linux-2.6.40
  2011-03-24 10:21     ` Henrique de Moraes Holschuh
@ 2011-03-24 23:05       ` Len Brown
  2011-03-25  1:07         ` Henrique de Moraes Holschuh
  0 siblings, 1 reply; 37+ messages in thread
From: Len Brown @ 2011-03-24 23:05 UTC (permalink / raw)
  To: Henrique de Moraes Holschuh; +Cc: Stephen Rothwell, linux-pm, linux-kernel

> People with a ThinkPad T23, T30 will really not appreciate this, and it
> should not be too difficult to recruit some as testers.

I have both, and they both support ACPI.

Re: lasting for years.
Actually, I used to have several of both, but they're dying off,
and they are excruciatingly slow...

-Len




^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] APM: delete APM in Linux-2.6.40
  2011-03-24 12:15     ` Ondrej Zary
@ 2011-03-24 23:29       ` Len Brown
  2011-03-25  8:07         ` Ondrej Zary
  0 siblings, 1 reply; 37+ messages in thread
From: Len Brown @ 2011-03-24 23:29 UTC (permalink / raw)
  To: Ondrej Zary; +Cc: Stephen Rothwell, linux-pm, linux-kernel

> Please don't turn Linux into second Windows.

No worry there.

I mention Microsoft not to advocate that Linux be Windows,
but to point out that this (hardware/firmware) ship sank 5 years
ago and Linux is still on the boat.  MS was able to delete 
APM support in 2006 from their source tree, yet we still carry it.

> If you don't want APM in the 
> kernel, just don't compile it. There are many people using older systems with 
> APM - and most of them wouldn't oppose to this removal as they don't even 
> know about it.

They can still run old Linux on an old APM-only laptop --
just like they can still run Windows 3.1 or Windows XP if they want to.

What we'd be taking away is their ability to run the latest
Linux kernel on that laptop.

The issue at hand is people (like me) who have to maintain
the latest Linux source code.  In sort, I don't want to
write, debug, and test a cpuidle driver for an apm-only laptop
when I could be spending effort on code that people will
actually run.

thanks,
-Len



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] x86 APM: delete Linux kernel APM support
  2011-03-24  8:39       ` [PATCH] x86 APM: delete Linux kernel APM support Ingo Molnar
@ 2011-03-24 23:49         ` Len Brown
  2011-03-25 11:30           ` Ingo Molnar
  2011-03-25 15:41           ` Calvin Walton
  0 siblings, 2 replies; 37+ messages in thread
From: Len Brown @ 2011-03-24 23:49 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Stephen Rothwell, x86, linux-pm, linux-kernel, Linus Torvalds,
	Thomas Gleixner, H. Peter Anvin, Andrew Morton

> > Microsoft was able to delete APM from Windows in 2006
> > with the release of Windows Vista. [...]
> 
> Does Windows XP still support it?

yes, and so does Red Hat Linux 9.

> Is weird as there's no such CONFIG_APM entry upstream, and never was. Which 
> tree is this entry included in?

It is a menuconfig option in arch/x86/Kconfig.
APM is available only for X86_32 kernels.

> While i'm not a fan of APM at all, this removal is a tad fast IMHO.
>
> Beyond the lack of a upstream-visible feature-removal-schedule entry, we still 
> have an Arcnet driver which hardware was obsoleted by Ethernet in the late 80s, 
> and we still have i486 support and those are *much* older than APM.

How would you like to write i486 specific code for the latest kernel
and test it on i486 hardware, honestly?

> If you look at the diffstat:
> 
> >  Documentation/feature-removal-schedule.txt |    9 -
> >  MAINTAINERS                                |    8 -
> >  arch/x86/Kconfig                           |  125 --
> >  arch/x86/boot/Makefile                     |    1 -
> >  arch/x86/boot/apm.c                        |   75 -
> >  arch/x86/boot/main.c                       |    5 -
> >  arch/x86/include/asm/bootparam.h           |    3 +-
> >  arch/x86/kernel/Makefile                   |    2 -
> >  arch/x86/kernel/apm_32.c                   | 2463 ----------------------------
> >  arch/x86/kernel/process.c                  |    3 -
> >  arch/x86/kernel/reboot.c                   |    3 -
> >  arch/x86/kernel/setup.c                    |    4 -
> >  12 files changed, 1 insertions(+), 2700 deletions(-)
> 
> You see that the kernel implementation is nicely modularized and its 
> cross-section to the rest of arch/x86/ is minimal. To arch/x86/ it's little 
> more than an obscure driver.

If you look at the hooks in the the diffstat you may be be less
impressed about how modular APM is.  Start with the use of pm_idle
from a module, or pm_flags.  The hackery is not a large number of lines,
but it is still hackery.

> Thus from a maintenance POV APM has not been much of a drag on the x86 
> maintainer side. Sure, we do not test it, but that's the case with most of the 
> obsolete drivers in the kernel.
> 
> The principle is that as long as there's no ongoing drag, the cost of carrying 
> obsolete drivers is minimal - and the unknown cost of screwing someone in a big 
> way by removing hardware support is hard to measure reliably. So we are 
> cautious and err on the side of supporting too much hardware.

I think this reasoning would apply in 2006, but that was 5 years ago.

> Removal could be prepared by:
> 
>  - moving CONFIG_APM to under CONFIG_EXPERT though, and keep it there for a few 
>    releases, and see whether anyone complains
> 
>  - we could emit a WARN() with a "APM support will be obsoleted, please report 
>    this if you depend on this feature" text or so, and see what happens for a 
>    couple of releases.

Okay, I can delay this way:

2.6.39:
	feature-removal.txt targets 2.6.42 removal
	depend on CONFIG_EXPERT

2.6.40, 2.6.41:
	WARN once on run-time access

2.6.42:
	remove.

How does that look?

thanks,
-Len



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] APM: delete APM in Linux-2.6.40
  2011-03-24 23:05       ` Len Brown
@ 2011-03-25  1:07         ` Henrique de Moraes Holschuh
  2011-03-25  1:34           ` Len Brown
  2011-04-04 16:44           ` Pavel Machek
  0 siblings, 2 replies; 37+ messages in thread
From: Henrique de Moraes Holschuh @ 2011-03-25  1:07 UTC (permalink / raw)
  To: Len Brown; +Cc: Stephen Rothwell, linux-pm, linux-kernel

On Thu, 24 Mar 2011, Len Brown wrote:
> > People with a ThinkPad T23, T30 will really not appreciate this, and it
> > should not be too difficult to recruit some as testers.
> 
> I have both, and they both support ACPI.

I wonder why I had some users of those two boxes advocating APM, maybe
it used to work better or something.  Or I got the T21 and A30 confused
with the T23.

Well, I don't think we need to support the thre-digit series ThinkPads,
the number of those still working is probably on the four digits
world-wide.  And I haven't heard from anyone with a T21 or A31 in a
while, so they might be down to five digits already.

If the T23 can actually work well in ACPI mode, I retract my objection.

> Re: lasting for years.
> Actually, I used to have several of both, but they're dying off,
> and they are excruciatingly slow...

Depends on what you use them for, I suppose.

-- 
  "One disk to rule them all, One disk to find them. One disk to bring
  them all and in the darkness grind them. In the Land of Redmond
  where the shadows lie." -- The Silicon Valley Tarot
  Henrique Holschuh

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] APM: delete APM in Linux-2.6.40
  2011-03-25  1:07         ` Henrique de Moraes Holschuh
@ 2011-03-25  1:34           ` Len Brown
  2011-04-04 16:44           ` Pavel Machek
  1 sibling, 0 replies; 37+ messages in thread
From: Len Brown @ 2011-03-25  1:34 UTC (permalink / raw)
  To: Henrique de Moraes Holschuh; +Cc: Stephen Rothwell, linux-pm, linux-kernel

> > > People with a ThinkPad T23, T30 will really not appreciate this, and it
> > > should not be too difficult to recruit some as testers.
> > 
> > I have both, and they both support ACPI.
> 
> I wonder why I had some users of those two boxes advocating APM, maybe
> it used to work better or something.  Or I got the T21 and A30 confused
> with the T23.

In 2003, APM worked better than ACPI on the T21 and the T23.
In 2005 or so, I think ACPI was working fine on them.

> Well, I don't think we need to support the thre-digit series ThinkPads,
> the number of those still working is probably on the four digits
> world-wide.  And I haven't heard from anyone with a T21 or A31 in a
> while, so they might be down to five digits already.
> 
> If the T23 can actually work well in ACPI mode, I retract my objection.

Thanks, ACPI works well on the T23.
Indeed, it works well back to the T20:-)

> > Re: lasting for years.
> > Actually, I used to have several of both, but they're dying off,
> > and they are excruciatingly slow...
> 
> Depends on what you use them for, I suppose.

My experience with old-laptops is:

1. hdd dies
2. CMOS battery dies
3. main battery dies

But from a practical view of runing a new distro on an old laptop,
the distros seem to drop the video support for the old controllers,
leaving you in VGA mode.  That is the case with the T23, which
has an S3 SuperSavage video controller.

cheers,
Len Brown, Intel Open Source Technolgy Center



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] APM: delete APM in Linux-2.6.40
  2011-03-24 23:29       ` Len Brown
@ 2011-03-25  8:07         ` Ondrej Zary
  2011-03-26  5:09           ` Len Brown
  0 siblings, 1 reply; 37+ messages in thread
From: Ondrej Zary @ 2011-03-25  8:07 UTC (permalink / raw)
  To: Len Brown; +Cc: Stephen Rothwell, linux-pm, linux-kernel

On Friday 25 March 2011, Len Brown wrote:
> > Please don't turn Linux into second Windows.
>
> No worry there.
>
> I mention Microsoft not to advocate that Linux be Windows,
> but to point out that this (hardware/firmware) ship sank 5 years
> ago and Linux is still on the boat.  MS was able to delete
> APM support in 2006 from their source tree, yet we still carry it.

And we also support ISA cards (network/sound/whatever). That's why many people 
(including me) like and use Linux. Take any old machine that has enough power 
to do the job you want and install Linux - e.g. get a Pentium box, install 
Debian and you have a mail server (and if you need to power it down, you need 
APM too). It's not possible with any other OS (well, maybe *BSD but Linux has 
more drivers).

If we remove support for older HW, Linux will never get a decent desktop 
market share. The common use case is "new Windows will not run (or run slow) 
on that (old) box, let's try Linux".

> > If you don't want APM in the
> > kernel, just don't compile it. There are many people using older systems
> > with APM - and most of them wouldn't oppose to this removal as they don't
> > even know about it.
>
> They can still run old Linux on an old APM-only laptop --
> just like they can still run Windows 3.1 or Windows XP if they want to.
>
> What we'd be taking away is their ability to run the latest
> Linux kernel on that laptop.

And that's bad. With Linux philosophy, you need new kernel to get new HW 
support. So if you have an APM-only laptop and would want to use a new USB 
device, you're out of luck. What to do then? Delete Linux and install Windows 
XP?

> The issue at hand is people (like me) who have to maintain
> the latest Linux source code.  In sort, I don't want to
> write, debug, and test a cpuidle driver for an apm-only laptop
> when I could be spending effort on code that people will
> actually run.

So don't do it then. If APM works now, keep it as is. Just like hgafb (HGA 
hardware is from 1984).

-- 
Ondrej Zary

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] x86 APM: delete Linux kernel APM support
  2011-03-24 23:49         ` Len Brown
@ 2011-03-25 11:30           ` Ingo Molnar
  2011-03-25 12:38             ` Ingo Molnar
                               ` (2 more replies)
  2011-03-25 15:41           ` Calvin Walton
  1 sibling, 3 replies; 37+ messages in thread
From: Ingo Molnar @ 2011-03-25 11:30 UTC (permalink / raw)
  To: Len Brown
  Cc: Stephen Rothwell, x86, linux-pm, linux-kernel, Linus Torvalds,
	Thomas Gleixner, H. Peter Anvin, Andrew Morton


* Len Brown <lenb@kernel.org> wrote:

> > Thus from a maintenance POV APM has not been much of a drag on the x86 
> > maintainer side. Sure, we do not test it, but that's the case with most of 
> > the obsolete drivers in the kernel.
> > 
> > The principle is that as long as there's no ongoing drag, the cost of 
> > carrying obsolete drivers is minimal - and the unknown cost of screwing 
> > someone in a big way by removing hardware support is hard to measure 
> > reliably. So we are cautious and err on the side of supporting too much 
> > hardware.
> 
> I think this reasoning would apply in 2006, but that was 5 years ago.

I cited a few real examples:

 > > Beyond the lack of a upstream-visible feature-removal-schedule entry, we 
 > > still have an Arcnet driver which hardware was obsoleted by Ethernet in the 
 > > late 80s, and we still have i486 support and those are *much* older than 
 > > APM.

So how does your reasoning not apply to those drivers? There's several which 
are older than APM support.

We had this really big battle about x86/Voyager two years ago, which x86 
subarchitecture literally had just a single user left, and the code was more 
intrusive than APM. Even there after much flaming the eventual consensus was 
that we'd accept it back if it was done cleanly, as part of the new-style 
x86_platform code.

Given that APM fits into the current PM frameworks there's no such problem here 
that i can see.

> Okay, I can delay this way:
> 
> 2.6.39:
> 	feature-removal.txt targets 2.6.42 removal
> 	depend on CONFIG_EXPERT
> 
> 2.6.40, 2.6.41:
> 	WARN once on run-time access
> 
> 2.6.42:
> 	remove.

Regardless of removal, i'd suggest a "this code is not supported" kind of 
WARN() message to the APM code today, into .39 - to see whether it pops up 
anywhere - and mark it for -stable as well.

.42 removal might be too fast, considering the typical release schedule of 
Linux distributions. And i'm still doubting the removal itself: we are adding 
lots of special-purpose subarch drivers to arch/x86/ as we speak (the embedded 
mess coming to x86) - which drivers will be tomorrow's APM code. On what 
grounds do we treat APM support differently?

Our general compatibility with old hardware is an *asset* that we should value.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] x86 APM: delete Linux kernel APM support
  2011-03-25 11:30           ` Ingo Molnar
@ 2011-03-25 12:38             ` Ingo Molnar
  2011-03-25 12:41               ` Ingo Molnar
  2011-03-25 22:33             ` Rafael J. Wysocki
  2011-03-26  5:01             ` Len Brown
  2 siblings, 1 reply; 37+ messages in thread
From: Ingo Molnar @ 2011-03-25 12:38 UTC (permalink / raw)
  To: Len Brown
  Cc: Stephen Rothwell, x86, linux-pm, linux-kernel, Linus Torvalds,
	Thomas Gleixner, H. Peter Anvin, Andrew Morton


* Ingo Molnar <mingo@elte.hu> wrote:

> > Okay, I can delay this way:
> > 
> > 2.6.39:
> > 	feature-removal.txt targets 2.6.42 removal
> > 	depend on CONFIG_EXPERT
> > 
> > 2.6.40, 2.6.41:
> > 	WARN once on run-time access
> > 
> > 2.6.42:
> > 	remove.
> 
> Regardless of removal, i'd suggest a "this code is not supported" kind of 
> WARN() message to the APM code today, into .39 - to see whether it pops up 
> anywhere - and mark it for -stable as well.
> 
> .42 removal might be too fast, considering the typical release schedule of 
> Linux distributions. [...]

Anyway, i'd ack this schedule if you queued up the WARN() today with a -stable 
tag, on the condition that if we get complaints about that message, we keep APM 
support.

If there are people who are still using it then we should not remove it, 
agreed?

	Ingo

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] x86 APM: delete Linux kernel APM support
  2011-03-25 12:38             ` Ingo Molnar
@ 2011-03-25 12:41               ` Ingo Molnar
  0 siblings, 0 replies; 37+ messages in thread
From: Ingo Molnar @ 2011-03-25 12:41 UTC (permalink / raw)
  To: Len Brown
  Cc: Stephen Rothwell, x86, linux-pm, linux-kernel, Linus Torvalds,
	Thomas Gleixner, H. Peter Anvin, Andrew Morton


* Ingo Molnar <mingo@elte.hu> wrote:

> 
> * Ingo Molnar <mingo@elte.hu> wrote:
> 
> > > Okay, I can delay this way:
> > > 
> > > 2.6.39:
> > > 	feature-removal.txt targets 2.6.42 removal
> > > 	depend on CONFIG_EXPERT
> > > 
> > > 2.6.40, 2.6.41:
> > > 	WARN once on run-time access
> > > 
> > > 2.6.42:
> > > 	remove.
> > 
> > Regardless of removal, i'd suggest a "this code is not supported" kind of 
> > WARN() message to the APM code today, into .39 - to see whether it pops up 
> > anywhere - and mark it for -stable as well.
> > 
> > .42 removal might be too fast, considering the typical release schedule of 
> > Linux distributions. [...]
> 
> Anyway, i'd ack this schedule if you queued up the WARN() today with a -stable 
> tag, on the condition that if we get complaints about that message, we keep APM 
> support.

s/today/for .39

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] x86 APM: delete Linux kernel APM support
  2011-03-24 23:49         ` Len Brown
  2011-03-25 11:30           ` Ingo Molnar
@ 2011-03-25 15:41           ` Calvin Walton
  1 sibling, 0 replies; 37+ messages in thread
From: Calvin Walton @ 2011-03-25 15:41 UTC (permalink / raw)
  To: Len Brown
  Cc: Ingo Molnar, Stephen Rothwell, x86, linux-pm, linux-kernel,
	Linus Torvalds, Thomas Gleixner, H. Peter Anvin, Andrew Morton

On Thu, 2011-03-24 at 19:49 -0400, Len Brown wrote:
> > > Microsoft was able to delete APM from Windows in 2006
> > > with the release of Windows Vista. [...]
> > 
> > Does Windows XP still support it?
> 
> yes, and so does Red Hat Linux 9.

> > While i'm not a fan of APM at all, this removal is a tad fast IMHO.
> >
> > Beyond the lack of a upstream-visible feature-removal-schedule entry, we still 
> > have an Arcnet driver which hardware was obsoleted by Ethernet in the late 80s, 
> > and we still have i486 support and those are *much* older than APM.
> 
> How would you like to write i486 specific code for the latest kernel
> and test it on i486 hardware, honestly?

Hmm, that reminds me: I should try a newer kernel on my 486 some time,
it's still running 2.6.25. I'm actually quite honestly surprised that
the modern libata drivers include code for and fully support my old
vesa-bus IDE controller! (X has been less friendly, they dropped support
for the graphics chipset during the Xfree86 4 development--but I mostly
use this box headless.)

-- 
Calvin Walton <calvin.walton@kepstin.ca>


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] x86 APM: delete Linux kernel APM support
  2011-03-25 11:30           ` Ingo Molnar
  2011-03-25 12:38             ` Ingo Molnar
@ 2011-03-25 22:33             ` Rafael J. Wysocki
  2011-03-26  4:35               ` Len Brown
  2011-04-08  6:25               ` Pavel Machek
  2011-03-26  5:01             ` Len Brown
  2 siblings, 2 replies; 37+ messages in thread
From: Rafael J. Wysocki @ 2011-03-25 22:33 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Len Brown, Stephen Rothwell, x86, linux-pm, linux-kernel,
	Linus Torvalds, Thomas Gleixner, H. Peter Anvin, Andrew Morton

On Friday, March 25, 2011, Ingo Molnar wrote:
> 
> * Len Brown <lenb@kernel.org> wrote:
> 
> > > Thus from a maintenance POV APM has not been much of a drag on the x86 
> > > maintainer side. Sure, we do not test it, but that's the case with most of 
> > > the obsolete drivers in the kernel.
> > > 
> > > The principle is that as long as there's no ongoing drag, the cost of 
> > > carrying obsolete drivers is minimal - and the unknown cost of screwing 
> > > someone in a big way by removing hardware support is hard to measure 
> > > reliably. So we are cautious and err on the side of supporting too much 
> > > hardware.
> > 
> > I think this reasoning would apply in 2006, but that was 5 years ago.
> 
> I cited a few real examples:
> 
>  > > Beyond the lack of a upstream-visible feature-removal-schedule entry, we 
>  > > still have an Arcnet driver which hardware was obsoleted by Ethernet in the 
>  > > late 80s, and we still have i486 support and those are *much* older than 
>  > > APM.
> 
> So how does your reasoning not apply to those drivers? There's several which 
> are older than APM support.
> 
> We had this really big battle about x86/Voyager two years ago, which x86 
> subarchitecture literally had just a single user left, and the code was more 
> intrusive than APM. Even there after much flaming the eventual consensus was 
> that we'd accept it back if it was done cleanly, as part of the new-style 
> x86_platform code.
> 
> Given that APM fits into the current PM frameworks there's no such problem here 
> that i can see.

Well, it kind of does but not really. :-)

The main problem with APM is that nobody really works on it and I'm not sure
if there are any active users.  At least no one reports any problems with it,
which is kind of surprising, given the number of chages we've made in the PM
core for the last couple of years.  So quite likely it's just become
non-functional over time anyway, but we have no confirmation.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] x86 APM: delete Linux kernel APM support
  2011-03-25 22:33             ` Rafael J. Wysocki
@ 2011-03-26  4:35               ` Len Brown
  2011-04-08  6:25               ` Pavel Machek
  1 sibling, 0 replies; 37+ messages in thread
From: Len Brown @ 2011-03-26  4:35 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Ingo Molnar, Stephen Rothwell, x86, linux-pm, linux-kernel,
	Linus Torvalds, Thomas Gleixner, H. Peter Anvin, Andrew Morton

> >  > > Beyond the lack of a upstream-visible feature-removal-schedule entry, we 
> >  > > still have an Arcnet driver which hardware was obsoleted by Ethernet in the 
> >  > > late 80s, and we still have i486 support and those are *much* older than 
> >  > > APM.

> > So how does your reasoning not apply to those drivers? There's several which 
> > are older than APM support.

If we follow-through with the proposed cpuidle changes,
then we'll have to cut APM code.   The problem isn't cutting
the code, it is testing it.  I do have a couple of 15-year old
laptops which include APM support.  However, with ACPI disabled
to enable APM, they don't even boot the upstream kernel today.

> > We had this really big battle about x86/Voyager two years ago, which x86 
> > subarchitecture literally had just a single user left, and the code was more 
> > intrusive than APM. Even there after much flaming the eventual consensus was 
> > that we'd accept it back if it was done cleanly, as part of the new-style 
> > x86_platform code.
> > 
> > Given that APM fits into the current PM frameworks there's no such problem here 
> > that i can see.

Somebody was pushing for Voyager support in the kernel
and was energetic about maintaining it.

cheers,
-Len


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] x86 APM: delete Linux kernel APM support
  2011-03-25 11:30           ` Ingo Molnar
  2011-03-25 12:38             ` Ingo Molnar
  2011-03-25 22:33             ` Rafael J. Wysocki
@ 2011-03-26  5:01             ` Len Brown
  2011-03-26  9:31               ` Ingo Molnar
                                 ` (2 more replies)
  2 siblings, 3 replies; 37+ messages in thread
From: Len Brown @ 2011-03-26  5:01 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Stephen Rothwell, x86, linux-pm, linux-kernel, Linus Torvalds,
	Thomas Gleixner, H. Peter Anvin, Andrew Morton

> Regardless of removal, i'd suggest a "this code is not supported" kind of 
> WARN() message to the APM code today, into .39 - to see whether it pops up 
> anywhere - and mark it for -stable as well.

Okay, can do.

> .42 removal might be too fast, considering the typical release schedule of 
> Linux distributions. And i'm still doubting the removal itself: we are adding 
> lots of special-purpose subarch drivers to arch/x86/ as we speak (the embedded 
> mess coming to x86) - which drivers will be tomorrow's APM code. On what 
> grounds do we treat APM support differently?
>
> Our general compatibility with old hardware is an *asset* that we should value.

My guess is that the customers have died off,
and so the code is no longer an asset, but a maintenance liability.

If there is a buzzing community of people running 2011
linux kernels on their ancient laptops in APM mode,
then the APM maintainer would probably know about them.

Personally, my oldest usable laptop is a T23 from March 2002.
It supports APM and ACPI (it shipped with Win2K).
Linux works well on it in ACPI mode, but doesn't even boot in APM mode.
If anybody was really using the latest kernel in APM mode,
I suspect this laptop would boot...

Is there somebody on LKML that has a older laptop than me
and is able to get it to boot in APM mode?  I'd be astonished
if there was not.  Are they willing to regularly test changes
to the upstream kernel to make sure that APM still works?
If yes, where have they been for the last 5 years?

I suspect when there is nobody using the latest kernel on mrst,
then the latest kernel can delete support for mrst, and nobody will care.
Like APM, it will probably undergo "maintenance without testing",
aka bit rot, for a period before that happens.

cheers,
-Len

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] APM: delete APM in Linux-2.6.40
  2011-03-25  8:07         ` Ondrej Zary
@ 2011-03-26  5:09           ` Len Brown
  0 siblings, 0 replies; 37+ messages in thread
From: Len Brown @ 2011-03-26  5:09 UTC (permalink / raw)
  To: Ondrej Zary; +Cc: Stephen Rothwell, linux-pm, linux-kernel

> > > Please don't turn Linux into second Windows.
> >
> > No worry there.
> >
> > I mention Microsoft not to advocate that Linux be Windows,
> > but to point out that this (hardware/firmware) ship sank 5 years
> > ago and Linux is still on the boat.  MS was able to delete
> > APM support in 2006 from their source tree, yet we still carry it.
> 
> And we also support ISA cards (network/sound/whatever). That's why many people 
> (including me) like and use Linux. Take any old machine that has enough power 
> to do the job you want and install Linux - e.g. get a Pentium box, install 
> Debian and you have a mail server (and if you need to power it down, you need 
> APM too). It's not possible with any other OS (well, maybe *BSD but Linux has 
> more drivers).
> 
> If we remove support for older HW, Linux will never get a decent desktop 
> market share. The common use case is "new Windows will not run (or run slow) 
> on that (old) box, let's try Linux".

Supporting APM is not a path to increased desktop market share.
Indeed, one could easily argue it would be the opposite.

> > > If you don't want APM in the
> > > kernel, just don't compile it. There are many people using older systems
> > > with APM - and most of them wouldn't oppose to this removal as they don't
> > > even know about it.
> >
> > They can still run old Linux on an old APM-only laptop --
> > just like they can still run Windows 3.1 or Windows XP if they want to.
> >
> > What we'd be taking away is their ability to run the latest
> > Linux kernel on that laptop.
> 
> And that's bad. With Linux philosophy, you need new kernel to get new HW 
> support. So if you have an APM-only laptop and would want to use a new USB 
> device, you're out of luck. What to do then? Delete Linux and install Windows 
> XP?
> 
> > The issue at hand is people (like me) who have to maintain
> > the latest Linux source code.  In sort, I don't want to
> > write, debug, and test a cpuidle driver for an apm-only laptop
> > when I could be spending effort on code that people will
> > actually run.
> 
> So don't do it then. If APM works now, keep it as is. Just like hgafb (HGA 
> hardware is from 1984).

Speaking for the only old system I have with APM support,
today's kernel already doesn't boot on it in APM mode.
(it boots fine in ACPI mode, though as you mentioned,
 X already dropped support for its decade-old graphics controller)

cheers,
-Len


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] x86 APM: delete Linux kernel APM support
  2011-03-26  5:01             ` Len Brown
@ 2011-03-26  9:31               ` Ingo Molnar
  2011-03-27 21:40               ` Ondrej Zary
  2011-03-28  5:18               ` Ingo Molnar
  2 siblings, 0 replies; 37+ messages in thread
From: Ingo Molnar @ 2011-03-26  9:31 UTC (permalink / raw)
  To: Len Brown
  Cc: Stephen Rothwell, x86, linux-pm, linux-kernel, Linus Torvalds,
	Thomas Gleixner, H. Peter Anvin, Andrew Morton


* Len Brown <lenb@kernel.org> wrote:

> Personally, my oldest usable laptop is a T23 from March 2002.
> It supports APM and ACPI (it shipped with Win2K).
> Linux works well on it in ACPI mode, but doesn't even boot in APM mode.
> If anybody was really using the latest kernel in APM mode,
> I suspect this laptop would boot...

I boot non-ACPI kernels all the time:

  mercury:~> grep -E 'PM|ACPI' /proc/config.gz 
  mercury:~> 
  mercury:~> uname -a
  Linux mercury 2.6.38-tip+ #110579 SMP Sat Mar 26 11:47:58 CET 2011 x86_64 x86_64 x86_64 GNU/Linux

How does it fail for you?

Could you describe the steps you'd like to see from folks using APM to see it 
tested? What kernel configs, BIOS options, etc., what should they see in the 
syslog, etc. - to make sure APM mode is still working fine?

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] x86 APM: delete Linux kernel APM support
  2011-03-26  5:01             ` Len Brown
  2011-03-26  9:31               ` Ingo Molnar
@ 2011-03-27 21:40               ` Ondrej Zary
  2011-03-28  4:51                 ` Ingo Molnar
  2011-03-28 12:57                 ` H. Peter Anvin
  2011-03-28  5:18               ` Ingo Molnar
  2 siblings, 2 replies; 37+ messages in thread
From: Ondrej Zary @ 2011-03-27 21:40 UTC (permalink / raw)
  To: Len Brown
  Cc: Ingo Molnar, Stephen Rothwell, x86, linux-pm, linux-kernel,
	Linus Torvalds, Thomas Gleixner, H. Peter Anvin, Andrew Morton

On Saturday 26 March 2011 06:01:38 Len Brown wrote:
> > Regardless of removal, i'd suggest a "this code is not supported" kind of
> > WARN() message to the APM code today, into .39 - to see whether it pops
> > up anywhere - and mark it for -stable as well.
>
> Okay, can do.
>
> > .42 removal might be too fast, considering the typical release schedule
> > of Linux distributions. And i'm still doubting the removal itself: we are
> > adding lots of special-purpose subarch drivers to arch/x86/ as we speak
> > (the embedded mess coming to x86) - which drivers will be tomorrow's APM
> > code. On what grounds do we treat APM support differently?
> >
> > Our general compatibility with old hardware is an *asset* that we should
> > value.
>
> My guess is that the customers have died off,
> and so the code is no longer an asset, but a maintenance liability.
>
> If there is a buzzing community of people running 2011
> linux kernels on their ancient laptops in APM mode,
> then the APM maintainer would probably know about them.
>
> Personally, my oldest usable laptop is a T23 from March 2002.
> It supports APM and ACPI (it shipped with Win2K).
> Linux works well on it in ACPI mode, but doesn't even boot in APM mode.
> If anybody was really using the latest kernel in APM mode,
> I suspect this laptop would boot...
>
> Is there somebody on LKML that has a older laptop than me
> and is able to get it to boot in APM mode?  I'd be astonished
> if there was not.  Are they willing to regularly test changes
> to the upstream kernel to make sure that APM still works?
> If yes, where have they been for the last 5 years?

I just tested 2.6.38-rc4 on a desktop board and it works (power off at least). 
If using Grub2, linux16 command must be used instead of linux in grub.cfg 
(otherwise loading apm module will fail with "apm: BIOS not found").

I also have some working laptops with APM but haven't tried recent kernels 
yet.

> I suspect when there is nobody using the latest kernel on mrst,
> then the latest kernel can delete support for mrst, and nobody will care.
> Like APM, it will probably undergo "maintenance without testing",
> aka bit rot, for a period before that happens.

-- 
Ondrej Zary

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] x86 APM: delete Linux kernel APM support
  2011-03-27 21:40               ` Ondrej Zary
@ 2011-03-28  4:51                 ` Ingo Molnar
  2011-03-28  5:43                   ` H. Peter Anvin
  2011-03-28 12:57                 ` H. Peter Anvin
  1 sibling, 1 reply; 37+ messages in thread
From: Ingo Molnar @ 2011-03-28  4:51 UTC (permalink / raw)
  To: Ondrej Zary
  Cc: Len Brown, Stephen Rothwell, x86, linux-pm, linux-kernel,
	Linus Torvalds, Thomas Gleixner, H. Peter Anvin, Andrew Morton


* Ondrej Zary <linux@rainbow-software.org> wrote:

> > Is there somebody on LKML that has a older laptop than me
> > and is able to get it to boot in APM mode?  I'd be astonished
> > if there was not.  Are they willing to regularly test changes
> > to the upstream kernel to make sure that APM still works?
> > If yes, where have they been for the last 5 years?
> 
> I just tested 2.6.38-rc4 on a desktop board and it works (power off at least). 

Ok, thanks for testing. I too tried APM poweroff in the not too distant past 
and it worked - but not very recent kernels.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] x86 APM: delete Linux kernel APM support
  2011-03-26  5:01             ` Len Brown
  2011-03-26  9:31               ` Ingo Molnar
  2011-03-27 21:40               ` Ondrej Zary
@ 2011-03-28  5:18               ` Ingo Molnar
  2 siblings, 0 replies; 37+ messages in thread
From: Ingo Molnar @ 2011-03-28  5:18 UTC (permalink / raw)
  To: Len Brown
  Cc: Stephen Rothwell, x86, linux-pm, linux-kernel, Linus Torvalds,
	Thomas Gleixner, H. Peter Anvin, Andrew Morton


* Len Brown <lenb@kernel.org> wrote:

> > .42 removal might be too fast, considering the typical release schedule of 
> > Linux distributions. And i'm still doubting the removal itself: we are 
> > adding lots of special-purpose subarch drivers to arch/x86/ as we speak 
> > (the embedded mess coming to x86) - which drivers will be tomorrow's APM 
> > code. On what grounds do we treat APM support differently?
> >
> > Our general compatibility with old hardware is an *asset* that we should value.
> 
> My guess is that the customers have died off,

How do we know that? Users are on a bell curve, with a fat tail. If stuff just 
works - and that's not unexpected from relatively simple (and most likely to be 
used) APM functionality like APM-poweroff, why should they ever report 
problems?

Removing a driver based on lack of visible feedback is like removing 190,000 
apps from a 200,000 apps app store, on the (valid) observation that the top 
1000 apps receive 99% of the traffic and use so the remaining 1% are just a 
maintenance burden.

There's value in the concept of knowing that we do not do forced obscolescence 
in Linux and there's a value in a very broad "there's a driver for that" 
concept, just like there's value in a very broad "there's an app for that" 
concept.

> and so the code is no longer an asset, but a maintenance liability.
> 
> If there is a buzzing community of people running 2011
> linux kernels on their ancient laptops in APM mode,
> then the APM maintainer would probably know about them.

Not if most of them use APM-poweroff. I think i even had a desktop box (not a 
laptop) that supported APM suspend (or am i mistaken there, was APM suspend 
support only limited to laptops?).

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] x86 APM: delete Linux kernel APM support
  2011-03-28  4:51                 ` Ingo Molnar
@ 2011-03-28  5:43                   ` H. Peter Anvin
  0 siblings, 0 replies; 37+ messages in thread
From: H. Peter Anvin @ 2011-03-28  5:43 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Ondrej Zary, Len Brown, Stephen Rothwell, x86, linux-pm,
	linux-kernel, Linus Torvalds, Thomas Gleixner, Andrew Morton

On 03/27/2011 09:51 PM, Ingo Molnar wrote:
> 
> * Ondrej Zary <linux@rainbow-software.org> wrote:
> 
>>> Is there somebody on LKML that has a older laptop than me
>>> and is able to get it to boot in APM mode?  I'd be astonished
>>> if there was not.  Are they willing to regularly test changes
>>> to the upstream kernel to make sure that APM still works?
>>> If yes, where have they been for the last 5 years?
>>
>> I just tested 2.6.38-rc4 on a desktop board and it works (power off at least). 
> 
> Ok, thanks for testing. I too tried APM poweroff in the not too distant past 
> and it worked - but not very recent kernels.
> 

Given that the current merge window rewrote this code, it would be good
to get it tested on 2.6.39-rc1 when it becomes available.

	-hpa

-- 
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] x86 APM: delete Linux kernel APM support
  2011-03-27 21:40               ` Ondrej Zary
  2011-03-28  4:51                 ` Ingo Molnar
@ 2011-03-28 12:57                 ` H. Peter Anvin
  1 sibling, 0 replies; 37+ messages in thread
From: H. Peter Anvin @ 2011-03-28 12:57 UTC (permalink / raw)
  To: Ondrej Zary
  Cc: Len Brown, Ingo Molnar, Stephen Rothwell, x86, linux-pm,
	linux-kernel, Linus Torvalds, Thomas Gleixner, Andrew Morton

On 03/27/2011 02:40 PM, Ondrej Zary wrote:
> 
> I just tested 2.6.38-rc4 on a desktop board and it works (power off at least). 
> If using Grub2, linux16 command must be used instead of linux in grub.cfg 
> (otherwise loading apm module will fail with "apm: BIOS not found").
> 

This is just Yet Another Example of the Grub2 people doing things in the
absolutely most idiotic way possible by default, and then blaming the user.

	-hpa

-- 
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.


^ permalink raw reply	[flat|nested] 37+ messages in thread

* RE: [PATCH] APM: delete APM in Linux-2.6.40
  2011-03-24  7:39   ` [PATCH] APM: delete APM in Linux-2.6.40 Len Brown
                       ` (4 preceding siblings ...)
  2011-03-24 12:15     ` Ondrej Zary
@ 2011-04-02 21:40     ` Yuhong Bao
  5 siblings, 0 replies; 37+ messages in thread
From: Yuhong Bao @ 2011-04-02 21:40 UTC (permalink / raw)
  To: lenb, sfr; +Cc: linux-pm, linux-kernel


> +Why: Microsoft deleted APM from Windows as of Vista in in 2006.

To be more precise, support for all hardware that do not support ACPI.
Also required for Vista and later is a 586 processor with TSC, such as Intel Pentium or later
 
Yuhong Bao 		 	   		  

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] APM: delete APM in Linux-2.6.40
  2011-03-25  1:07         ` Henrique de Moraes Holschuh
  2011-03-25  1:34           ` Len Brown
@ 2011-04-04 16:44           ` Pavel Machek
  2011-04-04 20:18             ` Len Brown
  1 sibling, 1 reply; 37+ messages in thread
From: Pavel Machek @ 2011-04-04 16:44 UTC (permalink / raw)
  To: Henrique de Moraes Holschuh
  Cc: Len Brown, Stephen Rothwell, linux-pm, linux-kernel

Hi!

> > > People with a ThinkPad T23, T30 will really not appreciate this, and it
> > > should not be too difficult to recruit some as testers.
> > 
> > I have both, and they both support ACPI.
> 
> I wonder why I had some users of those two boxes advocating APM, maybe
> it used to work better or something.  Or I got the T21 and A30 confused
> with the T23.
> 
> Well, I don't think we need to support the thre-digit series ThinkPads,
> the number of those still working is probably on the four digits
> world-wide.  And I haven't heard from anyone with a T21 or A31 in a
> while, so they might be down to five digits already.

I still have working thinkpad 560X, my brother occassionaly uses it...

I do not think we should remove APM support like this. It does not
seem to be huge maintainance burden...
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] APM: delete APM in Linux-2.6.40
  2011-04-04 16:44           ` Pavel Machek
@ 2011-04-04 20:18             ` Len Brown
  0 siblings, 0 replies; 37+ messages in thread
From: Len Brown @ 2011-04-04 20:18 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Henrique de Moraes Holschuh, Stephen Rothwell, linux-pm, linux-kernel


> I still have working thinkpad 560X, my brother occassionaly uses it...

There is no doubt that there are still people running Linux
on old APM laptops.

The question, however, is if they're running (or will run)
the latest upstream kernel.  Further, are they available
to test APM patches to the latest upstream kernel.

> I do not think we should remove APM support like this. It does not
> seem to be huge maintainance burden...

Last week we decided not to delete APM yet.
The jury is still out on APM's idle hooks.

cheers,
Len Brown, Intel Open Source Technology Center


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] x86 APM: delete Linux kernel APM support
  2011-03-25 22:33             ` Rafael J. Wysocki
  2011-03-26  4:35               ` Len Brown
@ 2011-04-08  6:25               ` Pavel Machek
  2011-04-08 20:55                 ` H. Peter Anvin
  1 sibling, 1 reply; 37+ messages in thread
From: Pavel Machek @ 2011-04-08  6:25 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Ingo Molnar, Len Brown, Stephen Rothwell, x86, linux-pm,
	linux-kernel, Linus Torvalds, Thomas Gleixner, H. Peter Anvin,
	Andrew Morton

Hi!

> > So how does your reasoning not apply to those drivers? There's several which 
> > are older than APM support.
> > 
> > We had this really big battle about x86/Voyager two years ago, which x86 
> > subarchitecture literally had just a single user left, and the code was more 
> > intrusive than APM. Even there after much flaming the eventual consensus was 
> > that we'd accept it back if it was done cleanly, as part of the new-style 
> > x86_platform code.
> > 
> > Given that APM fits into the current PM frameworks there's no such problem here 
> > that i can see.
> 
> Well, it kind of does but not really. :-)
> 
> The main problem with APM is that nobody really works on it and I'm not sure
> if there are any active users.  At least no one reports any problems with it,
> which is kind of surprising, given the number of chages we've made in the PM
> core for the last couple of years.  So quite likely it's just become
> non-functional over time anyway, but we have no confirmation.

It was working ok last time I tried -- cca 6/2010.
								Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] x86 APM: delete Linux kernel APM support
  2011-04-08  6:25               ` Pavel Machek
@ 2011-04-08 20:55                 ` H. Peter Anvin
  2011-04-11 13:05                   ` Pavel Machek
  0 siblings, 1 reply; 37+ messages in thread
From: H. Peter Anvin @ 2011-04-08 20:55 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Rafael J. Wysocki, Ingo Molnar, Len Brown, Stephen Rothwell, x86,
	linux-pm, linux-kernel, Linus Torvalds, Thomas Gleixner,
	Andrew Morton

On 04/07/2011 11:25 PM, Pavel Machek wrote:
>>
>> Well, it kind of does but not really. :-)
>>
>> The main problem with APM is that nobody really works on it and I'm not sure
>> if there are any active users.  At least no one reports any problems with it,
>> which is kind of surprising, given the number of chages we've made in the PM
>> core for the last couple of years.  So quite likely it's just become
>> non-functional over time anyway, but we have no confirmation.
> 
> It was working ok last time I tried -- cca 6/2010.
> 								Pavel

What aspects of it did you test, and on what platform?

	-hpa


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] x86 APM: delete Linux kernel APM support
  2011-04-08 20:55                 ` H. Peter Anvin
@ 2011-04-11 13:05                   ` Pavel Machek
  2011-04-11 18:19                     ` H. Peter Anvin
  0 siblings, 1 reply; 37+ messages in thread
From: Pavel Machek @ 2011-04-11 13:05 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Rafael J. Wysocki, Ingo Molnar, Len Brown, Stephen Rothwell, x86,
	linux-pm, linux-kernel, Linus Torvalds, Thomas Gleixner,
	Andrew Morton

Hi!

> >> Well, it kind of does but not really. :-)
> >>
> >> The main problem with APM is that nobody really works on it and I'm not sure
> >> if there are any active users.  At least no one reports any problems with it,
> >> which is kind of surprising, given the number of chages we've made in the PM
> >> core for the last couple of years.  So quite likely it's just become
> >> non-functional over time anyway, but we have no confirmation.
> > 
> > It was working ok last time I tried -- cca 6/2010.
> 
> What aspects of it did you test, and on what platform?

thinkpad 560X.

I tested basic boot, IIRC it did turn backlight off properly in
screensaver and even suspend worked.
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] x86 APM: delete Linux kernel APM support
  2011-04-11 13:05                   ` Pavel Machek
@ 2011-04-11 18:19                     ` H. Peter Anvin
  2011-04-13 13:30                       ` Pavel Machek
  0 siblings, 1 reply; 37+ messages in thread
From: H. Peter Anvin @ 2011-04-11 18:19 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Rafael J. Wysocki, Ingo Molnar, Len Brown, Stephen Rothwell, x86,
	linux-pm, linux-kernel, Linus Torvalds, Thomas Gleixner,
	Andrew Morton

On 04/11/2011 06:05 AM, Pavel Machek wrote:
> Hi!
> 
>>>> Well, it kind of does but not really. :-)
>>>>
>>>> The main problem with APM is that nobody really works on it and I'm not sure
>>>> if there are any active users.  At least no one reports any problems with it,
>>>> which is kind of surprising, given the number of chages we've made in the PM
>>>> core for the last couple of years.  So quite likely it's just become
>>>> non-functional over time anyway, but we have no confirmation.
>>>
>>> It was working ok last time I tried -- cca 6/2010.
>>
>> What aspects of it did you test, and on what platform?
> 
> thinkpad 560X.
> 
> I tested basic boot, IIRC it did turn backlight off properly in
> screensaver and even suspend worked.
> 									Pavel

OK, but I presume runtime power management wasn't on the list at least
on what matters.

	-hpa


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH] x86 APM: delete Linux kernel APM support
  2011-04-11 18:19                     ` H. Peter Anvin
@ 2011-04-13 13:30                       ` Pavel Machek
  0 siblings, 0 replies; 37+ messages in thread
From: Pavel Machek @ 2011-04-13 13:30 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Rafael J. Wysocki, Ingo Molnar, Len Brown, Stephen Rothwell, x86,
	linux-pm, linux-kernel, Linus Torvalds, Thomas Gleixner,
	Andrew Morton

On Mon 2011-04-11 11:19:05, H. Peter Anvin wrote:
> On 04/11/2011 06:05 AM, Pavel Machek wrote:
> > Hi!
...
> >> What aspects of it did you test, and on what platform?
> > 
> > thinkpad 560X.
> > 
> > I tested basic boot, IIRC it did turn backlight off properly in
> > screensaver and even suspend worked.
> 
> OK, but I presume runtime power management wasn't on the list at least
> on what matters.

No, I was not measuring with the multimeter. (This machine still
has 2nd, good battery, I could...). I'd notice if it broke horribly.

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2011-04-13 13:32 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <alpine.LFD.2.02.1103232321070.3848@x980>
     [not found] ` <20110324154505.934a56a0.sfr@canb.auug.org.au>
2011-03-24  7:39   ` [PATCH] APM: delete APM in Linux-2.6.40 Len Brown
2011-03-24  8:16     ` [PATCH] x86 APM: delete Linux kernel APM support Len Brown
2011-03-24  8:31       ` [PATCH] x86 APM: delete Linux kernel APM support (v2) Len Brown
2011-03-24 16:01         ` Andi Kleen
2011-03-24  8:39       ` [PATCH] x86 APM: delete Linux kernel APM support Ingo Molnar
2011-03-24 23:49         ` Len Brown
2011-03-25 11:30           ` Ingo Molnar
2011-03-25 12:38             ` Ingo Molnar
2011-03-25 12:41               ` Ingo Molnar
2011-03-25 22:33             ` Rafael J. Wysocki
2011-03-26  4:35               ` Len Brown
2011-04-08  6:25               ` Pavel Machek
2011-04-08 20:55                 ` H. Peter Anvin
2011-04-11 13:05                   ` Pavel Machek
2011-04-11 18:19                     ` H. Peter Anvin
2011-04-13 13:30                       ` Pavel Machek
2011-03-26  5:01             ` Len Brown
2011-03-26  9:31               ` Ingo Molnar
2011-03-27 21:40               ` Ondrej Zary
2011-03-28  4:51                 ` Ingo Molnar
2011-03-28  5:43                   ` H. Peter Anvin
2011-03-28 12:57                 ` H. Peter Anvin
2011-03-28  5:18               ` Ingo Molnar
2011-03-25 15:41           ` Calvin Walton
2011-03-24  8:18     ` [PATCH] APM: delete APM in Linux-2.6.40 Stephen Rothwell
2011-03-24  8:38     ` Alexander Stein
2011-03-24 10:21     ` Henrique de Moraes Holschuh
2011-03-24 23:05       ` Len Brown
2011-03-25  1:07         ` Henrique de Moraes Holschuh
2011-03-25  1:34           ` Len Brown
2011-04-04 16:44           ` Pavel Machek
2011-04-04 20:18             ` Len Brown
2011-03-24 12:15     ` Ondrej Zary
2011-03-24 23:29       ` Len Brown
2011-03-25  8:07         ` Ondrej Zary
2011-03-26  5:09           ` Len Brown
2011-04-02 21:40     ` Yuhong Bao

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).