]> git.ipfire.org Git - thirdparty/kernel/stable.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)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 8 Jan 2026 09:17:02 +0000 (10:17 +0100)
commit 1cb053ea2e1dedd8f2d9653b7c3ca5b93c8c9275 upstream.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/power/supply/max77705_charger.c

index b1a227bf72e26ffcce3cd91b640349e5461289ca..1044bf58aeaca88e51d17b3abff416a1de75d839 100644 (file)
@@ -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");