diff options
| author | Ingo Molnar <mingo@elte.hu> | 2002-07-28 02:47:17 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2002-07-28 02:47:17 -0700 |
| commit | 06ba030ae8384314fd1ec79b62de216da81db0c4 (patch) | |
| tree | 070811ec592886af99209446ef7a4d2a0c40521e | |
| parent | ab12b34b7cad42799db7651f736d66969dec3d71 (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.c | 67 |
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; |
