I marked these as fixes, but the issue is not likely to trigger in normal conditions.
Not tested on hardware, please kindly provide tested-by, the best with some probe bind/unbind cycle.
Best regards, Krzysztof
--- Krzysztof Kozlowski (2): ASoC: codecs: pm4125: Fix potential conflict when probing two devices ASoC: codecs: pm4125: Remove irq_chip on component unbind
sound/soc/codecs/pm4125.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) --- base-commit: d22122bd89bc5ce7b3e057d99679ca50a72a8245 change-id: 20251023-asoc-regmap-irq-chip-bb2053c32168
Best regards,
Qualcomm PM4125 codec is always a single device on the board, however nothing stops board designers to have two of them, thus same device driver could probe twice.
Device driver is not ready for that case, because it allocates statically 'struct regmap_irq_chip' as non-const and stores during component bind in 'irq_drv_data' member a pointer to per-probe state container ('struct pm4125_priv').
Second component bind would overwrite the 'irq_drv_data' from previous device probe, so interrupts would be executed in wrong context.
The fix makes use of currently unused 'struct pm4125_priv' member 'pm4125_regmap_irq_chip', but renames it to a shorter name.
Fixes: 8ad529484937 ("ASoC: codecs: add new pm4125 audio codec driver") Cc: stable@vger.kernel.org Signed-off-by: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org
---
Not tested on hardware --- sound/soc/codecs/pm4125.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/sound/soc/codecs/pm4125.c b/sound/soc/codecs/pm4125.c index e8d00d85106e..410b2fa5246e 100644 --- a/sound/soc/codecs/pm4125.c +++ b/sound/soc/codecs/pm4125.c @@ -70,7 +70,7 @@ struct pm4125_priv { struct wcd_mbhc_config mbhc_cfg; struct wcd_mbhc_intr intr_ids; struct irq_domain *virq; - const struct regmap_irq_chip *pm4125_regmap_irq_chip; + const struct regmap_irq_chip *chip_desc; struct regmap_irq_chip_data *irq_chip; struct snd_soc_jack *jack; unsigned long status_mask; @@ -179,7 +179,7 @@ static const u32 pm4125_config_regs[] = { PM4125_DIG_SWR_INTR_LEVEL_0, };
-static struct regmap_irq_chip pm4125_regmap_irq_chip = { +static const struct regmap_irq_chip pm4125_regmap_irq_chip = { .name = "pm4125", .irqs = pm4125_irqs, .num_irqs = ARRAY_SIZE(pm4125_irqs), @@ -1320,10 +1320,8 @@ static int pm4125_irq_init(struct pm4125_priv *pm4125, struct device *dev) return -EINVAL; }
- pm4125_regmap_irq_chip.irq_drv_data = pm4125; - return devm_regmap_add_irq_chip(dev, pm4125->regmap, irq_create_mapping(pm4125->virq, 0), - IRQF_ONESHOT, 0, &pm4125_regmap_irq_chip, + IRQF_ONESHOT, 0, pm4125->chip_desc, &pm4125->irq_chip); }
@@ -1695,6 +1693,7 @@ static int pm4125_probe(struct platform_device *pdev) { struct component_match *match = NULL; struct device *dev = &pdev->dev; + struct regmap_irq_chip *chip_desc; struct pm4125_priv *pm4125; struct wcd_mbhc_config *cfg; int ret; @@ -1705,6 +1704,14 @@ static int pm4125_probe(struct platform_device *pdev)
dev_set_drvdata(dev, pm4125);
+ chip_desc = devm_kmemdup(dev, &pm4125_regmap_irq_chip, + sizeof(pm4125_regmap_irq_chip), + GFP_KERNEL); + if (!chip_desc) + return -ENOMEM; + chip_desc->irq_drv_data = pm4125; + pm4125->chip_desc = chip_desc; + ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(pm4125_power_supplies), pm4125_power_supplies); if (ret)
Component bind uses devm_regmap_add_irq_chip() to add IRQ chip, so it will be removed only during driver unbind, not component unbind. A component unbind-bind cycle for the same Linux device lifetime would result in two chips added. Fix this by manually removing the IRQ chip during component unbind.
Fixes: 8ad529484937 ("ASoC: codecs: add new pm4125 audio codec driver") Cc: stable@vger.kernel.org Signed-off-by: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org --- sound/soc/codecs/pm4125.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/sound/soc/codecs/pm4125.c b/sound/soc/codecs/pm4125.c index 410b2fa5246e..c5ac2e6bb44d 100644 --- a/sound/soc/codecs/pm4125.c +++ b/sound/soc/codecs/pm4125.c @@ -1658,6 +1658,8 @@ static void pm4125_unbind(struct device *dev) struct pm4125_priv *pm4125 = dev_get_drvdata(dev);
snd_soc_unregister_component(dev); + devm_regmap_del_irq_chip(dev, irq_find_mapping(pm4125->virq, 0), + pm4125->irq_chip); device_link_remove(dev, pm4125->txdev); device_link_remove(dev, pm4125->rxdev); device_link_remove(pm4125->rxdev, pm4125->txdev);
On 23/10/2025 11:02, Krzysztof Kozlowski wrote:
I marked these as fixes, but the issue is not likely to trigger in normal conditions.
Not tested on hardware, please kindly provide tested-by, the best with some probe bind/unbind cycle.
The email prefix should be "RFT", not "RFC". I miss here testing...
Best regards, Krzysztof
linux-stable-mirror@lists.linaro.org