3.16.44-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Liam Breck <liam@xxxxxxxxxxxxxxxxx> commit 2d9fee6a42ea170e4378b3363a7ad385d0e67281 upstream. We wrongly get uevents for bq24190-charger and bq24190-battery on every register change. Fix by checking the association with charger and battery before emitting uevent(s). Fixes: d7bf353fd0aa3 ("bq24190_charger: Add support for TI BQ24190 Battery Charger") Signed-off-by: Liam Breck <kernel@xxxxxxxxxxxxxxxxx> Acked-by: Mark Greer <mgreer@xxxxxxxxxxxxxxx> Acked-by: Tony Lindgren <tony@xxxxxxxxxxx> Signed-off-by: Sebastian Reichel <sre@xxxxxxxxxx> [bwh: Backported to 3.16: adjust filename, context] Signed-off-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx> --- drivers/power/bq24190_charger.c | 50 ++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 23 deletions(-) --- a/drivers/power/bq24190_charger.c +++ b/drivers/power/bq24190_charger.c @@ -159,7 +159,6 @@ struct bq24190_dev_info { unsigned int gpio_int; unsigned int irq; struct mutex f_reg_lock; - bool first_time; bool charger_health_valid; bool battery_health_valid; bool battery_status_valid; @@ -1207,7 +1206,10 @@ static void bq24190_battery_init(struct static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) { struct bq24190_dev_info *bdi = data; - bool alert_userspace = false; + const u8 battery_mask_ss = BQ24190_REG_SS_CHRG_STAT_MASK; + const u8 battery_mask_f = BQ24190_REG_F_BAT_FAULT_MASK + | BQ24190_REG_F_NTC_FAULT_MASK; + bool alert_charger = false, alert_battery = false; u8 ss_reg = 0, f_reg = 0; int ret; @@ -1235,8 +1237,12 @@ static irqreturn_t bq24190_irq_handler_t ret); } + if ((bdi->ss_reg & battery_mask_ss) != (ss_reg & battery_mask_ss)) + alert_battery = true; + if ((bdi->ss_reg & ~battery_mask_ss) != (ss_reg & ~battery_mask_ss)) + alert_charger = true; + bdi->ss_reg = ss_reg; - alert_userspace = true; } mutex_lock(&bdi->f_reg_lock); @@ -1249,33 +1255,23 @@ static irqreturn_t bq24190_irq_handler_t } if (f_reg != bdi->f_reg) { + if ((bdi->f_reg & battery_mask_f) != (f_reg & battery_mask_f)) + alert_battery = true; + if ((bdi->f_reg & ~battery_mask_f) != (f_reg & ~battery_mask_f)) + alert_charger = true; + bdi->f_reg = f_reg; bdi->charger_health_valid = true; bdi->battery_health_valid = true; bdi->battery_status_valid = true; - - alert_userspace = true; } mutex_unlock(&bdi->f_reg_lock); - /* - * Sometimes bq24190 gives a steady trickle of interrupts even - * though the watchdog timer is turned off and neither the STATUS - * nor FAULT registers have changed. Weed out these sprurious - * interrupts so userspace isn't alerted for no reason. - * In addition, the chip always generates an interrupt after - * register reset so we should ignore that one (the very first - * interrupt received). - */ - if (alert_userspace) { - if (!bdi->first_time) { - power_supply_changed(&bdi->charger); - power_supply_changed(&bdi->battery); - } else { - bdi->first_time = false; - } - } + if (alert_charger) + power_supply_changed(&bdi->charger); + if (alert_battery) + power_supply_changed(&bdi->battery); out: pm_runtime_put_sync(bdi->dev); @@ -1310,6 +1306,10 @@ static int bq24190_hw_init(struct bq2419 goto out; ret = bq24190_set_mode_host(bdi); + if (ret < 0) + goto out; + + ret = bq24190_read(bdi, BQ24190_REG_SS, &bdi->ss_reg); out: pm_runtime_put_sync(bdi->dev); return ret; @@ -1384,7 +1384,8 @@ static int bq24190_probe(struct i2c_clie bdi->model = id->driver_data; strncpy(bdi->model_name, id->name, I2C_NAME_SIZE); mutex_init(&bdi->f_reg_lock); - bdi->first_time = true; + bdi->f_reg = 0; + bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */ bdi->charger_health_valid = false; bdi->battery_health_valid = false; bdi->battery_status_valid = false; @@ -1494,6 +1495,8 @@ static int bq24190_pm_resume(struct devi struct i2c_client *client = to_i2c_client(dev); struct bq24190_dev_info *bdi = i2c_get_clientdata(client); + bdi->f_reg = 0; + bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */ bdi->charger_health_valid = false; bdi->battery_health_valid = false; bdi->battery_status_valid = false; @@ -1501,6 +1504,7 @@ static int bq24190_pm_resume(struct devi pm_runtime_get_sync(bdi->dev); bq24190_register_reset(bdi); bq24190_set_mode_host(bdi); + bq24190_read(bdi, BQ24190_REG_SS, &bdi->ss_reg); pm_runtime_put_sync(bdi->dev); /* Things may have changed while suspended so alert upper layer */