[patch] APM fixes, 2.5.29

From: Ingo Molnar (mingo@elte.hu)
Date: Sun Jul 28 2002 - 06:28:34 EST


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/



This archive was generated by hypermail 2b29 : Tue Jul 30 2002 - 14:00:28 EST