public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] da9030_battery: fix race between event handler and monitor
@ 2009-05-12  7:20 Mike Rapoport
  2009-05-13 18:40 ` Andrew Morton
  0 siblings, 1 reply; 3+ messages in thread
From: Mike Rapoport @ 2009-05-12  7:20 UTC (permalink / raw)
  To: cbou; +Cc: linux-kernel, Mike Rapoport

Signed-off-by: Mike Rapoport <mike@compulab.co.il>
---
 drivers/power/da9030_battery.c |   19 ++++++++++++-------
 1 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/power/da9030_battery.c b/drivers/power/da9030_battery.c
index 1662bb0..3364198 100644
--- a/drivers/power/da9030_battery.c
+++ b/drivers/power/da9030_battery.c
@@ -22,8 +22,6 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 
-#define DA9030_STATUS_CHDET	(1 << 3)
-
 #define DA9030_FAULT_LOG		0x0a
 #define DA9030_FAULT_LOG_OVER_TEMP	(1 << 7)
 #define DA9030_FAULT_LOG_VBAT_OVER	(1 << 4)
@@ -244,6 +242,8 @@ static void da9030_set_charge(struct da9030_charger *charger, int on)
 	}
 
 	da903x_write(charger->master, DA9030_CHARGE_CONTROL, val);
+
+	power_supply_changed(&charger->psy);
 }
 
 static void da9030_charger_check_state(struct da9030_charger *charger)
@@ -258,6 +258,12 @@ static void da9030_charger_check_state(struct da9030_charger *charger)
 			da9030_set_charge(charger, 1);
 		}
 	} else {
+		/* Charger has been pulled out */
+		if (!charger->chdet) {
+			da9030_set_charge(charger, 0);
+			return;
+		}
+
 		if (charger->adc.vbat_res >=
 		    charger->thresholds.vbat_charge_stop) {
 			da9030_set_charge(charger, 0);
@@ -395,13 +401,11 @@ static int da9030_battery_event(struct notifier_block *nb, unsigned long event,
 {
 	struct da9030_charger *charger =
 		container_of(nb, struct da9030_charger, nb);
-	int status;
 
 	switch (event) {
 	case DA9030_EVENT_CHDET:
-		status = da903x_query_status(charger->master,
-					     DA9030_STATUS_CHDET);
-		da9030_set_charge(charger, status);
+		cancel_delayed_work_sync(&charger->work);
+		schedule_work(&charger->work.work);
 		break;
 	case DA9030_EVENT_VBATMON:
 		da9030_battery_vbat_event(charger);
@@ -565,7 +569,8 @@ static int da9030_battery_remove(struct platform_device *dev)
 	da903x_unregister_notifier(charger->master, &charger->nb,
 				   DA9030_EVENT_CHDET | DA9030_EVENT_VBATMON |
 				   DA9030_EVENT_CHIOVER | DA9030_EVENT_TBAT);
-	cancel_delayed_work(&charger->work);
+	cancel_delayed_work_sync(&charger->work);
+	da9030_set_charge(charger, 0);
 	power_supply_unregister(&charger->psy);
 
 	kfree(charger);
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] da9030_battery: fix race between event handler and monitor
  2009-05-12  7:20 [PATCH] da9030_battery: fix race between event handler and monitor Mike Rapoport
@ 2009-05-13 18:40 ` Andrew Morton
  2009-05-14  5:39   ` Mike Rapoport
  0 siblings, 1 reply; 3+ messages in thread
From: Andrew Morton @ 2009-05-13 18:40 UTC (permalink / raw)
  To: Mike Rapoport; +Cc: cbou, linux-kernel, mike

On Tue, 12 May 2009 10:20:09 +0300
Mike Rapoport <mike@compulab.co.il> wrote:

> Signed-off-by: Mike Rapoport <mike@compulab.co.il>

We seem to be missing a changelog.

> 
> diff --git a/drivers/power/da9030_battery.c b/drivers/power/da9030_battery.c
> index 1662bb0..3364198 100644
> --- a/drivers/power/da9030_battery.c
> +++ b/drivers/power/da9030_battery.c
> @@ -22,8 +22,6 @@
>  #include <linux/debugfs.h>
>  #include <linux/seq_file.h>
>  
> -#define DA9030_STATUS_CHDET	(1 << 3)
> -
>  #define DA9030_FAULT_LOG		0x0a
>  #define DA9030_FAULT_LOG_OVER_TEMP	(1 << 7)
>  #define DA9030_FAULT_LOG_VBAT_OVER	(1 << 4)
> @@ -244,6 +242,8 @@ static void da9030_set_charge(struct da9030_charger *charger, int on)
>  	}
>  
>  	da903x_write(charger->master, DA9030_CHARGE_CONTROL, val);
> +
> +	power_supply_changed(&charger->psy);
>  }
>  
>  static void da9030_charger_check_state(struct da9030_charger *charger)
> @@ -258,6 +258,12 @@ static void da9030_charger_check_state(struct da9030_charger *charger)
>  			da9030_set_charge(charger, 1);
>  		}
>  	} else {
> +		/* Charger has been pulled out */
> +		if (!charger->chdet) {
> +			da9030_set_charge(charger, 0);
> +			return;
> +		}
> +
>  		if (charger->adc.vbat_res >=
>  		    charger->thresholds.vbat_charge_stop) {
>  			da9030_set_charge(charger, 0);
> @@ -395,13 +401,11 @@ static int da9030_battery_event(struct notifier_block *nb, unsigned long event,
>  {
>  	struct da9030_charger *charger =
>  		container_of(nb, struct da9030_charger, nb);
> -	int status;
>  
>  	switch (event) {
>  	case DA9030_EVENT_CHDET:
> -		status = da903x_query_status(charger->master,
> -					     DA9030_STATUS_CHDET);
> -		da9030_set_charge(charger, status);
> +		cancel_delayed_work_sync(&charger->work);
> +		schedule_work(&charger->work.work);
>  		break;
>  	case DA9030_EVENT_VBATMON:
>  		da9030_battery_vbat_event(charger);
> @@ -565,7 +569,8 @@ static int da9030_battery_remove(struct platform_device *dev)
>  	da903x_unregister_notifier(charger->master, &charger->nb,
>  				   DA9030_EVENT_CHDET | DA9030_EVENT_VBATMON |
>  				   DA9030_EVENT_CHIOVER | DA9030_EVENT_TBAT);
> -	cancel_delayed_work(&charger->work);
> +	cancel_delayed_work_sync(&charger->work);
> +	da9030_set_charge(charger, 0);
>  	power_supply_unregister(&charger->psy);
>  
>  	kfree(charger);

What is this race?  What are the user-visible effects when it occurs? 
How does the patch fix the race?


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] da9030_battery: fix race between event handler and monitor
  2009-05-13 18:40 ` Andrew Morton
@ 2009-05-14  5:39   ` Mike Rapoport
  0 siblings, 0 replies; 3+ messages in thread
From: Mike Rapoport @ 2009-05-14  5:39 UTC (permalink / raw)
  To: Andrew Morton; +Cc: cbou, linux-kernel



Andrew Morton wrote:
> On Tue, 12 May 2009 10:20:09 +0300
> Mike Rapoport <mike@compulab.co.il> wrote:
> 
>> Signed-off-by: Mike Rapoport <mike@compulab.co.il>
> 
> We seem to be missing a changelog.

My bad...

>> diff --git a/drivers/power/da9030_battery.c b/drivers/power/da9030_battery.c
>> index 1662bb0..3364198 100644
>> --- a/drivers/power/da9030_battery.c
>> +++ b/drivers/power/da9030_battery.c
>> @@ -22,8 +22,6 @@
>>  #include <linux/debugfs.h>
>>  #include <linux/seq_file.h>

[ snip ]

> What is this race? What are the user-visible effects when it occurs? 

There are cases when charging monitor and the event handler try to change the
charger state simultaneously. For instance, a charger is connected to the
system, there's the detection event and the event handler tries to enable
charging. It is possible that the periodic charging monitor runs at the same
time and it still thinks there's no external charger. So it tries to disable the
charging. As the result, even if the conditions necessary to charge the battery
hold, there will be no actual charging.

> How does the patch fix the race?

The patch changes the event handler so that instead of enabling/disabling the
charger immediately it would rather make the monitor run. The monitor code then
decides what should be the charger state.

> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 

-- 
Sincerely yours,
Mike.


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2009-05-14  5:39 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-05-12  7:20 [PATCH] da9030_battery: fix race between event handler and monitor Mike Rapoport
2009-05-13 18:40 ` Andrew Morton
2009-05-14  5:39   ` Mike Rapoport

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox