Messages in this thread Patch in this message | | | Date | Sun, 28 Jul 2002 13:28:34 +0200 (CEST) | From | Ingo Molnar <> | Subject | [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
Ingo
--- linux/arch/i386/kernel/apm.c.orig Sun Jul 28 11:58:55 2002 +++ linux/arch/i386/kernel/apm.c Sun Jul 28 13:27:54 2002 @@ -1589,7 +1589,7 @@ 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 @@ } } - 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 @@ 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 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 @@ 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 @@ * 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 @@ 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; - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |