MAX77705 charger is most likely always a single device on the board, however nothing stops board designers to have two of them, thus same device driver could probe twice. Or user could manually try to probing second time.
Device driver is not ready for that case, because it allocates statically 'struct regmap_irq_chip' as non-const and stores during probe in 'irq_drv_data' member a pointer to per-probe state container ('struct max77705_charger_data'). devm_regmap_add_irq_chip() does not make a copy of 'struct regmap_irq_chip' but stores the pointer.
Second probe - either successful or failure - would overwrite the 'irq_drv_data' from previous device probe, so interrupts would be executed in a wrong context.
Fixes: a6a494c8e3ce ("power: supply: max77705: Add charger driver for Maxim 77705") Cc: stable@vger.kernel.org Signed-off-by: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org
---
Not tested on hardware --- drivers/power/supply/max77705_charger.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/power/supply/max77705_charger.c b/drivers/power/supply/max77705_charger.c index b1a227bf72e2..1044bf58aeac 100644 --- a/drivers/power/supply/max77705_charger.c +++ b/drivers/power/supply/max77705_charger.c @@ -60,7 +60,7 @@ static const struct regmap_irq max77705_charger_irqs[] = { REGMAP_IRQ_REG_LINE(MAX77705_AICL_I, BITS_PER_BYTE), };
-static struct regmap_irq_chip max77705_charger_irq_chip = { +static const struct regmap_irq_chip max77705_charger_irq_chip = { .name = "max77705-charger", .status_base = MAX77705_CHG_REG_INT, .mask_base = MAX77705_CHG_REG_INT_MASK, @@ -567,6 +567,7 @@ static int max77705_charger_probe(struct i2c_client *i2c) { struct power_supply_config pscfg = {}; struct max77705_charger_data *chg; + struct regmap_irq_chip *chip_desc; struct device *dev; struct regmap_irq_chip_data *irq_data; int ret; @@ -580,6 +581,13 @@ static int max77705_charger_probe(struct i2c_client *i2c) chg->dev = dev; i2c_set_clientdata(i2c, chg);
+ chip_desc = devm_kmemdup(dev, &max77705_charger_irq_chip, + sizeof(max77705_charger_irq_chip), + GFP_KERNEL); + if (!chip_desc) + return -ENOMEM; + chip_desc->irq_drv_data = chg; + chg->regmap = devm_regmap_init_i2c(i2c, &max77705_chg_regmap_config); if (IS_ERR(chg->regmap)) return PTR_ERR(chg->regmap); @@ -599,11 +607,9 @@ static int max77705_charger_probe(struct i2c_client *i2c) if (IS_ERR(chg->psy_chg)) return PTR_ERR(chg->psy_chg);
- max77705_charger_irq_chip.irq_drv_data = chg; ret = devm_regmap_add_irq_chip(chg->dev, chg->regmap, i2c->irq, IRQF_ONESHOT, 0, - &max77705_charger_irq_chip, - &irq_data); + chip_desc, &irq_data); if (ret) return dev_err_probe(dev, ret, "failed to add irq chip\n");