204 #define pr_fmt(fmt) "apm: " fmt
206 #include <linux/module.h>
208 #include <linux/poll.h>
209 #include <linux/types.h>
210 #include <linux/stddef.h>
212 #include <linux/fcntl.h>
213 #include <linux/slab.h>
214 #include <linux/stat.h>
218 #include <linux/apm_bios.h>
220 #include <linux/time.h>
221 #include <linux/sched.h>
223 #include <linux/capability.h>
224 #include <linux/device.h>
225 #include <linux/kernel.h>
236 #include <asm/uaccess.h>
237 #include <asm/desc.h>
239 #include <asm/paravirt.h>
240 #include <asm/reboot.h>
242 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
250 #define APM_MINOR_DEV 134
295 #define ALWAYS_CALL_BUSY 1
302 #define APM_ZERO_SEGS
311 #undef INIT_TIMER_AFTER_SUSPEND
313 #ifdef INIT_TIMER_AFTER_SUSPEND
314 #include <linux/timex.h>
322 #define APM_CHECK_TIMEOUT (HZ)
327 #define DEFAULT_BOUNCE_INTERVAL (3 * HZ)
332 #define APM_MAX_EVENTS 20
357 #define APM_BIOS_MAGIC 0x4101
362 #ifdef CONFIG_APM_CPU_IDLE
363 #warning deprecated CONFIG_APM_CPU_IDLE will be deleted in 2012
364 #define DEFAULT_IDLE_THRESHOLD 95
366 #define DEFAULT_IDLE_THRESHOLD 100
368 #define DEFAULT_IDLE_PERIOD (100 / 3)
377 static int clock_slowed;
380 static int set_pm_idle;
381 static int suspends_pending;
382 static int standbys_pending;
383 static int ignore_sys_suspend;
384 static int ignore_normal_resume;
389 static int apm_disabled = -1;
391 static bool power_off;
393 static bool power_off = 1;
395 static bool realmode_power_off;
396 #ifdef CONFIG_APM_ALLOW_INTS
397 static bool allow_ints = 1;
399 static bool allow_ints;
401 static bool broken_psr;
418 static const char driver_version[] =
"1.16ac";
426 static const char *
const apm_event_name[] = {
432 "power status change",
437 "system standby resume",
438 "capabilities change"
440 #define NR_APM_EVENT_NAME ARRAY_SIZE(apm_event_name)
452 static const lookup_t error_table[] = {
471 #define ERROR_COUNT ARRAY_SIZE(error_table)
482 static void apm_error(
char *
str,
int err)
487 if (error_table[i].
key == err)
492 pr_notice(
"%s: linux error code %i\n", str, err);
494 pr_notice(
"%s: unknown error code %#2.2x\n",
515 static inline unsigned long __apm_irq_save(
void)
528 #define apm_irq_save(flags) \
529 do { flags = __apm_irq_save(); } while (0)
531 static inline void apm_irq_restore(
unsigned long flags)
540 # define APM_DECL_SEGS \
541 unsigned int saved_fs; unsigned int saved_gs;
542 # define APM_DO_SAVE_SEGS \
543 savesegment(fs, saved_fs); savesegment(gs, saved_gs)
544 # define APM_DO_RESTORE_SEGS \
545 loadsegment(fs, saved_fs); loadsegment(gs, saved_gs)
547 # define APM_DECL_SEGS
548 # define APM_DO_SAVE_SEGS
549 # define APM_DO_RESTORE_SEGS
580 static long __apm_bios_call(
void *_call)
591 gdt = get_cpu_gdt_table(cpu);
592 save_desc_40 = gdt[0x40 / 8];
593 gdt[0x40 / 8] = bad_bios_desc;
597 apm_bios_call_asm(call->
func, call->
ebx, call->
ecx,
601 apm_irq_restore(flags);
602 gdt[0x40 / 8] = save_desc_40;
605 return call->
eax & 0xff;
620 ret = work_on_cpu(0,
fn, call);
627 call->
err = (call->
eax >> 8) & 0xff;
640 return on_cpu0(__apm_bios_call, call);
655 static long __apm_bios_call_simple(
void *_call)
667 gdt = get_cpu_gdt_table(cpu);
668 save_desc_40 = gdt[0x40 / 8];
669 gdt[0x40 / 8] = bad_bios_desc;
673 error = apm_bios_call_simple_asm(call->
func, call->
ebx, call->
ecx,
676 apm_irq_restore(flags);
677 gdt[0x40 / 8] = save_desc_40;
706 ret = on_cpu0(__apm_bios_call_simple, &call);
804 static int set_system_power_state(
u_short state)
818 static int apm_do_idle(
void)
835 if (!need_resched()) {
846 static unsigned long t;
867 static void apm_do_busy(
void)
884 #define IDLE_CALC_LIMIT (HZ * 100)
885 #define IDLE_LEAKY_MAX 16
897 static void apm_cpu_idle(
void)
899 static int use_apm_idle;
900 static unsigned int last_jiffies;
901 static unsigned int last_stime;
903 int apm_idle_done = 0;
904 unsigned int jiffies_since_last_check =
jiffies - last_jiffies;
907 WARN_ONCE(1,
"deprecated apm_cpu_idle will be deleted in 2012");
913 }
else if (jiffies_since_last_check > idle_period) {
914 unsigned int idle_percentage;
916 idle_percentage =
current->stime - last_stime;
917 idle_percentage *= 100;
918 idle_percentage /= jiffies_since_last_check;
919 use_apm_idle = (idle_percentage > idle_threshold);
928 while (!need_resched()) {
933 switch (apm_do_idle()) {
953 if (original_pm_idle)
958 jiffies_since_last_check =
jiffies - last_jiffies;
959 if (jiffies_since_last_check > idle_period)
979 static void apm_power_off(
void)
990 #ifdef CONFIG_APM_DO_ENABLE
999 static int apm_enable_power_management(
int enable)
1007 enable, &eax, &err))
1054 static int apm_get_battery_status(
u_short which,
u_short *status,
1072 &ebx, &ecx, &edx, &esi))
1073 return (eax >> 8) & 0xff;
1091 static int apm_engage_power_management(
u_short device,
int enable)
1111 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
1123 static int apm_console_blank(
int blank)
1128 static const u_short dev[3] = { 0x100, 0x1FF, 0x101 };
1133 error = set_power_state(dev[i], state);
1148 apm_error(
"set display", error);
1149 apm_error(
"engage interface", eng_error);
1152 return apm_console_blank(blank);
1155 apm_error(
"set display", error);
1176 spin_lock(&user_list_lock);
1177 if (user_list ==
NULL)
1179 for (as = user_list; as !=
NULL; as = as->
next) {
1180 if ((as == sender) || (!as->
reader))
1186 static int notified;
1188 if (notified++ == 0)
1189 pr_err(
"an event queue overflowed\n");
1212 spin_unlock(&user_list_lock);
1215 static void reinit_timer(
void)
1217 #ifdef INIT_TIMER_AFTER_SUSPEND
1218 unsigned long flags;
1232 static int suspend(
int vetoable)
1247 ignore_normal_resume = 1;
1256 apm_error(
"suspend", err);
1266 spin_lock(&user_list_lock);
1267 for (as = user_list; as !=
NULL; as = as->
next) {
1271 spin_unlock(&user_list_lock);
1288 apm_error(
"standby", err);
1303 static int notified;
1306 error = apm_get_event(&event, &info);
1311 apm_error(
"get_event", error);
1316 static void check_events(
void)
1319 static unsigned long last_resume;
1320 static int ignore_bounce;
1322 while ((event = get_event()) != 0) {
1326 apm_event_name[event - 1]);
1329 "event 0x%02x\n", event);
1332 && (
time_after(jiffies, last_resume + bounce_interval)))
1338 queue_event(event,
NULL);
1344 #ifdef CONFIG_APM_IGNORE_USER_SUSPEND
1350 if (ignore_bounce) {
1363 if (ignore_sys_suspend)
1365 ignore_sys_suspend = 1;
1366 queue_event(event,
NULL);
1374 ignore_sys_suspend = 0;
1378 || (ignore_normal_resume == 0)) {
1380 queue_event(event,
NULL);
1382 ignore_normal_resume = 0;
1388 queue_event(event,
NULL);
1405 static void apm_event_handler(
void)
1407 static int pending_count = 4;
1412 (pending_count-- <= 0)) {
1418 apm_error(
"busy", err);
1429 static void apm_mainloop(
void)
1444 apm_event_handler();
1449 static int check_apm_user(
struct apm_user *as,
const char *
func)
1452 pr_err(
"%s passed bad filp\n", func);
1465 if (check_apm_user(as,
"read"))
1473 while ((i >=
sizeof(event)) && !queue_empty(as)) {
1474 event = get_queued_event(as);
1491 buf +=
sizeof(
event);
1506 if (check_apm_user(as,
"poll"))
1508 poll_wait(fp, &apm_waitqueue, wait);
1509 if (!queue_empty(as))
1520 if (check_apm_user(as,
"ioctl"))
1567 if (check_apm_user(as,
"release"))
1580 spin_lock(&user_list_lock);
1581 if (user_list == as)
1582 user_list = as->
next;
1586 for (as1 = user_list;
1587 (as1 !=
NULL) && (as1->
next != as);
1591 pr_err(
"filp not in user list\n");
1595 spin_unlock(&user_list_lock);
1600 static int do_open(
struct inode *inode,
struct file *filp)
1622 spin_lock(&user_list_lock);
1623 as->
next = user_list;
1625 spin_unlock(&user_list_lock);
1630 static int proc_apm_show(
struct seq_file *
m,
void *
v)
1636 unsigned short ac_line_status = 0xff;
1637 unsigned short battery_status = 0xff;
1638 unsigned short battery_flag = 0xff;
1639 int percentage = -1;
1640 int time_units = -1;
1645 ac_line_status = (bx >> 8) & 0xff;
1646 battery_status = bx & 0xff;
1647 if ((cx & 0xff) != 0xff)
1648 percentage = cx & 0xff;
1651 battery_flag = (cx >> 8) & 0xff;
1653 units = (dx & 0x8000) ?
"min" :
"sec";
1654 time_units = dx & 0x7fff;
1696 seq_printf(m,
"%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
1710 static int proc_apm_open(
struct inode *inode,
struct file *
file)
1717 .open = proc_apm_open,
1723 static int apm(
void *
unused)
1751 apm_error(
"driver version", error);
1763 #ifdef CONFIG_APM_DO_ENABLE
1770 error = apm_enable_power_management(1);
1772 apm_error(
"enable power management", error);
1782 apm_error(
"engage power management", error);
1792 switch ((bx >> 8) & 0xff) {
1794 power_stat =
"off line";
1797 power_stat =
"on line";
1800 power_stat =
"on backup power";
1803 power_stat =
"unknown";
1806 switch (bx & 0xff) {
1814 bat_stat =
"critical";
1817 bat_stat =
"charging";
1820 bat_stat =
"unknown";
1824 "apm: AC %s, battery status %s, battery life ",
1825 power_stat, bat_stat);
1826 if ((cx & 0xff) == 0xff)
1829 printk(
"%d%%\n", cx & 0xff);
1832 "apm: battery flag 0x%02x, battery life ",
1837 printk(
"%d %s\n", dx & 0x7fff,
1839 "minutes" :
"seconds");
1849 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
1853 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
1866 while ((str !=
NULL) && (*str !=
'\0')) {
1867 if (
strncmp(str,
"off", 3) == 0)
1869 if (
strncmp(str,
"on", 2) == 0)
1871 if ((
strncmp(str,
"bounce-interval=", 16) == 0) ||
1872 (
strncmp(str,
"bounce_interval=", 16) == 0))
1874 if ((
strncmp(str,
"idle-threshold=", 15) == 0) ||
1875 (
strncmp(str,
"idle_threshold=", 15) == 0))
1877 if ((
strncmp(str,
"idle-period=", 12) == 0) ||
1878 (
strncmp(str,
"idle_period=", 12) == 0))
1880 invert = (
strncmp(str,
"no-", 3) == 0) ||
1881 (
strncmp(str,
"no_", 3) == 0);
1884 if (
strncmp(str,
"debug", 5) == 0)
1886 if ((
strncmp(str,
"power-off", 9) == 0) ||
1887 (
strncmp(str,
"power_off", 9) == 0))
1888 power_off = !invert;
1889 if (
strncmp(str,
"smp", 3) == 0) {
1891 idle_threshold = 100;
1893 if ((
strncmp(str,
"allow-ints", 10) == 0) ||
1894 (
strncmp(str,
"allow_ints", 10) == 0))
1896 if ((
strncmp(str,
"broken-psr", 10) == 0) ||
1897 (
strncmp(str,
"broken_psr", 10) == 0))
1899 if ((
strncmp(str,
"realmode-power-off", 18) == 0) ||
1900 (
strncmp(str,
"realmode_power_off", 18) == 0))
1904 str +=
strspn(str,
", \t");
1916 .unlocked_ioctl = do_ioctl,
1918 .release = do_release,
1943 "workaround hopefully not needed.\n", d->
ident);
1953 "Using realmode poweroff only.\n", d->
ident);
1964 "Enabling interrupts during APM calls.\n", d->
ident);
1975 "Disabling APM.\n", d->
ident);
1985 "Disabling APM.\n", d->
ident);
1986 printk(
KERN_INFO "This bug is fixed in bios P15 which is available for\n");
1998 "Disabling APM idle calls.\n", d->
ident);
2022 "disabling power status reporting.\n");
2034 "in minutes and wrong byte order.\n");
2041 KERN_WARNING "IBM T23 - BIOS 1.03b+ and controller firmware 1.02+ may be needed for Linux APM.",
2046 broken_ps2_resume,
"Dell Latitude C600",
2051 set_apm_ints,
"Dell Latitude",
2056 apm_is_horked,
"Dell Inspiron 2500",
2063 set_apm_ints,
"Dell Inspiron", {
2068 broken_apm_power,
"Dell Inspiron 5000e",
2074 broken_apm_power,
"Dell Inspiron 2500",
2080 apm_is_horked,
"Dell Dimension 4100",
2087 set_apm_ints,
"Compaq 12XL125",
2094 set_apm_ints,
"ASUSTeK",
2099 apm_is_horked,
"ABIT KX7-333[R]",
2104 apm_is_horked,
"Trigem Delhi3",
2109 apm_is_horked,
"Fujitsu-Siemens",
2114 apm_is_horked_d850md,
"Intel D850MD",
2119 apm_is_horked,
"Intel D810EMO",
2124 apm_is_horked,
"Dell XPS-Z",
2130 apm_is_horked,
"Sharp PC-PJ/AX",
2137 apm_is_horked,
"Dell Inspiron 2500",
2144 apm_likes_to_melt,
"Jabil AMD",
2149 apm_likes_to_melt,
"AMI Bios",
2154 swab_apm_power_in_minutes,
"Sony VAIO",
2160 swab_apm_power_in_minutes,
"Sony VAIO",
2166 swab_apm_power_in_minutes,
"Sony VAIO",
2172 swab_apm_power_in_minutes,
"Sony VAIO",
2178 swab_apm_power_in_minutes,
"Sony VAIO",
2184 swab_apm_power_in_minutes,
"Sony VAIO",
2190 swab_apm_power_in_minutes,
"Sony VAIO",
2196 swab_apm_power_in_minutes,
"Sony VAIO",
2202 swab_apm_power_in_minutes,
"Sony VAIO",
2208 swab_apm_power_in_minutes,
"Sony VAIO",
2215 swab_apm_power_in_minutes,
"Sony VAIO",
2221 swab_apm_power_in_minutes,
"Sony VAIO",
2227 swab_apm_power_in_minutes,
"Sony VAIO",
2233 set_realmode_power_off,
"Award Software v4.60 PGMA",
2242 set_apm_ints,
"IBM",
2259 static int __init apm_init(
void)
2271 "apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n",
2285 if (realmode_power_off)
2288 if (apm_disabled != -1)
2307 printk(
" cseg len %x, dseg len %x",
2316 pr_notice(
"disabled on user request.\n");
2320 pr_notice(
"disabled - APM is not SMP safe.\n");
2335 apm_bios_entry.segment =
APM_CS;
2347 gdt = get_cpu_gdt_table(0);
2348 set_desc_base(&gdt[
APM_CS >> 3],
2352 set_desc_base(&gdt[
APM_DS >> 3],
2355 proc_create(
"apm", 0,
NULL, &apm_file_ops);
2358 if (IS_ERR(kapmd_task)) {
2359 pr_err(
"disabled - Unable to start kernel thread\n");
2360 err = PTR_ERR(kapmd_task);
2369 "apm: disabled - APM is not SMP safe (power off active).\n");
2382 idle_period = (idle_period *
HZ) / 100;
2383 if (idle_threshold < 100) {
2392 static void __exit apm_exit(
void)
2409 apm_error(
"disengage power management", error);
2433 "Set the number of ticks to ignore suspend bounces");
2440 "Switch to real mode before powering off");
2443 "System idle percentage above which to make APM BIOS idle calls");
2446 "Period (in sec/100) over which to caculate the idle percentage");
2449 "Set this to enable APM use on an SMP platform. Use with caution on older systems");