summaryrefslogtreecommitdiffstats
path: root/target/linux/s3c24xx/patches-2.6.26/1058-fix-pcf50633-LOWBAT-kill-init.patch.patch
blob: 429a8c7dd9316c0d8c4b2ca1200a9f85a93b7cc8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
From 6d3172ba9f1b4a650c8fdb3b6e11dc71852fe6d1 Mon Sep 17 00:00:00 2001
From: mokopatches <mokopatches@openmoko.org>
Date: Fri, 25 Jul 2008 22:21:25 +0100
Subject: [PATCH] fix-pcf50633-LOWBAT-kill-init.patch

---
 drivers/i2c/chips/pcf50633.c |   56 ++++++++++++++++++++++++++++++++++++-----
 1 files changed, 49 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c
index 0cf5e53..fc1262e 100644
--- a/drivers/i2c/chips/pcf50633.c
+++ b/drivers/i2c/chips/pcf50633.c
@@ -690,8 +690,20 @@ static void pcf50633_work(struct work_struct *work)
 			if (pcf->onkey_seconds >=
 			    pcf->pdata->onkey_seconds_sig_init) {
 				/* Ask init to do 'ctrlaltdel' */
-				DEBUGPC("SIGINT(init) ");
-				kill_proc(1, SIGINT, 1);
+				/*
+				 * currently Linux reacts badly to issuing a
+				 * signal to PID #1 before init is started.
+				 * What happens is that the next kernel thread
+				 * to start, which is the JFFS2 Garbage
+				 * collector in our case, gets the signal
+				 * instead and proceeds to fail to fork --
+				 * which is very bad.  Therefore we confirm
+				 * PID #1 exists before issuing the signal
+				 */
+				if (find_task_by_pid(1)) {
+					DEBUGPC("SIGINT(init) ");
+					kill_proc(1, SIGINT, 1);
+				}
 				/* FIXME: what if userspace doesn't shut down? */
 			}
 			if (pcf->onkey_seconds >=
@@ -790,11 +802,41 @@ static void pcf50633_work(struct work_struct *work)
 	}
 
 	if (pcfirq[3] & (PCF50633_INT4_LOWBAT|PCF50633_INT4_LOWSYS)) {
-		/* Really low battery voltage, we have 8 seconds left */
-		DEBUGPC("LOWBAT ");
-		apm_queue_event(APM_LOW_BATTERY);
-		DEBUGPC("SIGPWR(init) ");
-		kill_proc(1, SIGPWR, 1);
+		if ((__reg_read(pcf, PCF50633_REG_MBCS1) &
+		    (PCF50633_MBCS1_USBPRES | PCF50633_MBCS1_USBOK)) ==
+		    (PCF50633_MBCS1_USBPRES | PCF50633_MBCS1_USBOK)) {
+			/*
+			 * hey no need to freak out, we have some kind of
+			 * valid charger power
+			 */
+			DEBUGPC("(NO)BAT ");
+		} else {
+			/* Really low battery voltage, we have 8 seconds left */
+			DEBUGPC("LOWBAT ");
+			/*
+			 * currently Linux reacts badly to issuing a signal to
+			 * PID #1 before init is started.  What happens is that
+			 * the next kernel thread to start, which is the JFFS2
+			 * Garbage collector in our case, gets the signal
+			 * instead and proceeds to fail to fork -- which is
+			 * very bad.  Therefore we confirm PID #1 exists
+			 * before issuing SPIGPWR
+			 */
+			if (find_task_by_pid(1)) {
+				apm_queue_event(APM_LOW_BATTERY);
+				DEBUGPC("SIGPWR(init) ");
+				kill_proc(1, SIGPWR, 1);
+			} else
+				/*
+				 * well, our situation is like this:  we do not
+				 * have any external power, we have a low
+				 * battery and since PID #1 doesn't exist yet,
+				 * we are early in the boot, likely before
+				 * rootfs mount.  We should just call it a day
+				 */
+				apm_queue_event(APM_CRITICAL_SUSPEND);
+		}
+
 		/* Tell PMU we are taking care of this */
 		reg_set_bit_mask(pcf, PCF50633_REG_OOCSHDWN,
 				 PCF50633_OOCSHDWN_TOTRST,
-- 
1.5.6.3