Skip to content

Commit 72d9cd9

Browse files
osctobesre
authored andcommitted
power: bq25890: protect view of the chip's state
Extend bq->lock over whole updating of the chip's state. Might get useful later for switching ADC modes correctly. Signed-off-by: Michał Mirosław <[email protected]> Signed-off-by: Sebastian Reichel <[email protected]>
1 parent a9c2419 commit 72d9cd9

File tree

1 file changed

+26
-56
lines changed

1 file changed

+26
-56
lines changed

drivers/power/supply/bq25890_charger.c

Lines changed: 26 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -510,74 +510,50 @@ static int bq25890_get_chip_state(struct bq25890_device *bq,
510510
return 0;
511511
}
512512

513-
static bool bq25890_state_changed(struct bq25890_device *bq,
514-
struct bq25890_state *new_state)
515-
{
516-
struct bq25890_state old_state;
517-
518-
mutex_lock(&bq->lock);
519-
old_state = bq->state;
520-
mutex_unlock(&bq->lock);
521-
522-
return (old_state.chrg_status != new_state->chrg_status ||
523-
old_state.chrg_fault != new_state->chrg_fault ||
524-
old_state.online != new_state->online ||
525-
old_state.bat_fault != new_state->bat_fault ||
526-
old_state.boost_fault != new_state->boost_fault ||
527-
old_state.vsys_status != new_state->vsys_status);
528-
}
529-
530-
static void bq25890_handle_state_change(struct bq25890_device *bq,
531-
struct bq25890_state *new_state)
513+
static irqreturn_t __bq25890_handle_irq(struct bq25890_device *bq)
532514
{
515+
struct bq25890_state new_state;
533516
int ret;
534-
struct bq25890_state old_state;
535517

536-
mutex_lock(&bq->lock);
537-
old_state = bq->state;
538-
mutex_unlock(&bq->lock);
518+
ret = bq25890_get_chip_state(bq, &new_state);
519+
if (ret < 0)
520+
return IRQ_NONE;
539521

540-
if (!new_state->online) { /* power removed */
522+
if (!memcmp(&bq->state, &new_state, sizeof(new_state)))
523+
return IRQ_NONE;
524+
525+
if (!new_state.online && bq->state.online) { /* power removed */
541526
/* disable ADC */
542527
ret = bq25890_field_write(bq, F_CONV_START, 0);
543528
if (ret < 0)
544529
goto error;
545-
} else if (!old_state.online) { /* power inserted */
530+
} else if (new_state.online && !bq->state.online) { /* power inserted */
546531
/* enable ADC, to have control of charge current/voltage */
547532
ret = bq25890_field_write(bq, F_CONV_START, 1);
548533
if (ret < 0)
549534
goto error;
550535
}
551536

552-
return;
537+
bq->state = new_state;
538+
power_supply_changed(bq->charger);
553539

540+
return IRQ_HANDLED;
554541
error:
555-
dev_err(bq->dev, "Error communicating with the chip.\n");
542+
dev_err(bq->dev, "Error communicating with the chip: %pe\n",
543+
ERR_PTR(ret));
544+
return IRQ_HANDLED;
556545
}
557546

558547
static irqreturn_t bq25890_irq_handler_thread(int irq, void *private)
559548
{
560549
struct bq25890_device *bq = private;
561-
int ret;
562-
struct bq25890_state state;
563-
564-
ret = bq25890_get_chip_state(bq, &state);
565-
if (ret < 0)
566-
goto handled;
567-
568-
if (!bq25890_state_changed(bq, &state))
569-
goto handled;
570-
571-
bq25890_handle_state_change(bq, &state);
550+
irqreturn_t ret;
572551

573552
mutex_lock(&bq->lock);
574-
bq->state = state;
553+
ret = __bq25890_handle_irq(bq);
575554
mutex_unlock(&bq->lock);
576555

577-
power_supply_changed(bq->charger);
578-
579-
handled:
580-
return IRQ_HANDLED;
556+
return ret;
581557
}
582558

583559
static int bq25890_chip_reset(struct bq25890_device *bq)
@@ -607,7 +583,6 @@ static int bq25890_hw_init(struct bq25890_device *bq)
607583
{
608584
int ret;
609585
int i;
610-
struct bq25890_state state;
611586

612587
const struct {
613588
enum bq25890_fields id;
@@ -655,16 +630,12 @@ static int bq25890_hw_init(struct bq25890_device *bq)
655630
return ret;
656631
}
657632

658-
ret = bq25890_get_chip_state(bq, &state);
633+
ret = bq25890_get_chip_state(bq, &bq->state);
659634
if (ret < 0) {
660635
dev_dbg(bq->dev, "Get state failed %d\n", ret);
661636
return ret;
662637
}
663638

664-
mutex_lock(&bq->lock);
665-
bq->state = state;
666-
mutex_unlock(&bq->lock);
667-
668639
return 0;
669640
}
670641

@@ -1001,19 +972,16 @@ static int bq25890_suspend(struct device *dev)
1001972
static int bq25890_resume(struct device *dev)
1002973
{
1003974
int ret;
1004-
struct bq25890_state state;
1005975
struct bq25890_device *bq = dev_get_drvdata(dev);
1006976

1007-
ret = bq25890_get_chip_state(bq, &state);
977+
mutex_lock(&bq->lock);
978+
979+
ret = bq25890_get_chip_state(bq, &bq->state);
1008980
if (ret < 0)
1009981
return ret;
1010982

1011-
mutex_lock(&bq->lock);
1012-
bq->state = state;
1013-
mutex_unlock(&bq->lock);
1014-
1015983
/* Re-enable ADC only if charger is plugged in. */
1016-
if (state.online) {
984+
if (bq->state.online) {
1017985
ret = bq25890_field_write(bq, F_CONV_START, 1);
1018986
if (ret < 0)
1019987
return ret;
@@ -1022,6 +990,8 @@ static int bq25890_resume(struct device *dev)
1022990
/* signal userspace, maybe state changed while suspended */
1023991
power_supply_changed(bq->charger);
1024992

993+
mutex_unlock(&bq->lock);
994+
1025995
return 0;
1026996
}
1027997
#endif

0 commit comments

Comments
 (0)