patch-2.2.16 linux/arch/i386/kernel/apm.c

Next file: linux/arch/i386/kernel/bios32.c
Previous file: linux/arch/i386/config.in
Back to the patch index
Back to the overall index

diff -urN v2.2.15/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c
@@ -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 <jima@hal.com>).
+ *   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;
 	}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)