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