Hi Alan,

Please apply this ...

This is a patch against 2.3.99pre10-3 (2.4.0-test1) to do the
following:

        - notify drivers when we get a CRITICAL SUSPEND request
          front the BIOS.
        - Fix the change to make kapmd use more of the available
          idle time.
        - Disable interrupts when we suspend until after the drivers
          have been notified of the resume.

This works fine on my Fujitsu Lifebook, but I cannot swear that
the last change will not have adverse effects on others.  I have
not tested the critical suspend notification.

Now I just need to reintegrate my other pending patch! :-(

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.3.99pre10-3/arch/i386/kernel/apm.c 2.3.99pre10-3-APM/arch/i386/kernel/apm.c
--- 2.3.99pre10-3/arch/i386/kernel/apm.c        Thu May 25 14:05:36 2000
+++ 2.3.99pre10-3-APM/arch/i386/kernel/apm.c    Fri May 26 17:37:08 2000
@@ -135,6 +135,11 @@
  *         Fix the Thinkpad (again) :-( (CONFIG_APM_IGNORE_MULTIPLE_SUSPENDS
  *         is now the way life works).
  *         Fix thinko in suspend() (wrong return).
+ *         Notify drivers on critical suspend.
+ *         Make kapmd absorb more idle time (Pavel Machek <[EMAIL PROTECTED]>
+ *         modified by sfr).
+ *         Disable interrupts while we are suspended (Andy Henroid
+ *         <[EMAIL PROTECTED]> fixed by sfr).
  *
  * APM 1.1 Reference:
  *
@@ -864,19 +869,51 @@
 #endif
 }
 
+static int send_event(apm_event_t event)
+{
+       switch (event) {
+       case APM_SYS_SUSPEND:
+       case APM_CRITICAL_SUSPEND:
+       case APM_USER_SUSPEND:
+               /* map all suspends to ACPI D3 */
+               if (pm_send_all(PM_SUSPEND, (void *)3)) {
+                       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;
+               }
+               break;
+       case APM_NORMAL_RESUME:
+       case APM_CRITICAL_RESUME:
+               /* map all resumes to ACPI D0 */
+               (void) pm_send_all(PM_RESUME, (void *)0);
+               break;
+       }
+
+       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();
        if (err == APM_NO_ERROR)
                err = APM_SUCCESS;
-       if (err != APM_SUCCESS)
+       if (err != APM_SUCCESS) {
                apm_error("suspend", err);
+               send_event(APM_NORMAL_RESUME);
+               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);
@@ -914,33 +951,6 @@
        return 0;
 }
 
-static int send_event(apm_event_t event, struct apm_user *sender)
-{
-       switch (event) {
-       case APM_SYS_SUSPEND:
-       case APM_CRITICAL_SUSPEND:
-       case APM_USER_SUSPEND:
-               /* map all suspends to ACPI D3 */
-               if (pm_send_all(PM_SUSPEND, (void *)3)) {
-                       if (event == APM_CRITICAL_SUSPEND) {
-                               printk(KERN_CRIT "apm: Critical suspend was vetoed, 
expect armagedon\n" );
-                               return 0;
-                       }
-                       if (apm_bios_info.version > 0x100)
-                               apm_set_power_state(APM_STATE_REJECT);
-                       return 0;
-               }
-               break;
-       case APM_NORMAL_RESUME:
-       case APM_CRITICAL_RESUME:
-               /* map all resumes to ACPI D0 */
-               (void) pm_send_all(PM_RESUME, (void *)0);
-               break;
-       }
-
-       return 1;
-}
-
 static void check_events(void)
 {
        apm_event_t             event;
@@ -966,7 +976,7 @@
                switch (event) {
                case APM_SYS_STANDBY:
                case APM_USER_STANDBY:
-                       if (send_event(event, NULL)) {
+                       if (send_event(event)) {
                                queue_event(event, NULL);
                                if (standbys_pending <= 0)
                                        standby();
@@ -984,17 +994,17 @@
                        if (ignore_bounce)
                                break;
 #endif
-                       /*
-                        * 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 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)
-                               return;
-                       if (send_event(event, NULL)) {
+                               return;
+                       if (send_event(event)) {
                                queue_event(event, NULL);
                                waiting_for_resume = 1;
                                if (suspends_pending <= 0)
@@ -1011,14 +1021,16 @@
                        ignore_bounce = 1;
 #endif
                        set_time();
-                       send_event(event, NULL);
+                       send_event(event);
+                       sti();
                        queue_event(event, NULL);
                        break;
 
                case APM_CAPABILITY_CHANGE:
                case APM_LOW_BATTERY:
                case APM_POWER_STATUS_CHANGE:
-                       send_event(event, NULL);
+                       send_event(event);
+                       queue_event(event, NULL);
                        break;
 
                case APM_UPDATE_TIME:
@@ -1026,7 +1038,11 @@
                        break;
 
                case APM_CRITICAL_SUSPEND:
-                       send_event(event, NULL);        /* We can only hope it worked; 
critical suspend may not fail */
+                       send_event(event);
+                       /*
+                        * We can only hope it worked - we are not allowed
+                        * to reject a critical suspend.
+                        */
                        (void) suspend();
                        break;
                }
@@ -1093,7 +1109,7 @@
                        unsigned long start = jiffies;
                        while ((!exit_kapmd) && system_idle()) {
                                apm_do_idle();
-                               if (jiffies - start > (5*APM_CHECK_TIMEOUT)) {
+                               if (jiffies - start > APM_CHECK_TIMEOUT) {
                                        apm_event_handler();
                                        start = jiffies;
                                }
@@ -1199,8 +1215,10 @@
                        as->standbys_read--;
                        as->standbys_pending--;
                        standbys_pending--;
-               } else if (!send_event(APM_USER_STANDBY, as))
+               } else if (!send_event(APM_USER_STANDBY))
                        return -EAGAIN;
+               else
+                       queue_event(APM_USER_STANDBY, as);
                if (standbys_pending <= 0)
                        standby();
                break;
@@ -1209,8 +1227,10 @@
                        as->suspends_read--;
                        as->suspends_pending--;
                        suspends_pending--;
-               } else if (!send_event(APM_USER_SUSPEND, as))
+               } else if (!send_event(APM_USER_SUSPEND))
                        return -EAGAIN;
+               else
+                       queue_event(APM_USER_SUSPEND, as);
                if (suspends_pending <= 0) {
                        if (suspend() != APM_SUCCESS)
                                return -EIO;
@@ -1403,6 +1423,7 @@
 
        strcpy(current->comm, "kapmd");
        sigfillset(&current->blocked);
+       current->tty = NULL;    /* get rid of controlling tty */
 
        if (apm_bios_info.version > 0x100) {
                /*

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to