linux/arch/x86/kernel/apm_32.c
<<
>>
Prefs
   1/* -*- linux-c -*-
   2 * APM BIOS driver for Linux
   3 * Copyright 1994-2001 Stephen Rothwell (sfr@canb.auug.org.au)
   4 *
   5 * Initial development of this driver was funded by NEC Australia P/L
   6 *      and NEC Corporation
   7 *
   8 * This program is free software; you can redistribute it and/or modify it
   9 * under the terms of the GNU General Public License as published by the
  10 * Free Software Foundation; either version 2, or (at your option) any
  11 * later version.
  12 *
  13 * This program is distributed in the hope that it will be useful, but
  14 * WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16 * General Public License for more details.
  17 *
  18 * October 1995, Rik Faith (faith@cs.unc.edu):
  19 *    Minor enhancements and updates (to the patch set) for 1.3.x
  20 *    Documentation
  21 * January 1996, Rik Faith (faith@cs.unc.edu):
  22 *    Make /proc/apm easy to format (bump driver version)
  23 * March 1996, Rik Faith (faith@cs.unc.edu):
  24 *    Prohibit APM BIOS calls unless apm_enabled.
  25 *    (Thanks to Ulrich Windl <Ulrich.Windl@rz.uni-regensburg.de>)
  26 * April 1996, Stephen Rothwell (sfr@canb.auug.org.au)
  27 *    Version 1.0 and 1.1
  28 * May 1996, Version 1.2
  29 * Feb 1998, Version 1.3
  30 * Feb 1998, Version 1.4
  31 * Aug 1998, Version 1.5
  32 * Sep 1998, Version 1.6
  33 * Nov 1998, Version 1.7
  34 * Jan 1999, Version 1.8
  35 * Jan 1999, Version 1.9
  36 * Oct 1999, Version 1.10
  37 * Nov 1999, Version 1.11
  38 * Jan 2000, Version 1.12
  39 * Feb 2000, Version 1.13
  40 * Nov 2000, Version 1.14
  41 * Oct 2001, Version 1.15
  42 * Jan 2002, Version 1.16
  43 * Oct 2002, Version 1.16ac
  44 *
  45 * History:
  46 *    0.6b: first version in official kernel, Linux 1.3.46
  47 *    0.7: changed /proc/apm format, Linux 1.3.58
  48 *    0.8: fixed gcc 2.7.[12] compilation problems, Linux 1.3.59
  49 *    0.9: only call bios if bios is present, Linux 1.3.72
  50 *    1.0: use fixed device number, consolidate /proc/apm into this file,
  51 *         Linux 1.3.85
  52 *    1.1: support user-space standby and suspend, power off after system
  53 *         halted, Linux 1.3.98
  54 *    1.2: When resetting RTC after resume, take care so that the time
  55 *         is only incorrect by 30-60mS (vs. 1S previously) (Gabor J. Toth
  56 *         <jtoth@princeton.edu>); improve interaction between
  57 *         screen-blanking and gpm (Stephen Rothwell); Linux 1.99.4
  58 *    1.2a:Simple change to stop mysterious bug reports with SMP also added
  59 *         levels to the printk calls. APM is not defined for SMP machines.
  60 *         The new replacement for it is, but Linux doesn't yet support this.
  61 *         Alan Cox Linux 2.1.55
  62 *    1.3: Set up a valid data descriptor 0x40 for buggy BIOS's
  63 *    1.4: Upgraded to support APM 1.2. Integrated ThinkPad suspend patch by
  64 *         Dean Gaudet <dgaudet@arctic.org>.
  65 *         C. Scott Ananian <cananian@alumni.princeton.edu> Linux 2.1.87
  66 *    1.5: Fix segment register reloading (in case of bad segments saved
  67 *         across BIOS call).
  68 *         Stephen Rothwell
  69 *    1.6: Cope with compiler/assembler differences.
  70 *         Only try to turn off the first display device.
  71 *         Fix OOPS at power off with no APM BIOS by Jan Echternach
  72 *                   <echter@informatik.uni-rostock.de>
  73 *         Stephen Rothwell
  74 *    1.7: Modify driver's cached copy of the disabled/disengaged flags
  75 *         to reflect current state of APM BIOS.
  76 *         Chris Rankin <rankinc@bellsouth.net>
  77 *         Reset interrupt 0 timer to 100Hz after suspend
  78 *         Chad Miller <cmiller@surfsouth.com>
  79 *         Add CONFIG_APM_IGNORE_SUSPEND_BOUNCE
  80 *         Richard Gooch <rgooch@atnf.csiro.au>
  81 *         Allow boot time disabling of APM
  82 *         Make boot messages far less verbose by default
  83 *         Make asm safer
  84 *         Stephen Rothwell
  85 *    1.8: Add CONFIG_APM_RTC_IS_GMT
  86 *         Richard Gooch <rgooch@atnf.csiro.au>
  87 *         change APM_NOINTS to CONFIG_APM_ALLOW_INTS
  88 *         remove dependency on CONFIG_PROC_FS
  89 *         Stephen Rothwell
  90 *    1.9: Fix small typo.  <laslo@wodip.opole.pl>
  91 *         Try to cope with BIOS's that need to have all display
  92 *         devices blanked and not just the first one.
  93 *         Ross Paterson <ross@soi.city.ac.uk>
  94 *         Fix segment limit setting it has always been wrong as
  95 *         the segments needed to have byte granularity.
  96 *         Mark a few things __init.
  97 *         Add hack to allow power off of SMP systems by popular request.
  98 *         Use CONFIG_SMP instead of __SMP__
  99 *         Ignore BOUNCES for three seconds.
 100 *         Stephen Rothwell
 101 *   1.10: Fix for Thinkpad return code.
 102 *         Merge 2.2 and 2.3 drivers.
 103 *         Remove APM dependencies in arch/i386/kernel/process.c
 104 *         Remove APM dependencies in drivers/char/sysrq.c
 105 *         Reset time across standby.
 106 *         Allow more inititialisation on SMP.
 107 *         Remove CONFIG_APM_POWER_OFF and make it boot time
 108 *         configurable (default on).
 109 *         Make debug only a boot time parameter (remove APM_DEBUG).
 110 *         Try to blank all devices on any error.
 111 *   1.11: Remove APM dependencies in drivers/char/console.c
 112 *         Check nr_running to detect if we are idle (from
 113 *         Borislav Deianov <borislav@lix.polytechnique.fr>)
 114 *         Fix for bioses that don't zero the top part of the
 115 *         entrypoint offset (Mario Sitta <sitta@al.unipmn.it>)
 116 *         (reported by Panos Katsaloulis <teras@writeme.com>).
 117 *         Real mode power off patch (Walter Hofmann
 118 *         <Walter.Hofmann@physik.stud.uni-erlangen.de>).
 119 *   1.12: Remove CONFIG_SMP as the compiler will optimize
 120 *         the code away anyway (smp_num_cpus == 1 in UP)
 121 *         noted by Artur Skawina <skawina@geocities.com>.
 122 *         Make power off under SMP work again.
 123 *         Fix thinko with initial engaging of BIOS.
 124 *         Make sure power off only happens on CPU 0
 125 *         (Paul "Rusty" Russell <rusty@rustcorp.com.au>).
 126 *         Do error notification to user mode if BIOS calls fail.
 127 *         Move entrypoint offset fix to ...boot/setup.S
 128 *         where it belongs (Cosmos <gis88564@cis.nctu.edu.tw>).
 129 *         Remove smp-power-off. SMP users must now specify
 130 *         "apm=power-off" on the kernel command line. Suggested
 131 *         by Jim Avera <jima@hal.com>, modified by Alan Cox
 132 *         <alan@lxorguk.ukuu.org.uk>.
 133 *         Register the /proc/apm entry even on SMP so that
 134 *         scripts that check for it before doing power off
 135 *         work (Jim Avera <jima@hal.com>).
 136 *   1.13: Changes for new pm_ interfaces (Andy Henroid
 137 *         <andy_henroid@yahoo.com>).
 138 *         Modularize the code.
 139 *         Fix the Thinkpad (again) :-( (CONFIG_APM_IGNORE_MULTIPLE_SUSPENDS
 140 *         is now the way life works).
 141 *         Fix thinko in suspend() (wrong return).
 142 *         Notify drivers on critical suspend.
 143 *         Make kapmd absorb more idle time (Pavel Machek <pavel@ucw.cz>
 144 *         modified by sfr).
 145 *         Disable interrupts while we are suspended (Andy Henroid
 146 *         <andy_henroid@yahoo.com> fixed by sfr).
 147 *         Make power off work on SMP again (Tony Hoyle
 148 *         <tmh@magenta-logic.com> and <zlatko@iskon.hr>) modified by sfr.
 149 *         Remove CONFIG_APM_SUSPEND_BOUNCE.  The bounce ignore
 150 *         interval is now configurable.
 151 *   1.14: Make connection version persist across module unload/load.
 152 *         Enable and engage power management earlier.
 153 *         Disengage power management on module unload.
 154 *         Changed to use the sysrq-register hack for registering the
 155 *         power off function called by magic sysrq based upon discussions
 156 *         in irc://irc.openprojects.net/#kernelnewbies
 157 *         (Crutcher Dunnavant <crutcher+kernel@datastacks.com>).
 158 *         Make CONFIG_APM_REAL_MODE_POWER_OFF run time configurable.
 159 *         (Arjan van de Ven <arjanv@redhat.com>) modified by sfr.
 160 *         Work around byte swap bug in one of the Vaio's BIOS's
 161 *         (Marc Boucher <marc@mbsi.ca>).
 162 *         Exposed the disable flag to dmi so that we can handle known
 163 *         broken APM (Alan Cox <alan@lxorguk.ukuu.org.uk>).
 164 *   1.14ac: If the BIOS says "I slowed the CPU down" then don't spin
 165 *         calling it - instead idle. (Alan Cox <alan@lxorguk.ukuu.org.uk>)
 166 *         If an APM idle fails log it and idle sensibly
 167 *   1.15: Don't queue events to clients who open the device O_WRONLY.
 168 *         Don't expect replies from clients who open the device O_RDONLY.
 169 *         (Idea from Thomas Hood)
 170 *         Minor waitqueue cleanups. (John Fremlin <chief@bandits.org>)
 171 *   1.16: Fix idle calling. (Andreas Steinmetz <ast@domdv.de> et al.)
 172 *         Notify listeners of standby or suspend events before notifying
 173 *         drivers. Return EBUSY to ioctl() if suspend is rejected.
 174 *         (Russell King <rmk@arm.linux.org.uk> and Thomas Hood)
 175 *         Ignore first resume after we generate our own resume event
 176 *         after a suspend (Thomas Hood)
 177 *         Daemonize now gets rid of our controlling terminal (sfr).
 178 *         CONFIG_APM_CPU_IDLE now just affects the default value of
 179 *         idle_threshold (sfr).
 180 *         Change name of kernel apm daemon (as it no longer idles) (sfr).
 181 *   1.16ac: Fix up SMP support somewhat. You can now force SMP on and we
 182 *         make _all_ APM calls on the CPU#0. Fix unsafe sign bug.
 183 *         TODO: determine if its "boot CPU" or "CPU0" we want to lock to.
 184 *
 185 * APM 1.1 Reference:
 186 *
 187 *   Intel Corporation, Microsoft Corporation. Advanced Power Management
 188 *   (APM) BIOS Interface Specification, Revision 1.1, September 1993.
 189 *   Intel Order Number 241704-001.  Microsoft Part Number 781-110-X01.
 190 *
 191 * [This document is available free from Intel by calling 800.628.8686 (fax
 192 * 916.356.6100) or 800.548.4725; or from
 193 * http://www.microsoft.com/whdc/archive/amp_12.mspx  It is also
 194 * available from Microsoft by calling 206.882.8080.]
 195 *
 196 * APM 1.2 Reference:
 197 *   Intel Corporation, Microsoft Corporation. Advanced Power Management
 198 *   (APM) BIOS Interface Specification, Revision 1.2, February 1996.
 199 *
 200 * [This document is available from Microsoft at:
 201 *    http://www.microsoft.com/whdc/archive/amp_12.mspx]
 202 */
 203
 204#define pr_fmt(fmt) "apm: " fmt
 205
 206#include <linux/module.h>
 207
 208#include <linux/poll.h>
 209#include <linux/types.h>
 210#include <linux/stddef.h>
 211#include <linux/timer.h>
 212#include <linux/fcntl.h>
 213#include <linux/slab.h>
 214#include <linux/stat.h>
 215#include <linux/proc_fs.h>
 216#include <linux/seq_file.h>
 217#include <linux/miscdevice.h>
 218#include <linux/apm_bios.h>
 219#include <linux/init.h>
 220#include <linux/time.h>
 221#include <linux/sched.h>
 222#include <linux/pm.h>
 223#include <linux/capability.h>
 224#include <linux/device.h>
 225#include <linux/kernel.h>
 226#include <linux/freezer.h>
 227#include <linux/smp.h>
 228#include <linux/dmi.h>
 229#include <linux/suspend.h>
 230#include <linux/kthread.h>
 231#include <linux/jiffies.h>
 232#include <linux/acpi.h>
 233#include <linux/syscore_ops.h>
 234#include <linux/i8253.h>
 235#include <linux/cpuidle.h>
 236
 237#include <asm/uaccess.h>
 238#include <asm/desc.h>
 239#include <asm/olpc.h>
 240#include <asm/paravirt.h>
 241#include <asm/reboot.h>
 242
 243#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
 244extern int (*console_blank_hook)(int);
 245#endif
 246
 247/*
 248 * The apm_bios device is one of the misc char devices.
 249 * This is its minor number.
 250 */
 251#define APM_MINOR_DEV   134
 252
 253/*
 254 * Various options can be changed at boot time as follows:
 255 * (We allow underscores for compatibility with the modules code)
 256 *      apm=on/off                      enable/disable APM
 257 *          [no-]allow[-_]ints          allow interrupts during BIOS calls
 258 *          [no-]broken[-_]psr          BIOS has a broken GetPowerStatus call
 259 *          [no-]realmode[-_]power[-_]off       switch to real mode before
 260 *                                              powering off
 261 *          [no-]debug                  log some debugging messages
 262 *          [no-]power[-_]off           power off on shutdown
 263 *          [no-]smp                    Use apm even on an SMP box
 264 *          bounce[-_]interval=<n>      number of ticks to ignore suspend
 265 *                                      bounces
 266 *          idle[-_]threshold=<n>       System idle percentage above which to
 267 *                                      make APM BIOS idle calls. Set it to
 268 *                                      100 to disable.
 269 *          idle[-_]period=<n>          Period (in 1/100s of a second) over
 270 *                                      which the idle percentage is
 271 *                                      calculated.
 272 */
 273
 274/* KNOWN PROBLEM MACHINES:
 275 *
 276 * U: TI 4000M TravelMate: BIOS is *NOT* APM compliant
 277 *                         [Confirmed by TI representative]
 278 * ?: ACER 486DX4/75: uses dseg 0040, in violation of APM specification
 279 *                    [Confirmed by BIOS disassembly]
 280 *                    [This may work now ...]
 281 * P: Toshiba 1950S: battery life information only gets updated after resume
 282 * P: Midwest Micro Soundbook Elite DX2/66 monochrome: screen blanking
 283 *      broken in BIOS [Reported by Garst R. Reese <reese@isn.net>]
 284 * ?: AcerNote-950: oops on reading /proc/apm - workaround is a WIP
 285 *      Neale Banks <neale@lowendale.com.au> December 2000
 286 *
 287 * Legend: U = unusable with APM patches
 288 *         P = partially usable with APM patches
 289 */
 290
 291/*
 292 * Define as 1 to make the driver always call the APM BIOS busy
 293 * routine even if the clock was not reported as slowed by the
 294 * idle routine.  Otherwise, define as 0.
 295 */
 296#define ALWAYS_CALL_BUSY   1
 297
 298/*
 299 * Define to make the APM BIOS calls zero all data segment registers (so
 300 * that an incorrect BIOS implementation will cause a kernel panic if it
 301 * tries to write to arbitrary memory).
 302 */
 303#define APM_ZERO_SEGS
 304
 305#include <asm/apm.h>
 306
 307/*
 308 * Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend.
 309 * This patched by Chad Miller <cmiller@surfsouth.com>, original code by
 310 * David Chen <chen@ctpa04.mit.edu>
 311 */
 312#undef INIT_TIMER_AFTER_SUSPEND
 313
 314#ifdef INIT_TIMER_AFTER_SUSPEND
 315#include <linux/timex.h>
 316#include <asm/io.h>
 317#include <linux/delay.h>
 318#endif
 319
 320/*
 321 * Need to poll the APM BIOS every second
 322 */
 323#define APM_CHECK_TIMEOUT       (HZ)
 324
 325/*
 326 * Ignore suspend events for this amount of time after a resume
 327 */
 328#define DEFAULT_BOUNCE_INTERVAL (3 * HZ)
 329
 330/*
 331 * Maximum number of events stored
 332 */
 333#define APM_MAX_EVENTS          20
 334
 335/*
 336 * The per-file APM data
 337 */
 338struct apm_user {
 339        int             magic;
 340        struct apm_user *next;
 341        unsigned int    suser: 1;
 342        unsigned int    writer: 1;
 343        unsigned int    reader: 1;
 344        unsigned int    suspend_wait: 1;
 345        int             suspend_result;
 346        int             suspends_pending;
 347        int             standbys_pending;
 348        int             suspends_read;
 349        int             standbys_read;
 350        int             event_head;
 351        int             event_tail;
 352        apm_event_t     events[APM_MAX_EVENTS];
 353};
 354
 355/*
 356 * The magic number in apm_user
 357 */
 358#define APM_BIOS_MAGIC          0x4101
 359
 360/*
 361 * idle percentage above which bios idle calls are done
 362 */
 363#ifdef CONFIG_APM_CPU_IDLE
 364#define DEFAULT_IDLE_THRESHOLD  95
 365#else
 366#define DEFAULT_IDLE_THRESHOLD  100
 367#endif
 368#define DEFAULT_IDLE_PERIOD     (100 / 3)
 369
 370static int apm_cpu_idle(struct cpuidle_device *dev,
 371                        struct cpuidle_driver *drv, int index);
 372
 373static struct cpuidle_driver apm_idle_driver = {
 374        .name = "apm_idle",
 375        .owner = THIS_MODULE,
 376        .en_core_tk_irqen = 1,
 377        .states = {
 378                { /* entry 0 is for polling */ },
 379                { /* entry 1 is for APM idle */
 380                        .name = "APM",
 381                        .desc = "APM idle",
 382                        .flags = CPUIDLE_FLAG_TIME_VALID,
 383                        .exit_latency = 250,    /* WAG */
 384                        .target_residency = 500,        /* WAG */
 385                        .enter = &apm_cpu_idle
 386                },
 387        },
 388        .state_count = 2,
 389};
 390
 391static struct cpuidle_device apm_cpuidle_device;
 392
 393/*
 394 * Local variables
 395 */
 396static struct {
 397        unsigned long   offset;
 398        unsigned short  segment;
 399} apm_bios_entry;
 400static int clock_slowed;
 401static int idle_threshold __read_mostly = DEFAULT_IDLE_THRESHOLD;
 402static int idle_period __read_mostly = DEFAULT_IDLE_PERIOD;
 403static int suspends_pending;
 404static int standbys_pending;
 405static int ignore_sys_suspend;
 406static int ignore_normal_resume;
 407static int bounce_interval __read_mostly = DEFAULT_BOUNCE_INTERVAL;
 408
 409static bool debug __read_mostly;
 410static bool smp __read_mostly;
 411static int apm_disabled = -1;
 412#ifdef CONFIG_SMP
 413static bool power_off;
 414#else
 415static bool power_off = 1;
 416#endif
 417static bool realmode_power_off;
 418#ifdef CONFIG_APM_ALLOW_INTS
 419static bool allow_ints = 1;
 420#else
 421static bool allow_ints;
 422#endif
 423static bool broken_psr;
 424
 425static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
 426static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
 427static struct apm_user *user_list;
 428static DEFINE_SPINLOCK(user_list_lock);
 429static DEFINE_MUTEX(apm_mutex);
 430
 431/*
 432 * Set up a segment that references the real mode segment 0x40
 433 * that extends up to the end of page zero (that we have reserved).
 434 * This is for buggy BIOS's that refer to (real mode) segment 0x40
 435 * even though they are called in protected mode.
 436 */
 437static struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4092,
 438                        (unsigned long)__va(0x400UL), PAGE_SIZE - 0x400 - 1);
 439
 440static const char driver_version[] = "1.16ac";  /* no spaces */
 441
 442static struct task_struct *kapmd_task;
 443
 444/*
 445 *      APM event names taken from the APM 1.2 specification. These are
 446 *      the message codes that the BIOS uses to tell us about events
 447 */
 448static const char * const apm_event_name[] = {
 449        "system standby",
 450        "system suspend",
 451        "normal resume",
 452        "critical resume",
 453        "low battery",
 454        "power status change",
 455        "update time",
 456        "critical suspend",
 457        "user standby",
 458        "user suspend",
 459        "system standby resume",
 460        "capabilities change"
 461};
 462#define NR_APM_EVENT_NAME ARRAY_SIZE(apm_event_name)
 463
 464typedef struct lookup_t {
 465        int     key;
 466        char    *msg;
 467} lookup_t;
 468
 469/*
 470 *      The BIOS returns a set of standard error codes in AX when the
 471 *      carry flag is set.
 472 */
 473
 474static const lookup_t error_table[] = {
 475/* N/A  { APM_SUCCESS,          "Operation succeeded" }, */
 476        { APM_DISABLED,         "Power management disabled" },
 477        { APM_CONNECTED,        "Real mode interface already connected" },
 478        { APM_NOT_CONNECTED,    "Interface not connected" },
 479        { APM_16_CONNECTED,     "16 bit interface already connected" },
 480/* N/A  { APM_16_UNSUPPORTED,   "16 bit interface not supported" }, */
 481        { APM_32_CONNECTED,     "32 bit interface already connected" },
 482        { APM_32_UNSUPPORTED,   "32 bit interface not supported" },
 483        { APM_BAD_DEVICE,       "Unrecognized device ID" },
 484        { APM_BAD_PARAM,        "Parameter out of range" },
 485        { APM_NOT_ENGAGED,      "Interface not engaged" },
 486        { APM_BAD_FUNCTION,     "Function not supported" },
 487        { APM_RESUME_DISABLED,  "Resume timer disabled" },
 488        { APM_BAD_STATE,        "Unable to enter requested state" },
 489/* N/A  { APM_NO_EVENTS,        "No events pending" }, */
 490        { APM_NO_ERROR,         "BIOS did not set a return code" },
 491        { APM_NOT_PRESENT,      "No APM present" }
 492};
 493#define ERROR_COUNT     ARRAY_SIZE(error_table)
 494
 495/**
 496 *      apm_error       -       display an APM error
 497 *      @str: information string
 498 *      @err: APM BIOS return code
 499 *
 500 *      Write a meaningful log entry to the kernel log in the event of
 501 *      an APM error.  Note that this also handles (negative) kernel errors.
 502 */
 503
 504static void apm_error(char *str, int err)
 505{
 506        int i;
 507
 508        for (i = 0; i < ERROR_COUNT; i++)
 509                if (error_table[i].key == err)
 510                        break;
 511        if (i < ERROR_COUNT)
 512                pr_notice("%s: %s\n", str, error_table[i].msg);
 513        else if (err < 0)
 514                pr_notice("%s: linux error code %i\n", str, err);
 515        else
 516                pr_notice("%s: unknown error code %#2.2x\n",
 517                       str, err);
 518}
 519
 520/*
 521 * These are the actual BIOS calls.  Depending on APM_ZERO_SEGS and
 522 * apm_info.allow_ints, we are being really paranoid here!  Not only
 523 * are interrupts disabled, but all the segment registers (except SS)
 524 * are saved and zeroed this means that if the BIOS tries to reference
 525 * any data without explicitly loading the segment registers, the kernel
 526 * will fault immediately rather than have some unforeseen circumstances
 527 * for the rest of the kernel.  And it will be very obvious!  :-) Doing
 528 * this depends on CS referring to the same physical memory as DS so that
 529 * DS can be zeroed before the call. Unfortunately, we can't do anything
 530 * about the stack segment/pointer.  Also, we tell the compiler that
 531 * everything could change.
 532 *
 533 * Also, we KNOW that for the non error case of apm_bios_call, there
 534 * is no useful data returned in the low order 8 bits of eax.
 535 */
 536
 537static inline unsigned long __apm_irq_save(void)
 538{
 539        unsigned long flags;
 540        local_save_flags(flags);
 541        if (apm_info.allow_ints) {
 542                if (irqs_disabled_flags(flags))
 543                        local_irq_enable();
 544        } else
 545                local_irq_disable();
 546
 547        return flags;
 548}
 549
 550#define apm_irq_save(flags) \
 551        do { flags = __apm_irq_save(); } while (0)
 552
 553static inline void apm_irq_restore(unsigned long flags)
 554{
 555        if (irqs_disabled_flags(flags))
 556                local_irq_disable();
 557        else if (irqs_disabled())
 558                local_irq_enable();
 559}
 560
 561#ifdef APM_ZERO_SEGS
 562#       define APM_DECL_SEGS \
 563                unsigned int saved_fs; unsigned int saved_gs;
 564#       define APM_DO_SAVE_SEGS \
 565                savesegment(fs, saved_fs); savesegment(gs, saved_gs)
 566#       define APM_DO_RESTORE_SEGS \
 567                loadsegment(fs, saved_fs); loadsegment(gs, saved_gs)
 568#else
 569#       define APM_DECL_SEGS
 570#       define APM_DO_SAVE_SEGS
 571#       define APM_DO_RESTORE_SEGS
 572#endif
 573
 574struct apm_bios_call {
 575        u32 func;
 576        /* In and out */
 577        u32 ebx;
 578        u32 ecx;
 579        /* Out only */
 580        u32 eax;
 581        u32 edx;
 582        u32 esi;
 583
 584        /* Error: -ENOMEM, or bits 8-15 of eax */
 585        int err;
 586};
 587
 588/**
 589 *      __apm_bios_call - Make an APM BIOS 32bit call
 590 *      @_call: pointer to struct apm_bios_call.
 591 *
 592 *      Make an APM call using the 32bit protected mode interface. The
 593 *      caller is responsible for knowing if APM BIOS is configured and
 594 *      enabled. This call can disable interrupts for a long period of
 595 *      time on some laptops.  The return value is in AH and the carry
 596 *      flag is loaded into AL.  If there is an error, then the error
 597 *      code is returned in AH (bits 8-15 of eax) and this function
 598 *      returns non-zero.
 599 *
 600 *      Note: this makes the call on the current CPU.
 601 */
 602static long __apm_bios_call(void *_call)
 603{
 604        APM_DECL_SEGS
 605        unsigned long           flags;
 606        int                     cpu;
 607        struct desc_struct      save_desc_40;
 608        struct desc_struct      *gdt;
 609        struct apm_bios_call    *call = _call;
 610
 611        cpu = get_cpu();
 612        BUG_ON(cpu != 0);
 613        gdt = get_cpu_gdt_table(cpu);
 614        save_desc_40 = gdt[0x40 / 8];
 615        gdt[0x40 / 8] = bad_bios_desc;
 616
 617        apm_irq_save(flags);
 618        APM_DO_SAVE_SEGS;
 619        apm_bios_call_asm(call->func, call->ebx, call->ecx,
 620                          &call->eax, &call->ebx, &call->ecx, &call->edx,
 621                          &call->esi);
 622        APM_DO_RESTORE_SEGS;
 623        apm_irq_restore(flags);
 624        gdt[0x40 / 8] = save_desc_40;
 625        put_cpu();
 626
 627        return call->eax & 0xff;
 628}
 629
 630/* Run __apm_bios_call or __apm_bios_call_simple on CPU 0 */
 631static int on_cpu0(long (*fn)(void *), struct apm_bios_call *call)
 632{
 633        int ret;
 634
 635        /* Don't bother with work_on_cpu in the common case, so we don't
 636         * have to worry about OOM or overhead. */
 637        if (get_cpu() == 0) {
 638                ret = fn(call);
 639                put_cpu();
 640        } else {
 641                put_cpu();
 642                ret = work_on_cpu(0, fn, call);
 643        }
 644
 645        /* work_on_cpu can fail with -ENOMEM */
 646        if (ret < 0)
 647                call->err = ret;
 648        else
 649                call->err = (call->eax >> 8) & 0xff;
 650
 651        return ret;
 652}
 653
 654/**
 655 *      apm_bios_call   -       Make an APM BIOS 32bit call (on CPU 0)
 656 *      @call: the apm_bios_call registers.
 657 *
 658 *      If there is an error, it is returned in @call.err.
 659 */
 660static int apm_bios_call(struct apm_bios_call *call)
 661{
 662        return on_cpu0(__apm_bios_call, call);
 663}
 664
 665/**
 666 *      __apm_bios_call_simple - Make an APM BIOS 32bit call (on CPU 0)
 667 *      @_call: pointer to struct apm_bios_call.
 668 *
 669 *      Make a BIOS call that returns one value only, or just status.
 670 *      If there is an error, then the error code is returned in AH
 671 *      (bits 8-15 of eax) and this function returns non-zero (it can
 672 *      also return -ENOMEM). This is used for simpler BIOS operations.
 673 *      This call may hold interrupts off for a long time on some laptops.
 674 *
 675 *      Note: this makes the call on the current CPU.
 676 */
 677static long __apm_bios_call_simple(void *_call)
 678{
 679        u8                      error;
 680        APM_DECL_SEGS
 681        unsigned long           flags;
 682        int                     cpu;
 683        struct desc_struct      save_desc_40;
 684        struct desc_struct      *gdt;
 685        struct apm_bios_call    *call = _call;
 686
 687        cpu = get_cpu();
 688        BUG_ON(cpu != 0);
 689        gdt = get_cpu_gdt_table(cpu);
 690        save_desc_40 = gdt[0x40 / 8];
 691        gdt[0x40 / 8] = bad_bios_desc;
 692
 693        apm_irq_save(flags);
 694        APM_DO_SAVE_SEGS;
 695        error = apm_bios_call_simple_asm(call->func, call->ebx, call->ecx,
 696                                         &call->eax);
 697        APM_DO_RESTORE_SEGS;
 698        apm_irq_restore(flags);
 699        gdt[0x40 / 8] = save_desc_40;
 700        put_cpu();
 701        return error;
 702}
 703
 704/**
 705 *      apm_bios_call_simple    -       make a simple APM BIOS 32bit call
 706 *      @func: APM function to invoke
 707 *      @ebx_in: EBX register value for BIOS call
 708 *      @ecx_in: ECX register value for BIOS call
 709 *      @eax: EAX register on return from the BIOS call
 710 *      @err: bits
 711 *
 712 *      Make a BIOS call that returns one value only, or just status.
 713 *      If there is an error, then the error code is returned in @err
 714 *      and this function returns non-zero. This is used for simpler
 715 *      BIOS operations.  This call may hold interrupts off for a long
 716 *      time on some laptops.
 717 */
 718static int apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax,
 719                                int *err)
 720{
 721        struct apm_bios_call call;
 722        int ret;
 723
 724        call.func = func;
 725        call.ebx = ebx_in;
 726        call.ecx = ecx_in;
 727
 728        ret = on_cpu0(__apm_bios_call_simple, &call);
 729        *eax = call.eax;
 730        *err = call.err;
 731        return ret;
 732}
 733
 734/**
 735 *      apm_driver_version      -       APM driver version
 736 *      @val:   loaded with the APM version on return
 737 *
 738 *      Retrieve the APM version supported by the BIOS. This is only
 739 *      supported for APM 1.1 or higher. An error indicates APM 1.0 is
 740 *      probably present.
 741 *
 742 *      On entry val should point to a value indicating the APM driver
 743 *      version with the high byte being the major and the low byte the
 744 *      minor number both in BCD
 745 *
 746 *      On return it will hold the BIOS revision supported in the
 747 *      same format.
 748 */
 749
 750static int apm_driver_version(u_short *val)
 751{
 752        u32 eax;
 753        int err;
 754
 755        if (apm_bios_call_simple(APM_FUNC_VERSION, 0, *val, &eax, &err))
 756                return err;
 757        *val = eax;
 758        return APM_SUCCESS;
 759}
 760
 761/**
 762 *      apm_get_event   -       get an APM event from the BIOS
 763 *      @event: pointer to the event
 764 *      @info: point to the event information
 765 *
 766 *      The APM BIOS provides a polled information for event
 767 *      reporting. The BIOS expects to be polled at least every second
 768 *      when events are pending. When a message is found the caller should
 769 *      poll until no more messages are present.  However, this causes
 770 *      problems on some laptops where a suspend event notification is
 771 *      not cleared until it is acknowledged.
 772 *
 773 *      Additional information is returned in the info pointer, providing
 774 *      that APM 1.2 is in use. If no messges are pending the value 0x80
 775 *      is returned (No power management events pending).
 776 */
 777static int apm_get_event(apm_event_t *event, apm_eventinfo_t *info)
 778{
 779        struct apm_bios_call call;
 780
 781        call.func = APM_FUNC_GET_EVENT;
 782        call.ebx = call.ecx = 0;
 783
 784        if (apm_bios_call(&call))
 785                return call.err;
 786
 787        *event = call.ebx;
 788        if (apm_info.connection_version < 0x0102)
 789                *info = ~0; /* indicate info not valid */
 790        else
 791                *info = call.ecx;
 792        return APM_SUCCESS;
 793}
 794
 795/**
 796 *      set_power_state -       set the power management state
 797 *      @what: which items to transition
 798 *      @state: state to transition to
 799 *
 800 *      Request an APM change of state for one or more system devices. The
 801 *      processor state must be transitioned last of all. what holds the
 802 *      class of device in the upper byte and the device number (0xFF for
 803 *      all) for the object to be transitioned.
 804 *
 805 *      The state holds the state to transition to, which may in fact
 806 *      be an acceptance of a BIOS requested state change.
 807 */
 808
 809static int set_power_state(u_short what, u_short state)
 810{
 811        u32 eax;
 812        int err;
 813
 814        if (apm_bios_call_simple(APM_FUNC_SET_STATE, what, state, &eax, &err))
 815                return err;
 816        return APM_SUCCESS;
 817}
 818
 819/**
 820 *      set_system_power_state - set system wide power state
 821 *      @state: which state to enter
 822 *
 823 *      Transition the entire system into a new APM power state.
 824 */
 825
 826static int set_system_power_state(u_short state)
 827{
 828        return set_power_state(APM_DEVICE_ALL, state);
 829}
 830
 831/**
 832 *      apm_do_idle     -       perform power saving
 833 *
 834 *      This function notifies the BIOS that the processor is (in the view
 835 *      of the OS) idle. It returns -1 in the event that the BIOS refuses
 836 *      to handle the idle request. On a success the function returns 1
 837 *      if the BIOS did clock slowing or 0 otherwise.
 838 */
 839
 840static int apm_do_idle(void)
 841{
 842        u32 eax;
 843        u8 ret = 0;
 844        int idled = 0;
 845        int polling;
 846        int err = 0;
 847
 848        polling = !!(current_thread_info()->status & TS_POLLING);
 849        if (polling) {
 850                current_thread_info()->status &= ~TS_POLLING;
 851                /*
 852                 * TS_POLLING-cleared state must be visible before we
 853                 * test NEED_RESCHED:
 854                 */
 855                smp_mb();
 856        }
 857        if (!need_resched()) {
 858                idled = 1;
 859                ret = apm_bios_call_simple(APM_FUNC_IDLE, 0, 0, &eax, &err);
 860        }
 861        if (polling)
 862                current_thread_info()->status |= TS_POLLING;
 863
 864        if (!idled)
 865                return 0;
 866
 867        if (ret) {
 868                static unsigned long t;
 869
 870                /* This always fails on some SMP boards running UP kernels.
 871                 * Only report the failure the first 5 times.
 872                 */
 873                if (++t < 5) {
 874                        printk(KERN_DEBUG "apm_do_idle failed (%d)\n", err);
 875                        t = jiffies;
 876                }
 877                return -1;
 878        }
 879        clock_slowed = (apm_info.bios.flags & APM_IDLE_SLOWS_CLOCK) != 0;
 880        return clock_slowed;
 881}
 882
 883/**
 884 *      apm_do_busy     -       inform the BIOS the CPU is busy
 885 *
 886 *      Request that the BIOS brings the CPU back to full performance.
 887 */
 888
 889static void apm_do_busy(void)
 890{
 891        u32 dummy;
 892        int err;
 893
 894        if (clock_slowed || ALWAYS_CALL_BUSY) {
 895                (void)apm_bios_call_simple(APM_FUNC_BUSY, 0, 0, &dummy, &err);
 896                clock_slowed = 0;
 897        }
 898}
 899
 900/*
 901 * If no process has really been interested in
 902 * the CPU for some time, we want to call BIOS
 903 * power management - we probably want
 904 * to conserve power.
 905 */
 906#define IDLE_CALC_LIMIT (HZ * 100)
 907#define IDLE_LEAKY_MAX  16
 908
 909/**
 910 * apm_cpu_idle         -       cpu idling for APM capable Linux
 911 *
 912 * This is the idling function the kernel executes when APM is available. It
 913 * tries to do BIOS powermanagement based on the average system idle time.
 914 * Furthermore it calls the system default idle routine.
 915 */
 916
 917static int apm_cpu_idle(struct cpuidle_device *dev,
 918        struct cpuidle_driver *drv, int index)
 919{
 920        static int use_apm_idle; /* = 0 */
 921        static unsigned int last_jiffies; /* = 0 */
 922        static unsigned int last_stime; /* = 0 */
 923        cputime_t stime;
 924
 925        int apm_idle_done = 0;
 926        unsigned int jiffies_since_last_check = jiffies - last_jiffies;
 927        unsigned int bucket;
 928
 929recalc:
 930        task_cputime(current, NULL, &stime);
 931        if (jiffies_since_last_check > IDLE_CALC_LIMIT) {
 932                use_apm_idle = 0;
 933        } else if (jiffies_since_last_check > idle_period) {
 934                unsigned int idle_percentage;
 935
 936                idle_percentage = stime - last_stime;
 937                idle_percentage *= 100;
 938                idle_percentage /= jiffies_since_last_check;
 939                use_apm_idle = (idle_percentage > idle_threshold);
 940                if (apm_info.forbid_idle)
 941                        use_apm_idle = 0;
 942        }
 943
 944        last_jiffies = jiffies;
 945        last_stime = stime;
 946
 947        bucket = IDLE_LEAKY_MAX;
 948
 949        while (!need_resched()) {
 950                if (use_apm_idle) {
 951                        unsigned int t;
 952
 953                        t = jiffies;
 954                        switch (apm_do_idle()) {
 955                        case 0:
 956                                apm_idle_done = 1;
 957                                if (t != jiffies) {
 958                                        if (bucket) {
 959                                                bucket = IDLE_LEAKY_MAX;
 960                                                continue;
 961                                        }
 962                                } else if (bucket) {
 963                                        bucket--;
 964                                        continue;
 965                                }
 966                                break;
 967                        case 1:
 968                                apm_idle_done = 1;
 969                                break;
 970                        default: /* BIOS refused */
 971                                break;
 972                        }
 973                }
 974                default_idle();
 975                local_irq_disable();
 976                jiffies_since_last_check = jiffies - last_jiffies;
 977                if (jiffies_since_last_check > idle_period)
 978                        goto recalc;
 979        }
 980
 981        if (apm_idle_done)
 982                apm_do_busy();
 983
 984        return index;
 985}
 986
 987/**
 988 *      apm_power_off   -       ask the BIOS to power off
 989 *
 990 *      Handle the power off sequence. This is the one piece of code we
 991 *      will execute even on SMP machines. In order to deal with BIOS
 992 *      bugs we support real mode APM BIOS power off calls. We also make
 993 *      the SMP call on CPU0 as some systems will only honour this call
 994 *      on their first cpu.
 995 */
 996
 997static void apm_power_off(void)
 998{
 999        /* Some bioses don't like being called from CPU != 0 */
1000        if (apm_info.realmode_power_off) {
1001                set_cpus_allowed_ptr(current, cpumask_of(0));
1002                machine_real_restart(MRR_APM);
1003        } else {
1004                (void)set_system_power_state(APM_STATE_OFF);
1005        }
1006}
1007
1008#ifdef CONFIG_APM_DO_ENABLE
1009
1010/**
1011 *      apm_enable_power_management - enable BIOS APM power management
1012 *      @enable: enable yes/no
1013 *
1014 *      Enable or disable the APM BIOS power services.
1015 */
1016
1017static int apm_enable_power_management(int enable)
1018{
1019        u32 eax;
1020        int err;
1021
1022        if ((enable == 0) && (apm_info.bios.flags & APM_BIOS_DISENGAGED))
1023                return APM_NOT_ENGAGED;
1024        if (apm_bios_call_simple(APM_FUNC_ENABLE_PM, APM_DEVICE_BALL,
1025                                 enable, &eax, &err))
1026                return err;
1027        if (enable)
1028                apm_info.bios.flags &= ~APM_BIOS_DISABLED;
1029        else
1030                apm_info.bios.flags |= APM_BIOS_DISABLED;
1031        return APM_SUCCESS;
1032}
1033#endif
1034
1035/**
1036 *      apm_get_power_status    -       get current power state
1037 *      @status: returned status
1038 *      @bat: battery info
1039 *      @life: estimated life
1040 *
1041 *      Obtain the current power status from the APM BIOS. We return a
1042 *      status which gives the rough battery status, and current power
1043 *      source. The bat value returned give an estimate as a percentage
1044 *      of life and a status value for the battery. The estimated life
1045 *      if reported is a lifetime in secodnds/minutes at current powwer
1046 *      consumption.
1047 */
1048
1049static int apm_get_power_status(u_short *status, u_short *bat, u_short *life)
1050{
1051        struct apm_bios_call call;
1052
1053        call.func = APM_FUNC_GET_STATUS;
1054        call.ebx = APM_DEVICE_ALL;
1055        call.ecx = 0;
1056
1057        if (apm_info.get_power_status_broken)
1058                return APM_32_UNSUPPORTED;
1059        if (apm_bios_call(&call))
1060                return call.err;
1061        *status = call.ebx;
1062        *bat = call.ecx;
1063        if (apm_info.get_power_status_swabinminutes) {
1064                *life = swab16((u16)call.edx);
1065                *life |= 0x8000;
1066        } else
1067                *life = call.edx;
1068        return APM_SUCCESS;
1069}
1070
1071#if 0
1072static int apm_get_battery_status(u_short which, u_short *status,
1073                                  u_short *bat, u_short *life, u_short *nbat)
1074{
1075        u32 eax;
1076        u32 ebx;
1077        u32 ecx;
1078        u32 edx;
1079        u32 esi;
1080
1081        if (apm_info.connection_version < 0x0102) {
1082                /* pretend we only have one battery. */
1083                if (which != 1)
1084                        return APM_BAD_DEVICE;
1085                *nbat = 1;
1086                return apm_get_power_status(status, bat, life);
1087        }
1088
1089        if (apm_bios_call(APM_FUNC_GET_STATUS, (0x8000 | (which)), 0, &eax,
1090                          &ebx, &ecx, &edx, &esi))
1091                return (eax >> 8) & 0xff;
1092        *status = ebx;
1093        *bat = ecx;
1094        *life = edx;
1095        *nbat = esi;
1096        return APM_SUCCESS;
1097}
1098#endif
1099
1100/**
1101 *      apm_engage_power_management     -       enable PM on a device
1102 *      @device: identity of device
1103 *      @enable: on/off
1104 *
1105 *      Activate or deactive power management on either a specific device
1106 *      or the entire system (%APM_DEVICE_ALL).
1107 */
1108
1109static int apm_engage_power_management(u_short device, int enable)
1110{
1111        u32 eax;
1112        int err;
1113
1114        if ((enable == 0) && (device == APM_DEVICE_ALL)
1115            && (apm_info.bios.flags & APM_BIOS_DISABLED))
1116                return APM_DISABLED;
1117        if (apm_bios_call_simple(APM_FUNC_ENGAGE_PM, device, enable,
1118                                 &eax, &err))
1119                return err;
1120        if (device == APM_DEVICE_ALL) {
1121                if (enable)
1122                        apm_info.bios.flags &= ~APM_BIOS_DISENGAGED;
1123                else
1124                        apm_info.bios.flags |= APM_BIOS_DISENGAGED;
1125        }
1126        return APM_SUCCESS;
1127}
1128
1129#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
1130
1131/**
1132 *      apm_console_blank       -       blank the display
1133 *      @blank: on/off
1134 *
1135 *      Attempt to blank the console, firstly by blanking just video device
1136 *      zero, and if that fails (some BIOSes don't support it) then it blanks
1137 *      all video devices. Typically the BIOS will do laptop backlight and
1138 *      monitor powerdown for us.
1139 */
1140
1141static int apm_console_blank(int blank)
1142{
1143        int error = APM_NOT_ENGAGED; /* silence gcc */
1144        int i;
1145        u_short state;
1146        static const u_short dev[3] = { 0x100, 0x1FF, 0x101 };
1147
1148        state = blank ? APM_STATE_STANDBY : APM_STATE_READY;
1149
1150        for (i = 0; i < ARRAY_SIZE(dev); i++) {
1151                error = set_power_state(dev[i], state);
1152
1153                if ((error == APM_SUCCESS) || (error == APM_NO_ERROR))
1154                        return 1;
1155
1156                if (error == APM_NOT_ENGAGED)
1157                        break;
1158        }
1159
1160        if (error == APM_NOT_ENGAGED) {
1161                static int tried;
1162                int eng_error;
1163                if (tried++ == 0) {
1164                        eng_error = apm_engage_power_management(APM_DEVICE_ALL, 1);
1165                        if (eng_error) {
1166                                apm_error("set display", error);
1167                                apm_error("engage interface", eng_error);
1168                                return 0;
1169                        } else
1170                                return apm_console_blank(blank);
1171                }
1172        }
1173        apm_error("set display", error);
1174        return 0;
1175}
1176#endif
1177
1178static int queue_empty(struct apm_user *as)
1179{
1180        return as->event_head == as->event_tail;
1181}
1182
1183static apm_event_t get_queued_event(struct apm_user *as)
1184{
1185        if (++as->event_tail >= APM_MAX_EVENTS)
1186                as->event_tail = 0;
1187        return as->events[as->event_tail];
1188}
1189
1190static void queue_event(apm_event_t event, struct apm_user *sender)
1191{
1192        struct apm_user *as;
1193
1194        spin_lock(&user_list_lock);
1195        if (user_list == NULL)
1196                goto out;
1197        for (as = user_list; as != NULL; as = as->next) {
1198                if ((as == sender) || (!as->reader))
1199                        continue;
1200                if (++as->event_head >= APM_MAX_EVENTS)
1201                        as->event_head = 0;
1202
1203                if (as->event_head == as->event_tail) {
1204                        static int notified;
1205
1206                        if (notified++ == 0)
1207                                pr_err("an event queue overflowed\n");
1208                        if (++as->event_tail >= APM_MAX_EVENTS)
1209                                as->event_tail = 0;
1210                }
1211                as->events[as->event_head] = event;
1212                if (!as->suser || !as->writer)
1213                        continue;
1214                switch (event) {
1215                case APM_SYS_SUSPEND:
1216                case APM_USER_SUSPEND:
1217                        as->suspends_pending++;
1218                        suspends_pending++;
1219                        break;
1220
1221                case APM_SYS_STANDBY:
1222                case APM_USER_STANDBY:
1223                        as->standbys_pending++;
1224                        standbys_pending++;
1225                        break;
1226                }
1227        }
1228        wake_up_interruptible(&apm_waitqueue);
1229out:
1230        spin_unlock(&user_list_lock);
1231}
1232
1233static void reinit_timer(void)
1234{
1235#ifdef INIT_TIMER_AFTER_SUSPEND
1236        unsigned long flags;
1237
1238        raw_spin_lock_irqsave(&i8253_lock, flags);
1239        /* set the clock to HZ */
1240        outb_p(0x34, PIT_MODE);         /* binary, mode 2, LSB/MSB, ch 0 */
1241        udelay(10);
1242        outb_p(LATCH & 0xff, PIT_CH0);  /* LSB */
1243        udelay(10);
1244        outb_p(LATCH >> 8, PIT_CH0);    /* MSB */
1245        udelay(10);
1246        raw_spin_unlock_irqrestore(&i8253_lock, flags);
1247#endif
1248}
1249
1250static int suspend(int vetoable)
1251{
1252        int err;
1253        struct apm_user *as;
1254
1255        dpm_suspend_start(PMSG_SUSPEND);
1256        dpm_suspend_end(PMSG_SUSPEND);
1257
1258        local_irq_disable();
1259        syscore_suspend();
1260
1261        local_irq_enable();
1262
1263        save_processor_state();
1264        err = set_system_power_state(APM_STATE_SUSPEND);
1265        ignore_normal_resume = 1;
1266        restore_processor_state();
1267
1268        local_irq_disable();
1269        reinit_timer();
1270
1271        if (err == APM_NO_ERROR)
1272                err = APM_SUCCESS;
1273        if (err != APM_SUCCESS)
1274                apm_error("suspend", err);
1275        err = (err == APM_SUCCESS) ? 0 : -EIO;
1276
1277        syscore_resume();
1278        local_irq_enable();
1279
1280        dpm_resume_start(PMSG_RESUME);
1281        dpm_resume_end(PMSG_RESUME);
1282
1283        queue_event(APM_NORMAL_RESUME, NULL);
1284        spin_lock(&user_list_lock);
1285        for (as = user_list; as != NULL; as = as->next) {
1286                as->suspend_wait = 0;
1287                as->suspend_result = err;
1288        }
1289        spin_unlock(&user_list_lock);
1290        wake_up_interruptible(&apm_suspend_waitqueue);
1291        return err;
1292}
1293
1294static void standby(void)
1295{
1296        int err;
1297
1298        dpm_suspend_end(PMSG_SUSPEND);
1299
1300        local_irq_disable();
1301        syscore_suspend();
1302        local_irq_enable();
1303
1304        err = set_system_power_state(APM_STATE_STANDBY);
1305        if ((err != APM_SUCCESS) && (err != APM_NO_ERROR))
1306                apm_error("standby", err);
1307
1308        local_irq_disable();
1309        syscore_resume();
1310        local_irq_enable();
1311
1312        dpm_resume_start(PMSG_RESUME);
1313}
1314
1315static apm_event_t get_event(void)
1316{
1317        int error;
1318        apm_event_t event = APM_NO_EVENTS; /* silence gcc */
1319        apm_eventinfo_t info;
1320
1321        static int notified;
1322
1323        /* we don't use the eventinfo */
1324        error = apm_get_event(&event, &info);
1325        if (error == APM_SUCCESS)
1326                return event;
1327
1328        if ((error != APM_NO_EVENTS) && (notified++ == 0))
1329                apm_error("get_event", error);
1330
1331        return 0;
1332}
1333
1334static void check_events(void)
1335{
1336        apm_event_t event;
1337        static unsigned long last_resume;
1338        static int ignore_bounce;
1339
1340        while ((event = get_event()) != 0) {
1341                if (debug) {
1342                        if (event <= NR_APM_EVENT_NAME)
1343                                printk(KERN_DEBUG "apm: received %s notify\n",
1344                                       apm_event_name[event - 1]);
1345                        else
1346                                printk(KERN_DEBUG "apm: received unknown "
1347                                       "event 0x%02x\n", event);
1348                }
1349                if (ignore_bounce
1350                    && (time_after(jiffies, last_resume + bounce_interval)))
1351                        ignore_bounce = 0;
1352
1353                switch (event) {
1354                case APM_SYS_STANDBY:
1355                case APM_USER_STANDBY:
1356                        queue_event(event, NULL);
1357                        if (standbys_pending <= 0)
1358                                standby();
1359                        break;
1360
1361                case APM_USER_SUSPEND:
1362#ifdef CONFIG_APM_IGNORE_USER_SUSPEND
1363                        if (apm_info.connection_version > 0x100)
1364                                set_system_power_state(APM_STATE_REJECT);
1365                        break;
1366#endif
1367                case APM_SYS_SUSPEND:
1368                        if (ignore_bounce) {
1369                                if (apm_info.connection_version > 0x100)
1370                                        set_system_power_state(APM_STATE_REJECT);
1371                                break;
1372                        }
1373                        /*
1374                         * If we are already processing a SUSPEND,
1375                         * then further SUSPEND events from the BIOS
1376                         * will be ignored.  We also return here to
1377                         * cope with the fact that the Thinkpads keep
1378                         * sending a SUSPEND event until something else
1379                         * happens!
1380                         */
1381                        if (ignore_sys_suspend)
1382                                return;
1383                        ignore_sys_suspend = 1;
1384                        queue_event(event, NULL);
1385                        if (suspends_pending <= 0)
1386                                (void) suspend(1);
1387                        break;
1388
1389                case APM_NORMAL_RESUME:
1390                case APM_CRITICAL_RESUME:
1391                case APM_STANDBY_RESUME:
1392                        ignore_sys_suspend = 0;
1393                        last_resume = jiffies;
1394                        ignore_bounce = 1;
1395                        if ((event != APM_NORMAL_RESUME)
1396                            || (ignore_normal_resume == 0)) {
1397                                dpm_resume_end(PMSG_RESUME);
1398                                queue_event(event, NULL);
1399                        }
1400                        ignore_normal_resume = 0;
1401                        break;
1402
1403                case APM_CAPABILITY_CHANGE:
1404                case APM_LOW_BATTERY:
1405                case APM_POWER_STATUS_CHANGE:
1406                        queue_event(event, NULL);
1407                        /* If needed, notify drivers here */
1408                        break;
1409
1410                case APM_UPDATE_TIME:
1411                        break;
1412
1413                case APM_CRITICAL_SUSPEND:
1414                        /*
1415                         * We are not allowed to reject a critical suspend.
1416                         */
1417                        (void)suspend(0);
1418                        break;
1419                }
1420        }
1421}
1422
1423static void apm_event_handler(void)
1424{
1425        static int pending_count = 4;
1426        int err;
1427
1428        if ((standbys_pending > 0) || (suspends_pending > 0)) {
1429                if ((apm_info.connection_version > 0x100) &&
1430                    (pending_count-- <= 0)) {
1431                        pending_count = 4;
1432                        if (debug)
1433                                printk(KERN_DEBUG "apm: setting state busy\n");
1434                        err = set_system_power_state(APM_STATE_BUSY);
1435                        if (err)
1436                                apm_error("busy", err);
1437                }
1438        } else
1439                pending_count = 4;
1440        check_events();
1441}
1442
1443/*
1444 * This is the APM thread main loop.
1445 */
1446
1447static void apm_mainloop(void)
1448{
1449        DECLARE_WAITQUEUE(wait, current);
1450
1451        add_wait_queue(&apm_waitqueue, &wait);
1452        set_current_state(TASK_INTERRUPTIBLE);
1453        for (;;) {
1454                schedule_timeout(APM_CHECK_TIMEOUT);
1455                if (kthread_should_stop())
1456                        break;
1457                /*
1458                 * Ok, check all events, check for idle (and mark us sleeping
1459                 * so as not to count towards the load average)..
1460                 */
1461                set_current_state(TASK_INTERRUPTIBLE);
1462                apm_event_handler();
1463        }
1464        remove_wait_queue(&apm_waitqueue, &wait);
1465}
1466
1467static int check_apm_user(struct apm_user *as, const char *func)
1468{
1469        if (as == NULL || as->magic != APM_BIOS_MAGIC) {
1470                pr_err("%s passed bad filp\n", func);
1471                return 1;
1472        }
1473        return 0;
1474}
1475
1476static ssize_t do_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
1477{
1478        struct apm_user *as;
1479        int i;
1480        apm_event_t event;
1481
1482        as = fp->private_data;
1483        if (check_apm_user(as, "read"))
1484                return -EIO;
1485        if ((int)count < sizeof(apm_event_t))
1486                return -EINVAL;
1487        if ((queue_empty(as)) && (fp->f_flags & O_NONBLOCK))
1488                return -EAGAIN;
1489        wait_event_interruptible(apm_waitqueue, !queue_empty(as));
1490        i = count;
1491        while ((i >= sizeof(event)) && !queue_empty(as)) {
1492                event = get_queued_event(as);
1493                if (copy_to_user(buf, &event, sizeof(event))) {
1494                        if (i < count)
1495                                break;
1496                        return -EFAULT;
1497                }
1498                switch (event) {
1499                case APM_SYS_SUSPEND:
1500                case APM_USER_SUSPEND:
1501                        as->suspends_read++;
1502                        break;
1503
1504                case APM_SYS_STANDBY:
1505                case APM_USER_STANDBY:
1506                        as->standbys_read++;
1507                        break;
1508                }
1509                buf += sizeof(event);
1510                i -= sizeof(event);
1511        }
1512        if (i < count)
1513                return count - i;
1514        if (signal_pending(current))
1515                return -ERESTARTSYS;
1516        return 0;
1517}
1518
1519static unsigned int do_poll(struct file *fp, poll_table *wait)
1520{
1521        struct apm_user *as;
1522
1523        as = fp->private_data;
1524        if (check_apm_user(as, "poll"))
1525                return 0;
1526        poll_wait(fp, &apm_waitqueue, wait);
1527        if (!queue_empty(as))
1528                return POLLIN | POLLRDNORM;
1529        return 0;
1530}
1531
1532static long do_ioctl(struct file *filp, u_int cmd, u_long arg)
1533{
1534        struct apm_user *as;
1535        int ret;
1536
1537        as = filp->private_data;
1538        if (check_apm_user(as, "ioctl"))
1539                return -EIO;
1540        if (!as->suser || !as->writer)
1541                return -EPERM;
1542        switch (cmd) {
1543        case APM_IOC_STANDBY:
1544                mutex_lock(&apm_mutex);
1545                if (as->standbys_read > 0) {
1546                        as->standbys_read--;
1547                        as->standbys_pending--;
1548                        standbys_pending--;
1549                } else
1550                        queue_event(APM_USER_STANDBY, as);
1551                if (standbys_pending <= 0)
1552                        standby();
1553                mutex_unlock(&apm_mutex);
1554                break;
1555        case APM_IOC_SUSPEND:
1556                mutex_lock(&apm_mutex);
1557                if (as->suspends_read > 0) {
1558                        as->suspends_read--;
1559                        as->suspends_pending--;
1560                        suspends_pending--;
1561                } else
1562                        queue_event(APM_USER_SUSPEND, as);
1563                if (suspends_pending <= 0) {
1564                        ret = suspend(1);
1565                        mutex_unlock(&apm_mutex);
1566                } else {
1567                        as->suspend_wait = 1;
1568                        mutex_unlock(&apm_mutex);
1569                        wait_event_interruptible(apm_suspend_waitqueue,
1570                                        as->suspend_wait == 0);
1571                        ret = as->suspend_result;
1572                }
1573                return ret;
1574        default:
1575                return -ENOTTY;
1576        }
1577        return 0;
1578}
1579
1580static int do_release(struct inode *inode, struct file *filp)
1581{
1582        struct apm_user *as;
1583
1584        as = filp->private_data;
1585        if (check_apm_user(as, "release"))
1586                return 0;
1587        filp->private_data = NULL;
1588        if (as->standbys_pending > 0) {
1589                standbys_pending -= as->standbys_pending;
1590                if (standbys_pending <= 0)
1591                        standby();
1592        }
1593        if (as->suspends_pending > 0) {
1594                suspends_pending -= as->suspends_pending;
1595                if (suspends_pending <= 0)
1596                        (void) suspend(1);
1597        }
1598        spin_lock(&user_list_lock);
1599        if (user_list == as)
1600                user_list = as->next;
1601        else {
1602                struct apm_user *as1;
1603
1604                for (as1 = user_list;
1605                     (as1 != NULL) && (as1->next != as);
1606                     as1 = as1->next)
1607                        ;
1608                if (as1 == NULL)
1609                        pr_err("filp not in user list\n");
1610                else
1611                        as1->next = as->next;
1612        }
1613        spin_unlock(&user_list_lock);
1614        kfree(as);
1615        return 0;
1616}
1617
1618static int do_open(struct inode *inode, struct file *filp)
1619{
1620        struct apm_user *as;
1621
1622        as = kmalloc(sizeof(*as), GFP_KERNEL);
1623        if (as == NULL)
1624                return -ENOMEM;
1625
1626        as->magic = APM_BIOS_MAGIC;
1627        as->event_tail = as->event_head = 0;
1628        as->suspends_pending = as->standbys_pending = 0;
1629        as->suspends_read = as->standbys_read = 0;
1630        /*
1631         * XXX - this is a tiny bit broken, when we consider BSD
1632         * process accounting. If the device is opened by root, we
1633         * instantly flag that we used superuser privs. Who knows,
1634         * we might close the device immediately without doing a
1635         * privileged operation -- cevans
1636         */
1637        as->suser = capable(CAP_SYS_ADMIN);
1638        as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
1639        as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
1640        spin_lock(&user_list_lock);
1641        as->next = user_list;
1642        user_list = as;
1643        spin_unlock(&user_list_lock);
1644        filp->private_data = as;
1645        return 0;
1646}
1647
1648static int proc_apm_show(struct seq_file *m, void *v)
1649{
1650        unsigned short  bx;
1651        unsigned short  cx;
1652        unsigned short  dx;
1653        int             error;
1654        unsigned short  ac_line_status = 0xff;
1655        unsigned short  battery_status = 0xff;
1656        unsigned short  battery_flag   = 0xff;
1657        int             percentage     = -1;
1658        int             time_units     = -1;
1659        char            *units         = "?";
1660
1661        if ((num_online_cpus() == 1) &&
1662            !(error = apm_get_power_status(&bx, &cx, &dx))) {
1663                ac_line_status = (bx >> 8) & 0xff;
1664                battery_status = bx & 0xff;
1665                if ((cx & 0xff) != 0xff)
1666                        percentage = cx & 0xff;
1667
1668                if (apm_info.connection_version > 0x100) {
1669                        battery_flag = (cx >> 8) & 0xff;
1670                        if (dx != 0xffff) {
1671                                units = (dx & 0x8000) ? "min" : "sec";
1672                                time_units = dx & 0x7fff;
1673                        }
1674                }
1675        }
1676        /* Arguments, with symbols from linux/apm_bios.h.  Information is
1677           from the Get Power Status (0x0a) call unless otherwise noted.
1678
1679           0) Linux driver version (this will change if format changes)
1680           1) APM BIOS Version.  Usually 1.0, 1.1 or 1.2.
1681           2) APM flags from APM Installation Check (0x00):
1682              bit 0: APM_16_BIT_SUPPORT
1683              bit 1: APM_32_BIT_SUPPORT
1684              bit 2: APM_IDLE_SLOWS_CLOCK
1685              bit 3: APM_BIOS_DISABLED
1686              bit 4: APM_BIOS_DISENGAGED
1687           3) AC line status
1688              0x00: Off-line
1689              0x01: On-line
1690              0x02: On backup power (BIOS >= 1.1 only)
1691              0xff: Unknown
1692           4) Battery status
1693              0x00: High
1694              0x01: Low
1695              0x02: Critical
1696              0x03: Charging
1697              0x04: Selected battery not present (BIOS >= 1.2 only)
1698              0xff: Unknown
1699           5) Battery flag
1700              bit 0: High
1701              bit 1: Low
1702              bit 2: Critical
1703              bit 3: Charging
1704              bit 7: No system battery
1705              0xff: Unknown
1706           6) Remaining battery life (percentage of charge):
1707              0-100: valid
1708              -1: Unknown
1709           7) Remaining battery life (time units):
1710              Number of remaining minutes or seconds
1711              -1: Unknown
1712           8) min = minutes; sec = seconds */
1713
1714        seq_printf(m, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
1715                   driver_version,
1716                   (apm_info.bios.version >> 8) & 0xff,
1717                   apm_info.bios.version & 0xff,
1718                   apm_info.bios.flags,
1719                   ac_line_status,
1720                   battery_status,
1721                   battery_flag,
1722                   percentage,
1723                   time_units,
1724                   units);
1725        return 0;
1726}
1727
1728static int proc_apm_open(struct inode *inode, struct file *file)
1729{
1730        return single_open(file, proc_apm_show, NULL);
1731}
1732
1733static const struct file_operations apm_file_ops = {
1734        .owner          = THIS_MODULE,
1735        .open           = proc_apm_open,
1736        .read           = seq_read,
1737        .llseek         = seq_lseek,
1738        .release        = single_release,
1739};
1740
1741static int apm(void *unused)
1742{
1743        unsigned short  bx;
1744        unsigned short  cx;
1745        unsigned short  dx;
1746        int             error;
1747        char            *power_stat;
1748        char            *bat_stat;
1749
1750        /* 2002/08/01 - WT
1751         * This is to avoid random crashes at boot time during initialization
1752         * on SMP systems in case of "apm=power-off" mode. Seen on ASUS A7M266D.
1753         * Some bioses don't like being called from CPU != 0.
1754         * Method suggested by Ingo Molnar.
1755         */
1756        set_cpus_allowed_ptr(current, cpumask_of(0));
1757        BUG_ON(smp_processor_id() != 0);
1758
1759        if (apm_info.connection_version == 0) {
1760                apm_info.connection_version = apm_info.bios.version;
1761                if (apm_info.connection_version > 0x100) {
1762                        /*
1763                         * We only support BIOSs up to version 1.2
1764                         */
1765                        if (apm_info.connection_version > 0x0102)
1766                                apm_info.connection_version = 0x0102;
1767                        error = apm_driver_version(&apm_info.connection_version);
1768                        if (error != APM_SUCCESS) {
1769                                apm_error("driver version", error);
1770                                /* Fall back to an APM 1.0 connection. */
1771                                apm_info.connection_version = 0x100;
1772                        }
1773                }
1774        }
1775
1776        if (debug)
1777                printk(KERN_INFO "apm: Connection version %d.%d\n",
1778                        (apm_info.connection_version >> 8) & 0xff,
1779                        apm_info.connection_version & 0xff);
1780
1781#ifdef CONFIG_APM_DO_ENABLE
1782        if (apm_info.bios.flags & APM_BIOS_DISABLED) {
1783                /*
1784                 * This call causes my NEC UltraLite Versa 33/C to hang if it
1785                 * is booted with PM disabled but not in the docking station.
1786                 * Unfortunate ...
1787                 */
1788                error = apm_enable_power_management(1);
1789                if (error) {
1790                        apm_error("enable power management", error);
1791                        return -1;
1792                }
1793        }
1794#endif
1795
1796        if ((apm_info.bios.flags & APM_BIOS_DISENGAGED)
1797            && (apm_info.connection_version > 0x0100)) {
1798                error = apm_engage_power_management(APM_DEVICE_ALL, 1);
1799                if (error) {
1800                        apm_error("engage power management", error);
1801                        return -1;
1802                }
1803        }
1804
1805        if (debug && (num_online_cpus() == 1 || smp)) {
1806                error = apm_get_power_status(&bx, &cx, &dx);
1807                if (error)
1808                        printk(KERN_INFO "apm: power status not available\n");
1809                else {
1810                        switch ((bx >> 8) & 0xff) {
1811                        case 0:
1812                                power_stat = "off line";
1813                                break;
1814                        case 1:
1815                                power_stat = "on line";
1816                                break;
1817                        case 2:
1818                                power_stat = "on backup power";
1819                                break;
1820                        default:
1821                                power_stat = "unknown";
1822                                break;
1823                        }
1824                        switch (bx & 0xff) {
1825                        case 0:
1826                                bat_stat = "high";
1827                                break;
1828                        case 1:
1829                                bat_stat = "low";
1830                                break;
1831                        case 2:
1832                                bat_stat = "critical";
1833                                break;
1834                        case 3:
1835                                bat_stat = "charging";
1836                                break;
1837                        default:
1838                                bat_stat = "unknown";
1839                                break;
1840                        }
1841                        printk(KERN_INFO
1842                               "apm: AC %s, battery status %s, battery life ",
1843                               power_stat, bat_stat);
1844                        if ((cx & 0xff) == 0xff)
1845                                printk("unknown\n");
1846                        else
1847                                printk("%d%%\n", cx & 0xff);
1848                        if (apm_info.connection_version > 0x100) {
1849                                printk(KERN_INFO
1850                                       "apm: battery flag 0x%02x, battery life ",
1851                                       (cx >> 8) & 0xff);
1852                                if (dx == 0xffff)
1853                                        printk("unknown\n");
1854                                else
1855                                        printk("%d %s\n", dx & 0x7fff,
1856                                               (dx & 0x8000) ?
1857                                               "minutes" : "seconds");
1858                        }
1859                }
1860        }
1861
1862        /* Install our power off handler.. */
1863        if (power_off)
1864                pm_power_off = apm_power_off;
1865
1866        if (num_online_cpus() == 1 || smp) {
1867#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
1868                console_blank_hook = apm_console_blank;
1869#endif
1870                apm_mainloop();
1871#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
1872                console_blank_hook = NULL;
1873#endif
1874        }
1875
1876        return 0;
1877}
1878
1879#ifndef MODULE
1880static int __init apm_setup(char *str)
1881{
1882        int invert;
1883
1884        while ((str != NULL) && (*str != '\0')) {
1885                if (strncmp(str, "off", 3) == 0)
1886                        apm_disabled = 1;
1887                if (strncmp(str, "on", 2) == 0)
1888                        apm_disabled = 0;
1889                if ((strncmp(str, "bounce-interval=", 16) == 0) ||
1890                    (strncmp(str, "bounce_interval=", 16) == 0))
1891                        bounce_interval = simple_strtol(str + 16, NULL, 0);
1892                if ((strncmp(str, "idle-threshold=", 15) == 0) ||
1893                    (strncmp(str, "idle_threshold=", 15) == 0))
1894                        idle_threshold = simple_strtol(str + 15, NULL, 0);
1895                if ((strncmp(str, "idle-period=", 12) == 0) ||
1896                    (strncmp(str, "idle_period=", 12) == 0))
1897                        idle_period = simple_strtol(str + 12, NULL, 0);
1898                invert = (strncmp(str, "no-", 3) == 0) ||
1899                        (strncmp(str, "no_", 3) == 0);
1900                if (invert)
1901                        str += 3;
1902                if (strncmp(str, "debug", 5) == 0)
1903                        debug = !invert;
1904                if ((strncmp(str, "power-off", 9) == 0) ||
1905                    (strncmp(str, "power_off", 9) == 0))
1906                        power_off = !invert;
1907                if (strncmp(str, "smp", 3) == 0) {
1908                        smp = !invert;
1909                        idle_threshold = 100;
1910                }
1911                if ((strncmp(str, "allow-ints", 10) == 0) ||
1912                    (strncmp(str, "allow_ints", 10) == 0))
1913                        apm_info.allow_ints = !invert;
1914                if ((strncmp(str, "broken-psr", 10) == 0) ||
1915                    (strncmp(str, "broken_psr", 10) == 0))
1916                        apm_info.get_power_status_broken = !invert;
1917                if ((strncmp(str, "realmode-power-off", 18) == 0) ||
1918                    (strncmp(str, "realmode_power_off", 18) == 0))
1919                        apm_info.realmode_power_off = !invert;
1920                str = strchr(str, ',');
1921                if (str != NULL)
1922                        str += strspn(str, ", \t");
1923        }
1924        return 1;
1925}
1926
1927__setup("apm=", apm_setup);
1928#endif
1929
1930static const struct file_operations apm_bios_fops = {
1931        .owner          = THIS_MODULE,
1932        .read           = do_read,
1933        .poll           = do_poll,
1934        .unlocked_ioctl = do_ioctl,
1935        .open           = do_open,
1936        .release        = do_release,
1937        .llseek         = noop_llseek,
1938};
1939
1940static struct miscdevice apm_device = {
1941        APM_MINOR_DEV,
1942        "apm_bios",
1943        &apm_bios_fops
1944};
1945
1946
1947/* Simple "print if true" callback */
1948static int __init print_if_true(const struct dmi_system_id *d)
1949{
1950        printk("%s\n", d->ident);
1951        return 0;
1952}
1953
1954/*
1955 * Some Bioses enable the PS/2 mouse (touchpad) at resume, even if it was
1956 * disabled before the suspend. Linux used to get terribly confused by that.
1957 */
1958static int __init broken_ps2_resume(const struct dmi_system_id *d)
1959{
1960        printk(KERN_INFO "%s machine detected. Mousepad Resume Bug "
1961               "workaround hopefully not needed.\n", d->ident);
1962        return 0;
1963}
1964
1965/* Some bioses have a broken protected mode poweroff and need to use realmode */
1966static int __init set_realmode_power_off(const struct dmi_system_id *d)
1967{
1968        if (apm_info.realmode_power_off == 0) {
1969                apm_info.realmode_power_off = 1;
1970                printk(KERN_INFO "%s bios detected. "
1971                       "Using realmode poweroff only.\n", d->ident);
1972        }
1973        return 0;
1974}
1975
1976/* Some laptops require interrupts to be enabled during APM calls */
1977static int __init set_apm_ints(const struct dmi_system_id *d)
1978{
1979        if (apm_info.allow_ints == 0) {
1980                apm_info.allow_ints = 1;
1981                printk(KERN_INFO "%s machine detected. "
1982                       "Enabling interrupts during APM calls.\n", d->ident);
1983        }
1984        return 0;
1985}
1986
1987/* Some APM bioses corrupt memory or just plain do not work */
1988static int __init apm_is_horked(const struct dmi_system_id *d)
1989{
1990        if (apm_info.disabled == 0) {
1991                apm_info.disabled = 1;
1992                printk(KERN_INFO "%s machine detected. "
1993                       "Disabling APM.\n", d->ident);
1994        }
1995        return 0;
1996}
1997
1998static int __init apm_is_horked_d850md(const struct dmi_system_id *d)
1999{
2000        if (apm_info.disabled == 0) {
2001                apm_info.disabled = 1;
2002                printk(KERN_INFO "%s machine detected. "
2003                       "Disabling APM.\n", d->ident);
2004                printk(KERN_INFO "This bug is fixed in bios P15 which is available for\n");
2005                printk(KERN_INFO "download from support.intel.com\n");
2006        }
2007        return 0;
2008}
2009
2010/* Some APM bioses hang on APM idle calls */
2011static int __init apm_likes_to_melt(const struct dmi_system_id *d)
2012{
2013        if (apm_info.forbid_idle == 0) {
2014                apm_info.forbid_idle = 1;
2015                printk(KERN_INFO "%s machine detected. "
2016                       "Disabling APM idle calls.\n", d->ident);
2017        }
2018        return 0;
2019}
2020
2021/*
2022 *  Check for clue free BIOS implementations who use
2023 *  the following QA technique
2024 *
2025 *      [ Write BIOS Code ]<------
2026 *               |                ^
2027 *      < Does it Compile >----N--
2028 *               |Y               ^
2029 *      < Does it Boot Win98 >-N--
2030 *               |Y
2031 *           [Ship It]
2032 *
2033 *      Phoenix A04  08/24/2000 is known bad (Dell Inspiron 5000e)
2034 *      Phoenix A07  09/29/2000 is known good (Dell Inspiron 5000)
2035 */
2036static int __init broken_apm_power(const struct dmi_system_id *d)
2037{
2038        apm_info.get_power_status_broken = 1;
2039        printk(KERN_WARNING "BIOS strings suggest APM bugs, "
2040               "disabling power status reporting.\n");
2041        return 0;
2042}
2043
2044/*
2045 * This bios swaps the APM minute reporting bytes over (Many sony laptops
2046 * have this problem).
2047 */
2048static int __init swab_apm_power_in_minutes(const struct dmi_system_id *d)
2049{
2050        apm_info.get_power_status_swabinminutes = 1;
2051        printk(KERN_WARNING "BIOS strings suggest APM reports battery life "
2052               "in minutes and wrong byte order.\n");
2053        return 0;
2054}
2055
2056static struct dmi_system_id __initdata apm_dmi_table[] = {
2057        {
2058                print_if_true,
2059                KERN_WARNING "IBM T23 - BIOS 1.03b+ and controller firmware 1.02+ may be needed for Linux APM.",
2060                {       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
2061                        DMI_MATCH(DMI_BIOS_VERSION, "1AET38WW (1.01b)"), },
2062        },
2063        {       /* Handle problems with APM on the C600 */
2064                broken_ps2_resume, "Dell Latitude C600",
2065                {       DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
2066                        DMI_MATCH(DMI_PRODUCT_NAME, "Latitude C600"), },
2067        },
2068        {       /* Allow interrupts during suspend on Dell Latitude laptops*/
2069                set_apm_ints, "Dell Latitude",
2070                {       DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2071                        DMI_MATCH(DMI_PRODUCT_NAME, "Latitude C510"), }
2072        },
2073        {       /* APM crashes */
2074                apm_is_horked, "Dell Inspiron 2500",
2075                {       DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2076                        DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
2077                        DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2078                        DMI_MATCH(DMI_BIOS_VERSION, "A11"), },
2079        },
2080        {       /* Allow interrupts during suspend on Dell Inspiron laptops*/
2081                set_apm_ints, "Dell Inspiron", {
2082                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2083                        DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"), },
2084        },
2085        {       /* Handle problems with APM on Inspiron 5000e */
2086                broken_apm_power, "Dell Inspiron 5000e",
2087                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2088                        DMI_MATCH(DMI_BIOS_VERSION, "A04"),
2089                        DMI_MATCH(DMI_BIOS_DATE, "08/24/2000"), },
2090        },
2091        {       /* Handle problems with APM on Inspiron 2500 */
2092                broken_apm_power, "Dell Inspiron 2500",
2093                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2094                        DMI_MATCH(DMI_BIOS_VERSION, "A12"),
2095                        DMI_MATCH(DMI_BIOS_DATE, "02/04/2002"), },
2096        },
2097        {       /* APM crashes */
2098                apm_is_horked, "Dell Dimension 4100",
2099                {       DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2100                        DMI_MATCH(DMI_PRODUCT_NAME, "XPS-Z"),
2101                        DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
2102                        DMI_MATCH(DMI_BIOS_VERSION, "A11"), },
2103        },
2104        {       /* Allow interrupts during suspend on Compaq Laptops*/
2105                set_apm_ints, "Compaq 12XL125",
2106                {       DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
2107                        DMI_MATCH(DMI_PRODUCT_NAME, "Compaq PC"),
2108                        DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2109                        DMI_MATCH(DMI_BIOS_VERSION, "4.06"), },
2110        },
2111        {       /* Allow interrupts during APM or the clock goes slow */
2112                set_apm_ints, "ASUSTeK",
2113                {       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
2114                        DMI_MATCH(DMI_PRODUCT_NAME, "L8400K series Notebook PC"), },
2115        },
2116        {       /* APM blows on shutdown */
2117                apm_is_horked, "ABIT KX7-333[R]",
2118                {       DMI_MATCH(DMI_BOARD_VENDOR, "ABIT"),
2119                        DMI_MATCH(DMI_BOARD_NAME, "VT8367-8233A (KX7-333[R])"), },
2120        },
2121        {       /* APM crashes */
2122                apm_is_horked, "Trigem Delhi3",
2123                {       DMI_MATCH(DMI_SYS_VENDOR, "TriGem Computer, Inc"),
2124                        DMI_MATCH(DMI_PRODUCT_NAME, "Delhi3"), },
2125        },
2126        {       /* APM crashes */
2127                apm_is_horked, "Fujitsu-Siemens",
2128                {       DMI_MATCH(DMI_BIOS_VENDOR, "hoenix/FUJITSU SIEMENS"),
2129                        DMI_MATCH(DMI_BIOS_VERSION, "Version1.01"), },
2130        },
2131        {       /* APM crashes */
2132                apm_is_horked_d850md, "Intel D850MD",
2133                {       DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
2134                        DMI_MATCH(DMI_BIOS_VERSION, "MV85010A.86A.0016.P07.0201251536"), },
2135        },
2136        {       /* APM crashes */
2137                apm_is_horked, "Intel D810EMO",
2138                {       DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
2139                        DMI_MATCH(DMI_BIOS_VERSION, "MO81010A.86A.0008.P04.0004170800"), },
2140        },
2141        {       /* APM crashes */
2142                apm_is_horked, "Dell XPS-Z",
2143                {       DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
2144                        DMI_MATCH(DMI_BIOS_VERSION, "A11"),
2145                        DMI_MATCH(DMI_PRODUCT_NAME, "XPS-Z"), },
2146        },
2147        {       /* APM crashes */
2148                apm_is_horked, "Sharp PC-PJ/AX",
2149                {       DMI_MATCH(DMI_SYS_VENDOR, "SHARP"),
2150                        DMI_MATCH(DMI_PRODUCT_NAME, "PC-PJ/AX"),
2151                        DMI_MATCH(DMI_BIOS_VENDOR, "SystemSoft"),
2152                        DMI_MATCH(DMI_BIOS_VERSION, "Version R2.08"), },
2153        },
2154        {       /* APM crashes */
2155                apm_is_horked, "Dell Inspiron 2500",
2156                {       DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2157                        DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
2158                        DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2159                        DMI_MATCH(DMI_BIOS_VERSION, "A11"), },
2160        },
2161        {       /* APM idle hangs */
2162                apm_likes_to_melt, "Jabil AMD",
2163                {       DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
2164                        DMI_MATCH(DMI_BIOS_VERSION, "0AASNP06"), },
2165        },
2166        {       /* APM idle hangs */
2167                apm_likes_to_melt, "AMI Bios",
2168                {       DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
2169                        DMI_MATCH(DMI_BIOS_VERSION, "0AASNP05"), },
2170        },
2171        {       /* Handle problems with APM on Sony Vaio PCG-N505X(DE) */
2172                swab_apm_power_in_minutes, "Sony VAIO",
2173                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2174                        DMI_MATCH(DMI_BIOS_VERSION, "R0206H"),
2175                        DMI_MATCH(DMI_BIOS_DATE, "08/23/99"), },
2176        },
2177        {       /* Handle problems with APM on Sony Vaio PCG-N505VX */
2178                swab_apm_power_in_minutes, "Sony VAIO",
2179                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2180                        DMI_MATCH(DMI_BIOS_VERSION, "W2K06H0"),
2181                        DMI_MATCH(DMI_BIOS_DATE, "02/03/00"), },
2182        },
2183        {       /* Handle problems with APM on Sony Vaio PCG-XG29 */
2184                swab_apm_power_in_minutes, "Sony VAIO",
2185                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2186                        DMI_MATCH(DMI_BIOS_VERSION, "R0117A0"),
2187                        DMI_MATCH(DMI_BIOS_DATE, "04/25/00"), },
2188        },
2189        {       /* Handle problems with APM on Sony Vaio PCG-Z600NE */
2190                swab_apm_power_in_minutes, "Sony VAIO",
2191                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2192                        DMI_MATCH(DMI_BIOS_VERSION, "R0121Z1"),
2193                        DMI_MATCH(DMI_BIOS_DATE, "05/11/00"), },
2194        },
2195        {       /* Handle problems with APM on Sony Vaio PCG-Z600NE */
2196                swab_apm_power_in_minutes, "Sony VAIO",
2197                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2198                        DMI_MATCH(DMI_BIOS_VERSION, "WME01Z1"),
2199                        DMI_MATCH(DMI_BIOS_DATE, "08/11/00"), },
2200        },
2201        {       /* Handle problems with APM on Sony Vaio PCG-Z600LEK(DE) */
2202                swab_apm_power_in_minutes, "Sony VAIO",
2203                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2204                        DMI_MATCH(DMI_BIOS_VERSION, "R0206Z3"),
2205                        DMI_MATCH(DMI_BIOS_DATE, "12/25/00"), },
2206        },
2207        {       /* Handle problems with APM on Sony Vaio PCG-Z505LS */
2208                swab_apm_power_in_minutes, "Sony VAIO",
2209                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2210                        DMI_MATCH(DMI_BIOS_VERSION, "R0203D0"),
2211                        DMI_MATCH(DMI_BIOS_DATE, "05/12/00"), },
2212        },
2213        {       /* Handle problems with APM on Sony Vaio PCG-Z505LS */
2214                swab_apm_power_in_minutes, "Sony VAIO",
2215                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2216                        DMI_MATCH(DMI_BIOS_VERSION, "R0203Z3"),
2217                        DMI_MATCH(DMI_BIOS_DATE, "08/25/00"), },
2218        },
2219        {       /* Handle problems with APM on Sony Vaio PCG-Z505LS (with updated BIOS) */
2220                swab_apm_power_in_minutes, "Sony VAIO",
2221                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2222                        DMI_MATCH(DMI_BIOS_VERSION, "R0209Z3"),
2223                        DMI_MATCH(DMI_BIOS_DATE, "05/12/01"), },
2224        },
2225        {       /* Handle problems with APM on Sony Vaio PCG-F104K */
2226                swab_apm_power_in_minutes, "Sony VAIO",
2227                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2228                        DMI_MATCH(DMI_BIOS_VERSION, "R0204K2"),
2229                        DMI_MATCH(DMI_BIOS_DATE, "08/28/00"), },
2230        },
2231
2232        {       /* Handle problems with APM on Sony Vaio PCG-C1VN/C1VE */
2233                swab_apm_power_in_minutes, "Sony VAIO",
2234                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2235                        DMI_MATCH(DMI_BIOS_VERSION, "R0208P1"),
2236                        DMI_MATCH(DMI_BIOS_DATE, "11/09/00"), },
2237        },
2238        {       /* Handle problems with APM on Sony Vaio PCG-C1VE */
2239                swab_apm_power_in_minutes, "Sony VAIO",
2240                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2241                        DMI_MATCH(DMI_BIOS_VERSION, "R0204P1"),
2242                        DMI_MATCH(DMI_BIOS_DATE, "09/12/00"), },
2243        },
2244        {       /* Handle problems with APM on Sony Vaio PCG-C1VE */
2245                swab_apm_power_in_minutes, "Sony VAIO",
2246                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2247                        DMI_MATCH(DMI_BIOS_VERSION, "WXPO1Z3"),
2248                        DMI_MATCH(DMI_BIOS_DATE, "10/26/01"), },
2249        },
2250        {       /* broken PM poweroff bios */
2251                set_realmode_power_off, "Award Software v4.60 PGMA",
2252                {       DMI_MATCH(DMI_BIOS_VENDOR, "Award Software International, Inc."),
2253                        DMI_MATCH(DMI_BIOS_VERSION, "4.60 PGMA"),
2254                        DMI_MATCH(DMI_BIOS_DATE, "134526184"), },
2255        },
2256
2257        /* Generic per vendor APM settings  */
2258
2259        {       /* Allow interrupts during suspend on IBM laptops */
2260                set_apm_ints, "IBM",
2261                {       DMI_MATCH(DMI_SYS_VENDOR, "IBM"), },
2262        },
2263
2264        { }
2265};
2266
2267/*
2268 * Just start the APM thread. We do NOT want to do APM BIOS
2269 * calls from anything but the APM thread, if for no other reason
2270 * than the fact that we don't trust the APM BIOS. This way,
2271 * most common APM BIOS problems that lead to protection errors
2272 * etc will have at least some level of being contained...
2273 *
2274 * In short, if something bad happens, at least we have a choice
2275 * of just killing the apm thread..
2276 */
2277static int __init apm_init(void)
2278{
2279        struct desc_struct *gdt;
2280        int err;
2281
2282        dmi_check_system(apm_dmi_table);
2283
2284        if (apm_info.bios.version == 0 || paravirt_enabled() || machine_is_olpc()) {
2285                printk(KERN_INFO "apm: BIOS not found.\n");
2286                return -ENODEV;
2287        }
2288        printk(KERN_INFO
2289               "apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n",
2290               ((apm_info.bios.version >> 8) & 0xff),
2291               (apm_info.bios.version & 0xff),
2292               apm_info.bios.flags,
2293               driver_version);
2294        if ((apm_info.bios.flags & APM_32_BIT_SUPPORT) == 0) {
2295                printk(KERN_INFO "apm: no 32 bit BIOS support\n");
2296                return -ENODEV;
2297        }
2298
2299        if (allow_ints)
2300                apm_info.allow_ints = 1;
2301        if (broken_psr)
2302                apm_info.get_power_status_broken = 1;
2303        if (realmode_power_off)
2304                apm_info.realmode_power_off = 1;
2305        /* User can override, but default is to trust DMI */
2306        if (apm_disabled != -1)
2307                apm_info.disabled = apm_disabled;
2308
2309        /*
2310         * Fix for the Compaq Contura 3/25c which reports BIOS version 0.1
2311         * but is reportedly a 1.0 BIOS.
2312         */
2313        if (apm_info.bios.version == 0x001)
2314                apm_info.bios.version = 0x100;
2315
2316        /* BIOS < 1.2 doesn't set cseg_16_len */
2317        if (apm_info.bios.version < 0x102)
2318                apm_info.bios.cseg_16_len = 0; /* 64k */
2319
2320        if (debug) {
2321                printk(KERN_INFO "apm: entry %x:%x cseg16 %x dseg %x",
2322                        apm_info.bios.cseg, apm_info.bios.offset,
2323                        apm_info.bios.cseg_16, apm_info.bios.dseg);
2324                if (apm_info.bios.version > 0x100)
2325                        printk(" cseg len %x, dseg len %x",
2326                                apm_info.bios.cseg_len,
2327                                apm_info.bios.dseg_len);
2328                if (apm_info.bios.version > 0x101)
2329                        printk(" cseg16 len %x", apm_info.bios.cseg_16_len);
2330                printk("\n");
2331        }
2332
2333        if (apm_info.disabled) {
2334                pr_notice("disabled on user request.\n");
2335                return -ENODEV;
2336        }
2337        if ((num_online_cpus() > 1) && !power_off && !smp) {
2338                pr_notice("disabled - APM is not SMP safe.\n");
2339                apm_info.disabled = 1;
2340                return -ENODEV;
2341        }
2342        if (!acpi_disabled) {
2343                pr_notice("overridden by ACPI.\n");
2344                apm_info.disabled = 1;
2345                return -ENODEV;
2346        }
2347
2348        /*
2349         * Set up the long jump entry point to the APM BIOS, which is called
2350         * from inline assembly.
2351         */
2352        apm_bios_entry.offset = apm_info.bios.offset;
2353        apm_bios_entry.segment = APM_CS;
2354
2355        /*
2356         * The APM 1.1 BIOS is supposed to provide limit information that it
2357         * recognizes.  Many machines do this correctly, but many others do
2358         * not restrict themselves to their claimed limit.  When this happens,
2359         * they will cause a segmentation violation in the kernel at boot time.
2360         * Most BIOS's, however, will respect a 64k limit, so we use that.
2361         *
2362         * Note we only set APM segments on CPU zero, since we pin the APM
2363         * code to that CPU.
2364         */
2365        gdt = get_cpu_gdt_table(0);
2366        set_desc_base(&gdt[APM_CS >> 3],
2367                 (unsigned long)__va((unsigned long)apm_info.bios.cseg << 4));
2368        set_desc_base(&gdt[APM_CS_16 >> 3],
2369                 (unsigned long)__va((unsigned long)apm_info.bios.cseg_16 << 4));
2370        set_desc_base(&gdt[APM_DS >> 3],
2371                 (unsigned long)__va((unsigned long)apm_info.bios.dseg << 4));
2372
2373        proc_create("apm", 0, NULL, &apm_file_ops);
2374
2375        kapmd_task = kthread_create(apm, NULL, "kapmd");
2376        if (IS_ERR(kapmd_task)) {
2377                pr_err("disabled - Unable to start kernel thread\n");
2378                err = PTR_ERR(kapmd_task);
2379                kapmd_task = NULL;
2380                remove_proc_entry("apm", NULL);
2381                return err;
2382        }
2383        wake_up_process(kapmd_task);
2384
2385        if (num_online_cpus() > 1 && !smp) {
2386                printk(KERN_NOTICE
2387                       "apm: disabled - APM is not SMP safe (power off active).\n");
2388                return 0;
2389        }
2390
2391        /*
2392         * Note we don't actually care if the misc_device cannot be registered.
2393         * this driver can do its job without it, even if userspace can't
2394         * control it.  just log the error
2395         */
2396        if (misc_register(&apm_device))
2397                printk(KERN_WARNING "apm: Could not register misc device.\n");
2398
2399        if (HZ != 100)
2400                idle_period = (idle_period * HZ) / 100;
2401        if (idle_threshold < 100) {
2402                if (!cpuidle_register_driver(&apm_idle_driver))
2403                        if (cpuidle_register_device(&apm_cpuidle_device))
2404                                cpuidle_unregister_driver(&apm_idle_driver);
2405        }
2406
2407        return 0;
2408}
2409
2410static void __exit apm_exit(void)
2411{
2412        int error;
2413
2414        cpuidle_unregister_device(&apm_cpuidle_device);
2415        cpuidle_unregister_driver(&apm_idle_driver);
2416
2417        if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0)
2418            && (apm_info.connection_version > 0x0100)) {
2419                error = apm_engage_power_management(APM_DEVICE_ALL, 0);
2420                if (error)
2421                        apm_error("disengage power management", error);
2422        }
2423        misc_deregister(&apm_device);
2424        remove_proc_entry("apm", NULL);
2425        if (power_off)
2426                pm_power_off = NULL;
2427        if (kapmd_task) {
2428                kthread_stop(kapmd_task);
2429                kapmd_task = NULL;
2430        }
2431}
2432
2433module_init(apm_init);
2434module_exit(apm_exit);
2435
2436MODULE_AUTHOR("Stephen Rothwell");
2437MODULE_DESCRIPTION("Advanced Power Management");
2438MODULE_LICENSE("GPL");
2439module_param(debug, bool, 0644);
2440MODULE_PARM_DESC(debug, "Enable debug mode");
2441module_param(power_off, bool, 0444);
2442MODULE_PARM_DESC(power_off, "Enable power off");
2443module_param(bounce_interval, int, 0444);
2444MODULE_PARM_DESC(bounce_interval,
2445                "Set the number of ticks to ignore suspend bounces");
2446module_param(allow_ints, bool, 0444);
2447MODULE_PARM_DESC(allow_ints, "Allow interrupts during BIOS calls");
2448module_param(broken_psr, bool, 0444);
2449MODULE_PARM_DESC(broken_psr, "BIOS has a broken GetPowerStatus call");
2450module_param(realmode_power_off, bool, 0444);
2451MODULE_PARM_DESC(realmode_power_off,
2452                "Switch to real mode before powering off");
2453module_param(idle_threshold, int, 0444);
2454MODULE_PARM_DESC(idle_threshold,
2455        "System idle percentage above which to make APM BIOS idle calls");
2456module_param(idle_period, int, 0444);
2457MODULE_PARM_DESC(idle_period,
2458        "Period (in sec/100) over which to caculate the idle percentage");
2459module_param(smp, bool, 0444);
2460MODULE_PARM_DESC(smp,
2461        "Set this to enable APM use on an SMP platform. Use with caution on older systems");
2462MODULE_ALIAS_MISCDEV(APM_MINOR_DEV);
2463