From nobody Mon May 25 05:56:02 2026 Received: from mta-64-227.siemens.flowmailer.net (mta-64-227.siemens.flowmailer.net [185.136.64.227]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 664FE3E314D for ; Mon, 18 May 2026 08:34:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.136.64.227 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779093288; cv=none; b=nQ907nppDoDQDgkmlHQutnjD47dFU/H6fgExJ+b5Tj2CIXUKpq4Ns8i/2MN5ApGVAGptBkuhlawxEpPf1dNxOmgXTa1O6RpCHxsx7FfMcODxxPVnX/nsMz4BrHNOr1hjZvRbEuQFzcex0qO7/Z61n7xdSIn3BrdqV+6CDIUQekw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779093288; c=relaxed/simple; bh=we1xnXX8MUtA6FfqKhG1wNOnLPLMBgN2q7Nal2yqL4U=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=Vhsm7nmbsv0wQjISExYzDRcLGvG3efQzw/45EFw3mrhTwOJsd/BSbVYbEwBnNRWf2+oLdouRzpS3WsHnhuifdWr2gk4o9Cyexx3kSmmdI5vBVAmwCHuuQC36Bti9t4mhA91JIfxwslxWUnaEi2xibXCEd5LjlXNRf/bDggICiVw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=siemens.com; spf=pass smtp.mailfrom=rts-flowmailer.siemens.com; dkim=pass (2048-bit key) header.d=siemens.com header.i=alexander.sverdlin@siemens.com header.b=HzMGiasL; arc=none smtp.client-ip=185.136.64.227 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=siemens.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rts-flowmailer.siemens.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=siemens.com header.i=alexander.sverdlin@siemens.com header.b="HzMGiasL" Received: by mta-64-227.siemens.flowmailer.net with ESMTPSA id 20260518083435877bd4e5f4000207bb for ; Mon, 18 May 2026 10:34:35 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=alexander.sverdlin@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc; bh=pfjQVAg4y4PH7Vz3fwwpIZnd2n5nYb+HdAus0R/Y2+M=; b=HzMGiasLfFBoRVmeuDGtoKkuCoX1HtCJaVZjpRm2oSUQIwIKUDjMyBl5tFC0+Kq/mgjPl+ krhm/KxpvvLyVdQsyXMG6t+8E32eqwjMKQwAJ7Z7ZmRrJdW8R3f/ca22THoELih4nuxirD2B CVldqgEhA81DOZI3alwAZWITEnraRf6r8oqFtLLv6mnrni10zZUMjiZhTEP5tEsJy0UByV1m 3sXkAAFV1x/caoeiTPxKpC9ChLlDjJ7n7XOiNaGhL4kXbujXc5UFsiN0rlIZ7OL5zYqqzoMY 0aefwxQZq7ulUWFIe8vJ6+hC3vi6ytkF1unc1sQUEX+yaCrsrVqWg7Pg==; From: "A. Sverdlin" To: linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Alexander Sverdlin , Aaro Koskinen , Andreas Kemnade , Kevin Hilman , Roger Quadros , Tony Lindgren , Liam Girdwood , Mark Brown , Shree Ramamoorthy , Francesco Dolcini , Nishanth Menon , Vignesh Raghavendra , stable@vger.kernel.org Subject: [PATCH v2] regulator: tps65219: fix irq_data.rdev not being assigned Date: Mon, 18 May 2026 10:31:11 +0200 Message-ID: <20260518083113.2063368-1-alexander.sverdlin@siemens.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-456497:519-21489:flowmailer Content-Type: text/plain; charset="utf-8" From: Alexander Sverdlin Commit 64a6b577490c ("regulator: tps65219: Remove debugging helper function") removed the tps65219_get_rdev_by_name() helper along with the irq_data.rdev assignment that depended on it. This left irq_data.rdev uninitialized for all IRQs, causing undefined behavior when regulator_notifier_call_chain() is called from the IRQ handler: Internal error: Oops: 0000000096000004 pc : regulator_notifier_call_chain lr : tps65219_regulator_irq_handler Call trace: regulator_notifier_call_chain tps65219_regulator_irq_handler handle_nested_irq regmap_irq_thread irq_thread_fn irq_thread kthread ret_from_fork Instead of restoring a dedicated lookup array, restructure the probe function to combine regulator registration with IRQ registration in the same loop. This way the rdev returned by devm_regulator_register() is naturally available for assigning to irq_data.rdev without any auxiliary data structure. Non-regulator IRQs (SENSOR, TIMEOUT) that don't correspond to any registered regulator are registered with rdev=3DNULL, and the IRQ handler is protected with a NULL check to avoid crashing. Cc: stable@vger.kernel.org Closes: https://lore.kernel.org/all/aBDSTxALaOc-PD7X@gaggiata.pivistrello.i= t/ Reported-by: Francesco Dolcini Fixes: 64a6b577490c ("regulator: tps65219: Remove debugging helper function= ") Signed-off-by: Alexander Sverdlin --- Changelog: v2: - added "Reported-by:"; "Closes:" instead of "Link:"; Cc: stable@... drivers/regulator/tps65219-regulator.c | 135 +++++++++++++++++-------- 1 file changed, 95 insertions(+), 40 deletions(-) diff --git a/drivers/regulator/tps65219-regulator.c b/drivers/regulator/tps= 65219-regulator.c index d77ca486879fd..324c3a33af8a4 100644 --- a/drivers/regulator/tps65219-regulator.c +++ b/drivers/regulator/tps65219-regulator.c @@ -346,8 +346,9 @@ static irqreturn_t tps65219_regulator_irq_handler(int i= rq, void *data) return IRQ_HANDLED; } =20 - regulator_notifier_call_chain(irq_data->rdev, - irq_data->type->event, NULL); + if (irq_data->rdev) + regulator_notifier_call_chain(irq_data->rdev, + irq_data->type->event, NULL); =20 dev_err(irq_data->dev, "Error IRQ trap %s for %s\n", irq_data->type->event_name, irq_data->type->regulator_name); @@ -398,14 +399,65 @@ static struct tps65219_chip_data chip_info_table[] = =3D { }, }; =20 -static int tps65219_regulator_probe(struct platform_device *pdev) +static bool tps65219_is_regulator_name(const struct tps65219_chip_data *pm= ic, + const char *name) +{ + int i; + + for (i =3D 0; i < pmic->common_rdesc_size; i++) + if (!strcmp(pmic->common_rdesc[i].name, name)) + return true; + for (i =3D 0; i < pmic->rdesc_size; i++) + if (!strcmp(pmic->rdesc[i].name, name)) + return true; + return false; +} + +static int tps65219_register_irqs(struct platform_device *pdev, + struct tps65219 *tps, + struct regulator_dev *rdev, + struct tps65219_regulator_irq_type *irq_types, + int nirqs, + const char *regulator_name) { struct tps65219_regulator_irq_data *irq_data; + int i, irq, error; + + for (i =3D 0; i < nirqs; i++) { + if (strcmp(irq_types[i].regulator_name, regulator_name)) + continue; + + irq =3D platform_get_irq_byname(pdev, irq_types[i].irq_name); + if (irq < 0) + return -EINVAL; + + irq_data =3D devm_kmalloc(tps->dev, sizeof(*irq_data), GFP_KERNEL); + if (!irq_data) + return -ENOMEM; + + irq_data->dev =3D tps->dev; + irq_data->type =3D &irq_types[i]; + irq_data->rdev =3D rdev; + + error =3D devm_request_threaded_irq(tps->dev, irq, NULL, + tps65219_regulator_irq_handler, + IRQF_ONESHOT, + irq_types[i].irq_name, + irq_data); + if (error) + return dev_err_probe(tps->dev, error, + "Failed to request %s IRQ %d\n", + irq_types[i].irq_name, irq); + } + return 0; +} + +static int tps65219_regulator_probe(struct platform_device *pdev) +{ struct tps65219_regulator_irq_type *irq_type; struct tps65219_chip_data *pmic; struct regulator_dev *rdev; int error; - int irq; int i; =20 struct tps65219 *tps =3D dev_get_drvdata(pdev->dev.parent); @@ -425,6 +477,19 @@ static int tps65219_regulator_probe(struct platform_de= vice *pdev) return dev_err_probe(tps->dev, PTR_ERR(rdev), "Failed to register %s regulator\n", pmic->common_rdesc[i].name); + + error =3D tps65219_register_irqs(pdev, tps, rdev, + pmic->common_irq_types, + pmic->common_irq_size, + pmic->common_rdesc[i].name); + if (error) + return error; + error =3D tps65219_register_irqs(pdev, tps, rdev, + pmic->irq_types, + pmic->dev_irq_size, + pmic->common_rdesc[i].name); + if (error) + return error; } =20 for (i =3D 0; i < pmic->rdesc_size; i++) { @@ -434,52 +499,42 @@ static int tps65219_regulator_probe(struct platform_d= evice *pdev) return dev_err_probe(tps->dev, PTR_ERR(rdev), "Failed to register %s regulator\n", pmic->rdesc[i].name); + + error =3D tps65219_register_irqs(pdev, tps, rdev, + pmic->common_irq_types, + pmic->common_irq_size, + pmic->rdesc[i].name); + if (error) + return error; + error =3D tps65219_register_irqs(pdev, tps, rdev, + pmic->irq_types, + pmic->dev_irq_size, + pmic->rdesc[i].name); + if (error) + return error; } =20 + /* Register non-regulator IRQs (TIMEOUT, SENSOR) with rdev=3DNULL */ for (i =3D 0; i < pmic->common_irq_size; ++i) { irq_type =3D &pmic->common_irq_types[i]; - irq =3D platform_get_irq_byname(pdev, irq_type->irq_name); - if (irq < 0) - return -EINVAL; - - irq_data =3D devm_kmalloc(tps->dev, sizeof(*irq_data), GFP_KERNEL); - if (!irq_data) - return -ENOMEM; - - irq_data->dev =3D tps->dev; - irq_data->type =3D irq_type; - error =3D devm_request_threaded_irq(tps->dev, irq, NULL, - tps65219_regulator_irq_handler, - IRQF_ONESHOT, - irq_type->irq_name, - irq_data); + if (tps65219_is_regulator_name(pmic, irq_type->regulator_name)) + continue; + error =3D tps65219_register_irqs(pdev, tps, NULL, + irq_type, 1, + irq_type->regulator_name); if (error) - return dev_err_probe(tps->dev, error, - "Failed to request %s IRQ %d\n", - irq_type->irq_name, irq); + return error; } =20 for (i =3D 0; i < pmic->dev_irq_size; ++i) { irq_type =3D &pmic->irq_types[i]; - irq =3D platform_get_irq_byname(pdev, irq_type->irq_name); - if (irq < 0) - return -EINVAL; - - irq_data =3D devm_kmalloc(tps->dev, sizeof(*irq_data), GFP_KERNEL); - if (!irq_data) - return -ENOMEM; - - irq_data->dev =3D tps->dev; - irq_data->type =3D irq_type; - error =3D devm_request_threaded_irq(tps->dev, irq, NULL, - tps65219_regulator_irq_handler, - IRQF_ONESHOT, - irq_type->irq_name, - irq_data); + if (tps65219_is_regulator_name(pmic, irq_type->regulator_name)) + continue; + error =3D tps65219_register_irqs(pdev, tps, NULL, + irq_type, 1, + irq_type->regulator_name); if (error) - return dev_err_probe(tps->dev, error, - "Failed to request %s IRQ %d\n", - irq_type->irq_name, irq); + return error; } =20 return 0; --=20 2.52.0