Hi Alan,

This is a backport of relevent changes to the 2.3 APM driver.  It
also includes the previous patch I sent you today.

This patch does:
        - Remove CONFIG_APM_SUSPEND_BOUNCE.  The bounce ignore
        interval is now configurable.
        - Disable interrupts while we are suspended.
        - Notify drivers on critical suspend.
        - remove zero initialisations.
        - general resync with 2.3/4 driver.

It also (as a side effect) makes 2.2.18pre4 boot - if you enable
APM support :-)).

Cheers,
Stephen
-- 
Stephen Rothwell, Open Source Researcher, Linuxcare, Inc.
+61-2-62628990 tel, +61-2-62628991 fax 
[EMAIL PROTECTED], http://www.linuxcare.com/ 
Linuxcare. Support for the revolution.

diff -ruN 2.2.18pre4/arch/i386/config.in 2.2.18pre4-APM.1/arch/i386/config.in
--- 2.2.18pre4/arch/i386/config.in      Mon Sep 11 10:17:09 2000
+++ 2.2.18pre4-APM.1/arch/i386/config.in        Mon Sep 11 16:22:50 2000
@@ -111,7 +111,6 @@
   bool '   Enable PM at boot time' CONFIG_APM_DO_ENABLE
   bool '   Make CPU Idle calls when idle' CONFIG_APM_CPU_IDLE
   bool '   Enable console blanking using APM' CONFIG_APM_DISPLAY_BLANK
-  bool '   Ignore multiple suspend/resume cycles' CONFIG_APM_IGNORE_SUSPEND_BOUNCE
   bool '   RTC stores time in GMT' CONFIG_APM_RTC_IS_GMT
   bool '   Allow interrupts during APM BIOS calls' CONFIG_APM_ALLOW_INTS
   bool '   Use real mode APM BIOS call to power off' CONFIG_APM_REAL_MODE_POWER_OFF
diff -ruN 2.2.18pre4/arch/i386/kernel/apm.c 2.2.18pre4-APM.1/arch/i386/kernel/apm.c
--- 2.2.18pre4/arch/i386/kernel/apm.c   Mon Sep 11 10:17:09 2000
+++ 2.2.18pre4-APM.1/arch/i386/kernel/apm.c     Mon Sep 11 16:19:47 2000
@@ -36,6 +36,7 @@
  * Oct 1999, Version 1.10
  * Nov 1999, Version 1.11
  * Jan 2000, Version 1.12
+ * Feb 2000, Version 1.13
  *
  * History:
  *    0.6b: first version in official kernel, Linux 1.3.46
@@ -55,7 +56,7 @@
  *         The new replacment for it is, but Linux doesn't yet support this.
  *         Alan Cox Linux 2.1.55
  *    1.3: Set up a valid data descriptor 0x40 for buggy BIOS's
- *    1.4: Upgraded to support APM 1.2. Integrated ThinkPad suspend patch by 
+ *    1.4: Upgraded to support APM 1.2. Integrated ThinkPad suspend patch by
  *         Dean Gaudet <[EMAIL PROTECTED]>.
  *         C. Scott Ananian <[EMAIL PROTECTED]> Linux 2.1.87
  *    1.5: Fix segment register reloading (in case of bad segments saved
@@ -127,8 +128,13 @@
  *         scripts that check for it before doing power off
  *         work (Jim Avera <[EMAIL PROTECTED]>).
  *   1.13: Fix the Thinkpad (again) :-( (CONFIG_APM_IGNORE_MULTIPLE_SUSPENDS
- *         is now the way life works). 
+ *         is now the way life works).
  *         Fix thinko in suspend() (wrong return).
+ *         Notify drivers on critical suspend.
+ *         Disable interrupts while we are suspended (Andy Henroid
+ *         <[EMAIL PROTECTED]> fixed by sfr).
+ *         Remove CONFIG_APM_SUSPEND_BOUNCE.  The bounce ignore
+ *         interval is now configurable.
  *
  * APM 1.1 Reference:
  *
@@ -170,10 +176,6 @@
 #include <asm/desc.h>
 #include <asm/softirq.h>
 
-/* 2.2-2.3 Compatability defines */
-#define __setup(x, y)
-#define module_init(x)
-
 EXPORT_SYMBOL(apm_register_callback);
 EXPORT_SYMBOL(apm_unregister_callback);
 
@@ -199,9 +201,12 @@
  * See Documentation/Config.help for the configuration options.
  *
  * Various options can be changed at boot time as follows:
+ * (We allow underscores for compatibility with the modules code)
  *     apm=on/off                      enable/disable APM
  *         [no-]debug                  log some debugging messages
- *         [no-]power-off              power off on shutdown
+ *         [no-]power[-_]off           power off on shutdown
+ *         bounce[-_]interval          ignore suspend bounces for this many
+ *                                     ticks
  */
 
 /* KNOWN PROBLEM MACHINES:
@@ -245,8 +250,8 @@
 
 /*
  * Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend.
- * This patched by Chad Miller <[EMAIL PROTECTED]>, orig code by David 
- * Chen <[EMAIL PROTECTED]>
+ * This patched by Chad Miller <[EMAIL PROTECTED]>, original code by
+ * David Chen <[EMAIL PROTECTED]>
  */
 #undef INIT_TIMER_AFTER_SUSPEND
 
@@ -262,10 +267,9 @@
 #define APM_CHECK_TIMEOUT      (HZ)
 
 /*
- * If CONFIG_APM_IGNORE_SUSPEND_BOUNCE is defined then
- * ignore suspend events for this amount of time after a resume
+ * Ignore suspend events for this amount of time after a resume
  */
-#define BOUNCE_INTERVAL                (3 * HZ)
+#define DEFAULT_BOUNCE_INTERVAL                (3 * HZ)
 
 /*
  * Save a segment register away
@@ -309,25 +313,27 @@
        unsigned short  segment;
 }                              apm_bios_entry;
 #ifdef CONFIG_APM_CPU_IDLE
-static int                     clock_slowed = 0;
+static int                     clock_slowed;
 #endif
-static int                     suspends_pending = 0;
-static int                     standbys_pending = 0;
-static int                     waiting_for_resume = 0;
+static int                     suspends_pending;
+static int                     standbys_pending;
+static int                     waiting_for_resume;
+static int                     ignore_normal_resume;
+static int                     bounce_interval = DEFAULT_BOUNCE_INTERVAL;
 
 #ifdef CONFIG_APM_RTC_IS_GMT
 #      define  clock_cmos_diff 0
 #      define  got_clock_diff  1
 #else
 static long                    clock_cmos_diff;
-static int                     got_clock_diff = 0;
+static int                     got_clock_diff;
 #endif
-static int                     debug = 0;
-static int                     apm_disabled = 0;
+static int                     debug;
+static int                     apm_disabled;
 #ifdef CONFIG_SMP
-static int                     power_off_enabled = 0;
+static int                     power_off;
 #else
-static int                     power_off_enabled = 1;
+static int                     power_off = 1;
 #endif
 
 static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
@@ -407,7 +413,7 @@
 #ifndef CONFIG_APM_ALLOW_INTS
 #      define APM_DO_CLI       __cli()
 #else
-#      define APM_DO_CLI
+#      define APM_DO_CLI       __sti()
 #endif
 #ifdef APM_ZERO_SEGS
 #      define APM_DECL_SEGS \
@@ -622,7 +628,7 @@
         * This may be called on an SMP machine.
         */
 #ifdef CONFIG_SMP
-       /* Many bioses don't like being called from CPU != 0 */
+       /* Some bioses don't like being called from CPU != 0 */
        while (cpu_number_map[smp_processor_id()] != 0) {
                kernel_thread(apm_magic, NULL,
                        CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD);
@@ -636,6 +642,7 @@
 #endif
 }
 
+#ifdef CONFIG_APM_DO_ENABLE
 static int apm_enable_power_management(int enable)
 {
        u32     eax;
@@ -651,6 +658,7 @@
                apm_bios_info.flags |= APM_BIOS_DISABLED;
        return APM_SUCCESS;
 }
+#endif
 
 static int apm_get_power_status(u_short *status, u_short *bat, u_short *life)
 {
@@ -873,12 +881,35 @@
 #endif
 }
 
+static int send_event(apm_event_t event, apm_event_t undo)
+{
+       callback_list_t *       call;
+       callback_list_t *       fix;
+
+       for (call = callback_list; call != NULL; call = call->next) {
+               if (call->callback(event) && undo) {
+                       for (fix = callback_list; fix != call; fix = fix->next)
+                               fix->callback(undo);
+                       if (event == APM_CRITICAL_SUSPEND) {
+                               printk(KERN_CRIT "apm: Critical suspend was vetoed, 
+expect armageddon\n" );
+                               return 0;
+                       }
+                       if (apm_bios_info.version > 0x100)
+                               apm_set_power_state(APM_STATE_REJECT);
+                       return 0;
+               }
+       }
+
+       return 1;
+}
+
 static int suspend(void)
 {
        int             err;
        struct apm_user *as;
 
        get_time_diff();
+       cli();
        err = apm_set_power_state(APM_STATE_SUSPEND);
        reinit_timer();
        set_time();
@@ -886,10 +917,14 @@
                err = APM_SUCCESS;
        if (err != APM_SUCCESS)
                apm_error("suspend", err);
+       send_event(APM_NORMAL_RESUME, 0);
+       sti();
+       queue_event(APM_NORMAL_RESUME, NULL);
        for (as = user_list; as != NULL; as = as->next) {
                as->suspend_wait = 0;
                as->suspend_result = ((err == APM_SUCCESS) ? 0 : -EIO);
        }
+       ignore_normal_resume = 1;
        wake_up_interruptible(&apm_suspend_waitqueue);
        return err;
 }
@@ -910,7 +945,7 @@
        apm_event_t     event;
        apm_eventinfo_t info;
 
-       static int notified = 0;
+       static int notified;
 
        /* we don't use the eventinfo */
        error = apm_get_event(&event, &info);
@@ -923,33 +958,11 @@
        return 0;
 }
 
-static int send_event(apm_event_t event, apm_event_t undo,
-                      struct apm_user *sender)
-{
-       callback_list_t *       call;
-       callback_list_t *       fix;
-
-       for (call = callback_list; call != NULL; call = call->next) {
-               if (call->callback(event) && undo) {
-                       for (fix = callback_list; fix != call; fix = fix->next)
-                               fix->callback(undo);
-                       if (apm_bios_info.version > 0x100)
-                               apm_set_power_state(APM_STATE_REJECT);
-                       return 0;
-               }
-       }
-
-       queue_event(event, sender);
-       return 1;
-}
-
 static void check_events(void)
 {
        apm_event_t             event;
-#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
-       static unsigned long    last_resume = 0;
-       static int              ignore_bounce = 0;
-#endif
+       static unsigned long    last_resume;
+       static int              ignore_bounce;
 
        while ((event = get_event()) != 0) {
                if (debug) {
@@ -960,15 +973,17 @@
                                printk(KERN_DEBUG "apm: received unknown "
                                       "event 0x%02x\n", event);
                }
-#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
                if (ignore_bounce
-                   && ((jiffies - last_resume) > BOUNCE_INTERVAL))
+                   && ((jiffies - last_resume) > bounce_interval))
                        ignore_bounce = 0;
-#endif
+               if (ignore_normal_resume && (event != APM_NORMAL_RESUME))
+                       ignore_normal_resume = 0;
+
                switch (event) {
                case APM_SYS_STANDBY:
                case APM_USER_STANDBY:
-                       if (send_event(event, APM_STANDBY_RESUME, NULL)) {
+                       if (send_event(event, APM_STANDBY_RESUME)) {
+                               queue_event(event, NULL);
                                if (standbys_pending <= 0)
                                        standby();
                        }
@@ -981,10 +996,11 @@
                        break;
 #endif
                case APM_SYS_SUSPEND:
-#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
-                       if (ignore_bounce)
+                       if (ignore_bounce) {
+                               if (apm_bios_info.version > 0x100)
+                                       apm_set_power_state(APM_STATE_REJECT);
                                break;
-#endif
+                       }
                        /*
                         * If we are already processing a SUSPEND,
                         * then further SUSPEND events from the BIOS
@@ -995,7 +1011,8 @@
                         */
                        if (waiting_for_resume)
                                return;
-                       if (send_event(event, APM_NORMAL_RESUME, NULL)) {
+                       if (send_event(event, APM_NORMAL_RESUME)) {
+                               queue_event(event, NULL);
                                waiting_for_resume = 1;
                                if (suspends_pending <= 0)
                                        (void) suspend();
@@ -1006,18 +1023,21 @@
                case APM_CRITICAL_RESUME:
                case APM_STANDBY_RESUME:
                        waiting_for_resume = 0;
-#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
                        last_resume = jiffies;
                        ignore_bounce = 1;
-#endif
-                       set_time();
-                       send_event(event, 0, NULL);
+                       if ((event != APM_NORMAL_RESUME)
+                           || (ignore_normal_resume == 0)) {
+                               set_time();
+                               send_event(event, 0);
+                               queue_event(event, NULL);
+                       }
                        break;
 
                case APM_CAPABILITY_CHANGE:
                case APM_LOW_BATTERY:
                case APM_POWER_STATUS_CHANGE:
-                       send_event(event, 0, NULL);
+                       send_event(event, 0);
+                       queue_event(event, NULL);
                        break;
 
                case APM_UPDATE_TIME:
@@ -1025,6 +1045,11 @@
                        break;
 
                case APM_CRITICAL_SUSPEND:
+                       send_event(event, 0);
+                       /*
+                        * We can only hope it worked - we are not allowed
+                        * to reject a critical suspend.
+                        */
                        (void) suspend();
                        break;
                }
@@ -1084,7 +1109,7 @@
                        schedule();
                        goto repeat;
                }
-               current->state = TASK_RUNNING;
+               set_current_state(TASK_RUNNING);
                remove_wait_queue(&apm_waitqueue, &wait);
        }
        i = count;
@@ -1146,8 +1171,10 @@
                        as->standbys_read--;
                        as->standbys_pending--;
                        standbys_pending--;
-               } else if (!send_event(APM_USER_STANDBY, APM_STANDBY_RESUME, as))
+               } else if (!send_event(APM_USER_STANDBY, APM_STANDBY_RESUME))
                        return -EAGAIN;
+               else
+                       queue_event(APM_USER_STANDBY, as);
                if (standbys_pending <= 0)
                        standby();
                break;
@@ -1156,8 +1183,10 @@
                        as->suspends_read--;
                        as->suspends_pending--;
                        suspends_pending--;
-               } else if (!send_event(APM_USER_SUSPEND, APM_NORMAL_RESUME, as))
+               } else if (!send_event(APM_USER_SUSPEND, APM_NORMAL_RESUME))
                        return -EAGAIN;
+               else
+                       queue_event(APM_USER_SUSPEND, as);
                if (suspends_pending <= 0) {
                        if (suspend() != APM_SUCCESS)
                                return -EIO;
@@ -1171,7 +1200,7 @@
                                        break;
                                schedule();
                        }
-                       current->state = TASK_RUNNING;
+                       set_current_state(TASK_RUNNING);
                        remove_wait_queue(&apm_suspend_waitqueue, &wait);
                        return as->suspend_result;
                }
@@ -1417,7 +1446,7 @@
        }
 
        /* Install our power off handler.. */
-       if (power_off_enabled)
+       if (power_off)
                acpi_power_off = apm_power_off;
 #ifdef CONFIG_MAGIC_SYSRQ
        sysrq_power_off = apm_power_off;
@@ -1430,7 +1459,7 @@
        return 0;
 }
 
-void __init apm_setup(char *str, int *dummy)
+static int __init apm_setup(char *str)
 {
        int     invert;
 
@@ -1444,12 +1473,17 @@
                        str += 3;
                if (strncmp(str, "debug", 5) == 0)
                        debug = !invert;
-               if (strncmp(str, "power-off", 9) == 0)
-                       power_off_enabled = !invert;
+               if ((strncmp(str, "power-off", 9) == 0) ||
+                   (strncmp(str, "power_off", 9) == 0))
+                       power_off = !invert;
+               if ((strncmp(str, "bounce-interval=", 16) == 0) ||
+                   (strncmp(str, "bounce_interval=", 16) == 0))
+                       bounce_interval = simple_strtol(str + 16, NULL, 0);
                str = strchr(str, ',');
                if (str != NULL)
                        str += strspn(str, ", \t");
        }
+       return 1;
 }
 
 __setup("apm=", apm_setup);
@@ -1464,17 +1498,16 @@
 
 static struct miscdevice apm_device = {
        APM_MINOR_DEV,
-       "apm",
+       "apm_bios",
        &apm_bios_fops
 };
 
-#define APM_INIT_ERROR_RETURN  return
 
-void __init apm_init(void)
+static int __init apm_init(void)
 {
        if (apm_bios_info.version == 0) {
                printk(KERN_INFO "apm: BIOS not found.\n");
-               APM_INIT_ERROR_RETURN;
+               return -ENODEV;
        }
        printk(KERN_INFO
                "apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n",
@@ -1484,7 +1517,7 @@
                driver_version);
        if ((apm_bios_info.flags & APM_32_BIT_SUPPORT) == 0) {
                printk(KERN_INFO "apm: no 32 bit BIOS support\n");
-               APM_INIT_ERROR_RETURN;
+               return -ENODEV;
        }
 
        /*
@@ -1513,11 +1546,11 @@
 
        if (apm_disabled) {
                printk(KERN_NOTICE "apm: disabled on user request.\n");
-               APM_INIT_ERROR_RETURN;
+               return -ENODEV;
        }
-       if ((smp_num_cpus > 1) && !power_off_enabled) {
+       if ((smp_num_cpus > 1) && !power_off) {
                printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
-               APM_INIT_ERROR_RETURN;
+               return -ENODEV;
        }
 
        /*
@@ -1560,12 +1593,12 @@
 
        apm(0);
 
-       create_proc_info_entry("apm", 0, 0, apm_get_info);
+       create_proc_info_entry("apm", 0, NULL, apm_get_info);
 
        if (smp_num_cpus > 1) {
                printk(KERN_NOTICE
                   "apm: disabled - APM is not SMP safe (power off active).\n");
-               APM_INIT_ERROR_RETURN;
+               return 0;
        }
 
        init_timer(&apm_timer);
@@ -1578,6 +1611,7 @@
 #ifdef CONFIG_APM_CPU_IDLE
        acpi_idle = apm_cpu_idle;
 #endif
+       return 0;
 }
 
 module_init(apm_init)
diff -ruN 2.2.18pre4/drivers/char/misc.c 2.2.18pre4-APM.1/drivers/char/misc.c
--- 2.2.18pre4/drivers/char/misc.c      Sun Sep 10 17:05:16 2000
+++ 2.2.18pre4-APM.1/drivers/char/misc.c        Mon Sep 11 12:26:39 2000
@@ -43,9 +43,6 @@
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/init.h>
-#ifdef CONFIG_APM
-#include <linux/apm_bios.h>
-#endif
 
 #include <linux/tty.h>
 #include <linux/selection.h>
@@ -240,9 +237,6 @@
 #endif
 #ifdef CONFIG_DTLK
        dtlk_init();
-#endif
-#ifdef CONFIG_APM
-       apm_init();
 #endif
 #ifdef CONFIG_H8
        h8_init();
diff -ruN 2.2.18pre4/include/linux/apm_bios.h 2.2.18pre4-APM.1/include/linux/apm_bios.h
--- 2.2.18pre4/include/linux/apm_bios.h Thu May  4 10:16:51 2000
+++ 2.2.18pre4-APM.1/include/linux/apm_bios.h   Mon Sep 11 12:26:12 2000
@@ -95,9 +95,6 @@
  */
 extern struct apm_bios_info    apm_bios_info;
 
-extern void            apm_init(void);
-extern void            apm_setup(char *, int *);
-
 extern int             apm_register_callback(int (*callback)(apm_event_t));
 extern void            apm_unregister_callback(int (*callback)(apm_event_t));
 
diff -ruN 2.2.18pre4/init/main.c 2.2.18pre4-APM.1/init/main.c
--- 2.2.18pre4/init/main.c      Mon Sep 11 10:17:48 2000
+++ 2.2.18pre4-APM.1/init/main.c        Mon Sep 11 12:31:17 2000
@@ -43,10 +43,6 @@
 #  include <asm/mtrr.h>
 #endif
 
-#ifdef CONFIG_APM
-#include <linux/apm_bios.h>
-#endif
-
 #ifdef CONFIG_DASD
 #include <asm/dasd.h>
 #endif
@@ -1095,9 +1091,6 @@
 #endif
 #ifdef CONFIG_PARIDE_PG
         { "pg.", pg_setup },
-#endif
-#ifdef CONFIG_APM
-       { "apm=", apm_setup },
 #endif
 #ifdef CONFIG_N2
        { "n2=", n2_setup },
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
Please read the FAQ at http://www.tux.org/lkml/

Reply via email to