]> Gentwo Git Trees - linux/.git/commitdiff
power: supply: max77705: Fix potential IRQ chip conflict when probing two devices
authorKrzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Thu, 23 Oct 2025 10:29:06 +0000 (12:29 +0200)
committerSebastian Reichel <sebastian.reichel@collabora.com>
Sun, 2 Nov 2025 23:02:32 +0000 (00:02 +0100)
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>
Link: https://patch.msgid.link/20251023102905.71535-2-krzysztof.kozlowski@linaro.org
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
drivers/power/supply/max77705_charger.c

index 35cdb10a0e895436f858d3bbe9bdde70ac92c6ff..5dd02f658f5bd34eafdd8e855b31c87161adfc7b 100644 (file)
@@ -93,7 +93,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,
@@ -600,6 +600,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;
@@ -613,6 +614,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);
@@ -632,11 +640,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");