Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* -*- linux-c -*-
0003  * APM BIOS driver for Linux
0004  * Copyright 1994-2001 Stephen Rothwell (sfr@canb.auug.org.au)
0005  *
0006  * Initial development of this driver was funded by NEC Australia P/L
0007  *  and NEC Corporation
0008  *
0009  * October 1995, Rik Faith (faith@cs.unc.edu):
0010  *    Minor enhancements and updates (to the patch set) for 1.3.x
0011  *    Documentation
0012  * January 1996, Rik Faith (faith@cs.unc.edu):
0013  *    Make /proc/apm easy to format (bump driver version)
0014  * March 1996, Rik Faith (faith@cs.unc.edu):
0015  *    Prohibit APM BIOS calls unless apm_enabled.
0016  *    (Thanks to Ulrich Windl <Ulrich.Windl@rz.uni-regensburg.de>)
0017  * April 1996, Stephen Rothwell (sfr@canb.auug.org.au)
0018  *    Version 1.0 and 1.1
0019  * May 1996, Version 1.2
0020  * Feb 1998, Version 1.3
0021  * Feb 1998, Version 1.4
0022  * Aug 1998, Version 1.5
0023  * Sep 1998, Version 1.6
0024  * Nov 1998, Version 1.7
0025  * Jan 1999, Version 1.8
0026  * Jan 1999, Version 1.9
0027  * Oct 1999, Version 1.10
0028  * Nov 1999, Version 1.11
0029  * Jan 2000, Version 1.12
0030  * Feb 2000, Version 1.13
0031  * Nov 2000, Version 1.14
0032  * Oct 2001, Version 1.15
0033  * Jan 2002, Version 1.16
0034  * Oct 2002, Version 1.16ac
0035  *
0036  * History:
0037  *    0.6b: first version in official kernel, Linux 1.3.46
0038  *    0.7: changed /proc/apm format, Linux 1.3.58
0039  *    0.8: fixed gcc 2.7.[12] compilation problems, Linux 1.3.59
0040  *    0.9: only call bios if bios is present, Linux 1.3.72
0041  *    1.0: use fixed device number, consolidate /proc/apm into this file,
0042  *         Linux 1.3.85
0043  *    1.1: support user-space standby and suspend, power off after system
0044  *         halted, Linux 1.3.98
0045  *    1.2: When resetting RTC after resume, take care so that the time
0046  *         is only incorrect by 30-60mS (vs. 1S previously) (Gabor J. Toth
0047  *         <jtoth@princeton.edu>); improve interaction between
0048  *         screen-blanking and gpm (Stephen Rothwell); Linux 1.99.4
0049  *    1.2a:Simple change to stop mysterious bug reports with SMP also added
0050  *     levels to the printk calls. APM is not defined for SMP machines.
0051  *         The new replacement for it is, but Linux doesn't yet support this.
0052  *         Alan Cox Linux 2.1.55
0053  *    1.3: Set up a valid data descriptor 0x40 for buggy BIOS's
0054  *    1.4: Upgraded to support APM 1.2. Integrated ThinkPad suspend patch by
0055  *         Dean Gaudet <dgaudet@arctic.org>.
0056  *         C. Scott Ananian <cananian@alumni.princeton.edu> Linux 2.1.87
0057  *    1.5: Fix segment register reloading (in case of bad segments saved
0058  *         across BIOS call).
0059  *         Stephen Rothwell
0060  *    1.6: Cope with compiler/assembler differences.
0061  *         Only try to turn off the first display device.
0062  *         Fix OOPS at power off with no APM BIOS by Jan Echternach
0063  *                   <echter@informatik.uni-rostock.de>
0064  *         Stephen Rothwell
0065  *    1.7: Modify driver's cached copy of the disabled/disengaged flags
0066  *         to reflect current state of APM BIOS.
0067  *         Chris Rankin <rankinc@bellsouth.net>
0068  *         Reset interrupt 0 timer to 100Hz after suspend
0069  *         Chad Miller <cmiller@surfsouth.com>
0070  *         Add CONFIG_APM_IGNORE_SUSPEND_BOUNCE
0071  *         Richard Gooch <rgooch@atnf.csiro.au>
0072  *         Allow boot time disabling of APM
0073  *         Make boot messages far less verbose by default
0074  *         Make asm safer
0075  *         Stephen Rothwell
0076  *    1.8: Add CONFIG_APM_RTC_IS_GMT
0077  *         Richard Gooch <rgooch@atnf.csiro.au>
0078  *         change APM_NOINTS to CONFIG_APM_ALLOW_INTS
0079  *         remove dependency on CONFIG_PROC_FS
0080  *         Stephen Rothwell
0081  *    1.9: Fix small typo.  <laslo@wodip.opole.pl>
0082  *         Try to cope with BIOS's that need to have all display
0083  *         devices blanked and not just the first one.
0084  *         Ross Paterson <ross@soi.city.ac.uk>
0085  *         Fix segment limit setting it has always been wrong as
0086  *         the segments needed to have byte granularity.
0087  *         Mark a few things __init.
0088  *         Add hack to allow power off of SMP systems by popular request.
0089  *         Use CONFIG_SMP instead of __SMP__
0090  *         Ignore BOUNCES for three seconds.
0091  *         Stephen Rothwell
0092  *   1.10: Fix for Thinkpad return code.
0093  *         Merge 2.2 and 2.3 drivers.
0094  *         Remove APM dependencies in arch/i386/kernel/process.c
0095  *         Remove APM dependencies in drivers/char/sysrq.c
0096  *         Reset time across standby.
0097  *         Allow more initialisation on SMP.
0098  *         Remove CONFIG_APM_POWER_OFF and make it boot time
0099  *         configurable (default on).
0100  *         Make debug only a boot time parameter (remove APM_DEBUG).
0101  *         Try to blank all devices on any error.
0102  *   1.11: Remove APM dependencies in drivers/char/console.c
0103  *         Check nr_running to detect if we are idle (from
0104  *         Borislav Deianov <borislav@lix.polytechnique.fr>)
0105  *         Fix for bioses that don't zero the top part of the
0106  *         entrypoint offset (Mario Sitta <sitta@al.unipmn.it>)
0107  *         (reported by Panos Katsaloulis <teras@writeme.com>).
0108  *         Real mode power off patch (Walter Hofmann
0109  *         <Walter.Hofmann@physik.stud.uni-erlangen.de>).
0110  *   1.12: Remove CONFIG_SMP as the compiler will optimize
0111  *         the code away anyway (smp_num_cpus == 1 in UP)
0112  *         noted by Artur Skawina <skawina@geocities.com>.
0113  *         Make power off under SMP work again.
0114  *         Fix thinko with initial engaging of BIOS.
0115  *         Make sure power off only happens on CPU 0
0116  *         (Paul "Rusty" Russell <rusty@rustcorp.com.au>).
0117  *         Do error notification to user mode if BIOS calls fail.
0118  *         Move entrypoint offset fix to ...boot/setup.S
0119  *         where it belongs (Cosmos <gis88564@cis.nctu.edu.tw>).
0120  *         Remove smp-power-off. SMP users must now specify
0121  *         "apm=power-off" on the kernel command line. Suggested
0122  *         by Jim Avera <jima@hal.com>, modified by Alan Cox
0123  *         <alan@lxorguk.ukuu.org.uk>.
0124  *         Register the /proc/apm entry even on SMP so that
0125  *         scripts that check for it before doing power off
0126  *         work (Jim Avera <jima@hal.com>).
0127  *   1.13: Changes for new pm_ interfaces (Andy Henroid
0128  *         <andy_henroid@yahoo.com>).
0129  *         Modularize the code.
0130  *         Fix the Thinkpad (again) :-( (CONFIG_APM_IGNORE_MULTIPLE_SUSPENDS
0131  *         is now the way life works).
0132  *         Fix thinko in suspend() (wrong return).
0133  *         Notify drivers on critical suspend.
0134  *         Make kapmd absorb more idle time (Pavel Machek <pavel@ucw.cz>
0135  *         modified by sfr).
0136  *         Disable interrupts while we are suspended (Andy Henroid
0137  *         <andy_henroid@yahoo.com> fixed by sfr).
0138  *         Make power off work on SMP again (Tony Hoyle
0139  *         <tmh@magenta-logic.com> and <zlatko@iskon.hr>) modified by sfr.
0140  *         Remove CONFIG_APM_SUSPEND_BOUNCE.  The bounce ignore
0141  *         interval is now configurable.
0142  *   1.14: Make connection version persist across module unload/load.
0143  *         Enable and engage power management earlier.
0144  *         Disengage power management on module unload.
0145  *         Changed to use the sysrq-register hack for registering the
0146  *         power off function called by magic sysrq based upon discussions
0147  *         in irc://irc.openprojects.net/#kernelnewbies
0148  *         (Crutcher Dunnavant <crutcher+kernel@datastacks.com>).
0149  *         Make CONFIG_APM_REAL_MODE_POWER_OFF run time configurable.
0150  *         (Arjan van de Ven <arjanv@redhat.com>) modified by sfr.
0151  *         Work around byte swap bug in one of the Vaio's BIOS's
0152  *         (Marc Boucher <marc@mbsi.ca>).
0153  *         Exposed the disable flag to dmi so that we can handle known
0154  *         broken APM (Alan Cox <alan@lxorguk.ukuu.org.uk>).
0155  *   1.14ac: If the BIOS says "I slowed the CPU down" then don't spin
0156  *         calling it - instead idle. (Alan Cox <alan@lxorguk.ukuu.org.uk>)
0157  *         If an APM idle fails log it and idle sensibly
0158  *   1.15: Don't queue events to clients who open the device O_WRONLY.
0159  *         Don't expect replies from clients who open the device O_RDONLY.
0160  *         (Idea from Thomas Hood)
0161  *         Minor waitqueue cleanups. (John Fremlin <chief@bandits.org>)
0162  *   1.16: Fix idle calling. (Andreas Steinmetz <ast@domdv.de> et al.)
0163  *         Notify listeners of standby or suspend events before notifying
0164  *         drivers. Return EBUSY to ioctl() if suspend is rejected.
0165  *         (Russell King <rmk@arm.linux.org.uk> and Thomas Hood)
0166  *         Ignore first resume after we generate our own resume event
0167  *         after a suspend (Thomas Hood)
0168  *         Daemonize now gets rid of our controlling terminal (sfr).
0169  *         CONFIG_APM_CPU_IDLE now just affects the default value of
0170  *         idle_threshold (sfr).
0171  *         Change name of kernel apm daemon (as it no longer idles) (sfr).
0172  *   1.16ac: Fix up SMP support somewhat. You can now force SMP on and we
0173  *     make _all_ APM calls on the CPU#0. Fix unsafe sign bug.
0174  *     TODO: determine if its "boot CPU" or "CPU0" we want to lock to.
0175  *
0176  * APM 1.1 Reference:
0177  *
0178  *   Intel Corporation, Microsoft Corporation. Advanced Power Management
0179  *   (APM) BIOS Interface Specification, Revision 1.1, September 1993.
0180  *   Intel Order Number 241704-001.  Microsoft Part Number 781-110-X01.
0181  *
0182  * [This document is available free from Intel by calling 800.628.8686 (fax
0183  * 916.356.6100) or 800.548.4725; or from
0184  * http://www.microsoft.com/whdc/archive/amp_12.mspx  It is also
0185  * available from Microsoft by calling 206.882.8080.]
0186  *
0187  * APM 1.2 Reference:
0188  *   Intel Corporation, Microsoft Corporation. Advanced Power Management
0189  *   (APM) BIOS Interface Specification, Revision 1.2, February 1996.
0190  *
0191  * [This document is available from Microsoft at:
0192  *    http://www.microsoft.com/whdc/archive/amp_12.mspx]
0193  */
0194 
0195 #define pr_fmt(fmt) "apm: " fmt
0196 
0197 #include <linux/module.h>
0198 
0199 #include <linux/poll.h>
0200 #include <linux/types.h>
0201 #include <linux/stddef.h>
0202 #include <linux/timer.h>
0203 #include <linux/fcntl.h>
0204 #include <linux/slab.h>
0205 #include <linux/stat.h>
0206 #include <linux/proc_fs.h>
0207 #include <linux/seq_file.h>
0208 #include <linux/miscdevice.h>
0209 #include <linux/apm_bios.h>
0210 #include <linux/init.h>
0211 #include <linux/time.h>
0212 #include <linux/sched/signal.h>
0213 #include <linux/sched/cputime.h>
0214 #include <linux/pm.h>
0215 #include <linux/capability.h>
0216 #include <linux/device.h>
0217 #include <linux/kernel.h>
0218 #include <linux/freezer.h>
0219 #include <linux/smp.h>
0220 #include <linux/dmi.h>
0221 #include <linux/suspend.h>
0222 #include <linux/kthread.h>
0223 #include <linux/jiffies.h>
0224 #include <linux/acpi.h>
0225 #include <linux/syscore_ops.h>
0226 #include <linux/i8253.h>
0227 #include <linux/cpuidle.h>
0228 
0229 #include <linux/uaccess.h>
0230 #include <asm/desc.h>
0231 #include <asm/olpc.h>
0232 #include <asm/paravirt.h>
0233 #include <asm/reboot.h>
0234 #include <asm/nospec-branch.h>
0235 #include <asm/ibt.h>
0236 
0237 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
0238 extern int (*console_blank_hook)(int);
0239 #endif
0240 
0241 /*
0242  * The apm_bios device is one of the misc char devices.
0243  * This is its minor number.
0244  */
0245 #define APM_MINOR_DEV   134
0246 
0247 /*
0248  * Various options can be changed at boot time as follows:
0249  * (We allow underscores for compatibility with the modules code)
0250  *  apm=on/off          enable/disable APM
0251  *      [no-]allow[-_]ints      allow interrupts during BIOS calls
0252  *      [no-]broken[-_]psr      BIOS has a broken GetPowerStatus call
0253  *      [no-]realmode[-_]power[-_]off   switch to real mode before
0254  *                          powering off
0255  *      [no-]debug          log some debugging messages
0256  *      [no-]power[-_]off       power off on shutdown
0257  *      [no-]smp            Use apm even on an SMP box
0258  *      bounce[-_]interval=<n>  number of ticks to ignore suspend
0259  *                      bounces
0260  *          idle[-_]threshold=<n>       System idle percentage above which to
0261  *                                      make APM BIOS idle calls. Set it to
0262  *                                      100 to disable.
0263  *          idle[-_]period=<n>          Period (in 1/100s of a second) over
0264  *                                      which the idle percentage is
0265  *                                      calculated.
0266  */
0267 
0268 /* KNOWN PROBLEM MACHINES:
0269  *
0270  * U: TI 4000M TravelMate: BIOS is *NOT* APM compliant
0271  *                         [Confirmed by TI representative]
0272  * ?: ACER 486DX4/75: uses dseg 0040, in violation of APM specification
0273  *                    [Confirmed by BIOS disassembly]
0274  *                    [This may work now ...]
0275  * P: Toshiba 1950S: battery life information only gets updated after resume
0276  * P: Midwest Micro Soundbook Elite DX2/66 monochrome: screen blanking
0277  *  broken in BIOS [Reported by Garst R. Reese <reese@isn.net>]
0278  * ?: AcerNote-950: oops on reading /proc/apm - workaround is a WIP
0279  *  Neale Banks <neale@lowendale.com.au> December 2000
0280  *
0281  * Legend: U = unusable with APM patches
0282  *         P = partially usable with APM patches
0283  */
0284 
0285 /*
0286  * Define as 1 to make the driver always call the APM BIOS busy
0287  * routine even if the clock was not reported as slowed by the
0288  * idle routine.  Otherwise, define as 0.
0289  */
0290 #define ALWAYS_CALL_BUSY   1
0291 
0292 /*
0293  * Define to make the APM BIOS calls zero all data segment registers (so
0294  * that an incorrect BIOS implementation will cause a kernel panic if it
0295  * tries to write to arbitrary memory).
0296  */
0297 #define APM_ZERO_SEGS
0298 
0299 #include <asm/apm.h>
0300 
0301 /*
0302  * Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend.
0303  * This patched by Chad Miller <cmiller@surfsouth.com>, original code by
0304  * David Chen <chen@ctpa04.mit.edu>
0305  */
0306 #undef INIT_TIMER_AFTER_SUSPEND
0307 
0308 #ifdef INIT_TIMER_AFTER_SUSPEND
0309 #include <linux/timex.h>
0310 #include <asm/io.h>
0311 #include <linux/delay.h>
0312 #endif
0313 
0314 /*
0315  * Need to poll the APM BIOS every second
0316  */
0317 #define APM_CHECK_TIMEOUT   (HZ)
0318 
0319 /*
0320  * Ignore suspend events for this amount of time after a resume
0321  */
0322 #define DEFAULT_BOUNCE_INTERVAL (3 * HZ)
0323 
0324 /*
0325  * Maximum number of events stored
0326  */
0327 #define APM_MAX_EVENTS      20
0328 
0329 /*
0330  * The per-file APM data
0331  */
0332 struct apm_user {
0333     int     magic;
0334     struct apm_user *next;
0335     unsigned int    suser: 1;
0336     unsigned int    writer: 1;
0337     unsigned int    reader: 1;
0338     unsigned int    suspend_wait: 1;
0339     int     suspend_result;
0340     int     suspends_pending;
0341     int     standbys_pending;
0342     int     suspends_read;
0343     int     standbys_read;
0344     int     event_head;
0345     int     event_tail;
0346     apm_event_t events[APM_MAX_EVENTS];
0347 };
0348 
0349 /*
0350  * The magic number in apm_user
0351  */
0352 #define APM_BIOS_MAGIC      0x4101
0353 
0354 /*
0355  * idle percentage above which bios idle calls are done
0356  */
0357 #ifdef CONFIG_APM_CPU_IDLE
0358 #define DEFAULT_IDLE_THRESHOLD  95
0359 #else
0360 #define DEFAULT_IDLE_THRESHOLD  100
0361 #endif
0362 #define DEFAULT_IDLE_PERIOD (100 / 3)
0363 
0364 static int apm_cpu_idle(struct cpuidle_device *dev,
0365             struct cpuidle_driver *drv, int index);
0366 
0367 static struct cpuidle_driver apm_idle_driver = {
0368     .name = "apm_idle",
0369     .owner = THIS_MODULE,
0370     .states = {
0371         { /* entry 0 is for polling */ },
0372         { /* entry 1 is for APM idle */
0373             .name = "APM",
0374             .desc = "APM idle",
0375             .exit_latency = 250,    /* WAG */
0376             .target_residency = 500,    /* WAG */
0377             .enter = &apm_cpu_idle
0378         },
0379     },
0380     .state_count = 2,
0381 };
0382 
0383 static struct cpuidle_device apm_cpuidle_device;
0384 
0385 /*
0386  * Local variables
0387  */
0388 __visible struct {
0389     unsigned long   offset;
0390     unsigned short  segment;
0391 } apm_bios_entry;
0392 static int clock_slowed;
0393 static int idle_threshold __read_mostly = DEFAULT_IDLE_THRESHOLD;
0394 static int idle_period __read_mostly = DEFAULT_IDLE_PERIOD;
0395 static int suspends_pending;
0396 static int standbys_pending;
0397 static int ignore_sys_suspend;
0398 static int ignore_normal_resume;
0399 static int bounce_interval __read_mostly = DEFAULT_BOUNCE_INTERVAL;
0400 
0401 static bool debug __read_mostly;
0402 static bool smp __read_mostly;
0403 static int apm_disabled = -1;
0404 #ifdef CONFIG_SMP
0405 static bool power_off;
0406 #else
0407 static bool power_off = 1;
0408 #endif
0409 static bool realmode_power_off;
0410 #ifdef CONFIG_APM_ALLOW_INTS
0411 static bool allow_ints = 1;
0412 #else
0413 static bool allow_ints;
0414 #endif
0415 static bool broken_psr;
0416 
0417 static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
0418 static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
0419 static struct apm_user *user_list;
0420 static DEFINE_SPINLOCK(user_list_lock);
0421 static DEFINE_MUTEX(apm_mutex);
0422 
0423 /*
0424  * Set up a segment that references the real mode segment 0x40
0425  * that extends up to the end of page zero (that we have reserved).
0426  * This is for buggy BIOS's that refer to (real mode) segment 0x40
0427  * even though they are called in protected mode.
0428  */
0429 static struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4092,
0430             (unsigned long)__va(0x400UL), PAGE_SIZE - 0x400 - 1);
0431 
0432 static const char driver_version[] = "1.16ac";  /* no spaces */
0433 
0434 static struct task_struct *kapmd_task;
0435 
0436 /*
0437  *  APM event names taken from the APM 1.2 specification. These are
0438  *  the message codes that the BIOS uses to tell us about events
0439  */
0440 static const char * const apm_event_name[] = {
0441     "system standby",
0442     "system suspend",
0443     "normal resume",
0444     "critical resume",
0445     "low battery",
0446     "power status change",
0447     "update time",
0448     "critical suspend",
0449     "user standby",
0450     "user suspend",
0451     "system standby resume",
0452     "capabilities change"
0453 };
0454 #define NR_APM_EVENT_NAME ARRAY_SIZE(apm_event_name)
0455 
0456 typedef struct lookup_t {
0457     int key;
0458     char    *msg;
0459 } lookup_t;
0460 
0461 /*
0462  *  The BIOS returns a set of standard error codes in AX when the
0463  *  carry flag is set.
0464  */
0465 
0466 static const lookup_t error_table[] = {
0467 /* N/A  { APM_SUCCESS,      "Operation succeeded" }, */
0468     { APM_DISABLED,     "Power management disabled" },
0469     { APM_CONNECTED,    "Real mode interface already connected" },
0470     { APM_NOT_CONNECTED,    "Interface not connected" },
0471     { APM_16_CONNECTED, "16 bit interface already connected" },
0472 /* N/A  { APM_16_UNSUPPORTED,   "16 bit interface not supported" }, */
0473     { APM_32_CONNECTED, "32 bit interface already connected" },
0474     { APM_32_UNSUPPORTED,   "32 bit interface not supported" },
0475     { APM_BAD_DEVICE,   "Unrecognized device ID" },
0476     { APM_BAD_PARAM,    "Parameter out of range" },
0477     { APM_NOT_ENGAGED,  "Interface not engaged" },
0478     { APM_BAD_FUNCTION,     "Function not supported" },
0479     { APM_RESUME_DISABLED,  "Resume timer disabled" },
0480     { APM_BAD_STATE,    "Unable to enter requested state" },
0481 /* N/A  { APM_NO_EVENTS,    "No events pending" }, */
0482     { APM_NO_ERROR,     "BIOS did not set a return code" },
0483     { APM_NOT_PRESENT,  "No APM present" }
0484 };
0485 #define ERROR_COUNT ARRAY_SIZE(error_table)
0486 
0487 /**
0488  *  apm_error   -   display an APM error
0489  *  @str: information string
0490  *  @err: APM BIOS return code
0491  *
0492  *  Write a meaningful log entry to the kernel log in the event of
0493  *  an APM error.  Note that this also handles (negative) kernel errors.
0494  */
0495 
0496 static void apm_error(char *str, int err)
0497 {
0498     int i;
0499 
0500     for (i = 0; i < ERROR_COUNT; i++)
0501         if (error_table[i].key == err)
0502             break;
0503     if (i < ERROR_COUNT)
0504         pr_notice("%s: %s\n", str, error_table[i].msg);
0505     else if (err < 0)
0506         pr_notice("%s: linux error code %i\n", str, err);
0507     else
0508         pr_notice("%s: unknown error code %#2.2x\n",
0509                str, err);
0510 }
0511 
0512 /*
0513  * These are the actual BIOS calls.  Depending on APM_ZERO_SEGS and
0514  * apm_info.allow_ints, we are being really paranoid here!  Not only
0515  * are interrupts disabled, but all the segment registers (except SS)
0516  * are saved and zeroed this means that if the BIOS tries to reference
0517  * any data without explicitly loading the segment registers, the kernel
0518  * will fault immediately rather than have some unforeseen circumstances
0519  * for the rest of the kernel.  And it will be very obvious!  :-) Doing
0520  * this depends on CS referring to the same physical memory as DS so that
0521  * DS can be zeroed before the call. Unfortunately, we can't do anything
0522  * about the stack segment/pointer.  Also, we tell the compiler that
0523  * everything could change.
0524  *
0525  * Also, we KNOW that for the non error case of apm_bios_call, there
0526  * is no useful data returned in the low order 8 bits of eax.
0527  */
0528 
0529 static inline unsigned long __apm_irq_save(void)
0530 {
0531     unsigned long flags;
0532     local_save_flags(flags);
0533     if (apm_info.allow_ints) {
0534         if (irqs_disabled_flags(flags))
0535             local_irq_enable();
0536     } else
0537         local_irq_disable();
0538 
0539     return flags;
0540 }
0541 
0542 #define apm_irq_save(flags) \
0543     do { flags = __apm_irq_save(); } while (0)
0544 
0545 static inline void apm_irq_restore(unsigned long flags)
0546 {
0547     if (irqs_disabled_flags(flags))
0548         local_irq_disable();
0549     else if (irqs_disabled())
0550         local_irq_enable();
0551 }
0552 
0553 #ifdef APM_ZERO_SEGS
0554 #   define APM_DECL_SEGS \
0555         unsigned int saved_fs; unsigned int saved_gs;
0556 #   define APM_DO_SAVE_SEGS \
0557         savesegment(fs, saved_fs); savesegment(gs, saved_gs)
0558 #   define APM_DO_RESTORE_SEGS \
0559         loadsegment(fs, saved_fs); loadsegment(gs, saved_gs)
0560 #else
0561 #   define APM_DECL_SEGS
0562 #   define APM_DO_SAVE_SEGS
0563 #   define APM_DO_RESTORE_SEGS
0564 #endif
0565 
0566 struct apm_bios_call {
0567     u32 func;
0568     /* In and out */
0569     u32 ebx;
0570     u32 ecx;
0571     /* Out only */
0572     u32 eax;
0573     u32 edx;
0574     u32 esi;
0575 
0576     /* Error: -ENOMEM, or bits 8-15 of eax */
0577     int err;
0578 };
0579 
0580 /**
0581  *  __apm_bios_call - Make an APM BIOS 32bit call
0582  *  @_call: pointer to struct apm_bios_call.
0583  *
0584  *  Make an APM call using the 32bit protected mode interface. The
0585  *  caller is responsible for knowing if APM BIOS is configured and
0586  *  enabled. This call can disable interrupts for a long period of
0587  *  time on some laptops.  The return value is in AH and the carry
0588  *  flag is loaded into AL.  If there is an error, then the error
0589  *  code is returned in AH (bits 8-15 of eax) and this function
0590  *  returns non-zero.
0591  *
0592  *  Note: this makes the call on the current CPU.
0593  */
0594 static long __apm_bios_call(void *_call)
0595 {
0596     APM_DECL_SEGS
0597     unsigned long       flags;
0598     int         cpu;
0599     struct desc_struct  save_desc_40;
0600     struct desc_struct  *gdt;
0601     struct apm_bios_call    *call = _call;
0602     u64         ibt;
0603 
0604     cpu = get_cpu();
0605     BUG_ON(cpu != 0);
0606     gdt = get_cpu_gdt_rw(cpu);
0607     save_desc_40 = gdt[0x40 / 8];
0608     gdt[0x40 / 8] = bad_bios_desc;
0609 
0610     apm_irq_save(flags);
0611     firmware_restrict_branch_speculation_start();
0612     ibt = ibt_save();
0613     APM_DO_SAVE_SEGS;
0614     apm_bios_call_asm(call->func, call->ebx, call->ecx,
0615               &call->eax, &call->ebx, &call->ecx, &call->edx,
0616               &call->esi);
0617     APM_DO_RESTORE_SEGS;
0618     ibt_restore(ibt);
0619     firmware_restrict_branch_speculation_end();
0620     apm_irq_restore(flags);
0621     gdt[0x40 / 8] = save_desc_40;
0622     put_cpu();
0623 
0624     return call->eax & 0xff;
0625 }
0626 
0627 /* Run __apm_bios_call or __apm_bios_call_simple on CPU 0 */
0628 static int on_cpu0(long (*fn)(void *), struct apm_bios_call *call)
0629 {
0630     int ret;
0631 
0632     /* Don't bother with work_on_cpu in the common case, so we don't
0633      * have to worry about OOM or overhead. */
0634     if (get_cpu() == 0) {
0635         ret = fn(call);
0636         put_cpu();
0637     } else {
0638         put_cpu();
0639         ret = work_on_cpu(0, fn, call);
0640     }
0641 
0642     /* work_on_cpu can fail with -ENOMEM */
0643     if (ret < 0)
0644         call->err = ret;
0645     else
0646         call->err = (call->eax >> 8) & 0xff;
0647 
0648     return ret;
0649 }
0650 
0651 /**
0652  *  apm_bios_call   -   Make an APM BIOS 32bit call (on CPU 0)
0653  *  @call: the apm_bios_call registers.
0654  *
0655  *  If there is an error, it is returned in @call.err.
0656  */
0657 static int apm_bios_call(struct apm_bios_call *call)
0658 {
0659     return on_cpu0(__apm_bios_call, call);
0660 }
0661 
0662 /**
0663  *  __apm_bios_call_simple - Make an APM BIOS 32bit call (on CPU 0)
0664  *  @_call: pointer to struct apm_bios_call.
0665  *
0666  *  Make a BIOS call that returns one value only, or just status.
0667  *  If there is an error, then the error code is returned in AH
0668  *  (bits 8-15 of eax) and this function returns non-zero (it can
0669  *  also return -ENOMEM). This is used for simpler BIOS operations.
0670  *  This call may hold interrupts off for a long time on some laptops.
0671  *
0672  *  Note: this makes the call on the current CPU.
0673  */
0674 static long __apm_bios_call_simple(void *_call)
0675 {
0676     u8          error;
0677     APM_DECL_SEGS
0678     unsigned long       flags;
0679     int         cpu;
0680     struct desc_struct  save_desc_40;
0681     struct desc_struct  *gdt;
0682     struct apm_bios_call    *call = _call;
0683     u64         ibt;
0684 
0685     cpu = get_cpu();
0686     BUG_ON(cpu != 0);
0687     gdt = get_cpu_gdt_rw(cpu);
0688     save_desc_40 = gdt[0x40 / 8];
0689     gdt[0x40 / 8] = bad_bios_desc;
0690 
0691     apm_irq_save(flags);
0692     firmware_restrict_branch_speculation_start();
0693     ibt = ibt_save();
0694     APM_DO_SAVE_SEGS;
0695     error = apm_bios_call_simple_asm(call->func, call->ebx, call->ecx,
0696                      &call->eax);
0697     APM_DO_RESTORE_SEGS;
0698     ibt_restore(ibt);
0699     firmware_restrict_branch_speculation_end();
0700     apm_irq_restore(flags);
0701     gdt[0x40 / 8] = save_desc_40;
0702     put_cpu();
0703     return error;
0704 }
0705 
0706 /**
0707  *  apm_bios_call_simple    -   make a simple APM BIOS 32bit call
0708  *  @func: APM function to invoke
0709  *  @ebx_in: EBX register value for BIOS call
0710  *  @ecx_in: ECX register value for BIOS call
0711  *  @eax: EAX register on return from the BIOS call
0712  *  @err: bits
0713  *
0714  *  Make a BIOS call that returns one value only, or just status.
0715  *  If there is an error, then the error code is returned in @err
0716  *  and this function returns non-zero. This is used for simpler
0717  *  BIOS operations.  This call may hold interrupts off for a long
0718  *  time on some laptops.
0719  */
0720 static int apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax,
0721                 int *err)
0722 {
0723     struct apm_bios_call call;
0724     int ret;
0725 
0726     call.func = func;
0727     call.ebx = ebx_in;
0728     call.ecx = ecx_in;
0729 
0730     ret = on_cpu0(__apm_bios_call_simple, &call);
0731     *eax = call.eax;
0732     *err = call.err;
0733     return ret;
0734 }
0735 
0736 /**
0737  *  apm_driver_version  -   APM driver version
0738  *  @val:   loaded with the APM version on return
0739  *
0740  *  Retrieve the APM version supported by the BIOS. This is only
0741  *  supported for APM 1.1 or higher. An error indicates APM 1.0 is
0742  *  probably present.
0743  *
0744  *  On entry val should point to a value indicating the APM driver
0745  *  version with the high byte being the major and the low byte the
0746  *  minor number both in BCD
0747  *
0748  *  On return it will hold the BIOS revision supported in the
0749  *  same format.
0750  */
0751 
0752 static int apm_driver_version(u_short *val)
0753 {
0754     u32 eax;
0755     int err;
0756 
0757     if (apm_bios_call_simple(APM_FUNC_VERSION, 0, *val, &eax, &err))
0758         return err;
0759     *val = eax;
0760     return APM_SUCCESS;
0761 }
0762 
0763 /**
0764  *  apm_get_event   -   get an APM event from the BIOS
0765  *  @event: pointer to the event
0766  *  @info: point to the event information
0767  *
0768  *  The APM BIOS provides a polled information for event
0769  *  reporting. The BIOS expects to be polled at least every second
0770  *  when events are pending. When a message is found the caller should
0771  *  poll until no more messages are present.  However, this causes
0772  *  problems on some laptops where a suspend event notification is
0773  *  not cleared until it is acknowledged.
0774  *
0775  *  Additional information is returned in the info pointer, providing
0776  *  that APM 1.2 is in use. If no messages are pending the value 0x80
0777  *  is returned (No power management events pending).
0778  */
0779 static int apm_get_event(apm_event_t *event, apm_eventinfo_t *info)
0780 {
0781     struct apm_bios_call call;
0782 
0783     call.func = APM_FUNC_GET_EVENT;
0784     call.ebx = call.ecx = 0;
0785 
0786     if (apm_bios_call(&call))
0787         return call.err;
0788 
0789     *event = call.ebx;
0790     if (apm_info.connection_version < 0x0102)
0791         *info = ~0; /* indicate info not valid */
0792     else
0793         *info = call.ecx;
0794     return APM_SUCCESS;
0795 }
0796 
0797 /**
0798  *  set_power_state -   set the power management state
0799  *  @what: which items to transition
0800  *  @state: state to transition to
0801  *
0802  *  Request an APM change of state for one or more system devices. The
0803  *  processor state must be transitioned last of all. what holds the
0804  *  class of device in the upper byte and the device number (0xFF for
0805  *  all) for the object to be transitioned.
0806  *
0807  *  The state holds the state to transition to, which may in fact
0808  *  be an acceptance of a BIOS requested state change.
0809  */
0810 
0811 static int set_power_state(u_short what, u_short state)
0812 {
0813     u32 eax;
0814     int err;
0815 
0816     if (apm_bios_call_simple(APM_FUNC_SET_STATE, what, state, &eax, &err))
0817         return err;
0818     return APM_SUCCESS;
0819 }
0820 
0821 /**
0822  *  set_system_power_state - set system wide power state
0823  *  @state: which state to enter
0824  *
0825  *  Transition the entire system into a new APM power state.
0826  */
0827 
0828 static int set_system_power_state(u_short state)
0829 {
0830     return set_power_state(APM_DEVICE_ALL, state);
0831 }
0832 
0833 /**
0834  *  apm_do_idle -   perform power saving
0835  *
0836  *  This function notifies the BIOS that the processor is (in the view
0837  *  of the OS) idle. It returns -1 in the event that the BIOS refuses
0838  *  to handle the idle request. On a success the function returns 1
0839  *  if the BIOS did clock slowing or 0 otherwise.
0840  */
0841 
0842 static int apm_do_idle(void)
0843 {
0844     u32 eax;
0845     u8 ret = 0;
0846     int idled = 0;
0847     int err = 0;
0848 
0849     if (!need_resched()) {
0850         idled = 1;
0851         ret = apm_bios_call_simple(APM_FUNC_IDLE, 0, 0, &eax, &err);
0852     }
0853 
0854     if (!idled)
0855         return 0;
0856 
0857     if (ret) {
0858         static unsigned long t;
0859 
0860         /* This always fails on some SMP boards running UP kernels.
0861          * Only report the failure the first 5 times.
0862          */
0863         if (++t < 5) {
0864             printk(KERN_DEBUG "apm_do_idle failed (%d)\n", err);
0865             t = jiffies;
0866         }
0867         return -1;
0868     }
0869     clock_slowed = (apm_info.bios.flags & APM_IDLE_SLOWS_CLOCK) != 0;
0870     return clock_slowed;
0871 }
0872 
0873 /**
0874  *  apm_do_busy -   inform the BIOS the CPU is busy
0875  *
0876  *  Request that the BIOS brings the CPU back to full performance.
0877  */
0878 
0879 static void apm_do_busy(void)
0880 {
0881     u32 dummy;
0882     int err;
0883 
0884     if (clock_slowed || ALWAYS_CALL_BUSY) {
0885         (void)apm_bios_call_simple(APM_FUNC_BUSY, 0, 0, &dummy, &err);
0886         clock_slowed = 0;
0887     }
0888 }
0889 
0890 /*
0891  * If no process has really been interested in
0892  * the CPU for some time, we want to call BIOS
0893  * power management - we probably want
0894  * to conserve power.
0895  */
0896 #define IDLE_CALC_LIMIT (HZ * 100)
0897 #define IDLE_LEAKY_MAX  16
0898 
0899 /**
0900  * apm_cpu_idle     -   cpu idling for APM capable Linux
0901  *
0902  * This is the idling function the kernel executes when APM is available. It
0903  * tries to do BIOS powermanagement based on the average system idle time.
0904  * Furthermore it calls the system default idle routine.
0905  */
0906 
0907 static int apm_cpu_idle(struct cpuidle_device *dev,
0908     struct cpuidle_driver *drv, int index)
0909 {
0910     static int use_apm_idle; /* = 0 */
0911     static unsigned int last_jiffies; /* = 0 */
0912     static u64 last_stime; /* = 0 */
0913     u64 stime, utime;
0914 
0915     int apm_idle_done = 0;
0916     unsigned int jiffies_since_last_check = jiffies - last_jiffies;
0917     unsigned int bucket;
0918 
0919 recalc:
0920     task_cputime(current, &utime, &stime);
0921     if (jiffies_since_last_check > IDLE_CALC_LIMIT) {
0922         use_apm_idle = 0;
0923     } else if (jiffies_since_last_check > idle_period) {
0924         unsigned int idle_percentage;
0925 
0926         idle_percentage = nsecs_to_jiffies(stime - last_stime);
0927         idle_percentage *= 100;
0928         idle_percentage /= jiffies_since_last_check;
0929         use_apm_idle = (idle_percentage > idle_threshold);
0930         if (apm_info.forbid_idle)
0931             use_apm_idle = 0;
0932     }
0933 
0934     last_jiffies = jiffies;
0935     last_stime = stime;
0936 
0937     bucket = IDLE_LEAKY_MAX;
0938 
0939     while (!need_resched()) {
0940         if (use_apm_idle) {
0941             unsigned int t;
0942 
0943             t = jiffies;
0944             switch (apm_do_idle()) {
0945             case 0:
0946                 apm_idle_done = 1;
0947                 if (t != jiffies) {
0948                     if (bucket) {
0949                         bucket = IDLE_LEAKY_MAX;
0950                         continue;
0951                     }
0952                 } else if (bucket) {
0953                     bucket--;
0954                     continue;
0955                 }
0956                 break;
0957             case 1:
0958                 apm_idle_done = 1;
0959                 break;
0960             default: /* BIOS refused */
0961                 break;
0962             }
0963         }
0964         default_idle();
0965         local_irq_disable();
0966         jiffies_since_last_check = jiffies - last_jiffies;
0967         if (jiffies_since_last_check > idle_period)
0968             goto recalc;
0969     }
0970 
0971     if (apm_idle_done)
0972         apm_do_busy();
0973 
0974     return index;
0975 }
0976 
0977 /**
0978  *  apm_power_off   -   ask the BIOS to power off
0979  *
0980  *  Handle the power off sequence. This is the one piece of code we
0981  *  will execute even on SMP machines. In order to deal with BIOS
0982  *  bugs we support real mode APM BIOS power off calls. We also make
0983  *  the SMP call on CPU0 as some systems will only honour this call
0984  *  on their first cpu.
0985  */
0986 
0987 static void apm_power_off(void)
0988 {
0989     /* Some bioses don't like being called from CPU != 0 */
0990     if (apm_info.realmode_power_off) {
0991         set_cpus_allowed_ptr(current, cpumask_of(0));
0992         machine_real_restart(MRR_APM);
0993     } else {
0994         (void)set_system_power_state(APM_STATE_OFF);
0995     }
0996 }
0997 
0998 #ifdef CONFIG_APM_DO_ENABLE
0999 
1000 /**
1001  *  apm_enable_power_management - enable BIOS APM power management
1002  *  @enable: enable yes/no
1003  *
1004  *  Enable or disable the APM BIOS power services.
1005  */
1006 
1007 static int apm_enable_power_management(int enable)
1008 {
1009     u32 eax;
1010     int err;
1011 
1012     if ((enable == 0) && (apm_info.bios.flags & APM_BIOS_DISENGAGED))
1013         return APM_NOT_ENGAGED;
1014     if (apm_bios_call_simple(APM_FUNC_ENABLE_PM, APM_DEVICE_BALL,
1015                  enable, &eax, &err))
1016         return err;
1017     if (enable)
1018         apm_info.bios.flags &= ~APM_BIOS_DISABLED;
1019     else
1020         apm_info.bios.flags |= APM_BIOS_DISABLED;
1021     return APM_SUCCESS;
1022 }
1023 #endif
1024 
1025 /**
1026  *  apm_get_power_status    -   get current power state
1027  *  @status: returned status
1028  *  @bat: battery info
1029  *  @life: estimated life
1030  *
1031  *  Obtain the current power status from the APM BIOS. We return a
1032  *  status which gives the rough battery status, and current power
1033  *  source. The bat value returned give an estimate as a percentage
1034  *  of life and a status value for the battery. The estimated life
1035  *  if reported is a lifetime in seconds/minutes at current power
1036  *  consumption.
1037  */
1038 
1039 static int apm_get_power_status(u_short *status, u_short *bat, u_short *life)
1040 {
1041     struct apm_bios_call call;
1042 
1043     call.func = APM_FUNC_GET_STATUS;
1044     call.ebx = APM_DEVICE_ALL;
1045     call.ecx = 0;
1046 
1047     if (apm_info.get_power_status_broken)
1048         return APM_32_UNSUPPORTED;
1049     if (apm_bios_call(&call)) {
1050         if (!call.err)
1051             return APM_NO_ERROR;
1052         return call.err;
1053     }
1054     *status = call.ebx;
1055     *bat = call.ecx;
1056     if (apm_info.get_power_status_swabinminutes) {
1057         *life = swab16((u16)call.edx);
1058         *life |= 0x8000;
1059     } else
1060         *life = call.edx;
1061     return APM_SUCCESS;
1062 }
1063 
1064 #if 0
1065 static int apm_get_battery_status(u_short which, u_short *status,
1066                   u_short *bat, u_short *life, u_short *nbat)
1067 {
1068     u32 eax;
1069     u32 ebx;
1070     u32 ecx;
1071     u32 edx;
1072     u32 esi;
1073 
1074     if (apm_info.connection_version < 0x0102) {
1075         /* pretend we only have one battery. */
1076         if (which != 1)
1077             return APM_BAD_DEVICE;
1078         *nbat = 1;
1079         return apm_get_power_status(status, bat, life);
1080     }
1081 
1082     if (apm_bios_call(APM_FUNC_GET_STATUS, (0x8000 | (which)), 0, &eax,
1083               &ebx, &ecx, &edx, &esi))
1084         return (eax >> 8) & 0xff;
1085     *status = ebx;
1086     *bat = ecx;
1087     *life = edx;
1088     *nbat = esi;
1089     return APM_SUCCESS;
1090 }
1091 #endif
1092 
1093 /**
1094  *  apm_engage_power_management -   enable PM on a device
1095  *  @device: identity of device
1096  *  @enable: on/off
1097  *
1098  *  Activate or deactivate power management on either a specific device
1099  *  or the entire system (%APM_DEVICE_ALL).
1100  */
1101 
1102 static int apm_engage_power_management(u_short device, int enable)
1103 {
1104     u32 eax;
1105     int err;
1106 
1107     if ((enable == 0) && (device == APM_DEVICE_ALL)
1108         && (apm_info.bios.flags & APM_BIOS_DISABLED))
1109         return APM_DISABLED;
1110     if (apm_bios_call_simple(APM_FUNC_ENGAGE_PM, device, enable,
1111                  &eax, &err))
1112         return err;
1113     if (device == APM_DEVICE_ALL) {
1114         if (enable)
1115             apm_info.bios.flags &= ~APM_BIOS_DISENGAGED;
1116         else
1117             apm_info.bios.flags |= APM_BIOS_DISENGAGED;
1118     }
1119     return APM_SUCCESS;
1120 }
1121 
1122 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
1123 
1124 /**
1125  *  apm_console_blank   -   blank the display
1126  *  @blank: on/off
1127  *
1128  *  Attempt to blank the console, firstly by blanking just video device
1129  *  zero, and if that fails (some BIOSes don't support it) then it blanks
1130  *  all video devices. Typically the BIOS will do laptop backlight and
1131  *  monitor powerdown for us.
1132  */
1133 
1134 static int apm_console_blank(int blank)
1135 {
1136     int error = APM_NOT_ENGAGED; /* silence gcc */
1137     int i;
1138     u_short state;
1139     static const u_short dev[3] = { 0x100, 0x1FF, 0x101 };
1140 
1141     state = blank ? APM_STATE_STANDBY : APM_STATE_READY;
1142 
1143     for (i = 0; i < ARRAY_SIZE(dev); i++) {
1144         error = set_power_state(dev[i], state);
1145 
1146         if ((error == APM_SUCCESS) || (error == APM_NO_ERROR))
1147             return 1;
1148 
1149         if (error == APM_NOT_ENGAGED)
1150             break;
1151     }
1152 
1153     if (error == APM_NOT_ENGAGED) {
1154         static int tried;
1155         int eng_error;
1156         if (tried++ == 0) {
1157             eng_error = apm_engage_power_management(APM_DEVICE_ALL, 1);
1158             if (eng_error) {
1159                 apm_error("set display", error);
1160                 apm_error("engage interface", eng_error);
1161                 return 0;
1162             } else
1163                 return apm_console_blank(blank);
1164         }
1165     }
1166     apm_error("set display", error);
1167     return 0;
1168 }
1169 #endif
1170 
1171 static int queue_empty(struct apm_user *as)
1172 {
1173     return as->event_head == as->event_tail;
1174 }
1175 
1176 static apm_event_t get_queued_event(struct apm_user *as)
1177 {
1178     if (++as->event_tail >= APM_MAX_EVENTS)
1179         as->event_tail = 0;
1180     return as->events[as->event_tail];
1181 }
1182 
1183 static void queue_event(apm_event_t event, struct apm_user *sender)
1184 {
1185     struct apm_user *as;
1186 
1187     spin_lock(&user_list_lock);
1188     if (user_list == NULL)
1189         goto out;
1190     for (as = user_list; as != NULL; as = as->next) {
1191         if ((as == sender) || (!as->reader))
1192             continue;
1193         if (++as->event_head >= APM_MAX_EVENTS)
1194             as->event_head = 0;
1195 
1196         if (as->event_head == as->event_tail) {
1197             static int notified;
1198 
1199             if (notified++ == 0)
1200                 pr_err("an event queue overflowed\n");
1201             if (++as->event_tail >= APM_MAX_EVENTS)
1202                 as->event_tail = 0;
1203         }
1204         as->events[as->event_head] = event;
1205         if (!as->suser || !as->writer)
1206             continue;
1207         switch (event) {
1208         case APM_SYS_SUSPEND:
1209         case APM_USER_SUSPEND:
1210             as->suspends_pending++;
1211             suspends_pending++;
1212             break;
1213 
1214         case APM_SYS_STANDBY:
1215         case APM_USER_STANDBY:
1216             as->standbys_pending++;
1217             standbys_pending++;
1218             break;
1219         }
1220     }
1221     wake_up_interruptible(&apm_waitqueue);
1222 out:
1223     spin_unlock(&user_list_lock);
1224 }
1225 
1226 static void reinit_timer(void)
1227 {
1228 #ifdef INIT_TIMER_AFTER_SUSPEND
1229     unsigned long flags;
1230 
1231     raw_spin_lock_irqsave(&i8253_lock, flags);
1232     /* set the clock to HZ */
1233     outb_p(0x34, PIT_MODE);     /* binary, mode 2, LSB/MSB, ch 0 */
1234     udelay(10);
1235     outb_p(LATCH & 0xff, PIT_CH0);  /* LSB */
1236     udelay(10);
1237     outb_p(LATCH >> 8, PIT_CH0);    /* MSB */
1238     udelay(10);
1239     raw_spin_unlock_irqrestore(&i8253_lock, flags);
1240 #endif
1241 }
1242 
1243 static int suspend(int vetoable)
1244 {
1245     int err;
1246     struct apm_user *as;
1247 
1248     dpm_suspend_start(PMSG_SUSPEND);
1249     dpm_suspend_end(PMSG_SUSPEND);
1250 
1251     local_irq_disable();
1252     syscore_suspend();
1253 
1254     local_irq_enable();
1255 
1256     save_processor_state();
1257     err = set_system_power_state(APM_STATE_SUSPEND);
1258     ignore_normal_resume = 1;
1259     restore_processor_state();
1260 
1261     local_irq_disable();
1262     reinit_timer();
1263 
1264     if (err == APM_NO_ERROR)
1265         err = APM_SUCCESS;
1266     if (err != APM_SUCCESS)
1267         apm_error("suspend", err);
1268     err = (err == APM_SUCCESS) ? 0 : -EIO;
1269 
1270     syscore_resume();
1271     local_irq_enable();
1272 
1273     dpm_resume_start(PMSG_RESUME);
1274     dpm_resume_end(PMSG_RESUME);
1275 
1276     queue_event(APM_NORMAL_RESUME, NULL);
1277     spin_lock(&user_list_lock);
1278     for (as = user_list; as != NULL; as = as->next) {
1279         as->suspend_wait = 0;
1280         as->suspend_result = err;
1281     }
1282     spin_unlock(&user_list_lock);
1283     wake_up_interruptible(&apm_suspend_waitqueue);
1284     return err;
1285 }
1286 
1287 static void standby(void)
1288 {
1289     int err;
1290 
1291     dpm_suspend_end(PMSG_SUSPEND);
1292 
1293     local_irq_disable();
1294     syscore_suspend();
1295     local_irq_enable();
1296 
1297     err = set_system_power_state(APM_STATE_STANDBY);
1298     if ((err != APM_SUCCESS) && (err != APM_NO_ERROR))
1299         apm_error("standby", err);
1300 
1301     local_irq_disable();
1302     syscore_resume();
1303     local_irq_enable();
1304 
1305     dpm_resume_start(PMSG_RESUME);
1306 }
1307 
1308 static apm_event_t get_event(void)
1309 {
1310     int error;
1311     apm_event_t event = APM_NO_EVENTS; /* silence gcc */
1312     apm_eventinfo_t info;
1313 
1314     static int notified;
1315 
1316     /* we don't use the eventinfo */
1317     error = apm_get_event(&event, &info);
1318     if (error == APM_SUCCESS)
1319         return event;
1320 
1321     if ((error != APM_NO_EVENTS) && (notified++ == 0))
1322         apm_error("get_event", error);
1323 
1324     return 0;
1325 }
1326 
1327 static void check_events(void)
1328 {
1329     apm_event_t event;
1330     static unsigned long last_resume;
1331     static int ignore_bounce;
1332 
1333     while ((event = get_event()) != 0) {
1334         if (debug) {
1335             if (event <= NR_APM_EVENT_NAME)
1336                 printk(KERN_DEBUG "apm: received %s notify\n",
1337                        apm_event_name[event - 1]);
1338             else
1339                 printk(KERN_DEBUG "apm: received unknown "
1340                        "event 0x%02x\n", event);
1341         }
1342         if (ignore_bounce
1343             && (time_after(jiffies, last_resume + bounce_interval)))
1344             ignore_bounce = 0;
1345 
1346         switch (event) {
1347         case APM_SYS_STANDBY:
1348         case APM_USER_STANDBY:
1349             queue_event(event, NULL);
1350             if (standbys_pending <= 0)
1351                 standby();
1352             break;
1353 
1354         case APM_USER_SUSPEND:
1355 #ifdef CONFIG_APM_IGNORE_USER_SUSPEND
1356             if (apm_info.connection_version > 0x100)
1357                 set_system_power_state(APM_STATE_REJECT);
1358             break;
1359 #endif
1360         case APM_SYS_SUSPEND:
1361             if (ignore_bounce) {
1362                 if (apm_info.connection_version > 0x100)
1363                     set_system_power_state(APM_STATE_REJECT);
1364                 break;
1365             }
1366             /*
1367              * If we are already processing a SUSPEND,
1368              * then further SUSPEND events from the BIOS
1369              * will be ignored.  We also return here to
1370              * cope with the fact that the Thinkpads keep
1371              * sending a SUSPEND event until something else
1372              * happens!
1373              */
1374             if (ignore_sys_suspend)
1375                 return;
1376             ignore_sys_suspend = 1;
1377             queue_event(event, NULL);
1378             if (suspends_pending <= 0)
1379                 (void) suspend(1);
1380             break;
1381 
1382         case APM_NORMAL_RESUME:
1383         case APM_CRITICAL_RESUME:
1384         case APM_STANDBY_RESUME:
1385             ignore_sys_suspend = 0;
1386             last_resume = jiffies;
1387             ignore_bounce = 1;
1388             if ((event != APM_NORMAL_RESUME)
1389                 || (ignore_normal_resume == 0)) {
1390                 dpm_resume_end(PMSG_RESUME);
1391                 queue_event(event, NULL);
1392             }
1393             ignore_normal_resume = 0;
1394             break;
1395 
1396         case APM_CAPABILITY_CHANGE:
1397         case APM_LOW_BATTERY:
1398         case APM_POWER_STATUS_CHANGE:
1399             queue_event(event, NULL);
1400             /* If needed, notify drivers here */
1401             break;
1402 
1403         case APM_UPDATE_TIME:
1404             break;
1405 
1406         case APM_CRITICAL_SUSPEND:
1407             /*
1408              * We are not allowed to reject a critical suspend.
1409              */
1410             (void)suspend(0);
1411             break;
1412         }
1413     }
1414 }
1415 
1416 static void apm_event_handler(void)
1417 {
1418     static int pending_count = 4;
1419     int err;
1420 
1421     if ((standbys_pending > 0) || (suspends_pending > 0)) {
1422         if ((apm_info.connection_version > 0x100) &&
1423             (pending_count-- <= 0)) {
1424             pending_count = 4;
1425             if (debug)
1426                 printk(KERN_DEBUG "apm: setting state busy\n");
1427             err = set_system_power_state(APM_STATE_BUSY);
1428             if (err)
1429                 apm_error("busy", err);
1430         }
1431     } else
1432         pending_count = 4;
1433     check_events();
1434 }
1435 
1436 /*
1437  * This is the APM thread main loop.
1438  */
1439 
1440 static void apm_mainloop(void)
1441 {
1442     DECLARE_WAITQUEUE(wait, current);
1443 
1444     add_wait_queue(&apm_waitqueue, &wait);
1445     set_current_state(TASK_INTERRUPTIBLE);
1446     for (;;) {
1447         schedule_timeout(APM_CHECK_TIMEOUT);
1448         if (kthread_should_stop())
1449             break;
1450         /*
1451          * Ok, check all events, check for idle (and mark us sleeping
1452          * so as not to count towards the load average)..
1453          */
1454         set_current_state(TASK_INTERRUPTIBLE);
1455         apm_event_handler();
1456     }
1457     remove_wait_queue(&apm_waitqueue, &wait);
1458 }
1459 
1460 static int check_apm_user(struct apm_user *as, const char *func)
1461 {
1462     if (as == NULL || as->magic != APM_BIOS_MAGIC) {
1463         pr_err("%s passed bad filp\n", func);
1464         return 1;
1465     }
1466     return 0;
1467 }
1468 
1469 static ssize_t do_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
1470 {
1471     struct apm_user *as;
1472     int i;
1473     apm_event_t event;
1474 
1475     as = fp->private_data;
1476     if (check_apm_user(as, "read"))
1477         return -EIO;
1478     if ((int)count < sizeof(apm_event_t))
1479         return -EINVAL;
1480     if ((queue_empty(as)) && (fp->f_flags & O_NONBLOCK))
1481         return -EAGAIN;
1482     wait_event_interruptible(apm_waitqueue, !queue_empty(as));
1483     i = count;
1484     while ((i >= sizeof(event)) && !queue_empty(as)) {
1485         event = get_queued_event(as);
1486         if (copy_to_user(buf, &event, sizeof(event))) {
1487             if (i < count)
1488                 break;
1489             return -EFAULT;
1490         }
1491         switch (event) {
1492         case APM_SYS_SUSPEND:
1493         case APM_USER_SUSPEND:
1494             as->suspends_read++;
1495             break;
1496 
1497         case APM_SYS_STANDBY:
1498         case APM_USER_STANDBY:
1499             as->standbys_read++;
1500             break;
1501         }
1502         buf += sizeof(event);
1503         i -= sizeof(event);
1504     }
1505     if (i < count)
1506         return count - i;
1507     if (signal_pending(current))
1508         return -ERESTARTSYS;
1509     return 0;
1510 }
1511 
1512 static __poll_t do_poll(struct file *fp, poll_table *wait)
1513 {
1514     struct apm_user *as;
1515 
1516     as = fp->private_data;
1517     if (check_apm_user(as, "poll"))
1518         return 0;
1519     poll_wait(fp, &apm_waitqueue, wait);
1520     if (!queue_empty(as))
1521         return EPOLLIN | EPOLLRDNORM;
1522     return 0;
1523 }
1524 
1525 static long do_ioctl(struct file *filp, u_int cmd, u_long arg)
1526 {
1527     struct apm_user *as;
1528     int ret;
1529 
1530     as = filp->private_data;
1531     if (check_apm_user(as, "ioctl"))
1532         return -EIO;
1533     if (!as->suser || !as->writer)
1534         return -EPERM;
1535     switch (cmd) {
1536     case APM_IOC_STANDBY:
1537         mutex_lock(&apm_mutex);
1538         if (as->standbys_read > 0) {
1539             as->standbys_read--;
1540             as->standbys_pending--;
1541             standbys_pending--;
1542         } else
1543             queue_event(APM_USER_STANDBY, as);
1544         if (standbys_pending <= 0)
1545             standby();
1546         mutex_unlock(&apm_mutex);
1547         break;
1548     case APM_IOC_SUSPEND:
1549         mutex_lock(&apm_mutex);
1550         if (as->suspends_read > 0) {
1551             as->suspends_read--;
1552             as->suspends_pending--;
1553             suspends_pending--;
1554         } else
1555             queue_event(APM_USER_SUSPEND, as);
1556         if (suspends_pending <= 0) {
1557             ret = suspend(1);
1558             mutex_unlock(&apm_mutex);
1559         } else {
1560             as->suspend_wait = 1;
1561             mutex_unlock(&apm_mutex);
1562             wait_event_interruptible(apm_suspend_waitqueue,
1563                     as->suspend_wait == 0);
1564             ret = as->suspend_result;
1565         }
1566         return ret;
1567     default:
1568         return -ENOTTY;
1569     }
1570     return 0;
1571 }
1572 
1573 static int do_release(struct inode *inode, struct file *filp)
1574 {
1575     struct apm_user *as;
1576 
1577     as = filp->private_data;
1578     if (check_apm_user(as, "release"))
1579         return 0;
1580     filp->private_data = NULL;
1581     if (as->standbys_pending > 0) {
1582         standbys_pending -= as->standbys_pending;
1583         if (standbys_pending <= 0)
1584             standby();
1585     }
1586     if (as->suspends_pending > 0) {
1587         suspends_pending -= as->suspends_pending;
1588         if (suspends_pending <= 0)
1589             (void) suspend(1);
1590     }
1591     spin_lock(&user_list_lock);
1592     if (user_list == as)
1593         user_list = as->next;
1594     else {
1595         struct apm_user *as1;
1596 
1597         for (as1 = user_list;
1598              (as1 != NULL) && (as1->next != as);
1599              as1 = as1->next)
1600             ;
1601         if (as1 == NULL)
1602             pr_err("filp not in user list\n");
1603         else
1604             as1->next = as->next;
1605     }
1606     spin_unlock(&user_list_lock);
1607     kfree(as);
1608     return 0;
1609 }
1610 
1611 static int do_open(struct inode *inode, struct file *filp)
1612 {
1613     struct apm_user *as;
1614 
1615     as = kmalloc(sizeof(*as), GFP_KERNEL);
1616     if (as == NULL)
1617         return -ENOMEM;
1618 
1619     as->magic = APM_BIOS_MAGIC;
1620     as->event_tail = as->event_head = 0;
1621     as->suspends_pending = as->standbys_pending = 0;
1622     as->suspends_read = as->standbys_read = 0;
1623     /*
1624      * XXX - this is a tiny bit broken, when we consider BSD
1625      * process accounting. If the device is opened by root, we
1626      * instantly flag that we used superuser privs. Who knows,
1627      * we might close the device immediately without doing a
1628      * privileged operation -- cevans
1629      */
1630     as->suser = capable(CAP_SYS_ADMIN);
1631     as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
1632     as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
1633     spin_lock(&user_list_lock);
1634     as->next = user_list;
1635     user_list = as;
1636     spin_unlock(&user_list_lock);
1637     filp->private_data = as;
1638     return 0;
1639 }
1640 
1641 #ifdef CONFIG_PROC_FS
1642 static int proc_apm_show(struct seq_file *m, void *v)
1643 {
1644     unsigned short  bx;
1645     unsigned short  cx;
1646     unsigned short  dx;
1647     int     error;
1648     unsigned short  ac_line_status = 0xff;
1649     unsigned short  battery_status = 0xff;
1650     unsigned short  battery_flag   = 0xff;
1651     int     percentage     = -1;
1652     int             time_units     = -1;
1653     char            *units         = "?";
1654 
1655     if ((num_online_cpus() == 1) &&
1656         !(error = apm_get_power_status(&bx, &cx, &dx))) {
1657         ac_line_status = (bx >> 8) & 0xff;
1658         battery_status = bx & 0xff;
1659         if ((cx & 0xff) != 0xff)
1660             percentage = cx & 0xff;
1661 
1662         if (apm_info.connection_version > 0x100) {
1663             battery_flag = (cx >> 8) & 0xff;
1664             if (dx != 0xffff) {
1665                 units = (dx & 0x8000) ? "min" : "sec";
1666                 time_units = dx & 0x7fff;
1667             }
1668         }
1669     }
1670     /* Arguments, with symbols from linux/apm_bios.h.  Information is
1671        from the Get Power Status (0x0a) call unless otherwise noted.
1672 
1673        0) Linux driver version (this will change if format changes)
1674        1) APM BIOS Version.  Usually 1.0, 1.1 or 1.2.
1675        2) APM flags from APM Installation Check (0x00):
1676           bit 0: APM_16_BIT_SUPPORT
1677           bit 1: APM_32_BIT_SUPPORT
1678           bit 2: APM_IDLE_SLOWS_CLOCK
1679           bit 3: APM_BIOS_DISABLED
1680           bit 4: APM_BIOS_DISENGAGED
1681        3) AC line status
1682           0x00: Off-line
1683           0x01: On-line
1684           0x02: On backup power (BIOS >= 1.1 only)
1685           0xff: Unknown
1686        4) Battery status
1687           0x00: High
1688           0x01: Low
1689           0x02: Critical
1690           0x03: Charging
1691           0x04: Selected battery not present (BIOS >= 1.2 only)
1692           0xff: Unknown
1693        5) Battery flag
1694           bit 0: High
1695           bit 1: Low
1696           bit 2: Critical
1697           bit 3: Charging
1698           bit 7: No system battery
1699           0xff: Unknown
1700        6) Remaining battery life (percentage of charge):
1701           0-100: valid
1702           -1: Unknown
1703        7) Remaining battery life (time units):
1704           Number of remaining minutes or seconds
1705           -1: Unknown
1706        8) min = minutes; sec = seconds */
1707 
1708     seq_printf(m, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
1709            driver_version,
1710            (apm_info.bios.version >> 8) & 0xff,
1711            apm_info.bios.version & 0xff,
1712            apm_info.bios.flags,
1713            ac_line_status,
1714            battery_status,
1715            battery_flag,
1716            percentage,
1717            time_units,
1718            units);
1719     return 0;
1720 }
1721 #endif
1722 
1723 static int apm(void *unused)
1724 {
1725     unsigned short  bx;
1726     unsigned short  cx;
1727     unsigned short  dx;
1728     int     error;
1729     char        *power_stat;
1730     char        *bat_stat;
1731 
1732     /* 2002/08/01 - WT
1733      * This is to avoid random crashes at boot time during initialization
1734      * on SMP systems in case of "apm=power-off" mode. Seen on ASUS A7M266D.
1735      * Some bioses don't like being called from CPU != 0.
1736      * Method suggested by Ingo Molnar.
1737      */
1738     set_cpus_allowed_ptr(current, cpumask_of(0));
1739     BUG_ON(smp_processor_id() != 0);
1740 
1741     if (apm_info.connection_version == 0) {
1742         apm_info.connection_version = apm_info.bios.version;
1743         if (apm_info.connection_version > 0x100) {
1744             /*
1745              * We only support BIOSs up to version 1.2
1746              */
1747             if (apm_info.connection_version > 0x0102)
1748                 apm_info.connection_version = 0x0102;
1749             error = apm_driver_version(&apm_info.connection_version);
1750             if (error != APM_SUCCESS) {
1751                 apm_error("driver version", error);
1752                 /* Fall back to an APM 1.0 connection. */
1753                 apm_info.connection_version = 0x100;
1754             }
1755         }
1756     }
1757 
1758     if (debug)
1759         printk(KERN_INFO "apm: Connection version %d.%d\n",
1760             (apm_info.connection_version >> 8) & 0xff,
1761             apm_info.connection_version & 0xff);
1762 
1763 #ifdef CONFIG_APM_DO_ENABLE
1764     if (apm_info.bios.flags & APM_BIOS_DISABLED) {
1765         /*
1766          * This call causes my NEC UltraLite Versa 33/C to hang if it
1767          * is booted with PM disabled but not in the docking station.
1768          * Unfortunate ...
1769          */
1770         error = apm_enable_power_management(1);
1771         if (error) {
1772             apm_error("enable power management", error);
1773             return -1;
1774         }
1775     }
1776 #endif
1777 
1778     if ((apm_info.bios.flags & APM_BIOS_DISENGAGED)
1779         && (apm_info.connection_version > 0x0100)) {
1780         error = apm_engage_power_management(APM_DEVICE_ALL, 1);
1781         if (error) {
1782             apm_error("engage power management", error);
1783             return -1;
1784         }
1785     }
1786 
1787     if (debug && (num_online_cpus() == 1 || smp)) {
1788         error = apm_get_power_status(&bx, &cx, &dx);
1789         if (error)
1790             printk(KERN_INFO "apm: power status not available\n");
1791         else {
1792             switch ((bx >> 8) & 0xff) {
1793             case 0:
1794                 power_stat = "off line";
1795                 break;
1796             case 1:
1797                 power_stat = "on line";
1798                 break;
1799             case 2:
1800                 power_stat = "on backup power";
1801                 break;
1802             default:
1803                 power_stat = "unknown";
1804                 break;
1805             }
1806             switch (bx & 0xff) {
1807             case 0:
1808                 bat_stat = "high";
1809                 break;
1810             case 1:
1811                 bat_stat = "low";
1812                 break;
1813             case 2:
1814                 bat_stat = "critical";
1815                 break;
1816             case 3:
1817                 bat_stat = "charging";
1818                 break;
1819             default:
1820                 bat_stat = "unknown";
1821                 break;
1822             }
1823             printk(KERN_INFO
1824                    "apm: AC %s, battery status %s, battery life ",
1825                    power_stat, bat_stat);
1826             if ((cx & 0xff) == 0xff)
1827                 printk("unknown\n");
1828             else
1829                 printk("%d%%\n", cx & 0xff);
1830             if (apm_info.connection_version > 0x100) {
1831                 printk(KERN_INFO
1832                        "apm: battery flag 0x%02x, battery life ",
1833                        (cx >> 8) & 0xff);
1834                 if (dx == 0xffff)
1835                     printk("unknown\n");
1836                 else
1837                     printk("%d %s\n", dx & 0x7fff,
1838                            (dx & 0x8000) ?
1839                            "minutes" : "seconds");
1840             }
1841         }
1842     }
1843 
1844     /* Install our power off handler.. */
1845     if (power_off)
1846         pm_power_off = apm_power_off;
1847 
1848     if (num_online_cpus() == 1 || smp) {
1849 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
1850         console_blank_hook = apm_console_blank;
1851 #endif
1852         apm_mainloop();
1853 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
1854         console_blank_hook = NULL;
1855 #endif
1856     }
1857 
1858     return 0;
1859 }
1860 
1861 #ifndef MODULE
1862 static int __init apm_setup(char *str)
1863 {
1864     int invert;
1865 
1866     while ((str != NULL) && (*str != '\0')) {
1867         if (strncmp(str, "off", 3) == 0)
1868             apm_disabled = 1;
1869         if (strncmp(str, "on", 2) == 0)
1870             apm_disabled = 0;
1871         if ((strncmp(str, "bounce-interval=", 16) == 0) ||
1872             (strncmp(str, "bounce_interval=", 16) == 0))
1873             bounce_interval = simple_strtol(str + 16, NULL, 0);
1874         if ((strncmp(str, "idle-threshold=", 15) == 0) ||
1875             (strncmp(str, "idle_threshold=", 15) == 0))
1876             idle_threshold = simple_strtol(str + 15, NULL, 0);
1877         if ((strncmp(str, "idle-period=", 12) == 0) ||
1878             (strncmp(str, "idle_period=", 12) == 0))
1879             idle_period = simple_strtol(str + 12, NULL, 0);
1880         invert = (strncmp(str, "no-", 3) == 0) ||
1881             (strncmp(str, "no_", 3) == 0);
1882         if (invert)
1883             str += 3;
1884         if (strncmp(str, "debug", 5) == 0)
1885             debug = !invert;
1886         if ((strncmp(str, "power-off", 9) == 0) ||
1887             (strncmp(str, "power_off", 9) == 0))
1888             power_off = !invert;
1889         if (strncmp(str, "smp", 3) == 0) {
1890             smp = !invert;
1891             idle_threshold = 100;
1892         }
1893         if ((strncmp(str, "allow-ints", 10) == 0) ||
1894             (strncmp(str, "allow_ints", 10) == 0))
1895             apm_info.allow_ints = !invert;
1896         if ((strncmp(str, "broken-psr", 10) == 0) ||
1897             (strncmp(str, "broken_psr", 10) == 0))
1898             apm_info.get_power_status_broken = !invert;
1899         if ((strncmp(str, "realmode-power-off", 18) == 0) ||
1900             (strncmp(str, "realmode_power_off", 18) == 0))
1901             apm_info.realmode_power_off = !invert;
1902         str = strchr(str, ',');
1903         if (str != NULL)
1904             str += strspn(str, ", \t");
1905     }
1906     return 1;
1907 }
1908 
1909 __setup("apm=", apm_setup);
1910 #endif
1911 
1912 static const struct file_operations apm_bios_fops = {
1913     .owner      = THIS_MODULE,
1914     .read       = do_read,
1915     .poll       = do_poll,
1916     .unlocked_ioctl = do_ioctl,
1917     .open       = do_open,
1918     .release    = do_release,
1919     .llseek     = noop_llseek,
1920 };
1921 
1922 static struct miscdevice apm_device = {
1923     APM_MINOR_DEV,
1924     "apm_bios",
1925     &apm_bios_fops
1926 };
1927 
1928 
1929 /* Simple "print if true" callback */
1930 static int __init print_if_true(const struct dmi_system_id *d)
1931 {
1932     printk("%s\n", d->ident);
1933     return 0;
1934 }
1935 
1936 /*
1937  * Some Bioses enable the PS/2 mouse (touchpad) at resume, even if it was
1938  * disabled before the suspend. Linux used to get terribly confused by that.
1939  */
1940 static int __init broken_ps2_resume(const struct dmi_system_id *d)
1941 {
1942     printk(KERN_INFO "%s machine detected. Mousepad Resume Bug "
1943            "workaround hopefully not needed.\n", d->ident);
1944     return 0;
1945 }
1946 
1947 /* Some bioses have a broken protected mode poweroff and need to use realmode */
1948 static int __init set_realmode_power_off(const struct dmi_system_id *d)
1949 {
1950     if (apm_info.realmode_power_off == 0) {
1951         apm_info.realmode_power_off = 1;
1952         printk(KERN_INFO "%s bios detected. "
1953                "Using realmode poweroff only.\n", d->ident);
1954     }
1955     return 0;
1956 }
1957 
1958 /* Some laptops require interrupts to be enabled during APM calls */
1959 static int __init set_apm_ints(const struct dmi_system_id *d)
1960 {
1961     if (apm_info.allow_ints == 0) {
1962         apm_info.allow_ints = 1;
1963         printk(KERN_INFO "%s machine detected. "
1964                "Enabling interrupts during APM calls.\n", d->ident);
1965     }
1966     return 0;
1967 }
1968 
1969 /* Some APM bioses corrupt memory or just plain do not work */
1970 static int __init apm_is_horked(const struct dmi_system_id *d)
1971 {
1972     if (apm_info.disabled == 0) {
1973         apm_info.disabled = 1;
1974         printk(KERN_INFO "%s machine detected. "
1975                "Disabling APM.\n", d->ident);
1976     }
1977     return 0;
1978 }
1979 
1980 static int __init apm_is_horked_d850md(const struct dmi_system_id *d)
1981 {
1982     if (apm_info.disabled == 0) {
1983         apm_info.disabled = 1;
1984         printk(KERN_INFO "%s machine detected. "
1985                "Disabling APM.\n", d->ident);
1986         printk(KERN_INFO "This bug is fixed in bios P15 which is available for\n");
1987         printk(KERN_INFO "download from support.intel.com\n");
1988     }
1989     return 0;
1990 }
1991 
1992 /* Some APM bioses hang on APM idle calls */
1993 static int __init apm_likes_to_melt(const struct dmi_system_id *d)
1994 {
1995     if (apm_info.forbid_idle == 0) {
1996         apm_info.forbid_idle = 1;
1997         printk(KERN_INFO "%s machine detected. "
1998                "Disabling APM idle calls.\n", d->ident);
1999     }
2000     return 0;
2001 }
2002 
2003 /*
2004  *  Check for clue free BIOS implementations who use
2005  *  the following QA technique
2006  *
2007  *      [ Write BIOS Code ]<------
2008  *               |                ^
2009  *      < Does it Compile >----N--
2010  *               |Y               ^
2011  *  < Does it Boot Win98 >-N--
2012  *               |Y
2013  *           [Ship It]
2014  *
2015  *  Phoenix A04  08/24/2000 is known bad (Dell Inspiron 5000e)
2016  *  Phoenix A07  09/29/2000 is known good (Dell Inspiron 5000)
2017  */
2018 static int __init broken_apm_power(const struct dmi_system_id *d)
2019 {
2020     apm_info.get_power_status_broken = 1;
2021     printk(KERN_WARNING "BIOS strings suggest APM bugs, "
2022            "disabling power status reporting.\n");
2023     return 0;
2024 }
2025 
2026 /*
2027  * This bios swaps the APM minute reporting bytes over (Many sony laptops
2028  * have this problem).
2029  */
2030 static int __init swab_apm_power_in_minutes(const struct dmi_system_id *d)
2031 {
2032     apm_info.get_power_status_swabinminutes = 1;
2033     printk(KERN_WARNING "BIOS strings suggest APM reports battery life "
2034            "in minutes and wrong byte order.\n");
2035     return 0;
2036 }
2037 
2038 static const struct dmi_system_id apm_dmi_table[] __initconst = {
2039     {
2040         print_if_true,
2041         KERN_WARNING "IBM T23 - BIOS 1.03b+ and controller firmware 1.02+ may be needed for Linux APM.",
2042         {   DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
2043             DMI_MATCH(DMI_BIOS_VERSION, "1AET38WW (1.01b)"), },
2044     },
2045     {   /* Handle problems with APM on the C600 */
2046         broken_ps2_resume, "Dell Latitude C600",
2047         {   DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
2048             DMI_MATCH(DMI_PRODUCT_NAME, "Latitude C600"), },
2049     },
2050     {   /* Allow interrupts during suspend on Dell Latitude laptops*/
2051         set_apm_ints, "Dell Latitude",
2052         {   DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2053             DMI_MATCH(DMI_PRODUCT_NAME, "Latitude C510"), }
2054     },
2055     {   /* APM crashes */
2056         apm_is_horked, "Dell Inspiron 2500",
2057         {   DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2058             DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
2059             DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2060             DMI_MATCH(DMI_BIOS_VERSION, "A11"), },
2061     },
2062     {   /* Allow interrupts during suspend on Dell Inspiron laptops*/
2063         set_apm_ints, "Dell Inspiron", {
2064             DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2065             DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"), },
2066     },
2067     {   /* Handle problems with APM on Inspiron 5000e */
2068         broken_apm_power, "Dell Inspiron 5000e",
2069         {   DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2070             DMI_MATCH(DMI_BIOS_VERSION, "A04"),
2071             DMI_MATCH(DMI_BIOS_DATE, "08/24/2000"), },
2072     },
2073     {   /* Handle problems with APM on Inspiron 2500 */
2074         broken_apm_power, "Dell Inspiron 2500",
2075         {   DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2076             DMI_MATCH(DMI_BIOS_VERSION, "A12"),
2077             DMI_MATCH(DMI_BIOS_DATE, "02/04/2002"), },
2078     },
2079     {   /* APM crashes */
2080         apm_is_horked, "Dell Dimension 4100",
2081         {   DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2082             DMI_MATCH(DMI_PRODUCT_NAME, "XPS-Z"),
2083             DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
2084             DMI_MATCH(DMI_BIOS_VERSION, "A11"), },
2085     },
2086     {   /* Allow interrupts during suspend on Compaq Laptops*/
2087         set_apm_ints, "Compaq 12XL125",
2088         {   DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
2089             DMI_MATCH(DMI_PRODUCT_NAME, "Compaq PC"),
2090             DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2091             DMI_MATCH(DMI_BIOS_VERSION, "4.06"), },
2092     },
2093     {   /* Allow interrupts during APM or the clock goes slow */
2094         set_apm_ints, "ASUSTeK",
2095         {   DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
2096             DMI_MATCH(DMI_PRODUCT_NAME, "L8400K series Notebook PC"), },
2097     },
2098     {   /* APM blows on shutdown */
2099         apm_is_horked, "ABIT KX7-333[R]",
2100         {   DMI_MATCH(DMI_BOARD_VENDOR, "ABIT"),
2101             DMI_MATCH(DMI_BOARD_NAME, "VT8367-8233A (KX7-333[R])"), },
2102     },
2103     {   /* APM crashes */
2104         apm_is_horked, "Trigem Delhi3",
2105         {   DMI_MATCH(DMI_SYS_VENDOR, "TriGem Computer, Inc"),
2106             DMI_MATCH(DMI_PRODUCT_NAME, "Delhi3"), },
2107     },
2108     {   /* APM crashes */
2109         apm_is_horked, "Fujitsu-Siemens",
2110         {   DMI_MATCH(DMI_BIOS_VENDOR, "hoenix/FUJITSU SIEMENS"),
2111             DMI_MATCH(DMI_BIOS_VERSION, "Version1.01"), },
2112     },
2113     {   /* APM crashes */
2114         apm_is_horked_d850md, "Intel D850MD",
2115         {   DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
2116             DMI_MATCH(DMI_BIOS_VERSION, "MV85010A.86A.0016.P07.0201251536"), },
2117     },
2118     {   /* APM crashes */
2119         apm_is_horked, "Intel D810EMO",
2120         {   DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
2121             DMI_MATCH(DMI_BIOS_VERSION, "MO81010A.86A.0008.P04.0004170800"), },
2122     },
2123     {   /* APM crashes */
2124         apm_is_horked, "Dell XPS-Z",
2125         {   DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
2126             DMI_MATCH(DMI_BIOS_VERSION, "A11"),
2127             DMI_MATCH(DMI_PRODUCT_NAME, "XPS-Z"), },
2128     },
2129     {   /* APM crashes */
2130         apm_is_horked, "Sharp PC-PJ/AX",
2131         {   DMI_MATCH(DMI_SYS_VENDOR, "SHARP"),
2132             DMI_MATCH(DMI_PRODUCT_NAME, "PC-PJ/AX"),
2133             DMI_MATCH(DMI_BIOS_VENDOR, "SystemSoft"),
2134             DMI_MATCH(DMI_BIOS_VERSION, "Version R2.08"), },
2135     },
2136     {   /* APM crashes */
2137         apm_is_horked, "Dell Inspiron 2500",
2138         {   DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2139             DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
2140             DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2141             DMI_MATCH(DMI_BIOS_VERSION, "A11"), },
2142     },
2143     {   /* APM idle hangs */
2144         apm_likes_to_melt, "Jabil AMD",
2145         {   DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
2146             DMI_MATCH(DMI_BIOS_VERSION, "0AASNP06"), },
2147     },
2148     {   /* APM idle hangs */
2149         apm_likes_to_melt, "AMI Bios",
2150         {   DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
2151             DMI_MATCH(DMI_BIOS_VERSION, "0AASNP05"), },
2152     },
2153     {   /* Handle problems with APM on Sony Vaio PCG-N505X(DE) */
2154         swab_apm_power_in_minutes, "Sony VAIO",
2155         {   DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2156             DMI_MATCH(DMI_BIOS_VERSION, "R0206H"),
2157             DMI_MATCH(DMI_BIOS_DATE, "08/23/99"), },
2158     },
2159     {   /* Handle problems with APM on Sony Vaio PCG-N505VX */
2160         swab_apm_power_in_minutes, "Sony VAIO",
2161         {   DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2162             DMI_MATCH(DMI_BIOS_VERSION, "W2K06H0"),
2163             DMI_MATCH(DMI_BIOS_DATE, "02/03/00"), },
2164     },
2165     {   /* Handle problems with APM on Sony Vaio PCG-XG29 */
2166         swab_apm_power_in_minutes, "Sony VAIO",
2167         {   DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2168             DMI_MATCH(DMI_BIOS_VERSION, "R0117A0"),
2169             DMI_MATCH(DMI_BIOS_DATE, "04/25/00"), },
2170     },
2171     {   /* Handle problems with APM on Sony Vaio PCG-Z600NE */
2172         swab_apm_power_in_minutes, "Sony VAIO",
2173         {   DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2174             DMI_MATCH(DMI_BIOS_VERSION, "R0121Z1"),
2175             DMI_MATCH(DMI_BIOS_DATE, "05/11/00"), },
2176     },
2177     {   /* Handle problems with APM on Sony Vaio PCG-Z600NE */
2178         swab_apm_power_in_minutes, "Sony VAIO",
2179         {   DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2180             DMI_MATCH(DMI_BIOS_VERSION, "WME01Z1"),
2181             DMI_MATCH(DMI_BIOS_DATE, "08/11/00"), },
2182     },
2183     {   /* Handle problems with APM on Sony Vaio PCG-Z600LEK(DE) */
2184         swab_apm_power_in_minutes, "Sony VAIO",
2185         {   DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2186             DMI_MATCH(DMI_BIOS_VERSION, "R0206Z3"),
2187             DMI_MATCH(DMI_BIOS_DATE, "12/25/00"), },
2188     },
2189     {   /* Handle problems with APM on Sony Vaio PCG-Z505LS */
2190         swab_apm_power_in_minutes, "Sony VAIO",
2191         {   DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2192             DMI_MATCH(DMI_BIOS_VERSION, "R0203D0"),
2193             DMI_MATCH(DMI_BIOS_DATE, "05/12/00"), },
2194     },
2195     {   /* Handle problems with APM on Sony Vaio PCG-Z505LS */
2196         swab_apm_power_in_minutes, "Sony VAIO",
2197         {   DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2198             DMI_MATCH(DMI_BIOS_VERSION, "R0203Z3"),
2199             DMI_MATCH(DMI_BIOS_DATE, "08/25/00"), },
2200     },
2201     {   /* Handle problems with APM on Sony Vaio PCG-Z505LS (with updated BIOS) */
2202         swab_apm_power_in_minutes, "Sony VAIO",
2203         {   DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2204             DMI_MATCH(DMI_BIOS_VERSION, "R0209Z3"),
2205             DMI_MATCH(DMI_BIOS_DATE, "05/12/01"), },
2206     },
2207     {   /* Handle problems with APM on Sony Vaio PCG-F104K */
2208         swab_apm_power_in_minutes, "Sony VAIO",
2209         {   DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2210             DMI_MATCH(DMI_BIOS_VERSION, "R0204K2"),
2211             DMI_MATCH(DMI_BIOS_DATE, "08/28/00"), },
2212     },
2213 
2214     {   /* Handle problems with APM on Sony Vaio PCG-C1VN/C1VE */
2215         swab_apm_power_in_minutes, "Sony VAIO",
2216         {   DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2217             DMI_MATCH(DMI_BIOS_VERSION, "R0208P1"),
2218             DMI_MATCH(DMI_BIOS_DATE, "11/09/00"), },
2219     },
2220     {   /* Handle problems with APM on Sony Vaio PCG-C1VE */
2221         swab_apm_power_in_minutes, "Sony VAIO",
2222         {   DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2223             DMI_MATCH(DMI_BIOS_VERSION, "R0204P1"),
2224             DMI_MATCH(DMI_BIOS_DATE, "09/12/00"), },
2225     },
2226     {   /* Handle problems with APM on Sony Vaio PCG-C1VE */
2227         swab_apm_power_in_minutes, "Sony VAIO",
2228         {   DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2229             DMI_MATCH(DMI_BIOS_VERSION, "WXPO1Z3"),
2230             DMI_MATCH(DMI_BIOS_DATE, "10/26/01"), },
2231     },
2232     {   /* broken PM poweroff bios */
2233         set_realmode_power_off, "Award Software v4.60 PGMA",
2234         {   DMI_MATCH(DMI_BIOS_VENDOR, "Award Software International, Inc."),
2235             DMI_MATCH(DMI_BIOS_VERSION, "4.60 PGMA"),
2236             DMI_MATCH(DMI_BIOS_DATE, "134526184"), },
2237     },
2238 
2239     /* Generic per vendor APM settings  */
2240 
2241     {   /* Allow interrupts during suspend on IBM laptops */
2242         set_apm_ints, "IBM",
2243         {   DMI_MATCH(DMI_SYS_VENDOR, "IBM"), },
2244     },
2245 
2246     { }
2247 };
2248 
2249 /*
2250  * Just start the APM thread. We do NOT want to do APM BIOS
2251  * calls from anything but the APM thread, if for no other reason
2252  * than the fact that we don't trust the APM BIOS. This way,
2253  * most common APM BIOS problems that lead to protection errors
2254  * etc will have at least some level of being contained...
2255  *
2256  * In short, if something bad happens, at least we have a choice
2257  * of just killing the apm thread..
2258  */
2259 static int __init apm_init(void)
2260 {
2261     struct desc_struct *gdt;
2262     int err;
2263 
2264     dmi_check_system(apm_dmi_table);
2265 
2266     if (apm_info.bios.version == 0 || machine_is_olpc()) {
2267         printk(KERN_INFO "apm: BIOS not found.\n");
2268         return -ENODEV;
2269     }
2270     printk(KERN_INFO
2271            "apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n",
2272            ((apm_info.bios.version >> 8) & 0xff),
2273            (apm_info.bios.version & 0xff),
2274            apm_info.bios.flags,
2275            driver_version);
2276     if ((apm_info.bios.flags & APM_32_BIT_SUPPORT) == 0) {
2277         printk(KERN_INFO "apm: no 32 bit BIOS support\n");
2278         return -ENODEV;
2279     }
2280 
2281     if (allow_ints)
2282         apm_info.allow_ints = 1;
2283     if (broken_psr)
2284         apm_info.get_power_status_broken = 1;
2285     if (realmode_power_off)
2286         apm_info.realmode_power_off = 1;
2287     /* User can override, but default is to trust DMI */
2288     if (apm_disabled != -1)
2289         apm_info.disabled = apm_disabled;
2290 
2291     /*
2292      * Fix for the Compaq Contura 3/25c which reports BIOS version 0.1
2293      * but is reportedly a 1.0 BIOS.
2294      */
2295     if (apm_info.bios.version == 0x001)
2296         apm_info.bios.version = 0x100;
2297 
2298     /* BIOS < 1.2 doesn't set cseg_16_len */
2299     if (apm_info.bios.version < 0x102)
2300         apm_info.bios.cseg_16_len = 0; /* 64k */
2301 
2302     if (debug) {
2303         printk(KERN_INFO "apm: entry %x:%x cseg16 %x dseg %x",
2304             apm_info.bios.cseg, apm_info.bios.offset,
2305             apm_info.bios.cseg_16, apm_info.bios.dseg);
2306         if (apm_info.bios.version > 0x100)
2307             printk(" cseg len %x, dseg len %x",
2308                 apm_info.bios.cseg_len,
2309                 apm_info.bios.dseg_len);
2310         if (apm_info.bios.version > 0x101)
2311             printk(" cseg16 len %x", apm_info.bios.cseg_16_len);
2312         printk("\n");
2313     }
2314 
2315     if (apm_info.disabled) {
2316         pr_notice("disabled on user request.\n");
2317         return -ENODEV;
2318     }
2319     if ((num_online_cpus() > 1) && !power_off && !smp) {
2320         pr_notice("disabled - APM is not SMP safe.\n");
2321         apm_info.disabled = 1;
2322         return -ENODEV;
2323     }
2324     if (!acpi_disabled) {
2325         pr_notice("overridden by ACPI.\n");
2326         apm_info.disabled = 1;
2327         return -ENODEV;
2328     }
2329 
2330     /*
2331      * Set up the long jump entry point to the APM BIOS, which is called
2332      * from inline assembly.
2333      */
2334     apm_bios_entry.offset = apm_info.bios.offset;
2335     apm_bios_entry.segment = APM_CS;
2336 
2337     /*
2338      * The APM 1.1 BIOS is supposed to provide limit information that it
2339      * recognizes.  Many machines do this correctly, but many others do
2340      * not restrict themselves to their claimed limit.  When this happens,
2341      * they will cause a segmentation violation in the kernel at boot time.
2342      * Most BIOS's, however, will respect a 64k limit, so we use that.
2343      *
2344      * Note we only set APM segments on CPU zero, since we pin the APM
2345      * code to that CPU.
2346      */
2347     gdt = get_cpu_gdt_rw(0);
2348     set_desc_base(&gdt[APM_CS >> 3],
2349          (unsigned long)__va((unsigned long)apm_info.bios.cseg << 4));
2350     set_desc_base(&gdt[APM_CS_16 >> 3],
2351          (unsigned long)__va((unsigned long)apm_info.bios.cseg_16 << 4));
2352     set_desc_base(&gdt[APM_DS >> 3],
2353          (unsigned long)__va((unsigned long)apm_info.bios.dseg << 4));
2354 
2355     proc_create_single("apm", 0, NULL, proc_apm_show);
2356 
2357     kapmd_task = kthread_create(apm, NULL, "kapmd");
2358     if (IS_ERR(kapmd_task)) {
2359         pr_err("disabled - Unable to start kernel thread\n");
2360         err = PTR_ERR(kapmd_task);
2361         kapmd_task = NULL;
2362         remove_proc_entry("apm", NULL);
2363         return err;
2364     }
2365     wake_up_process(kapmd_task);
2366 
2367     if (num_online_cpus() > 1 && !smp) {
2368         printk(KERN_NOTICE
2369                "apm: disabled - APM is not SMP safe (power off active).\n");
2370         return 0;
2371     }
2372 
2373     /*
2374      * Note we don't actually care if the misc_device cannot be registered.
2375      * this driver can do its job without it, even if userspace can't
2376      * control it.  just log the error
2377      */
2378     if (misc_register(&apm_device))
2379         printk(KERN_WARNING "apm: Could not register misc device.\n");
2380 
2381     if (HZ != 100)
2382         idle_period = (idle_period * HZ) / 100;
2383     if (idle_threshold < 100) {
2384         cpuidle_poll_state_init(&apm_idle_driver);
2385         if (!cpuidle_register_driver(&apm_idle_driver))
2386             if (cpuidle_register_device(&apm_cpuidle_device))
2387                 cpuidle_unregister_driver(&apm_idle_driver);
2388     }
2389 
2390     return 0;
2391 }
2392 
2393 static void __exit apm_exit(void)
2394 {
2395     int error;
2396 
2397     cpuidle_unregister_device(&apm_cpuidle_device);
2398     cpuidle_unregister_driver(&apm_idle_driver);
2399 
2400     if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0)
2401         && (apm_info.connection_version > 0x0100)) {
2402         error = apm_engage_power_management(APM_DEVICE_ALL, 0);
2403         if (error)
2404             apm_error("disengage power management", error);
2405     }
2406     misc_deregister(&apm_device);
2407     remove_proc_entry("apm", NULL);
2408     if (power_off)
2409         pm_power_off = NULL;
2410     if (kapmd_task) {
2411         kthread_stop(kapmd_task);
2412         kapmd_task = NULL;
2413     }
2414 }
2415 
2416 module_init(apm_init);
2417 module_exit(apm_exit);
2418 
2419 MODULE_AUTHOR("Stephen Rothwell");
2420 MODULE_DESCRIPTION("Advanced Power Management");
2421 MODULE_LICENSE("GPL");
2422 module_param(debug, bool, 0644);
2423 MODULE_PARM_DESC(debug, "Enable debug mode");
2424 module_param(power_off, bool, 0444);
2425 MODULE_PARM_DESC(power_off, "Enable power off");
2426 module_param(bounce_interval, int, 0444);
2427 MODULE_PARM_DESC(bounce_interval,
2428         "Set the number of ticks to ignore suspend bounces");
2429 module_param(allow_ints, bool, 0444);
2430 MODULE_PARM_DESC(allow_ints, "Allow interrupts during BIOS calls");
2431 module_param(broken_psr, bool, 0444);
2432 MODULE_PARM_DESC(broken_psr, "BIOS has a broken GetPowerStatus call");
2433 module_param(realmode_power_off, bool, 0444);
2434 MODULE_PARM_DESC(realmode_power_off,
2435         "Switch to real mode before powering off");
2436 module_param(idle_threshold, int, 0444);
2437 MODULE_PARM_DESC(idle_threshold,
2438     "System idle percentage above which to make APM BIOS idle calls");
2439 module_param(idle_period, int, 0444);
2440 MODULE_PARM_DESC(idle_period,
2441     "Period (in sec/100) over which to calculate the idle percentage");
2442 module_param(smp, bool, 0444);
2443 MODULE_PARM_DESC(smp,
2444     "Set this to enable APM use on an SMP platform. Use with caution on older systems");
2445 MODULE_ALIAS_MISCDEV(APM_MINOR_DEV);