regulator: tps6594-regulator: Fix random kernel crash
authorJerome Neanne <jneanne@baylibre.com>
Tue, 5 Sep 2023 14:07:34 +0000 (16:07 +0200)
committerMark Brown <broonie@kernel.org>
Tue, 5 Sep 2023 19:58:41 +0000 (20:58 +0100)
Random kernel crash detected in TI CICD when regulator driver is added.
This is root caused to irq index increment being done twice causing
irq_data being allocated outside of the range.

- Rework tps6594_request_reg_irqs with correct index increment
- Adjust irq_data kmalloc size to the exact size needed for the device

This has been reported on TI mainline. No public bug report associated.

Reported-by: Udit Kumar <u-kumar1@ti.com>
Fixes: f17ccc5deb4d ("regulator: tps6594-regulator: Add driver for TI TPS6594 regulators")
Signed-off-by: Jerome Neanne <jneanne@baylibre.com>
Link: https://lore.kernel.org/r/20230828-tps6594_random_boot_crash_fix-v1-1-f29cbf9ddb37@baylibre.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/regulator/tps6594-regulator.c

index 25ef102c82707c4becd4e99adcc09852273fc16c..b7f0c87797577eee4d34a9cbb16ccae039559169 100644 (file)
@@ -384,21 +384,19 @@ static int tps6594_request_reg_irqs(struct platform_device *pdev,
                if (irq < 0)
                        return -EINVAL;
 
-               irq_data[*irq_idx + j].dev = tps->dev;
-               irq_data[*irq_idx + j].type = irq_type;
-               irq_data[*irq_idx + j].rdev = rdev;
+               irq_data[*irq_idx].dev = tps->dev;
+               irq_data[*irq_idx].type = irq_type;
+               irq_data[*irq_idx].rdev = rdev;
 
                error = devm_request_threaded_irq(tps->dev, irq, NULL,
-                                                 tps6594_regulator_irq_handler,
-                                                 IRQF_ONESHOT,
-                                                 irq_type->irq_name,
-                                                 &irq_data[*irq_idx]);
-               (*irq_idx)++;
+                                                 tps6594_regulator_irq_handler, IRQF_ONESHOT,
+                                                 irq_type->irq_name, &irq_data[*irq_idx]);
                if (error) {
                        dev_err(tps->dev, "tps6594 failed to request %s IRQ %d: %d\n",
                                irq_type->irq_name, irq, error);
                        return error;
                }
+               (*irq_idx)++;
        }
        return 0;
 }
@@ -420,8 +418,8 @@ static int tps6594_regulator_probe(struct platform_device *pdev)
        int error, i, irq, multi, delta;
        int irq_idx = 0;
        int buck_idx = 0;
-       int ext_reg_irq_nb = 2;
-
+       size_t ext_reg_irq_nb = 2;
+       size_t reg_irq_nb;
        enum {
                MULTI_BUCK12,
                MULTI_BUCK123,
@@ -484,15 +482,16 @@ static int tps6594_regulator_probe(struct platform_device *pdev)
                }
        }
 
-       if (tps->chip_id == LP8764)
+       if (tps->chip_id == LP8764) {
                /* There is only 4 buck on LP8764 */
                buck_configured[4] = 1;
+               reg_irq_nb = size_mul(REGS_INT_NB, (BUCK_NB - 1));
+       } else {
+               reg_irq_nb = size_mul(REGS_INT_NB, (size_add(BUCK_NB, LDO_NB)));
+       }
 
-       irq_data = devm_kmalloc_array(tps->dev,
-                               REGS_INT_NB * sizeof(struct tps6594_regulator_irq_data),
-                               ARRAY_SIZE(tps6594_bucks_irq_types) +
-                               ARRAY_SIZE(tps6594_ldos_irq_types),
-                               GFP_KERNEL);
+       irq_data = devm_kmalloc_array(tps->dev, reg_irq_nb,
+                                     sizeof(struct tps6594_regulator_irq_data), GFP_KERNEL);
        if (!irq_data)
                return -ENOMEM;