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/signal.h>
 222#include <linux/sched/cputime.h>
 223#include <linux/pm.h>
 224#include <linux/capability.h>
 225#include <linux/device.h>
 226#include <linux/kernel.h>
 227#include <linux/freezer.h>
 228#include <linux/smp.h>
 229#include <linux/dmi.h>
 230#include <linux/suspend.h>
 231#include <linux/kthread.h>
 232#include <linux/jiffies.h>
 233#include <linux/acpi.h>
 234#include <linux/syscore_ops.h>
 235#include <linux/i8253.h>
 236#include <linux/cpuidle.h>
 237
 238#include <linux/uaccess.h>
 239#include <asm/desc.h>
 240#include <asm/olpc.h>
 241#include <asm/paravirt.h>
 242#include <asm/reboot.h>
 243#include <asm/nospec-branch.h>
 244
 245#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
 246extern int (*console_blank_hook)(int);
 247#endif
 248
 249/*
 250 * The apm_bios device is one of the misc char devices.
 251 * This is its minor number.
 252 */
 253#define APM_MINOR_DEV   134
 254
 255/*
 256 * Various options can be changed at boot time as follows:
 257 * (We allow underscores for compatibility with the modules code)
 258 *      apm=on/off                      enable/disable APM
 259 *          [no-]allow[-_]ints          allow interrupts during BIOS calls
 260 *          [no-]broken[-_]psr          BIOS has a broken GetPowerStatus call
 261 *          [no-]realmode[-_]power[-_]off       switch to real mode before
 262 *                                              powering off
 263 *          [no-]debug                  log some debugging messages
 264 *          [no-]power[-_]off           power off on shutdown
 265 *          [no-]smp                    Use apm even on an SMP box
 266 *          bounce[-_]interval=<n>      number of ticks to ignore suspend
 267 *                                      bounces
 268 *          idle[-_]threshold=<n>       System idle percentage above which to
 269 *                                      make APM BIOS idle calls. Set it to
 270 *                                      100 to disable.
 271 *          idle[-_]period=<n>          Period (in 1/100s of a second) over
 272 *                                      which the idle percentage is
 273 *                                      calculated.
 274 */
 275
 276/* KNOWN PROBLEM MACHINES:
 277 *
 278 * U: TI 4000M TravelMate: BIOS is *NOT* APM compliant
 279 *                         [Confirmed by TI representative]
 280 * ?: ACER 486DX4/75: uses dseg 0040, in violation of APM specification
 281 *                    [Confirmed by BIOS disassembly]
 282 *                    [This may work now ...]
 283 * P: Toshiba 1950S: battery life information only gets updated after resume
 284 * P: Midwest Micro Soundbook Elite DX2/66 monochrome: screen blanking
 285 *      broken in BIOS [Reported by Garst R. Reese <reese@isn.net>]
 286 * ?: AcerNote-950: oops on reading /proc/apm - workaround is a WIP
 287 *      Neale Banks <neale@lowendale.com.au> December 2000
 288 *
 289 * Legend: U = unusable with APM patches
 290 *         P = partially usable with APM patches
 291 */
 292
 293/*
 294 * Define as 1 to make the driver always call the APM BIOS busy
 295 * routine even if the clock was not reported as slowed by the
 296 * idle routine.  Otherwise, define as 0.
 297 */
 298#define ALWAYS_CALL_BUSY   1
 299
 300/*
 301 * Define to make the APM BIOS calls zero all data segment registers (so
 302 * that an incorrect BIOS implementation will cause a kernel panic if it
 303 * tries to write to arbitrary memory).
 304 */
 305#define APM_ZERO_SEGS
 306
 307#include <asm/apm.h>
 308
 309/*
 310 * Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend.
 311 * This patched by Chad Miller <cmiller@surfsouth.com>, original code by
 312 * David Chen <chen@ctpa04.mit.edu>
 313 */
 314#undef INIT_TIMER_AFTER_SUSPEND
 315
 316#ifdef INIT_TIMER_AFTER_SUSPEND
 317#include <linux/timex.h>
 318#include <asm/io.h>
 319#include <linux/delay.h>
 320#endif
 321
 322/*
 323 * Need to poll the APM BIOS every second
 324 */
 325#define APM_CHECK_TIMEOUT       (HZ)
 326
 327/*
 328 * Ignore suspend events for this amount of time after a resume
 329 */
 330#define DEFAULT_BOUNCE_INTERVAL (3 * HZ)
 331
 332/*
 333 * Maximum number of events stored
 334 */
 335#define APM_MAX_EVENTS          20
 336
 337/*
 338 * The per-file APM data
 339 */
 340struct apm_user {
 341        int             magic;
 342        struct apm_user *next;
 343        unsigned int    suser: 1;
 344        unsigned int    writer: 1;
 345        unsigned int    reader: 1;
 346        unsigned int    suspend_wait: 1;
 347        int             suspend_result;
 348        int             suspends_pending;
 349        int             standbys_pending;
 350        int             suspends_read;
 351        int             standbys_read;
 352        int             event_head;
 353        int             event_tail;
 354        apm_event_t     events[APM_MAX_EVENTS];
 355};
 356
 357/*
 358 * The magic number in apm_user
 359 */
 360#define APM_BIOS_MAGIC          0x4101
 361
 362/*
 363 * idle percentage above which bios idle calls are done
 364 */
 365#ifdef CONFIG_APM_CPU_IDLE
 366#define DEFAULT_IDLE_THRESHOLD  95
 367#else
 368#define DEFAULT_IDLE_THRESHOLD  100
 369#endif
 370#define DEFAULT_IDLE_PERIOD     (100 / 3)
 371
 372static int apm_cpu_idle(struct cpuidle_device *dev,
 373                        struct cpuidle_driver *drv, int index);
 374
 375static struct cpuidle_driver apm_idle_driver = {
 376        .name = "apm_idle",
 377        .owner = THIS_MODULE,
 378        .states = {
 379                { /* entry 0 is for polling */ },
 380                { /* entry 1 is for APM idle */
 381                        .name = "APM",
 382                        .desc = "APM idle",
 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 */
 396__visible 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_rw(cpu);
 614        save_desc_40 = gdt[0x40 / 8];
 615        gdt[0x40 / 8] = bad_bios_desc;
 616
 617        apm_irq_save(flags);
 618        firmware_restrict_branch_speculation_start();
 619        APM_DO_SAVE_SEGS;
 620        apm_bios_call_asm(call->func, call->ebx, call->ecx,
 621                          &call->eax, &call->ebx, &call->ecx, &call->edx,
 622                          &call->esi);
 623        APM_DO_RESTORE_SEGS;
 624        firmware_restrict_branch_speculation_end();
 625        apm_irq_restore(flags);
 626        gdt[0x40 / 8] = save_desc_40;
 627        put_cpu();
 628
 629        return call->eax & 0xff;
 630}
 631
 632/* Run __apm_bios_call or __apm_bios_call_simple on CPU 0 */
 633static int on_cpu0(long (*fn)(void *), struct apm_bios_call *call)
 634{
 635        int ret;
 636
 637        /* Don't bother with work_on_cpu in the common case, so we don't
 638         * have to worry about OOM or overhead. */
 639        if (get_cpu() == 0) {
 640                ret = fn(call);
 641                put_cpu();
 642        } else {
 643                put_cpu();
 644                ret = work_on_cpu(0, fn, call);
 645        }
 646
 647        /* work_on_cpu can fail with -ENOMEM */
 648        if (ret < 0)
 649                call->err = ret;
 650        else
 651                call->err = (call->eax >> 8) & 0xff;
 652
 653        return ret;
 654}
 655
 656/**
 657 *      apm_bios_call   -       Make an APM BIOS 32bit call (on CPU 0)
 658 *      @call: the apm_bios_call registers.
 659 *
 660 *      If there is an error, it is returned in @call.err.
 661 */
 662static int apm_bios_call(struct apm_bios_call *call)
 663{
 664        return on_cpu0(__apm_bios_call, call);
 665}
 666
 667/**
 668 *      __apm_bios_call_simple - Make an APM BIOS 32bit call (on CPU 0)
 669 *      @_call: pointer to struct apm_bios_call.
 670 *
 671 *      Make a BIOS call that returns one value only, or just status.
 672 *      If there is an error, then the error code is returned in AH
 673 *      (bits 8-15 of eax) and this function returns non-zero (it can
 674 *      also return -ENOMEM). This is used for simpler BIOS operations.
 675 *      This call may hold interrupts off for a long time on some laptops.
 676 *
 677 *      Note: this makes the call on the current CPU.
 678 */
 679static long __apm_bios_call_simple(void *_call)
 680{
 681        u8                      error;
 682        APM_DECL_SEGS
 683        unsigned long           flags;
 684        int                     cpu;
 685        struct desc_struct      save_desc_40;
 686        struct desc_struct      *gdt;
 687        struct apm_bios_call    *call = _call;
 688
 689        cpu = get_cpu();
 690        BUG_ON(cpu != 0);
 691        gdt = get_cpu_gdt_rw(cpu);
 692        save_desc_40 = gdt[0x40 / 8];
 693        gdt[0x40 / 8] = bad_bios_desc;
 694
 695        apm_irq_save(flags);
 696        firmware_restrict_branch_speculation_start();
 697        APM_DO_SAVE_SEGS;
 698        error = apm_bios_call_simple_asm(call->func, call->ebx, call->ecx,
 699                                         &call->eax);
 700        APM_DO_RESTORE_SEGS;
 701        firmware_restrict_branch_speculation_end();
 702        apm_irq_restore(flags);
 703        gdt[0x40 / 8] = save_desc_40;
 704        put_cpu();
 705        return error;
 706}
 707
 708/**
 709 *      apm_bios_call_simple    -       make a simple APM BIOS 32bit call
 710 *      @func: APM function to invoke
 711 *      @ebx_in: EBX register value for BIOS call
 712 *      @ecx_in: ECX register value for BIOS call
 713 *      @eax: EAX register on return from the BIOS call
 714 *      @err: bits
 715 *
 716 *      Make a BIOS call that returns one value only, or just status.
 717 *      If there is an error, then the error code is returned in @err
 718 *      and this function returns non-zero. This is used for simpler
 719 *      BIOS operations.  This call may hold interrupts off for a long
 720 *      time on some laptops.
 721 */
 722static int apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax,
 723                                int *err)
 724{
 725        struct apm_bios_call call;
 726        int ret;
 727
 728        call.func = func;
 729        call.ebx = ebx_in;
 730        call.ecx = ecx_in;
 731
 732        ret = on_cpu0(__apm_bios_call_simple, &call);
 733        *eax = call.eax;
 734        *err = call.err;
 735        return ret;
 736}
 737
 738/**
 739 *      apm_driver_version      -       APM driver version
 740 *      @val:   loaded with the APM version on return
 741 *
 742 *      Retrieve the APM version supported by the BIOS. This is only
 743 *      supported for APM 1.1 or higher. An error indicates APM 1.0 is
 744 *      probably present.
 745 *
 746 *      On entry val should point to a value indicating the APM driver
 747 *      version with the high byte being the major and the low byte the
 748 *      minor number both in BCD
 749 *
 750 *      On return it will hold the BIOS revision supported in the
 751 *      same format.
 752 */
 753
 754static int apm_driver_version(u_short *val)
 755{
 756        u32 eax;
 757        int err;
 758
 759        if (apm_bios_call_simple(APM_FUNC_VERSION, 0, *val, &eax, &err))
 760                return err;
 761        *val = eax;
 762        return APM_SUCCESS;
 763}
 764
 765/**
 766 *      apm_get_event   -       get an APM event from the BIOS
 767 *      @event: pointer to the event
 768 *      @info: point to the event information
 769 *
 770 *      The APM BIOS provides a polled information for event
 771 *      reporting. The BIOS expects to be polled at least every second
 772 *      when events are pending. When a message is found the caller should
 773 *      poll until no more messages are present.  However, this causes
 774 *      problems on some laptops where a suspend event notification is
 775 *      not cleared until it is acknowledged.
 776 *
 777 *      Additional information is returned in the info pointer, providing
 778 *      that APM 1.2 is in use. If no messges are pending the value 0x80
 779 *      is returned (No power management events pending).
 780 */
 781static int apm_get_event(apm_event_t *event, apm_eventinfo_t *info)
 782{
 783        struct apm_bios_call call;
 784
 785        call.func = APM_FUNC_GET_EVENT;
 786        call.ebx = call.ecx = 0;
 787
 788        if (apm_bios_call(&call))
 789                return call.err;
 790
 791        *event = call.ebx;
 792        if (apm_info.connection_version < 0x0102)
 793                *info = ~0; /* indicate info not valid */
 794        else
 795                *info = call.ecx;
 796        return APM_SUCCESS;
 797}
 798
 799/**
 800 *      set_power_state -       set the power management state
 801 *      @what: which items to transition
 802 *      @state: state to transition to
 803 *
 804 *      Request an APM change of state for one or more system devices. The
 805 *      processor state must be transitioned last of all. what holds the
 806 *      class of device in the upper byte and the device number (0xFF for
 807 *      all) for the object to be transitioned.
 808 *
 809 *      The state holds the state to transition to, which may in fact
 810 *      be an acceptance of a BIOS requested state change.
 811 */
 812
 813static int set_power_state(u_short what, u_short state)
 814{
 815        u32 eax;
 816        int err;
 817
 818        if (apm_bios_call_simple(APM_FUNC_SET_STATE, what, state, &eax, &err))
 819                return err;
 820        return APM_SUCCESS;
 821}
 822
 823/**
 824 *      set_system_power_state - set system wide power state
 825 *      @state: which state to enter
 826 *
 827 *      Transition the entire system into a new APM power state.
 828 */
 829
 830static int set_system_power_state(u_short state)
 831{
 832        return set_power_state(APM_DEVICE_ALL, state);
 833}
 834
 835/**
 836 *      apm_do_idle     -       perform power saving
 837 *
 838 *      This function notifies the BIOS that the processor is (in the view
 839 *      of the OS) idle. It returns -1 in the event that the BIOS refuses
 840 *      to handle the idle request. On a success the function returns 1
 841 *      if the BIOS did clock slowing or 0 otherwise.
 842 */
 843
 844static int apm_do_idle(void)
 845{
 846        u32 eax;
 847        u8 ret = 0;
 848        int idled = 0;
 849        int err = 0;
 850
 851        if (!need_resched()) {
 852                idled = 1;
 853                ret = apm_bios_call_simple(APM_FUNC_IDLE, 0, 0, &eax, &err);
 854        }
 855
 856        if (!idled)
 857                return 0;
 858
 859        if (ret) {
 860                static unsigned long t;
 861
 862                /* This always fails on some SMP boards running UP kernels.
 863                 * Only report the failure the first 5 times.
 864                 */
 865                if (++t < 5) {
 866                        printk(KERN_DEBUG "apm_do_idle failed (%d)\n", err);
 867                        t = jiffies;
 868                }
 869                return -1;
 870        }
 871        clock_slowed = (apm_info.bios.flags & APM_IDLE_SLOWS_CLOCK) != 0;
 872        return clock_slowed;
 873}
 874
 875/**
 876 *      apm_do_busy     -       inform the BIOS the CPU is busy
 877 *
 878 *      Request that the BIOS brings the CPU back to full performance.
 879 */
 880
 881static void apm_do_busy(void)
 882{
 883        u32 dummy;
 884        int err;
 885
 886        if (clock_slowed || ALWAYS_CALL_BUSY) {
 887                (void)apm_bios_call_simple(APM_FUNC_BUSY, 0, 0, &dummy, &err);
 888                clock_slowed = 0;
 889        }
 890}
 891
 892/*
 893 * If no process has really been interested in
 894 * the CPU for some time, we want to call BIOS
 895 * power management - we probably want
 896 * to conserve power.
 897 */
 898#define IDLE_CALC_LIMIT (HZ * 100)
 899#define IDLE_LEAKY_MAX  16
 900
 901/**
 902 * apm_cpu_idle         -       cpu idling for APM capable Linux
 903 *
 904 * This is the idling function the kernel executes when APM is available. It
 905 * tries to do BIOS powermanagement based on the average system idle time.
 906 * Furthermore it calls the system default idle routine.
 907 */
 908
 909static int apm_cpu_idle(struct cpuidle_device *dev,
 910        struct cpuidle_driver *drv, int index)
 911{
 912        static int use_apm_idle; /* = 0 */
 913        static unsigned int last_jiffies; /* = 0 */
 914        static u64 last_stime; /* = 0 */
 915        u64 stime, utime;
 916
 917        int apm_idle_done = 0;
 918        unsigned int jiffies_since_last_check = jiffies - last_jiffies;
 919        unsigned int bucket;
 920
 921recalc:
 922        task_cputime(current, &utime, &stime);
 923        if (jiffies_since_last_check > IDLE_CALC_LIMIT) {
 924                use_apm_idle = 0;
 925        } else if (jiffies_since_last_check > idle_period) {
 926                unsigned int idle_percentage;
 927
 928                idle_percentage = nsecs_to_jiffies(stime - last_stime);
 929                idle_percentage *= 100;
 930                idle_percentage /= jiffies_since_last_check;
 931                use_apm_idle = (idle_percentage > idle_threshold);
 932                if (apm_info.forbid_idle)
 933                        use_apm_idle = 0;
 934        }
 935
 936        last_jiffies = jiffies;
 937        last_stime = stime;
 938
 939        bucket = IDLE_LEAKY_MAX;
 940
 941        while (!need_resched()) {
 942                if (use_apm_idle) {
 943                        unsigned int t;
 944
 945                        t = jiffies;
 946                        switch (apm_do_idle()) {
 947                        case 0:
 948                                apm_idle_done = 1;
 949                                if (t != jiffies) {
 950                                        if (bucket) {
 951                                                bucket = IDLE_LEAKY_MAX;
 952                                                continue;
 953                                        }
 954                                } else if (bucket) {
 955                                        bucket--;
 956                                        continue;
 957                                }
 958                                break;
 959                        case 1:
 960                                apm_idle_done = 1;
 961                                break;
 962                        default: /* BIOS refused */
 963                                break;
 964                        }
 965                }
 966                default_idle();
 967                local_irq_disable();
 968                jiffies_since_last_check = jiffies - last_jiffies;
 969                if (jiffies_since_last_check > idle_period)
 970                        goto recalc;
 971        }
 972
 973        if (apm_idle_done)
 974                apm_do_busy();
 975
 976        return index;
 977}
 978
 979/**
 980 *      apm_power_off   -       ask the BIOS to power off
 981 *
 982 *      Handle the power off sequence. This is the one piece of code we
 983 *      will execute even on SMP machines. In order to deal with BIOS
 984 *      bugs we support real mode APM BIOS power off calls. We also make
 985 *      the SMP call on CPU0 as some systems will only honour this call
 986 *      on their first cpu.
 987 */
 988
 989static void apm_power_off(void)
 990{
 991        /* Some bioses don't like being called from CPU != 0 */
 992        if (apm_info.realmode_power_off) {
 993                set_cpus_allowed_ptr(current, cpumask_of(0));
 994                machine_real_restart(MRR_APM);
 995        } else {
 996                (void)set_system_power_state(APM_STATE_OFF);
 997        }
 998}
 999
1000#ifdef CONFIG_APM_DO_ENABLE
1001
1002/**
1003 *      apm_enable_power_management - enable BIOS APM power management
1004 *      @enable: enable yes/no
1005 *
1006 *      Enable or disable the APM BIOS power services.
1007 */
1008
1009static int apm_enable_power_management(int enable)
1010{
1011        u32 eax;
1012        int err;
1013
1014        if ((enable == 0) && (apm_info.bios.flags & APM_BIOS_DISENGAGED))
1015                return APM_NOT_ENGAGED;
1016        if (apm_bios_call_simple(APM_FUNC_ENABLE_PM, APM_DEVICE_BALL,
1017                                 enable, &eax, &err))
1018                return err;
1019        if (enable)
1020                apm_info.bios.flags &= ~APM_BIOS_DISABLED;
1021        else
1022                apm_info.bios.flags |= APM_BIOS_DISABLED;
1023        return APM_SUCCESS;
1024}
1025#endif
1026
1027/**
1028 *      apm_get_power_status    -       get current power state
1029 *      @status: returned status
1030 *      @bat: battery info
1031 *      @life: estimated life
1032 *
1033 *      Obtain the current power status from the APM BIOS. We return a
1034 *      status which gives the rough battery status, and current power
1035 *      source. The bat value returned give an estimate as a percentage
1036 *      of life and a status value for the battery. The estimated life
1037 *      if reported is a lifetime in secodnds/minutes at current powwer
1038 *      consumption.
1039 */
1040
1041static int apm_get_power_status(u_short *status, u_short *bat, u_short *life)
1042{
1043        struct apm_bios_call call;
1044
1045        call.func = APM_FUNC_GET_STATUS;
1046        call.ebx = APM_DEVICE_ALL;
1047        call.ecx = 0;
1048
1049        if (apm_info.get_power_status_broken)
1050                return APM_32_UNSUPPORTED;
1051        if (apm_bios_call(&call)) {
1052                if (!call.err)
1053                        return APM_NO_ERROR;
1054                return call.err;
1055        }
1056        *status = call.ebx;
1057        *bat = call.ecx;
1058        if (apm_info.get_power_status_swabinminutes) {
1059                *life = swab16((u16)call.edx);
1060                *life |= 0x8000;
1061        } else
1062                *life = call.edx;
1063        return APM_SUCCESS;
1064}
1065
1066#if 0
1067static int apm_get_battery_status(u_short which, u_short *status,
1068                                  u_short *bat, u_short *life, u_short *nbat)
1069{
1070        u32 eax;
1071        u32 ebx;
1072        u32 ecx;
1073        u32 edx;
1074        u32 esi;
1075
1076        if (apm_info.connection_version < 0x0102) {
1077                /* pretend we only have one battery. */
1078                if (which != 1)
1079                        return APM_BAD_DEVICE;
1080                *nbat = 1;
1081                return apm_get_power_status(status, bat, life);
1082        }
1083
1084        if (apm_bios_call(APM_FUNC_GET_STATUS, (0x8000 | (which)), 0, &eax,
1085                          &ebx, &ecx, &edx, &esi))
1086                return (eax >> 8) & 0xff;
1087        *status = ebx;
1088        *bat = ecx;
1089        *life = edx;
1090        *nbat = esi;
1091        return APM_SUCCESS;
1092}
1093#endif
1094
1095/**
1096 *      apm_engage_power_management     -       enable PM on a device
1097 *      @device: identity of device
1098 *      @enable: on/off
1099 *
1100 *      Activate or deactivate power management on either a specific device
1101 *      or the entire system (%APM_DEVICE_ALL).
1102 */
1103
1104static int apm_engage_power_management(u_short device, int enable)
1105{
1106        u32 eax;
1107        int err;
1108
1109        if ((enable == 0) && (device == APM_DEVICE_ALL)
1110            && (apm_info.bios.flags & APM_BIOS_DISABLED))
1111                return APM_DISABLED;
1112        if (apm_bios_call_simple(APM_FUNC_ENGAGE_PM, device, enable,
1113                                 &eax, &err))
1114                return err;
1115        if (device == APM_DEVICE_ALL) {
1116                if (enable)
1117                        apm_info.bios.flags &= ~APM_BIOS_DISENGAGED;
1118                else
1119                        apm_info.bios.flags |= APM_BIOS_DISENGAGED;
1120        }
1121        return APM_SUCCESS;
1122}
1123
1124#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
1125
1126/**
1127 *      apm_console_blank       -       blank the display
1128 *      @blank: on/off
1129 *
1130 *      Attempt to blank the console, firstly by blanking just video device
1131 *      zero, and if that fails (some BIOSes don't support it) then it blanks
1132 *      all video devices. Typically the BIOS will do laptop backlight and
1133 *      monitor powerdown for us.
1134 */
1135
1136static int apm_console_blank(int blank)
1137{
1138        int error = APM_NOT_ENGAGED; /* silence gcc */
1139        int i;
1140        u_short state;
1141        static const u_short dev[3] = { 0x100, 0x1FF, 0x101 };
1142
1143        state = blank ? APM_STATE_STANDBY : APM_STATE_READY;
1144
1145        for (i = 0; i < ARRAY_SIZE(dev); i++) {
1146                error = set_power_state(dev[i], state);
1147
1148                if ((error == APM_SUCCESS) || (error == APM_NO_ERROR))
1149                        return 1;
1150
1151                if (error == APM_NOT_ENGAGED)
1152                        break;
1153        }
1154
1155        if (error == APM_NOT_ENGAGED) {
1156                static int tried;
1157                int eng_error;
1158                if (tried++ == 0) {
1159                        eng_error = apm_engage_power_management(APM_DEVICE_ALL, 1);
1160                        if (eng_error) {
1161                                apm_error("set display", error);
1162                                apm_error("engage interface", eng_error);
1163                                return 0;
1164                        } else
1165                                return apm_console_blank(blank);
1166                }
1167        }
1168        apm_error("set display", error);
1169        return 0;
1170}
1171#endif
1172
1173static int queue_empty(struct apm_user *as)
1174{
1175        return as->event_head == as->event_tail;
1176}
1177
1178static apm_event_t get_queued_event(struct apm_user *as)
1179{
1180        if (++as->event_tail >= APM_MAX_EVENTS)
1181                as->event_tail = 0;
1182        return as->events[as->event_tail];
1183}
1184
1185static void queue_event(apm_event_t event, struct apm_user *sender)
1186{
1187        struct apm_user *as;
1188
1189        spin_lock(&user_list_lock);
1190        if (user_list == NULL)
1191                goto out;
1192        for (as = user_list; as != NULL; as = as->next) {
1193                if ((as == sender) || (!as->reader))
1194                        continue;
1195                if (++as->event_head >= APM_MAX_EVENTS)
1196                        as->event_head = 0;
1197
1198                if (as->event_head == as->event_tail) {
1199                        static int notified;
1200
1201                        if (notified++ == 0)
1202                                pr_err("an event queue overflowed\n");
1203                        if (++as->event_tail >= APM_MAX_EVENTS)
1204                                as->event_tail = 0;
1205                }
1206                as->events[as->event_head] = event;
1207                if (!as->suser || !as->writer)
1208                        continue;
1209                switch (event) {
1210                case APM_SYS_SUSPEND:
1211                case APM_USER_SUSPEND:
1212                        as->suspends_pending++;
1213                        suspends_pending++;
1214                        break;
1215
1216                case APM_SYS_STANDBY:
1217                case APM_USER_STANDBY:
1218                        as->standbys_pending++;
1219                        standbys_pending++;
1220                        break;
1221                }
1222        }
1223        wake_up_interruptible(&apm_waitqueue);
1224out:
1225        spin_unlock(&user_list_lock);
1226}
1227
1228static void reinit_timer(void)
1229{
1230#ifdef INIT_TIMER_AFTER_SUSPEND
1231        unsigned long flags;
1232
1233        raw_spin_lock_irqsave(&i8253_lock, flags);
1234        /* set the clock to HZ */
1235        outb_p(0x34, PIT_MODE);         /* binary, mode 2, LSB/MSB, ch 0 */
1236        udelay(10);
1237        outb_p(LATCH & 0xff, PIT_CH0);  /* LSB */
1238        udelay(10);
1239        outb_p(LATCH >> 8, PIT_CH0);    /* MSB */
1240        udelay(10);
1241        raw_spin_unlock_irqrestore(&i8253_lock, flags);
1242#endif
1243}
1244
1245static int suspend(int vetoable)
1246{
1247        int err;
1248        struct apm_user *as;
1249
1250        dpm_suspend_start(PMSG_SUSPEND);
1251        dpm_suspend_end(PMSG_SUSPEND);
1252
1253        local_irq_disable();
1254        syscore_suspend();
1255
1256        local_irq_enable();
1257
1258        save_processor_state();
1259        err = set_system_power_state(APM_STATE_SUSPEND);
1260        ignore_normal_resume = 1;
1261        restore_processor_state();
1262
1263        local_irq_disable();
1264        reinit_timer();
1265
1266        if (err == APM_NO_ERROR)
1267                err = APM_SUCCESS;
1268        if (err != APM_SUCCESS)
1269                apm_error("suspend", err);
1270        err = (err == APM_SUCCESS) ? 0 : -EIO;
1271
1272        syscore_resume();
1273        local_irq_enable();
1274
1275        dpm_resume_start(PMSG_RESUME);
1276        dpm_resume_end(PMSG_RESUME);
1277
1278        queue_event(APM_NORMAL_RESUME, NULL);
1279        spin_lock(&user_list_lock);
1280        for (as = user_list; as != NULL; as = as->next) {
1281                as->suspend_wait = 0;
1282                as->suspend_result = err;
1283        }
1284        spin_unlock(&user_list_lock);
1285        wake_up_interruptible(&apm_suspend_waitqueue);
1286        return err;
1287}
1288
1289static void standby(void)
1290{
1291        int err;
1292
1293        dpm_suspend_end(PMSG_SUSPEND);
1294
1295        local_irq_disable();
1296        syscore_suspend();
1297        local_irq_enable();
1298
1299        err = set_system_power_state(APM_STATE_STANDBY);
1300        if ((err != APM_SUCCESS) && (err != APM_NO_ERROR))
1301                apm_error("standby", err);
1302
1303        local_irq_disable();
1304        syscore_resume();
1305        local_irq_enable();
1306
1307        dpm_resume_start(PMSG_RESUME);
1308}
1309
1310static apm_event_t get_event(void)
1311{
1312        int error;
1313        apm_event_t event = APM_NO_EVENTS; /* silence gcc */
1314        apm_eventinfo_t info;
1315
1316        static int notified;
1317
1318        /* we don't use the eventinfo */
1319        error = apm_get_event(&event, &info);
1320        if (error == APM_SUCCESS)
1321                return event;
1322
1323        if ((error != APM_NO_EVENTS) && (notified++ == 0))
1324                apm_error("get_event", error);
1325
1326        return 0;
1327}
1328
1329static void check_events(void)
1330{
1331        apm_event_t event;
1332        static unsigned long last_resume;
1333        static int ignore_bounce;
1334
1335        while ((event = get_event()) != 0) {
1336                if (debug) {
1337                        if (event <= NR_APM_EVENT_NAME)
1338                                printk(KERN_DEBUG "apm: received %s notify\n",
1339                                       apm_event_name[event - 1]);
1340                        else
1341                                printk(KERN_DEBUG "apm: received unknown "
1342                                       "event 0x%02x\n", event);
1343                }
1344                if (ignore_bounce
1345                    && (time_after(jiffies, last_resume + bounce_interval)))
1346                        ignore_bounce = 0;
1347
1348                switch (event) {
1349                case APM_SYS_STANDBY:
1350                case APM_USER_STANDBY:
1351                        queue_event(event, NULL);
1352                        if (standbys_pending <= 0)
1353                                standby();
1354                        break;
1355
1356                case APM_USER_SUSPEND:
1357#ifdef CONFIG_APM_IGNORE_USER_SUSPEND
1358                        if (apm_info.connection_version > 0x100)
1359                                set_system_power_state(APM_STATE_REJECT);
1360                        break;
1361#endif
1362                case APM_SYS_SUSPEND:
1363                        if (ignore_bounce) {
1364                                if (apm_info.connection_version > 0x100)
1365                                        set_system_power_state(APM_STATE_REJECT);
1366                                break;
1367                        }
1368                        /*
1369                         * If we are already processing a SUSPEND,
1370                         * then further SUSPEND events from the BIOS
1371                         * will be ignored.  We also return here to
1372                         * cope with the fact that the Thinkpads keep
1373                         * sending a SUSPEND event until something else
1374                         * happens!
1375                         */
1376                        if (ignore_sys_suspend)
1377                                return;
1378                        ignore_sys_suspend = 1;
1379                        queue_event(event, NULL);
1380                        if (suspends_pending <= 0)
1381                                (void) suspend(1);
1382                        break;
1383
1384                case APM_NORMAL_RESUME:
1385                case APM_CRITICAL_RESUME:
1386                case APM_STANDBY_RESUME:
1387                        ignore_sys_suspend = 0;
1388                        last_resume = jiffies;
1389                        ignore_bounce = 1;
1390                        if ((event != APM_NORMAL_RESUME)
1391                            || (ignore_normal_resume == 0)) {
1392                                dpm_resume_end(PMSG_RESUME);
1393                                queue_event(event, NULL);
1394                        }
1395                        ignore_normal_resume = 0;
1396                        break;
1397
1398                case APM_CAPABILITY_CHANGE:
1399                case APM_LOW_BATTERY:
1400                case APM_POWER_STATUS_CHANGE:
1401                        queue_event(event, NULL);
1402                        /* If needed, notify drivers here */
1403                        break;
1404
1405                case APM_UPDATE_TIME:
1406                        break;
1407
1408                case APM_CRITICAL_SUSPEND:
1409                        /*
1410                         * We are not allowed to reject a critical suspend.
1411                         */
1412                        (void)suspend(0);
1413                        break;
1414                }
1415        }
1416}
1417
1418static void apm_event_handler(void)
1419{
1420        static int pending_count = 4;
1421        int err;
1422
1423        if ((standbys_pending > 0) || (suspends_pending > 0)) {
1424                if ((apm_info.connection_version > 0x100) &&
1425                    (pending_count-- <= 0)) {
1426                        pending_count = 4;
1427                        if (debug)
1428                                printk(KERN_DEBUG "apm: setting state busy\n");
1429                        err = set_system_power_state(APM_STATE_BUSY);
1430                        if (err)
1431                                apm_error("busy", err);
1432                }
1433        } else
1434                pending_count = 4;
1435        check_events();
1436}
1437
1438/*
1439 * This is the APM thread main loop.
1440 */
1441
1442static void apm_mainloop(void)
1443{
1444        DECLARE_WAITQUEUE(wait, current);
1445
1446        add_wait_queue(&apm_waitqueue, &wait);
1447        set_current_state(TASK_INTERRUPTIBLE);
1448        for (;;) {
1449                schedule_timeout(APM_CHECK_TIMEOUT);
1450                if (kthread_should_stop())
1451                        break;
1452                /*
1453                 * Ok, check all events, check for idle (and mark us sleeping
1454                 * so as not to count towards the load average)..
1455                 */
1456                set_current_state(TASK_INTERRUPTIBLE);
1457                apm_event_handler();
1458        }
1459        remove_wait_queue(&apm_waitqueue, &wait);
1460}
1461
1462static int check_apm_user(struct apm_user *as, const char *func)
1463{
1464        if (as == NULL || as->magic != APM_BIOS_MAGIC) {
1465                pr_err("%s passed bad filp\n", func);
1466                return 1;
1467        }
1468        return 0;
1469}
1470
1471static ssize_t do_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
1472{
1473        struct apm_user *as;
1474        int i;
1475        apm_event_t event;
1476
1477        as = fp->private_data;
1478        if (check_apm_user(as, "read"))
1479                return -EIO;
1480        if ((int)count < sizeof(apm_event_t))
1481                return -EINVAL;
1482        if ((queue_empty(as)) && (fp->f_flags & O_NONBLOCK))
1483                return -EAGAIN;
1484        wait_event_interruptible(apm_waitqueue, !queue_empty(as));
1485        i = count;
1486        while ((i >= sizeof(event)) && !queue_empty(as)) {
1487                event = get_queued_event(as);
1488                if (copy_to_user(buf, &event, sizeof(event))) {
1489                        if (i < count)
1490                                break;
1491                        return -EFAULT;
1492                }
1493                switch (event) {
1494                case APM_SYS_SUSPEND:
1495                case APM_USER_SUSPEND:
1496                        as->suspends_read++;
1497                        break;
1498
1499                case APM_SYS_STANDBY:
1500                case APM_USER_STANDBY:
1501                        as->standbys_read++;
1502                        break;
1503                }
1504                buf += sizeof(event);
1505                i -= sizeof(event);
1506        }
1507        if (i < count)
1508                return count - i;
1509        if (signal_pending(current))
1510                return -ERESTARTSYS;
1511        return 0;
1512}
1513
1514static __poll_t do_poll(struct file *fp, poll_table *wait)
1515{
1516        struct apm_user *as;
1517
1518        as = fp->private_data;
1519        if (check_apm_user(as, "poll"))
1520                return 0;
1521        poll_wait(fp, &apm_waitqueue, wait);
1522        if (!queue_empty(as))
1523                return EPOLLIN | EPOLLRDNORM;
1524        return 0;
1525}
1526
1527static long do_ioctl(struct file *filp, u_int cmd, u_long arg)
1528{
1529        struct apm_user *as;
1530        int ret;
1531
1532        as = filp->private_data;
1533        if (check_apm_user(as, "ioctl"))
1534                return -EIO;
1535        if (!as->suser || !as->writer)
1536                return -EPERM;
1537        switch (cmd) {
1538        case APM_IOC_STANDBY:
1539                mutex_lock(&apm_mutex);
1540                if (as->standbys_read > 0) {
1541                        as->standbys_read--;
1542                        as->standbys_pending--;
1543                        standbys_pending--;
1544                } else
1545                        queue_event(APM_USER_STANDBY, as);
1546                if (standbys_pending <= 0)
1547                        standby();
1548                mutex_unlock(&apm_mutex);
1549                break;
1550        case APM_IOC_SUSPEND:
1551                mutex_lock(&apm_mutex);
1552                if (as->suspends_read > 0) {
1553                        as->suspends_read--;
1554                        as->suspends_pending--;
1555                        suspends_pending--;
1556                } else
1557                        queue_event(APM_USER_SUSPEND, as);
1558                if (suspends_pending <= 0) {
1559                        ret = suspend(1);
1560                        mutex_unlock(&apm_mutex);
1561                } else {
1562                        as->suspend_wait = 1;
1563                        mutex_unlock(&apm_mutex);
1564                        wait_event_interruptible(apm_suspend_waitqueue,
1565                                        as->suspend_wait == 0);
1566                        ret = as->suspend_result;
1567                }
1568                return ret;
1569        default:
1570                return -ENOTTY;
1571        }
1572        return 0;
1573}
1574
1575static int do_release(struct inode *inode, struct file *filp)
1576{
1577        struct apm_user *as;
1578
1579        as = filp->private_data;
1580        if (check_apm_user(as, "release"))
1581                return 0;
1582        filp->private_data = NULL;
1583        if (as->standbys_pending > 0) {
1584                standbys_pending -= as->standbys_pending;
1585                if (standbys_pending <= 0)
1586                        standby();
1587        }
1588        if (as->suspends_pending > 0) {
1589                suspends_pending -= as->suspends_pending;
1590                if (suspends_pending <= 0)
1591                        (void) suspend(1);
1592        }
1593        spin_lock(&user_list_lock);
1594        if (user_list == as)
1595                user_list = as->next;
1596        else {
1597                struct apm_user *as1;
1598
1599                for (as1 = user_list;
1600                     (as1 != NULL) && (as1->next != as);
1601                     as1 = as1->next)
1602                        ;
1603                if (as1 == NULL)
1604                        pr_err("filp not in user list\n");
1605                else
1606                        as1->next = as->next;
1607        }
1608        spin_unlock(&user_list_lock);
1609        kfree(as);
1610        return 0;
1611}
1612
1613static int do_open(struct inode *inode, struct file *filp)
1614{
1615        struct apm_user *as;
1616
1617        as = kmalloc(sizeof(*as), GFP_KERNEL);
1618        if (as == NULL)
1619                return -ENOMEM;
1620
1621        as->magic = APM_BIOS_MAGIC;
1622        as->event_tail = as->event_head = 0;
1623        as->suspends_pending = as->standbys_pending = 0;
1624        as->suspends_read = as->standbys_read = 0;
1625        /*
1626         * XXX - this is a tiny bit broken, when we consider BSD
1627         * process accounting. If the device is opened by root, we
1628         * instantly flag that we used superuser privs. Who knows,
1629         * we might close the device immediately without doing a
1630         * privileged operation -- cevans
1631         */
1632        as->suser = capable(CAP_SYS_ADMIN);
1633        as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
1634        as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
1635        spin_lock(&user_list_lock);
1636        as->next = user_list;
1637        user_list = as;
1638        spin_unlock(&user_list_lock);
1639        filp->private_data = as;
1640        return 0;
1641}
1642
1643static int proc_apm_show(struct seq_file *m, void *v)
1644{
1645        unsigned short  bx;
1646        unsigned short  cx;
1647        unsigned short  dx;
1648        int             error;
1649        unsigned short  ac_line_status = 0xff;
1650        unsigned short  battery_status = 0xff;
1651        unsigned short  battery_flag   = 0xff;
1652        int             percentage     = -1;
1653        int             time_units     = -1;
1654        char            *units         = "?";
1655
1656        if ((num_online_cpus() == 1) &&
1657            !(error = apm_get_power_status(&bx, &cx, &dx))) {
1658                ac_line_status = (bx >> 8) & 0xff;
1659                battery_status = bx & 0xff;
1660                if ((cx & 0xff) != 0xff)
1661                        percentage = cx & 0xff;
1662
1663                if (apm_info.connection_version > 0x100) {
1664                        battery_flag = (cx >> 8) & 0xff;
1665                        if (dx != 0xffff) {
1666                                units = (dx & 0x8000) ? "min" : "sec";
1667                                time_units = dx & 0x7fff;
1668                        }
1669                }
1670        }
1671        /* Arguments, with symbols from linux/apm_bios.h.  Information is
1672           from the Get Power Status (0x0a) call unless otherwise noted.
1673
1674           0) Linux driver version (this will change if format changes)
1675           1) APM BIOS Version.  Usually 1.0, 1.1 or 1.2.
1676           2) APM flags from APM Installation Check (0x00):
1677              bit 0: APM_16_BIT_SUPPORT
1678              bit 1: APM_32_BIT_SUPPORT
1679              bit 2: APM_IDLE_SLOWS_CLOCK
1680              bit 3: APM_BIOS_DISABLED
1681              bit 4: APM_BIOS_DISENGAGED
1682           3) AC line status
1683              0x00: Off-line
1684              0x01: On-line
1685              0x02: On backup power (BIOS >= 1.1 only)
1686              0xff: Unknown
1687           4) Battery status
1688              0x00: High
1689              0x01: Low
1690              0x02: Critical
1691              0x03: Charging
1692              0x04: Selected battery not present (BIOS >= 1.2 only)
1693              0xff: Unknown
1694           5) Battery flag
1695              bit 0: High
1696              bit 1: Low
1697              bit 2: Critical
1698              bit 3: Charging
1699              bit 7: No system battery
1700              0xff: Unknown
1701           6) Remaining battery life (percentage of charge):
1702              0-100: valid
1703              -1: Unknown
1704           7) Remaining battery life (time units):
1705              Number of remaining minutes or seconds
1706              -1: Unknown
1707           8) min = minutes; sec = seconds */
1708
1709        seq_printf(m, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
1710                   driver_version,
1711                   (apm_info.bios.version >> 8) & 0xff,
1712                   apm_info.bios.version & 0xff,
1713                   apm_info.bios.flags,
1714                   ac_line_status,
1715                   battery_status,
1716                   battery_flag,
1717                   percentage,
1718                   time_units,
1719                   units);
1720        return 0;
1721}
1722
1723static int apm(void *unused)
1724{
1725        unsigned short  bx;
1726        unsigned short  cx;
1727        unsigned short  dx;
1728        int             error;
1729        char            *power_stat;
1730        char            *bat_stat;
1731
1732        /* 2002/08/01 - WT
1733         * This is to avoid random crashes at boot time during initialization
1734         * on SMP systems in case of "apm=power-off" mode. Seen on ASUS A7M266D.
1735         * Some bioses don't like being called from CPU != 0.
1736         * Method suggested by Ingo Molnar.
1737         */
1738        set_cpus_allowed_ptr(current, cpumask_of(0));
1739        BUG_ON(smp_processor_id() != 0);
1740
1741        if (apm_info.connection_version == 0) {
1742                apm_info.connection_version = apm_info.bios.version;
1743                if (apm_info.connection_version > 0x100) {
1744                        /*
1745                         * We only support BIOSs up to version 1.2
1746                         */
1747                        if (apm_info.connection_version > 0x0102)
1748                                apm_info.connection_version = 0x0102;
1749                        error = apm_driver_version(&apm_info.connection_version);
1750                        if (error != APM_SUCCESS) {
1751                                apm_error("driver version", error);
1752                                /* Fall back to an APM 1.0 connection. */
1753                                apm_info.connection_version = 0x100;
1754                        }
1755                }
1756        }
1757
1758        if (debug)
1759                printk(KERN_INFO "apm: Connection version %d.%d\n",
1760                        (apm_info.connection_version >> 8) & 0xff,
1761                        apm_info.connection_version & 0xff);
1762
1763#ifdef CONFIG_APM_DO_ENABLE
1764        if (apm_info.bios.flags & APM_BIOS_DISABLED) {
1765                /*
1766                 * This call causes my NEC UltraLite Versa 33/C to hang if it
1767                 * is booted with PM disabled but not in the docking station.
1768                 * Unfortunate ...
1769                 */
1770                error = apm_enable_power_management(1);
1771                if (error) {
1772                        apm_error("enable power management", error);
1773                        return -1;
1774                }
1775        }
1776#endif
1777
1778        if ((apm_info.bios.flags & APM_BIOS_DISENGAGED)
1779            && (apm_info.connection_version > 0x0100)) {
1780                error = apm_engage_power_management(APM_DEVICE_ALL, 1);
1781                if (error) {
1782                        apm_error("engage power management", error);
1783                        return -1;
1784                }
1785        }
1786
1787        if (debug && (num_online_cpus() == 1 || smp)) {
1788                error = apm_get_power_status(&bx, &cx, &dx);
1789                if (error)
1790                        printk(KERN_INFO "apm: power status not available\n");
1791                else {
1792                        switch ((bx >> 8) & 0xff) {
1793                        case 0:
1794                                power_stat = "off line";
1795                                break;
1796                        case 1:
1797                                power_stat = "on line";
1798                                break;
1799                        case 2:
1800                                power_stat = "on backup power";
1801                                break;
1802                        default:
1803                                power_stat = "unknown";
1804                                break;
1805                        }
1806                        switch (bx & 0xff) {
1807                        case 0:
1808                                bat_stat = "high";
1809                                break;
1810                        case 1:
1811                                bat_stat = "low";
1812                                break;
1813                        case 2:
1814                                bat_stat = "critical";
1815                                break;
1816                        case 3:
1817                                bat_stat = "charging";
1818                                break;
1819                        default:
1820                                bat_stat = "unknown";
1821                                break;
1822                        }
1823                        printk(KERN_INFO
1824                               "apm: AC %s, battery status %s, battery life ",
1825                               power_stat, bat_stat);
1826                        if ((cx & 0xff) == 0xff)
1827                                printk("unknown\n");
1828                        else
1829                                printk("%d%%\n", cx & 0xff);
1830                        if (apm_info.connection_version > 0x100) {
1831                                printk(KERN_INFO
1832                                       "apm: battery flag 0x%02x, battery life ",
1833                                       (cx >> 8) & 0xff);
1834                                if (dx == 0xffff)
1835                                        printk("unknown\n");
1836                                else
1837                                        printk("%d %s\n", dx & 0x7fff,
1838                                               (dx & 0x8000) ?
1839                                               "minutes" : "seconds");
1840                        }
1841                }
1842        }
1843
1844        /* Install our power off handler.. */
1845        if (power_off)
1846                pm_power_off = apm_power_off;
1847
1848        if (num_online_cpus() == 1 || smp) {
1849#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
1850                console_blank_hook = apm_console_blank;
1851#endif
1852                apm_mainloop();
1853#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
1854                console_blank_hook = NULL;
1855#endif
1856        }
1857
1858        return 0;
1859}
1860
1861#ifndef MODULE
1862static int __init apm_setup(char *str)
1863{
1864        int invert;
1865
1866        while ((str != NULL) && (*str != '\0')) {
1867                if (strncmp(str, "off", 3) == 0)
1868                        apm_disabled = 1;
1869                if (strncmp(str, "on", 2) == 0)
1870                        apm_disabled = 0;
1871                if ((strncmp(str, "bounce-interval=", 16) == 0) ||
1872                    (strncmp(str, "bounce_interval=", 16) == 0))
1873                        bounce_interval = simple_strtol(str + 16, NULL, 0);
1874                if ((strncmp(str, "idle-threshold=", 15) == 0) ||
1875                    (strncmp(str, "idle_threshold=", 15) == 0))
1876                        idle_threshold = simple_strtol(str + 15, NULL, 0);
1877                if ((strncmp(str, "idle-period=", 12) == 0) ||
1878                    (strncmp(str, "idle_period=", 12) == 0))
1879                        idle_period = simple_strtol(str + 12, NULL, 0);
1880                invert = (strncmp(str, "no-", 3) == 0) ||
1881                        (strncmp(str, "no_", 3) == 0);
1882                if (invert)
1883                        str += 3;
1884                if (strncmp(str, "debug", 5) == 0)
1885                        debug = !invert;
1886                if ((strncmp(str, "power-off", 9) == 0) ||
1887                    (strncmp(str, "power_off", 9) == 0))
1888                        power_off = !invert;
1889                if (strncmp(str, "smp", 3) == 0) {
1890                        smp = !invert;
1891                        idle_threshold = 100;
1892                }
1893                if ((strncmp(str, "allow-ints", 10) == 0) ||
1894                    (strncmp(str, "allow_ints", 10) == 0))
1895                        apm_info.allow_ints = !invert;
1896                if ((strncmp(str, "broken-psr", 10) == 0) ||
1897                    (strncmp(str, "broken_psr", 10) == 0))
1898                        apm_info.get_power_status_broken = !invert;
1899                if ((strncmp(str, "realmode-power-off", 18) == 0) ||
1900                    (strncmp(str, "realmode_power_off", 18) == 0))
1901                        apm_info.realmode_power_off = !invert;
1902                str = strchr(str, ',');
1903                if (str != NULL)
1904                        str += strspn(str, ", \t");
1905        }
1906        return 1;
1907}
1908
1909__setup("apm=", apm_setup);
1910#endif
1911
1912static const struct file_operations apm_bios_fops = {
1913        .owner          = THIS_MODULE,
1914        .read           = do_read,
1915        .poll           = do_poll,
1916        .unlocked_ioctl = do_ioctl,
1917        .open           = do_open,
1918        .release        = do_release,
1919        .llseek         = noop_llseek,
1920};
1921
1922static struct miscdevice apm_device = {
1923        APM_MINOR_DEV,
1924        "apm_bios",
1925        &apm_bios_fops
1926};
1927
1928
1929/* Simple "print if true" callback */
1930static int __init print_if_true(const struct dmi_system_id *d)
1931{
1932        printk("%s\n", d->ident);
1933        return 0;
1934}
1935
1936/*
1937 * Some Bioses enable the PS/2 mouse (touchpad) at resume, even if it was
1938 * disabled before the suspend. Linux used to get terribly confused by that.
1939 */
1940static int __init broken_ps2_resume(const struct dmi_system_id *d)
1941{
1942        printk(KERN_INFO "%s machine detected. Mousepad Resume Bug "
1943               "workaround hopefully not needed.\n", d->ident);
1944        return 0;
1945}
1946
1947/* Some bioses have a broken protected mode poweroff and need to use realmode */
1948static int __init set_realmode_power_off(const struct dmi_system_id *d)
1949{
1950        if (apm_info.realmode_power_off == 0) {
1951                apm_info.realmode_power_off = 1;
1952                printk(KERN_INFO "%s bios detected. "
1953                       "Using realmode poweroff only.\n", d->ident);
1954        }
1955        return 0;
1956}
1957
1958/* Some laptops require interrupts to be enabled during APM calls */
1959static int __init set_apm_ints(const struct dmi_system_id *d)
1960{
1961        if (apm_info.allow_ints == 0) {
1962                apm_info.allow_ints = 1;
1963                printk(KERN_INFO "%s machine detected. "
1964                       "Enabling interrupts during APM calls.\n", d->ident);
1965        }
1966        return 0;
1967}
1968
1969/* Some APM bioses corrupt memory or just plain do not work */
1970static int __init apm_is_horked(const struct dmi_system_id *d)
1971{
1972        if (apm_info.disabled == 0) {
1973                apm_info.disabled = 1;
1974                printk(KERN_INFO "%s machine detected. "
1975                       "Disabling APM.\n", d->ident);
1976        }
1977        return 0;
1978}
1979
1980static int __init apm_is_horked_d850md(const struct dmi_system_id *d)
1981{
1982        if (apm_info.disabled == 0) {
1983                apm_info.disabled = 1;
1984                printk(KERN_INFO "%s machine detected. "
1985                       "Disabling APM.\n", d->ident);
1986                printk(KERN_INFO "This bug is fixed in bios P15 which is available for\n");
1987                printk(KERN_INFO "download from support.intel.com\n");
1988        }
1989        return 0;
1990}
1991
1992/* Some APM bioses hang on APM idle calls */
1993static int __init apm_likes_to_melt(const struct dmi_system_id *d)
1994{
1995        if (apm_info.forbid_idle == 0) {
1996                apm_info.forbid_idle = 1;
1997                printk(KERN_INFO "%s machine detected. "
1998                       "Disabling APM idle calls.\n", d->ident);
1999        }
2000        return 0;
2001}
2002
2003/*
2004 *  Check for clue free BIOS implementations who use
2005 *  the following QA technique
2006 *
2007 *      [ Write BIOS Code ]<------
2008 *               |                ^
2009 *      < Does it Compile >----N--
2010 *               |Y               ^
2011 *      < Does it Boot Win98 >-N--
2012 *               |Y
2013 *           [Ship It]
2014 *
2015 *      Phoenix A04  08/24/2000 is known bad (Dell Inspiron 5000e)
2016 *      Phoenix A07  09/29/2000 is known good (Dell Inspiron 5000)
2017 */
2018static int __init broken_apm_power(const struct dmi_system_id *d)
2019{
2020        apm_info.get_power_status_broken = 1;
2021        printk(KERN_WARNING "BIOS strings suggest APM bugs, "
2022               "disabling power status reporting.\n");
2023        return 0;
2024}
2025
2026/*
2027 * This bios swaps the APM minute reporting bytes over (Many sony laptops
2028 * have this problem).
2029 */
2030static int __init swab_apm_power_in_minutes(const struct dmi_system_id *d)
2031{
2032        apm_info.get_power_status_swabinminutes = 1;
2033        printk(KERN_WARNING "BIOS strings suggest APM reports battery life "
2034               "in minutes and wrong byte order.\n");
2035        return 0;
2036}
2037
2038static const struct dmi_system_id apm_dmi_table[] __initconst = {
2039        {
2040                print_if_true,
2041                KERN_WARNING "IBM T23 - BIOS 1.03b+ and controller firmware 1.02+ may be needed for Linux APM.",
2042                {       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
2043                        DMI_MATCH(DMI_BIOS_VERSION, "1AET38WW (1.01b)"), },
2044        },
2045        {       /* Handle problems with APM on the C600 */
2046                broken_ps2_resume, "Dell Latitude C600",
2047                {       DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
2048                        DMI_MATCH(DMI_PRODUCT_NAME, "Latitude C600"), },
2049        },
2050        {       /* Allow interrupts during suspend on Dell Latitude laptops*/
2051                set_apm_ints, "Dell Latitude",
2052                {       DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2053                        DMI_MATCH(DMI_PRODUCT_NAME, "Latitude C510"), }
2054        },
2055        {       /* APM crashes */
2056                apm_is_horked, "Dell Inspiron 2500",
2057                {       DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2058                        DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
2059                        DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2060                        DMI_MATCH(DMI_BIOS_VERSION, "A11"), },
2061        },
2062        {       /* Allow interrupts during suspend on Dell Inspiron laptops*/
2063                set_apm_ints, "Dell Inspiron", {
2064                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2065                        DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"), },
2066        },
2067        {       /* Handle problems with APM on Inspiron 5000e */
2068                broken_apm_power, "Dell Inspiron 5000e",
2069                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2070                        DMI_MATCH(DMI_BIOS_VERSION, "A04"),
2071                        DMI_MATCH(DMI_BIOS_DATE, "08/24/2000"), },
2072        },
2073        {       /* Handle problems with APM on Inspiron 2500 */
2074                broken_apm_power, "Dell Inspiron 2500",
2075                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2076                        DMI_MATCH(DMI_BIOS_VERSION, "A12"),
2077                        DMI_MATCH(DMI_BIOS_DATE, "02/04/2002"), },
2078        },
2079        {       /* APM crashes */
2080                apm_is_horked, "Dell Dimension 4100",
2081                {       DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2082                        DMI_MATCH(DMI_PRODUCT_NAME, "XPS-Z"),
2083                        DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
2084                        DMI_MATCH(DMI_BIOS_VERSION, "A11"), },
2085        },
2086        {       /* Allow interrupts during suspend on Compaq Laptops*/
2087                set_apm_ints, "Compaq 12XL125",
2088                {       DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
2089                        DMI_MATCH(DMI_PRODUCT_NAME, "Compaq PC"),
2090                        DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2091                        DMI_MATCH(DMI_BIOS_VERSION, "4.06"), },
2092        },
2093        {       /* Allow interrupts during APM or the clock goes slow */
2094                set_apm_ints, "ASUSTeK",
2095                {       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
2096                        DMI_MATCH(DMI_PRODUCT_NAME, "L8400K series Notebook PC"), },
2097        },
2098        {       /* APM blows on shutdown */
2099                apm_is_horked, "ABIT KX7-333[R]",
2100                {       DMI_MATCH(DMI_BOARD_VENDOR, "ABIT"),
2101                        DMI_MATCH(DMI_BOARD_NAME, "VT8367-8233A (KX7-333[R])"), },
2102        },
2103        {       /* APM crashes */
2104                apm_is_horked, "Trigem Delhi3",
2105                {       DMI_MATCH(DMI_SYS_VENDOR, "TriGem Computer, Inc"),
2106                        DMI_MATCH(DMI_PRODUCT_NAME, "Delhi3"), },
2107        },
2108        {       /* APM crashes */
2109                apm_is_horked, "Fujitsu-Siemens",
2110                {       DMI_MATCH(DMI_BIOS_VENDOR, "hoenix/FUJITSU SIEMENS"),
2111                        DMI_MATCH(DMI_BIOS_VERSION, "Version1.01"), },
2112        },
2113        {       /* APM crashes */
2114                apm_is_horked_d850md, "Intel D850MD",
2115                {       DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
2116                        DMI_MATCH(DMI_BIOS_VERSION, "MV85010A.86A.0016.P07.0201251536"), },
2117        },
2118        {       /* APM crashes */
2119                apm_is_horked, "Intel D810EMO",
2120                {       DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
2121                        DMI_MATCH(DMI_BIOS_VERSION, "MO81010A.86A.0008.P04.0004170800"), },
2122        },
2123        {       /* APM crashes */
2124                apm_is_horked, "Dell XPS-Z",
2125                {       DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
2126                        DMI_MATCH(DMI_BIOS_VERSION, "A11"),
2127                        DMI_MATCH(DMI_PRODUCT_NAME, "XPS-Z"), },
2128        },
2129        {       /* APM crashes */
2130                apm_is_horked, "Sharp PC-PJ/AX",
2131                {       DMI_MATCH(DMI_SYS_VENDOR, "SHARP"),
2132                        DMI_MATCH(DMI_PRODUCT_NAME, "PC-PJ/AX"),
2133                        DMI_MATCH(DMI_BIOS_VENDOR, "SystemSoft"),
2134                        DMI_MATCH(DMI_BIOS_VERSION, "Version R2.08"), },
2135        },
2136        {       /* APM crashes */
2137                apm_is_horked, "Dell Inspiron 2500",
2138                {       DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2139                        DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
2140                        DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2141                        DMI_MATCH(DMI_BIOS_VERSION, "A11"), },
2142        },
2143        {       /* APM idle hangs */
2144                apm_likes_to_melt, "Jabil AMD",
2145                {       DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
2146                        DMI_MATCH(DMI_BIOS_VERSION, "0AASNP06"), },
2147        },
2148        {       /* APM idle hangs */
2149                apm_likes_to_melt, "AMI Bios",
2150                {       DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
2151                        DMI_MATCH(DMI_BIOS_VERSION, "0AASNP05"), },
2152        },
2153        {       /* Handle problems with APM on Sony Vaio PCG-N505X(DE) */
2154                swab_apm_power_in_minutes, "Sony VAIO",
2155                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2156                        DMI_MATCH(DMI_BIOS_VERSION, "R0206H"),
2157                        DMI_MATCH(DMI_BIOS_DATE, "08/23/99"), },
2158        },
2159        {       /* Handle problems with APM on Sony Vaio PCG-N505VX */
2160                swab_apm_power_in_minutes, "Sony VAIO",
2161                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2162                        DMI_MATCH(DMI_BIOS_VERSION, "W2K06H0"),
2163                        DMI_MATCH(DMI_BIOS_DATE, "02/03/00"), },
2164        },
2165        {       /* Handle problems with APM on Sony Vaio PCG-XG29 */
2166                swab_apm_power_in_minutes, "Sony VAIO",
2167                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2168                        DMI_MATCH(DMI_BIOS_VERSION, "R0117A0"),
2169                        DMI_MATCH(DMI_BIOS_DATE, "04/25/00"), },
2170        },
2171        {       /* Handle problems with APM on Sony Vaio PCG-Z600NE */
2172                swab_apm_power_in_minutes, "Sony VAIO",
2173                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2174                        DMI_MATCH(DMI_BIOS_VERSION, "R0121Z1"),
2175                        DMI_MATCH(DMI_BIOS_DATE, "05/11/00"), },
2176        },
2177        {       /* Handle problems with APM on Sony Vaio PCG-Z600NE */
2178                swab_apm_power_in_minutes, "Sony VAIO",
2179                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2180                        DMI_MATCH(DMI_BIOS_VERSION, "WME01Z1"),
2181                        DMI_MATCH(DMI_BIOS_DATE, "08/11/00"), },
2182        },
2183        {       /* Handle problems with APM on Sony Vaio PCG-Z600LEK(DE) */
2184                swab_apm_power_in_minutes, "Sony VAIO",
2185                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2186                        DMI_MATCH(DMI_BIOS_VERSION, "R0206Z3"),
2187                        DMI_MATCH(DMI_BIOS_DATE, "12/25/00"), },
2188        },
2189        {       /* Handle problems with APM on Sony Vaio PCG-Z505LS */
2190                swab_apm_power_in_minutes, "Sony VAIO",
2191                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2192                        DMI_MATCH(DMI_BIOS_VERSION, "R0203D0"),
2193                        DMI_MATCH(DMI_BIOS_DATE, "05/12/00"), },
2194        },
2195        {       /* Handle problems with APM on Sony Vaio PCG-Z505LS */
2196                swab_apm_power_in_minutes, "Sony VAIO",
2197                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2198                        DMI_MATCH(DMI_BIOS_VERSION, "R0203Z3"),
2199                        DMI_MATCH(DMI_BIOS_DATE, "08/25/00"), },
2200        },
2201        {       /* Handle problems with APM on Sony Vaio PCG-Z505LS (with updated BIOS) */
2202                swab_apm_power_in_minutes, "Sony VAIO",
2203                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2204                        DMI_MATCH(DMI_BIOS_VERSION, "R0209Z3"),
2205                        DMI_MATCH(DMI_BIOS_DATE, "05/12/01"), },
2206        },
2207        {       /* Handle problems with APM on Sony Vaio PCG-F104K */
2208                swab_apm_power_in_minutes, "Sony VAIO",
2209                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2210                        DMI_MATCH(DMI_BIOS_VERSION, "R0204K2"),
2211                        DMI_MATCH(DMI_BIOS_DATE, "08/28/00"), },
2212        },
2213
2214        {       /* Handle problems with APM on Sony Vaio PCG-C1VN/C1VE */
2215                swab_apm_power_in_minutes, "Sony VAIO",
2216                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2217                        DMI_MATCH(DMI_BIOS_VERSION, "R0208P1"),
2218                        DMI_MATCH(DMI_BIOS_DATE, "11/09/00"), },
2219        },
2220        {       /* Handle problems with APM on Sony Vaio PCG-C1VE */
2221                swab_apm_power_in_minutes, "Sony VAIO",
2222                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2223                        DMI_MATCH(DMI_BIOS_VERSION, "R0204P1"),
2224                        DMI_MATCH(DMI_BIOS_DATE, "09/12/00"), },
2225        },
2226        {       /* Handle problems with APM on Sony Vaio PCG-C1VE */
2227                swab_apm_power_in_minutes, "Sony VAIO",
2228                {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2229                        DMI_MATCH(DMI_BIOS_VERSION, "WXPO1Z3"),
2230                        DMI_MATCH(DMI_BIOS_DATE, "10/26/01"), },
2231        },
2232        {       /* broken PM poweroff bios */
2233                set_realmode_power_off, "Award Software v4.60 PGMA",
2234                {       DMI_MATCH(DMI_BIOS_VENDOR, "Award Software International, Inc."),
2235                        DMI_MATCH(DMI_BIOS_VERSION, "4.60 PGMA"),
2236                        DMI_MATCH(DMI_BIOS_DATE, "134526184"), },
2237        },
2238
2239        /* Generic per vendor APM settings  */
2240
2241        {       /* Allow interrupts during suspend on IBM laptops */
2242                set_apm_ints, "IBM",
2243                {       DMI_MATCH(DMI_SYS_VENDOR, "IBM"), },
2244        },
2245
2246        { }
2247};
2248
2249/*
2250 * Just start the APM thread. We do NOT want to do APM BIOS
2251 * calls from anything but the APM thread, if for no other reason
2252 * than the fact that we don't trust the APM BIOS. This way,
2253 * most common APM BIOS problems that lead to protection errors
2254 * etc will have at least some level of being contained...
2255 *
2256 * In short, if something bad happens, at least we have a choice
2257 * of just killing the apm thread..
2258 */
2259static int __init apm_init(void)
2260{
2261        struct desc_struct *gdt;
2262        int err;
2263
2264        dmi_check_system(apm_dmi_table);
2265
2266        if (apm_info.bios.version == 0 || machine_is_olpc()) {
2267                printk(KERN_INFO "apm: BIOS not found.\n");
2268                return -ENODEV;
2269        }
2270        printk(KERN_INFO
2271               "apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n",
2272               ((apm_info.bios.version >> 8) & 0xff),
2273               (apm_info.bios.version & 0xff),
2274               apm_info.bios.flags,
2275               driver_version);
2276        if ((apm_info.bios.flags & APM_32_BIT_SUPPORT) == 0) {
2277                printk(KERN_INFO "apm: no 32 bit BIOS support\n");
2278                return -ENODEV;
2279        }
2280
2281        if (allow_ints)
2282                apm_info.allow_ints = 1;
2283        if (broken_psr)
2284                apm_info.get_power_status_broken = 1;
2285        if (realmode_power_off)
2286                apm_info.realmode_power_off = 1;
2287        /* User can override, but default is to trust DMI */
2288        if (apm_disabled != -1)
2289                apm_info.disabled = apm_disabled;
2290
2291        /*
2292         * Fix for the Compaq Contura 3/25c which reports BIOS version 0.1
2293         * but is reportedly a 1.0 BIOS.
2294         */
2295        if (apm_info.bios.version == 0x001)
2296                apm_info.bios.version = 0x100;
2297
2298        /* BIOS < 1.2 doesn't set cseg_16_len */
2299        if (apm_info.bios.version < 0x102)
2300                apm_info.bios.cseg_16_len = 0; /* 64k */
2301
2302        if (debug) {
2303                printk(KERN_INFO "apm: entry %x:%x cseg16 %x dseg %x",
2304                        apm_info.bios.cseg, apm_info.bios.offset,
2305                        apm_info.bios.cseg_16, apm_info.bios.dseg);
2306                if (apm_info.bios.version > 0x100)
2307                        printk(" cseg len %x, dseg len %x",
2308                                apm_info.bios.cseg_len,
2309                                apm_info.bios.dseg_len);
2310                if (apm_info.bios.version > 0x101)
2311                        printk(" cseg16 len %x", apm_info.bios.cseg_16_len);
2312                printk("\n");
2313        }
2314
2315        if (apm_info.disabled) {
2316                pr_notice("disabled on user request.\n");
2317                return -ENODEV;
2318        }
2319        if ((num_online_cpus() > 1) && !power_off && !smp) {
2320                pr_notice("disabled - APM is not SMP safe.\n");
2321                apm_info.disabled = 1;
2322                return -ENODEV;
2323        }
2324        if (!acpi_disabled) {
2325                pr_notice("overridden by ACPI.\n");
2326                apm_info.disabled = 1;
2327                return -ENODEV;
2328        }
2329
2330        /*
2331         * Set up the long jump entry point to the APM BIOS, which is called
2332         * from inline assembly.
2333         */
2334        apm_bios_entry.offset = apm_info.bios.offset;
2335        apm_bios_entry.segment = APM_CS;
2336
2337        /*
2338         * The APM 1.1 BIOS is supposed to provide limit information that it
2339         * recognizes.  Many machines do this correctly, but many others do
2340         * not restrict themselves to their claimed limit.  When this happens,
2341         * they will cause a segmentation violation in the kernel at boot time.
2342         * Most BIOS's, however, will respect a 64k limit, so we use that.
2343         *
2344         * Note we only set APM segments on CPU zero, since we pin the APM
2345         * code to that CPU.
2346         */
2347        gdt = get_cpu_gdt_rw(0);
2348        set_desc_base(&gdt[APM_CS >> 3],
2349                 (unsigned long)__va((unsigned long)apm_info.bios.cseg << 4));
2350        set_desc_base(&gdt[APM_CS_16 >> 3],
2351                 (unsigned long)__va((unsigned long)apm_info.bios.cseg_16 << 4));
2352        set_desc_base(&gdt[APM_DS >> 3],
2353                 (unsigned long)__va((unsigned long)apm_info.bios.dseg << 4));
2354
2355        proc_create_single("apm", 0, NULL, proc_apm_show);
2356
2357        kapmd_task = kthread_create(apm, NULL, "kapmd");
2358        if (IS_ERR(kapmd_task)) {
2359                pr_err("disabled - Unable to start kernel thread\n");
2360                err = PTR_ERR(kapmd_task);
2361                kapmd_task = NULL;
2362                remove_proc_entry("apm", NULL);
2363                return err;
2364        }
2365        wake_up_process(kapmd_task);
2366
2367        if (num_online_cpus() > 1 && !smp) {
2368                printk(KERN_NOTICE
2369                       "apm: disabled - APM is not SMP safe (power off active).\n");
2370                return 0;
2371        }
2372
2373        /*
2374         * Note we don't actually care if the misc_device cannot be registered.
2375         * this driver can do its job without it, even if userspace can't
2376         * control it.  just log the error
2377         */
2378        if (misc_register(&apm_device))
2379                printk(KERN_WARNING "apm: Could not register misc device.\n");
2380
2381        if (HZ != 100)
2382                idle_period = (idle_period * HZ) / 100;
2383        if (idle_threshold < 100) {
2384                cpuidle_poll_state_init(&apm_idle_driver);
2385                if (!cpuidle_register_driver(&apm_idle_driver))
2386                        if (cpuidle_register_device(&apm_cpuidle_device))
2387                                cpuidle_unregister_driver(&apm_idle_driver);
2388        }
2389
2390        return 0;
2391}
2392
2393static void __exit apm_exit(void)
2394{
2395        int error;
2396
2397        cpuidle_unregister_device(&apm_cpuidle_device);
2398        cpuidle_unregister_driver(&apm_idle_driver);
2399
2400        if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0)
2401            && (apm_info.connection_version > 0x0100)) {
2402                error = apm_engage_power_management(APM_DEVICE_ALL, 0);
2403                if (error)
2404                        apm_error("disengage power management", error);
2405        }
2406        misc_deregister(&apm_device);
2407        remove_proc_entry("apm", NULL);
2408        if (power_off)
2409                pm_power_off = NULL;
2410        if (kapmd_task) {
2411                kthread_stop(kapmd_task);
2412                kapmd_task = NULL;
2413        }
2414}
2415
2416module_init(apm_init);
2417module_exit(apm_exit);
2418
2419MODULE_AUTHOR("Stephen Rothwell");
2420MODULE_DESCRIPTION("Advanced Power Management");
2421MODULE_LICENSE("GPL");
2422module_param(debug, bool, 0644);
2423MODULE_PARM_DESC(debug, "Enable debug mode");
2424module_param(power_off, bool, 0444);
2425MODULE_PARM_DESC(power_off, "Enable power off");
2426module_param(bounce_interval, int, 0444);
2427MODULE_PARM_DESC(bounce_interval,
2428                "Set the number of ticks to ignore suspend bounces");
2429module_param(allow_ints, bool, 0444);
2430MODULE_PARM_DESC(allow_ints, "Allow interrupts during BIOS calls");
2431module_param(broken_psr, bool, 0444);
2432MODULE_PARM_DESC(broken_psr, "BIOS has a broken GetPowerStatus call");
2433module_param(realmode_power_off, bool, 0444);
2434MODULE_PARM_DESC(realmode_power_off,
2435                "Switch to real mode before powering off");
2436module_param(idle_threshold, int, 0444);
2437MODULE_PARM_DESC(idle_threshold,
2438        "System idle percentage above which to make APM BIOS idle calls");
2439module_param(idle_period, int, 0444);
2440MODULE_PARM_DESC(idle_period,
2441        "Period (in sec/100) over which to calculate the idle percentage");
2442module_param(smp, bool, 0444);
2443MODULE_PARM_DESC(smp,
2444        "Set this to enable APM use on an SMP platform. Use with caution on older systems");
2445MODULE_ALIAS_MISCDEV(APM_MINOR_DEV);
2446