aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authormokopatches <mokopatches@openmoko.org>2008-11-19 17:03:22 +0000
committerwarmcat <andy@warmcat.com>2008-11-19 17:03:22 +0000
commit869f096757f111db0d0184a4d03d97813f7bd5a0 (patch)
tree0ea3c42bfffa45140deb59bc87cf226a5211f64a /drivers
parentc8693c549935d2b53b3ff982426709a847e11a01 (diff)
fix-pcf50633-LOWBAT-kill-init.patch
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/chips/pcf50633.c56
1 files changed, 49 insertions, 7 deletions
diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c
index 0cf5e53a551..fc1262e6ba4 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,