summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2002-07-28 02:47:17 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2002-07-28 02:47:17 -0700
commit06ba030ae8384314fd1ec79b62de216da81db0c4 (patch)
tree070811ec592886af99209446ef7a4d2a0c40521e
parentab12b34b7cad42799db7651f736d66969dec3d71 (diff)
[PATCH] APM fixes, 2.5.29
the attached patch fixes two things: - a TLS related bug noticed by Arjan van de Ven: apm_init() should set up all CPU's gdt entries - just in case some code happens to call in the APM BIOS on the wrong CPU. This should also handle the case when some APM code gets triggered (by suspend or power button or something). - compilation problem
-rw-r--r--arch/i386/kernel/apm.c67
1 files changed, 35 insertions, 32 deletions
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index 61f644279efd..b6475816bc4f 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -1589,7 +1589,7 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
p = buf;
- if ((num_possible_cpus() == 1) &&
+ if ((num_online_cpus() == 1) &&
!(error = apm_get_power_status(&bx, &cx, &dx))) {
ac_line_status = (bx >> 8) & 0xff;
battery_status = bx & 0xff;
@@ -1720,7 +1720,7 @@ static int apm(void *unused)
}
}
- if (debug && (num_possible_cpus() == 1)) {
+ if (debug && (num_online_cpus() == 1)) {
error = apm_get_power_status(&bx, &cx, &dx);
if (error)
printk(KERN_INFO "apm: power status not available\n");
@@ -1764,7 +1764,7 @@ static int apm(void *unused)
pm_power_off = apm_power_off;
register_sysrq_key('o', &sysrq_poweroff_op);
- if (num_possible_cpus() == 1) {
+ if (num_online_cpus() == 1) {
#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
console_blank_hook = apm_console_blank;
#endif
@@ -1853,6 +1853,7 @@ static struct miscdevice apm_device = {
static int __init apm_init(void)
{
struct proc_dir_entry *apm_proc;
+ int i;
if (apm_info.bios.version == 0) {
printk(KERN_INFO "apm: BIOS not found.\n");
@@ -1907,7 +1908,7 @@ static int __init apm_init(void)
printk(KERN_NOTICE "apm: disabled on user request.\n");
return -ENODEV;
}
- if ((num_possible_cpus() > 1) && !power_off) {
+ if ((num_online_cpus() > 1) && !power_off) {
printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
return -ENODEV;
}
@@ -1926,37 +1927,39 @@ static int __init apm_init(void)
* NOTE: on SMP we call into the APM BIOS only on CPU#0, so it's
* enough to modify CPU#0's GDT.
*/
- set_base(cpu_gdt_table[0][APM_40 >> 3],
- __va((unsigned long)0x40 << 4));
- _set_limit((char *)&cpu_gdt_table[0][APM_40 >> 3], 4095 - (0x40 << 4));
-
- apm_bios_entry.offset = apm_info.bios.offset;
- apm_bios_entry.segment = APM_CS;
- set_base(cpu_gdt_table[0][APM_CS >> 3],
- __va((unsigned long)apm_info.bios.cseg << 4));
- set_base(cpu_gdt_table[0][APM_CS_16 >> 3],
- __va((unsigned long)apm_info.bios.cseg_16 << 4));
- set_base(cpu_gdt_table[0][APM_DS >> 3],
- __va((unsigned long)apm_info.bios.dseg << 4));
+ for (i = 0; i < NR_CPUS; i++) {
+ set_base(cpu_gdt_table[i][APM_40 >> 3],
+ __va((unsigned long)0x40 << 4));
+ _set_limit((char *)&cpu_gdt_table[i][APM_40 >> 3], 4095 - (0x40 << 4));
+
+ apm_bios_entry.offset = apm_info.bios.offset;
+ apm_bios_entry.segment = APM_CS;
+ set_base(cpu_gdt_table[i][APM_CS >> 3],
+ __va((unsigned long)apm_info.bios.cseg << 4));
+ set_base(cpu_gdt_table[i][APM_CS_16 >> 3],
+ __va((unsigned long)apm_info.bios.cseg_16 << 4));
+ set_base(cpu_gdt_table[i][APM_DS >> 3],
+ __va((unsigned long)apm_info.bios.dseg << 4));
#ifndef APM_RELAX_SEGMENTS
- if (apm_info.bios.version == 0x100) {
+ if (apm_info.bios.version == 0x100) {
#endif
- /* For ASUS motherboard, Award BIOS rev 110 (and others?) */
- _set_limit((char *)&cpu_gdt_table[0][APM_CS >> 3], 64 * 1024 - 1);
- /* For some unknown machine. */
- _set_limit((char *)&cpu_gdt_table[0][APM_CS_16 >> 3], 64 * 1024 - 1);
- /* For the DEC Hinote Ultra CT475 (and others?) */
- _set_limit((char *)&cpu_gdt_table[0][APM_DS >> 3], 64 * 1024 - 1);
+ /* For ASUS motherboard, Award BIOS rev 110 (and others?) */
+ _set_limit((char *)&cpu_gdt_table[i][APM_CS >> 3], 64 * 1024 - 1);
+ /* For some unknown machine. */
+ _set_limit((char *)&cpu_gdt_table[i][APM_CS_16 >> 3], 64 * 1024 - 1);
+ /* For the DEC Hinote Ultra CT475 (and others?) */
+ _set_limit((char *)&cpu_gdt_table[i][APM_DS >> 3], 64 * 1024 - 1);
#ifndef APM_RELAX_SEGMENTS
- } else {
- _set_limit((char *)&cpu_gdt_table[0][APM_CS >> 3],
- (apm_info.bios.cseg_len - 1) & 0xffff);
- _set_limit((char *)&cpu_gdt_table[0][APM_CS_16 >> 3],
- (apm_info.bios.cseg_16_len - 1) & 0xffff);
- _set_limit((char *)&cpu_gdt_table[0][APM_DS >> 3],
- (apm_info.bios.dseg_len - 1) & 0xffff);
- }
+ } else {
+ _set_limit((char *)&cpu_gdt_table[i][APM_CS >> 3],
+ (apm_info.bios.cseg_len - 1) & 0xffff);
+ _set_limit((char *)&cpu_gdt_table[i][APM_CS_16 >> 3],
+ (apm_info.bios.cseg_16_len - 1) & 0xffff);
+ _set_limit((char *)&cpu_gdt_table[i][APM_DS >> 3],
+ (apm_info.bios.dseg_len - 1) & 0xffff);
+ }
#endif
+ }
apm_proc = create_proc_info_entry("apm", 0, NULL, apm_get_info);
if (apm_proc)
@@ -1964,7 +1967,7 @@ static int __init apm_init(void)
kernel_thread(apm, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD);
- if (num_possible_cpus() > 1) {
+ if (num_online_cpus() > 1) {
printk(KERN_NOTICE
"apm: disabled - APM is not SMP safe (power off active).\n");
return 0;