[PATCH 05/10] fix-pcf50633-LOWBAT-kill-init.patch
warmcat
andy at openmoko.com
Mon Feb 11 17:34:46 CET 2008
From: Andy Green <andy at openmoko.com>
Until now the driver treats LOWBAT as a fatal crisis and responds
by going postal on init. But the driver didn't think that we can
have adapter or USB power and no battery, which is fine.
This patch reserves the crisis behaviour for when we have no
adapter / USB power and just acknowledges the PMU exception when
we do.
In addition if init doesn't exist yet because we heard about LOWBAT
early in boot -- and we run on battery power only -- then we react
by doing an APM CRITICAL_SUSPEND right away
Signed-off-by: Andy Green <andy at openmoko.com>
---
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 78b4a2d..cf3f6b0 100644
--- a/drivers/i2c/chips/pcf50633.c
+++ b/drivers/i2c/chips/pcf50633.c
@@ -570,8 +570,20 @@ static void pcf50633_work(struct work_struct *work)
if (pcf->onkey_seconds >=
pcf->pdata->onkey_seconds_required) {
/* 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? */
}
}
@@ -641,11 +653,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,
More information about the openmoko-kernel
mailing list