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(¤t->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]