From 869f096757f111db0d0184a4d03d97813f7bd5a0 Mon Sep 17 00:00:00 2001 From: mokopatches Date: Wed, 19 Nov 2008 17:03:22 +0000 Subject: fix-pcf50633-LOWBAT-kill-init.patch --- drivers/i2c/chips/pcf50633.c | 56 ++++++++++++++++++++++++++++++++++++++------ 1 file 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, -- cgit v1.2.3