Hi Alan,

Well, Rusty finally collared me and showed me that he could not
suspend his Thinkpad since upgrading to 2.2.15.  Below is the fix
against 2.2.16pre4.  This patch actually eliminates the CONFIG
option that was there just for the Thinkpads and makes the fix
they require the behaviour for everyone (it does not hurt).

Along the way, I fixed a couple of typos and an incorrect return
code from the suspend() routine.

Please apply this for 2.2.16.

Cheers,
Stephen
-- 
Stephen Rothwell, Open Source Project Engineer, 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.16-pre4/Documentation/Configure.help 
2.2.16-pre4-APM/Documentation/Configure.help
--- 2.2.16-pre4/Documentation/Configure.help    Mon May 22 16:52:12 2000
+++ 2.2.16-pre4-APM/Documentation/Configure.help        Mon May 22 16:53:10 2000
@@ -9305,14 +9305,6 @@
   backlight at all, or it might print a lot of errors to the console,
   especially if you are using gpm.
 
-Ignore multiple suspend/standby events
-CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
-  This option is necessary on the IBM Thinkpad 560, but should work on
-  all other laptops. When the APM BIOS returns multiple suspend or
-  standby events while one is already being processed they will be
-  ignored. Without this the Thinkpad 560 has troubles with the user
-  level daemon apmd, and with the PCMCIA package pcmcia-cs.
-
 Ignore multiple suspend/resume cycles
 CONFIG_APM_IGNORE_SUSPEND_BOUNCE
   This option is necessary on the Dell Inspiron 3200 and others, but
diff -ruN 2.2.16-pre4/arch/i386/config.in 2.2.16-pre4-APM/arch/i386/config.in
--- 2.2.16-pre4/arch/i386/config.in     Thu May  4 12:20:30 2000
+++ 2.2.16-pre4-APM/arch/i386/config.in Tue May 23 10:22:20 2000
@@ -109,7 +109,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' CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
   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
diff -ruN 2.2.16-pre4/arch/i386/kernel/apm.c 2.2.16-pre4-APM/arch/i386/kernel/apm.c
--- 2.2.16-pre4/arch/i386/kernel/apm.c  Thu May  4 12:20:30 2000
+++ 2.2.16-pre4-APM/arch/i386/kernel/apm.c      Tue May 23 10:31:15 2000
@@ -126,6 +126,9 @@
  *         Register the /proc/apm entry even on SMP so that
  *         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). 
+ *         Fix thinko in suspend() (wrong return).
  *
  * APM 1.1 Reference:
  *
@@ -318,9 +321,7 @@
 #endif
 static int                     suspends_pending = 0;
 static int                     standbys_pending = 0;
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
 static int                     waiting_for_resume = 0;
-#endif
 
 #ifdef CONFIG_APM_RTC_IS_GMT
 #      define  clock_cmos_diff 0
@@ -343,7 +344,7 @@
 
 static struct timer_list       apm_timer;
 
-static char                    driver_version[] = "1.12";      /* no spaces */
+static char                    driver_version[] = "1.13";      /* no spaces */
 
 static char *  apm_event_name[] = {
        "system standby",
@@ -883,19 +884,19 @@
 static int suspend(void)
 {
        int             err;
-       int             ret;
        struct apm_user *as;
 
        get_time_diff();
        err = apm_set_power_state(APM_STATE_SUSPEND);
        reinit_timer();
        set_time();
-       ret = (err == APM_SUCCESS) || (err == APM_NO_ERROR);
-       if (!ret)
+       if (err == APM_NO_ERROR)
+               err = APM_SUCCESS;
+       if (err != APM_SUCCESS)
                apm_error("suspend", err);
        for (as = user_list; as != NULL; as = as->next) {
                as->suspend_wait = 0;
-               as->suspend_result = (ret ? 0 : -EIO);
+               as->suspend_result = ((err == APM_SUCCESS) ? 0 : -EIO);
        }
        wake_up_interruptible(&apm_suspend_waitqueue);
        return err;
@@ -975,14 +976,7 @@
                switch (event) {
                case APM_SYS_STANDBY:
                case APM_USER_STANDBY:
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
-                       if (waiting_for_resume)
-                               break;
-#endif
                        if (send_event(event, APM_STANDBY_RESUME, NULL)) {
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
-                               waiting_for_resume = 1;
-#endif
                                if (standbys_pending <= 0)
                                        standby();
                        }
@@ -999,14 +993,18 @@
                        if (ignore_bounce)
                                break;
 #endif
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
+                       /*
+                        * If we are already processing a SUSPEND,
+                        * then further SUSPEND events from the BIOS
+                        * will be ignored.  We also return here to
+                        * cope with the fact that the Thinkpads keep
+                        * sending a SUSPEND event until something else
+                        * happens!
+                        */
                        if (waiting_for_resume)
-                               break;
-#endif
+                               return;
                        if (send_event(event, APM_NORMAL_RESUME, NULL)) {
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
                                waiting_for_resume = 1;
-#endif
                                if (suspends_pending <= 0)
                                        (void) suspend();
                        }
@@ -1015,9 +1013,7 @@
                case APM_NORMAL_RESUME:
                case APM_CRITICAL_RESUME:
                case APM_STANDBY_RESUME:
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
                        waiting_for_resume = 0;
-#endif
 #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
                        last_resume = jiffies;
                        ignore_bounce = 1;
@@ -1049,8 +1045,10 @@
        int             err;
 
        if ((standbys_pending > 0) || (suspends_pending > 0)) {
-               if ((apm_bios_info.version > 0x100) && (pending_count-- < 0)) {
+               if ((apm_bios_info.version > 0x100) && (pending_count-- <= 0)) {
                        pending_count = 4;
+                       if (debug)
+                               printk(KERN_DEBUG "apm: setting state busy\n");
                        err = apm_set_power_state(APM_STATE_BUSY);
                        if (err)
                                apm_error("busy", err);
@@ -1066,7 +1064,7 @@
 static int check_apm_user(struct apm_user *as, const char *func)
 {
        if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
-               printk(KERN_ERR "apm: %s passed bad filp", func);
+               printk(KERN_ERR "apm: %s passed bad filp\n", func);
                return 1;
        }
        return 0;
@@ -1169,7 +1167,7 @@
                } else if (!send_event(APM_USER_SUSPEND, APM_NORMAL_RESUME, as))
                        return -EAGAIN;
                if (suspends_pending <= 0) {
-                       if (!suspend())
+                       if (suspend() != APM_SUCCESS)
                                return -EIO;
                } else {
                        as->suspend_wait = 1;
@@ -1220,7 +1218,7 @@
                     as1 = as1->next)
                        ;
                if (as1 == NULL)
-                       printk(KERN_ERR "apm: filp not in user list");
+                       printk(KERN_ERR "apm: filp not in user list\n");
                else
                        as1->next = as->next;
        }
@@ -1234,7 +1232,7 @@
 
        as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);
        if (as == NULL) {
-               printk(KERN_ERR "apm: cannot allocate struct of size %d bytes",
+               printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
                       sizeof(*as));
                return -ENOMEM;
        }

Reply via email to