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