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 sfr@linuxcare.com, 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 <pavel@suse.cz> + * modified by sfr). + * Disable interrupts while we are suspended (Andy Henroid + * <andy_henroid@yahoo.com> 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(¤t->blocked); + current->tty = NULL; /* get rid of controlling tty */ if (apm_bios_info.version > 0x100) { /*
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Wed May 31 2000 - 21:00:15 EST