--- /dev/null
+From 2196e8172bee2002e9baaa0d02b2f9f2dd213949 Mon Sep 17 00:00:00 2001
+From: Ma Ke <make24@iscas.ac.cn>
+Date: Sun, 16 Nov 2025 11:37:16 +0800
+Subject: ASoC: codecs: Fix error handling in pm4125 audio codec driver
+
+From: Ma Ke <make24@iscas.ac.cn>
+
+commit 2196e8172bee2002e9baaa0d02b2f9f2dd213949 upstream.
+
+pm4125_bind() acquires references through pm4125_sdw_device_get() but
+fails to release them in error paths and during normal unbind
+operations. This could result in reference count leaks, preventing
+proper cleanup and potentially causing resource exhaustion over
+multiple bind/unbind cycles.
+
+Calling path: pm4125_sdw_device_get() -> bus_find_device_by_of_node()
+-> bus_find_device() -> get_device.
+
+Found by code review.
+
+Cc: stable@vger.kernel.org
+Fixes: 8ad529484937 ("ASoC: codecs: add new pm4125 audio codec driver")
+Signed-off-by: Ma Ke <make24@iscas.ac.cn>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+Link: https://patch.msgid.link/20251116033716.29369-1-make24@iscas.ac.cn
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/codecs/pm4125.c | 21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+--- a/sound/soc/codecs/pm4125.c
++++ b/sound/soc/codecs/pm4125.c
+@@ -1549,6 +1549,10 @@ static int pm4125_bind(struct device *de
+ struct device_link *devlink;
+ int ret;
+
++ /* Initialize device pointers to NULL for safe cleanup */
++ pm4125->rxdev = NULL;
++ pm4125->txdev = NULL;
++
+ /* Give the soundwire subdevices some more time to settle */
+ usleep_range(15000, 15010);
+
+@@ -1572,7 +1576,7 @@ static int pm4125_bind(struct device *de
+ if (!pm4125->txdev) {
+ dev_err(dev, "could not find txslave with matching of node\n");
+ ret = -EINVAL;
+- goto error_unbind_all;
++ goto error_put_rx;
+ }
+
+ pm4125->sdw_priv[AIF1_CAP] = dev_get_drvdata(pm4125->txdev);
+@@ -1582,7 +1586,7 @@ static int pm4125_bind(struct device *de
+ if (!pm4125->tx_sdw_dev) {
+ dev_err(dev, "could not get txslave with matching of dev\n");
+ ret = -EINVAL;
+- goto error_unbind_all;
++ goto error_put_tx;
+ }
+
+ /*
+@@ -1594,7 +1598,7 @@ static int pm4125_bind(struct device *de
+ if (!devlink) {
+ dev_err(dev, "Could not devlink TX and RX\n");
+ ret = -EINVAL;
+- goto error_unbind_all;
++ goto error_put_tx;
+ }
+
+ devlink = device_link_add(dev, pm4125->txdev,
+@@ -1648,6 +1652,10 @@ link_remove_dev_tx:
+ device_link_remove(dev, pm4125->txdev);
+ link_remove_rx_tx:
+ device_link_remove(pm4125->rxdev, pm4125->txdev);
++error_put_tx:
++ put_device(pm4125->txdev);
++error_put_rx:
++ put_device(pm4125->rxdev);
+ error_unbind_all:
+ component_unbind_all(dev, pm4125);
+ return ret;
+@@ -1663,6 +1671,13 @@ static void pm4125_unbind(struct device
+ device_link_remove(dev, pm4125->txdev);
+ device_link_remove(dev, pm4125->rxdev);
+ device_link_remove(pm4125->rxdev, pm4125->txdev);
++
++ /* Release device references acquired in bind */
++ if (pm4125->txdev)
++ put_device(pm4125->txdev);
++ if (pm4125->rxdev)
++ put_device(pm4125->rxdev);
++
+ component_unbind_all(dev, pm4125);
+ }
+
--- /dev/null
+From 7c63b5a8ed972a2c8c03d984f6a43349007cea93 Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
+Date: Fri, 31 Oct 2025 12:06:58 +0000
+Subject: ASoC: codecs: lpass-tx-macro: fix SM6115 support
+
+From: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
+
+commit 7c63b5a8ed972a2c8c03d984f6a43349007cea93 upstream.
+
+SM6115 does have soundwire controller in tx. For some reason
+we ended up with this incorrect patch.
+
+Fix this by adding the flag to reflect this in SoC data.
+
+Fixes: 510c46884299 ("ASoC: codecs: lpass-tx-macro: Add SM6115 support")
+Cc: Stable@vger.kernel.org
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
+Link: https://patch.msgid.link/20251031120703.590201-2-srinivas.kandagatla@oss.qualcomm.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/codecs/lpass-tx-macro.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/sound/soc/codecs/lpass-tx-macro.c
++++ b/sound/soc/codecs/lpass-tx-macro.c
+@@ -2473,7 +2473,8 @@ static const struct tx_macro_data lpass_
+ };
+
+ static const struct tx_macro_data lpass_ver_10_sm6115 = {
+- .flags = LPASS_MACRO_FLAG_HAS_NPL_CLOCK,
++ .flags = LPASS_MACRO_FLAG_HAS_NPL_CLOCK |
++ LPASS_MACRO_FLAG_RESET_SWR,
+ .ver = LPASS_VER_10_0_0,
+ .extra_widgets = tx_macro_dapm_widgets_v9_2,
+ .extra_widgets_num = ARRAY_SIZE(tx_macro_dapm_widgets_v9_2),
--- /dev/null
+From fd94857a934cbe613353810a024c84d54826ead3 Mon Sep 17 00:00:00 2001
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Date: Thu, 23 Oct 2025 11:02:50 +0200
+Subject: ASoC: codecs: pm4125: Fix potential conflict when probing two devices
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+commit fd94857a934cbe613353810a024c84d54826ead3 upstream.
+
+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>
+Link: https://patch.msgid.link/20251023-asoc-regmap-irq-chip-v1-1-17ad32680913@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/codecs/pm4125.c | 17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+--- 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
+ 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_
+ {
+ 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_
+
+ 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)
--- /dev/null
+From e65b871c9b5af9265aefc5b8cd34993586d93aab Mon Sep 17 00:00:00 2001
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Date: Thu, 23 Oct 2025 11:02:51 +0200
+Subject: ASoC: codecs: pm4125: Remove irq_chip on component unbind
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+commit e65b871c9b5af9265aefc5b8cd34993586d93aab upstream.
+
+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>
+Link: https://patch.msgid.link/20251023-asoc-regmap-irq-chip-v1-2-17ad32680913@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/codecs/pm4125.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/sound/soc/codecs/pm4125.c
++++ b/sound/soc/codecs/pm4125.c
+@@ -1658,6 +1658,8 @@ static void pm4125_unbind(struct device
+ 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);
--- /dev/null
+From 578ccfe344c5f421c2c6343b872995b397ffd3ff Mon Sep 17 00:00:00 2001
+From: Ma Ke <make24@iscas.ac.cn>
+Date: Sun, 16 Nov 2025 14:16:23 +0800
+Subject: ASoC: codecs: wcd937x: Fix error handling in wcd937x codec driver
+
+From: Ma Ke <make24@iscas.ac.cn>
+
+commit 578ccfe344c5f421c2c6343b872995b397ffd3ff upstream.
+
+In wcd937x_bind(), the driver calls of_sdw_find_device_by_node() to
+obtain references to RX and TX SoundWire devices, which increment the
+device reference counts. However, the corresponding put_device() are
+missing in both the error paths and the normal unbind path in
+wcd937x_unbind().
+
+Add proper error handling with put_device() calls in all error paths
+of wcd937x_bind() and ensure devices are released in wcd937x_unbind().
+
+Found by code review.
+
+Cc: stable@vger.kernel.org
+Fixes: 772ed12bd04e ("ASoC: codecs: wcdxxxx: use of_sdw_find_device_by_node helper")
+Signed-off-by: Ma Ke <make24@iscas.ac.cn>
+Reviewed-by: David Heidelberg <david@ixit.cz>
+Link: https://patch.msgid.link/20251116061623.11830-1-make24@iscas.ac.cn
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/codecs/wcd937x.c | 43 ++++++++++++++++++++++++++++++++++---------
+ 1 file changed, 34 insertions(+), 9 deletions(-)
+
+--- a/sound/soc/codecs/wcd937x.c
++++ b/sound/soc/codecs/wcd937x.c
+@@ -2748,7 +2748,8 @@ static int wcd937x_bind(struct device *d
+ wcd937x->rxdev = of_sdw_find_device_by_node(wcd937x->rxnode);
+ if (!wcd937x->rxdev) {
+ dev_err(dev, "could not find slave with matching of node\n");
+- return -EINVAL;
++ ret = -EINVAL;
++ goto err_component_unbind;
+ }
+
+ wcd937x->sdw_priv[AIF1_PB] = dev_get_drvdata(wcd937x->rxdev);
+@@ -2757,7 +2758,8 @@ static int wcd937x_bind(struct device *d
+ wcd937x->txdev = of_sdw_find_device_by_node(wcd937x->txnode);
+ if (!wcd937x->txdev) {
+ dev_err(dev, "could not find txslave with matching of node\n");
+- return -EINVAL;
++ ret = -EINVAL;
++ goto err_put_rxdev;
+ }
+
+ wcd937x->sdw_priv[AIF1_CAP] = dev_get_drvdata(wcd937x->txdev);
+@@ -2765,7 +2767,8 @@ static int wcd937x_bind(struct device *d
+ wcd937x->tx_sdw_dev = dev_to_sdw_dev(wcd937x->txdev);
+ if (!wcd937x->tx_sdw_dev) {
+ dev_err(dev, "could not get txslave with matching of dev\n");
+- return -EINVAL;
++ ret = -EINVAL;
++ goto err_put_txdev;
+ }
+
+ /*
+@@ -2775,31 +2778,35 @@ static int wcd937x_bind(struct device *d
+ if (!device_link_add(wcd937x->rxdev, wcd937x->txdev,
+ DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME)) {
+ dev_err(dev, "Could not devlink TX and RX\n");
+- return -EINVAL;
++ ret = -EINVAL;
++ goto err_put_txdev;
+ }
+
+ if (!device_link_add(dev, wcd937x->txdev,
+ DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME)) {
+ dev_err(dev, "Could not devlink WCD and TX\n");
+- return -EINVAL;
++ ret = -EINVAL;
++ goto err_remove_link1;
+ }
+
+ if (!device_link_add(dev, wcd937x->rxdev,
+ DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME)) {
+ dev_err(dev, "Could not devlink WCD and RX\n");
+- return -EINVAL;
++ ret = -EINVAL;
++ goto err_remove_link2;
+ }
+
+ wcd937x->regmap = wcd937x->sdw_priv[AIF1_CAP]->regmap;
+ if (!wcd937x->regmap) {
+ dev_err(dev, "could not get TX device regmap\n");
+- return -EINVAL;
++ ret = -EINVAL;
++ goto err_remove_link3;
+ }
+
+ ret = wcd937x_irq_init(wcd937x, dev);
+ if (ret) {
+ dev_err(dev, "IRQ init failed: %d\n", ret);
+- return ret;
++ goto err_remove_link3;
+ }
+
+ wcd937x->sdw_priv[AIF1_PB]->slave_irq = wcd937x->virq;
+@@ -2809,9 +2816,25 @@ static int wcd937x_bind(struct device *d
+
+ ret = snd_soc_register_component(dev, &soc_codec_dev_wcd937x,
+ wcd937x_dais, ARRAY_SIZE(wcd937x_dais));
+- if (ret)
++ if (ret) {
+ dev_err(dev, "Codec registration failed\n");
++ goto err_remove_link3;
++ }
++
++ return ret;
+
++err_remove_link3:
++ device_link_remove(dev, wcd937x->rxdev);
++err_remove_link2:
++ device_link_remove(dev, wcd937x->txdev);
++err_remove_link1:
++ device_link_remove(wcd937x->rxdev, wcd937x->txdev);
++err_put_txdev:
++ put_device(wcd937x->txdev);
++err_put_rxdev:
++ put_device(wcd937x->rxdev);
++err_component_unbind:
++ component_unbind_all(dev, wcd937x);
+ return ret;
+ }
+
+@@ -2825,6 +2848,8 @@ static void wcd937x_unbind(struct device
+ device_link_remove(wcd937x->rxdev, wcd937x->txdev);
+ component_unbind_all(dev, wcd937x);
+ mutex_destroy(&wcd937x->micb_lock);
++ put_device(wcd937x->txdev);
++ put_device(wcd937x->rxdev);
+ }
+
+ static const struct component_master_ops wcd937x_comp_ops = {
--- /dev/null
+From 86dc090f737953f16f8dc60c546ae7854690d4f6 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Thu, 27 Nov 2025 14:50:57 +0100
+Subject: ASoC: codecs: wcd939x: fix regmap leak on probe failure
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 86dc090f737953f16f8dc60c546ae7854690d4f6 upstream.
+
+The soundwire regmap that may be allocated during probe is not freed on
+late probe failures.
+
+Add the missing error handling.
+
+Fixes: be2af391cea0 ("ASoC: codecs: Add WCD939x Soundwire devices driver")
+Cc: stable@vger.kernel.org # 6.9
+Cc: Neil Armstrong <neil.armstrong@linaro.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Link: https://patch.msgid.link/20251127135057.2216-1-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/codecs/wcd939x-sdw.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/sound/soc/codecs/wcd939x-sdw.c
++++ b/sound/soc/codecs/wcd939x-sdw.c
+@@ -1400,12 +1400,18 @@ static int wcd9390_probe(struct sdw_slav
+
+ ret = component_add(dev, &wcd_sdw_component_ops);
+ if (ret)
+- return ret;
++ goto err_free_regmap;
+
+ /* Set suspended until aggregate device is bind */
+ pm_runtime_set_suspended(dev);
+
+ return 0;
++
++err_free_regmap:
++ if (wcd->regmap)
++ regmap_exit(wcd->regmap);
++
++ return ret;
+ }
+
+ static int wcd9390_remove(struct sdw_slave *pdev)
--- /dev/null
+From b0ff70e9d4fe46cece25eb97b9b9b0166624af95 Mon Sep 17 00:00:00 2001
+From: Eric Naim <dnaim@cachyos.org>
+Date: Sun, 7 Dec 2025 03:38:12 +0800
+Subject: ASoC: cs35l41: Always return 0 when a subsystem ID is found
+
+From: Eric Naim <dnaim@cachyos.org>
+
+commit b0ff70e9d4fe46cece25eb97b9b9b0166624af95 upstream.
+
+When trying to get the system name in the _HID path, after successfully
+retrieving the subsystem ID the return value isn't set to 0 but instead
+still kept at -ENODATA, leading to a false negative:
+
+[ 12.382507] cs35l41 spi-VLV1776:00: Subsystem ID: VLV1776
+[ 12.382521] cs35l41 spi-VLV1776:00: probe with driver cs35l41 failed with error -61
+
+Always return 0 when a subsystem ID is found to mitigate these false
+negatives.
+
+Link: https://github.com/CachyOS/CachyOS-Handheld/issues/83
+Fixes: 46c8b4d2a693 ("ASoC: cs35l41: Fallback to reading Subsystem ID property if not ACPI")
+Cc: stable@vger.kernel.org # 6.18
+Signed-off-by: Eric Naim <dnaim@cachyos.org>
+Reviewed-by: Richard Fitzgerald <rf@opensource.cirrus.com>
+Link: https://patch.msgid.link/20251206193813.56955-1-dnaim@cachyos.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/codecs/cs35l41.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
+index 3a8a8dd065b7..ee56dfceedeb 100644
+--- a/sound/soc/codecs/cs35l41.c
++++ b/sound/soc/codecs/cs35l41.c
+@@ -1188,13 +1188,14 @@ static int cs35l41_get_system_name(struct cs35l41_private *cs35l41)
+ }
+ }
+
+-err:
+ if (sub) {
+ cs35l41->dsp.system_name = sub;
+ dev_info(cs35l41->dev, "Subsystem ID: %s\n", cs35l41->dsp.system_name);
+- } else
+- dev_warn(cs35l41->dev, "Subsystem ID not found\n");
++ return 0;
++ }
+
++err:
++ dev_warn(cs35l41->dev, "Subsystem ID not found\n");
+ return ret;
+ }
+
+--
+2.52.0
+
--- /dev/null
+From 74cc4f3ea4e99262ba0d619c6a4ee33e2cd47f65 Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
+Date: Thu, 23 Oct 2025 11:24:26 +0100
+Subject: ASoC: qcom: q6adm: the the copp device only during last instance
+
+From: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
+
+commit 74cc4f3ea4e99262ba0d619c6a4ee33e2cd47f65 upstream.
+
+A matching Common object post processing instance is normally resused
+across multiple streams. However currently we close this on DSP
+even though there is a refcount on this copp object, this can result in
+below error.
+
+q6routing ab00000.remoteproc:glink-edge:apr:service@8:routing: Found Matching Copp 0x0
+qcom-q6adm aprsvc:service:4:8: cmd = 0x10325 return error = 0x2
+q6routing ab00000.remoteproc:glink-edge:apr:service@8:routing: DSP returned error[2]
+q6routing ab00000.remoteproc:glink-edge:apr:service@8:routing: Found Matching Copp 0x0
+qcom-q6adm aprsvc:service:4:8: cmd = 0x10325 return error = 0x2
+q6routing ab00000.remoteproc:glink-edge:apr:service@8:routing: DSP returned error[2]
+qcom-q6adm aprsvc:service:4:8: cmd = 0x10327 return error = 0x2
+qcom-q6adm aprsvc:service:4:8: DSP returned error[2]
+qcom-q6adm aprsvc:service:4:8: Failed to close copp -22
+qcom-q6adm aprsvc:service:4:8: cmd = 0x10327 return error = 0x2
+qcom-q6adm aprsvc:service:4:8: DSP returned error[2]
+qcom-q6adm aprsvc:service:4:8: Failed to close copp -22
+
+Fix this by addressing moving the adm_close to copp_kref destructor
+callback.
+
+Fixes: 7b20b2be51e1 ("ASoC: qdsp6: q6adm: Add q6adm driver")
+Cc: Stable@vger.kernel.org
+Reported-by: Martino Facchin <m.facchin@arduino.cc>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
+Tested-by: Alexey Klimov <alexey.klimov@linaro.org> # RB5, RB3
+Link: https://patch.msgid.link/20251023102444.88158-3-srinivas.kandagatla@oss.qualcomm.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/qcom/qdsp6/q6adm.c | 146 ++++++++++++++++++++-----------------------
+ 1 file changed, 71 insertions(+), 75 deletions(-)
+
+--- a/sound/soc/qcom/qdsp6/q6adm.c
++++ b/sound/soc/qcom/qdsp6/q6adm.c
+@@ -109,11 +109,75 @@ static struct q6copp *q6adm_find_copp(st
+
+ }
+
++static int q6adm_apr_send_copp_pkt(struct q6adm *adm, struct q6copp *copp,
++ struct apr_pkt *pkt, uint32_t rsp_opcode)
++{
++ struct device *dev = adm->dev;
++ uint32_t opcode = pkt->hdr.opcode;
++ int ret;
++
++ mutex_lock(&adm->lock);
++ copp->result.opcode = 0;
++ copp->result.status = 0;
++ ret = apr_send_pkt(adm->apr, pkt);
++ if (ret < 0) {
++ dev_err(dev, "Failed to send APR packet\n");
++ ret = -EINVAL;
++ goto err;
++ }
++
++ /* Wait for the callback with copp id */
++ if (rsp_opcode)
++ ret = wait_event_timeout(copp->wait,
++ (copp->result.opcode == opcode) ||
++ (copp->result.opcode == rsp_opcode),
++ msecs_to_jiffies(TIMEOUT_MS));
++ else
++ ret = wait_event_timeout(copp->wait,
++ (copp->result.opcode == opcode),
++ msecs_to_jiffies(TIMEOUT_MS));
++
++ if (!ret) {
++ dev_err(dev, "ADM copp cmd timedout\n");
++ ret = -ETIMEDOUT;
++ } else if (copp->result.status > 0) {
++ dev_err(dev, "DSP returned error[%d]\n",
++ copp->result.status);
++ ret = -EINVAL;
++ }
++
++err:
++ mutex_unlock(&adm->lock);
++ return ret;
++}
++
++static int q6adm_device_close(struct q6adm *adm, struct q6copp *copp,
++ int port_id, int copp_idx)
++{
++ struct apr_pkt close;
++
++ close.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
++ APR_HDR_LEN(APR_HDR_SIZE),
++ APR_PKT_VER);
++ close.hdr.pkt_size = sizeof(close);
++ close.hdr.src_port = port_id;
++ close.hdr.dest_port = copp->id;
++ close.hdr.token = port_id << 16 | copp_idx;
++ close.hdr.opcode = ADM_CMD_DEVICE_CLOSE_V5;
++
++ return q6adm_apr_send_copp_pkt(adm, copp, &close, 0);
++}
++
+ static void q6adm_free_copp(struct kref *ref)
+ {
+ struct q6copp *c = container_of(ref, struct q6copp, refcount);
+ struct q6adm *adm = c->adm;
+ unsigned long flags;
++ int ret;
++
++ ret = q6adm_device_close(adm, c, c->afe_port, c->copp_idx);
++ if (ret < 0)
++ dev_err(adm->dev, "Failed to close copp %d\n", ret);
+
+ spin_lock_irqsave(&adm->copps_list_lock, flags);
+ clear_bit(c->copp_idx, &adm->copp_bitmap[c->afe_port]);
+@@ -155,13 +219,13 @@ static int q6adm_callback(struct apr_dev
+ switch (result->opcode) {
+ case ADM_CMD_DEVICE_OPEN_V5:
+ case ADM_CMD_DEVICE_CLOSE_V5:
+- copp = q6adm_find_copp(adm, port_idx, copp_idx);
+- if (!copp)
+- return 0;
+-
+- copp->result = *result;
+- wake_up(&copp->wait);
+- kref_put(&copp->refcount, q6adm_free_copp);
++ list_for_each_entry(copp, &adm->copps_list, node) {
++ if ((port_idx == copp->afe_port) && (copp_idx == copp->copp_idx)) {
++ copp->result = *result;
++ wake_up(&copp->wait);
++ break;
++ }
++ }
+ break;
+ case ADM_CMD_MATRIX_MAP_ROUTINGS_V5:
+ adm->result = *result;
+@@ -234,65 +298,6 @@ static struct q6copp *q6adm_alloc_copp(s
+ return c;
+ }
+
+-static int q6adm_apr_send_copp_pkt(struct q6adm *adm, struct q6copp *copp,
+- struct apr_pkt *pkt, uint32_t rsp_opcode)
+-{
+- struct device *dev = adm->dev;
+- uint32_t opcode = pkt->hdr.opcode;
+- int ret;
+-
+- mutex_lock(&adm->lock);
+- copp->result.opcode = 0;
+- copp->result.status = 0;
+- ret = apr_send_pkt(adm->apr, pkt);
+- if (ret < 0) {
+- dev_err(dev, "Failed to send APR packet\n");
+- ret = -EINVAL;
+- goto err;
+- }
+-
+- /* Wait for the callback with copp id */
+- if (rsp_opcode)
+- ret = wait_event_timeout(copp->wait,
+- (copp->result.opcode == opcode) ||
+- (copp->result.opcode == rsp_opcode),
+- msecs_to_jiffies(TIMEOUT_MS));
+- else
+- ret = wait_event_timeout(copp->wait,
+- (copp->result.opcode == opcode),
+- msecs_to_jiffies(TIMEOUT_MS));
+-
+- if (!ret) {
+- dev_err(dev, "ADM copp cmd timedout\n");
+- ret = -ETIMEDOUT;
+- } else if (copp->result.status > 0) {
+- dev_err(dev, "DSP returned error[%d]\n",
+- copp->result.status);
+- ret = -EINVAL;
+- }
+-
+-err:
+- mutex_unlock(&adm->lock);
+- return ret;
+-}
+-
+-static int q6adm_device_close(struct q6adm *adm, struct q6copp *copp,
+- int port_id, int copp_idx)
+-{
+- struct apr_pkt close;
+-
+- close.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+- APR_HDR_LEN(APR_HDR_SIZE),
+- APR_PKT_VER);
+- close.hdr.pkt_size = sizeof(close);
+- close.hdr.src_port = port_id;
+- close.hdr.dest_port = copp->id;
+- close.hdr.token = port_id << 16 | copp_idx;
+- close.hdr.opcode = ADM_CMD_DEVICE_CLOSE_V5;
+-
+- return q6adm_apr_send_copp_pkt(adm, copp, &close, 0);
+-}
+-
+ static struct q6copp *q6adm_find_matching_copp(struct q6adm *adm,
+ int port_id, int topology,
+ int mode, int rate,
+@@ -567,15 +572,6 @@ EXPORT_SYMBOL_GPL(q6adm_matrix_map);
+ */
+ int q6adm_close(struct device *dev, struct q6copp *copp)
+ {
+- struct q6adm *adm = dev_get_drvdata(dev->parent);
+- int ret = 0;
+-
+- ret = q6adm_device_close(adm, copp, copp->afe_port, copp->copp_idx);
+- if (ret < 0) {
+- dev_err(adm->dev, "Failed to close copp %d\n", ret);
+- return ret;
+- }
+-
+ kref_put(&copp->refcount, q6adm_free_copp);
+
+ return 0;
--- /dev/null
+From 950a4e5788fc7dc6e8e93614a7d4d0449c39fb8d Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
+Date: Thu, 23 Oct 2025 11:24:25 +0100
+Subject: ASoC: qcom: q6apm-dai: set flags to reflect correct operation of appl_ptr
+
+From: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
+
+commit 950a4e5788fc7dc6e8e93614a7d4d0449c39fb8d upstream.
+
+Driver does not expect the appl_ptr to move backward and requires
+explict sync. Make sure that the userspace does not do appl_ptr rewinds
+by specifying the correct flags in pcm_info.
+
+Without this patch, the result could be a forever loop as current logic assumes
+that appl_ptr can only move forward.
+
+Fixes: 3d4a4411aa8b ("ASoC: q6apm-dai: schedule all available frames to avoid dsp under-runs")
+Cc: Stable@vger.kernel.org
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
+Tested-by: Alexey Klimov <alexey.klimov@linaro.org> # RB5, RB3
+Link: https://patch.msgid.link/20251023102444.88158-2-srinivas.kandagatla@oss.qualcomm.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/qcom/qdsp6/q6apm-dai.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/sound/soc/qcom/qdsp6/q6apm-dai.c
++++ b/sound/soc/qcom/qdsp6/q6apm-dai.c
+@@ -86,6 +86,7 @@ static const struct snd_pcm_hardware q6a
+ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME |
++ SNDRV_PCM_INFO_NO_REWINDS | SNDRV_PCM_INFO_SYNC_APPLPTR |
+ SNDRV_PCM_INFO_BATCH),
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE),
+ .rates = SNDRV_PCM_RATE_8000_48000,
+@@ -105,6 +106,7 @@ static const struct snd_pcm_hardware q6a
+ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME |
++ SNDRV_PCM_INFO_NO_REWINDS | SNDRV_PCM_INFO_SYNC_APPLPTR |
+ SNDRV_PCM_INFO_BATCH),
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE),
+ .rates = SNDRV_PCM_RATE_8000_192000,
--- /dev/null
+From bfbb12dfa144d45575bcfe139a71360b3ce80237 Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
+Date: Thu, 23 Oct 2025 11:24:28 +0100
+Subject: ASoC: qcom: q6asm-dai: perform correct state check before closing
+
+From: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
+
+commit bfbb12dfa144d45575bcfe139a71360b3ce80237 upstream.
+
+Do not stop a q6asm stream if its not started, this can result in
+unnecessary dsp command which will timeout anyway something like below:
+
+q6asm-dai ab00000.remoteproc:glink-edge:apr:service@7:dais: CMD 10bcd timeout
+
+Fix this by correctly checking the state.
+
+Fixes: 2a9e92d371db ("ASoC: qdsp6: q6asm: Add q6asm dai driver")
+Cc: Stable@vger.kernel.org
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
+Tested-by: Alexey Klimov <alexey.klimov@linaro.org> # RB5, RB3
+Link: https://patch.msgid.link/20251023102444.88158-5-srinivas.kandagatla@oss.qualcomm.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/qcom/qdsp6/q6asm-dai.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/sound/soc/qcom/qdsp6/q6asm-dai.c
++++ b/sound/soc/qcom/qdsp6/q6asm-dai.c
+@@ -233,13 +233,14 @@ static int q6asm_dai_prepare(struct snd_
+ prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
+ prtd->pcm_irq_pos = 0;
+ /* rate and channels are sent to audio driver */
+- if (prtd->state) {
++ if (prtd->state == Q6ASM_STREAM_RUNNING) {
+ /* clear the previous setup if any */
+ q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
+ q6asm_unmap_memory_regions(substream->stream,
+ prtd->audio_client);
+ q6routing_stream_close(soc_prtd->dai_link->id,
+ substream->stream);
++ prtd->state = Q6ASM_STREAM_STOPPED;
+ }
+
+ ret = q6asm_map_memory_regions(substream->stream, prtd->audio_client,
--- /dev/null
+From 81c53b52de21b8d5a3de55ebd06b6bf188bf7efd Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
+Date: Thu, 23 Oct 2025 11:24:27 +0100
+Subject: ASoC: qcom: qdsp6: q6asm-dai: set 10 ms period and buffer alignment.
+
+From: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
+
+commit 81c53b52de21b8d5a3de55ebd06b6bf188bf7efd upstream.
+
+DSP expects the periods to be aligned to fragment sizes, currently
+setting up to hw constriants on periods bytes is not going to work
+correctly as we can endup with periods sizes aligned to 32 bytes however
+not aligned to fragment size.
+
+Update the constriants to use fragment size, and also set at step of
+10ms for period size to accommodate DSP requirements of 10ms latency.
+
+Fixes: 2a9e92d371db ("ASoC: qdsp6: q6asm: Add q6asm dai driver")
+Cc: Stable@vger.kernel.org
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
+Tested-by: Alexey Klimov <alexey.klimov@linaro.org> # RB5, RB3
+Link: https://patch.msgid.link/20251023102444.88158-4-srinivas.kandagatla@oss.qualcomm.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/qcom/qdsp6/q6asm-dai.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/sound/soc/qcom/qdsp6/q6asm-dai.c
++++ b/sound/soc/qcom/qdsp6/q6asm-dai.c
+@@ -404,13 +404,13 @@ static int q6asm_dai_open(struct snd_soc
+ }
+
+ ret = snd_pcm_hw_constraint_step(runtime, 0,
+- SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
++ SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 480);
+ if (ret < 0) {
+ dev_err(dev, "constraint for period bytes step ret = %d\n",
+ ret);
+ }
+ ret = snd_pcm_hw_constraint_step(runtime, 0,
+- SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
++ SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 480);
+ if (ret < 0) {
+ dev_err(dev, "constraint for buffer bytes step ret = %d\n",
+ ret);
--- /dev/null
+From bcba17279327c6e85dee6a97014dc642e2dc93cc Mon Sep 17 00:00:00 2001
+From: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
+Date: Wed, 22 Oct 2025 15:33:46 +0100
+Subject: ASoC: qcom: sdw: fix memory leak for sdw_stream_runtime
+
+From: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
+
+commit bcba17279327c6e85dee6a97014dc642e2dc93cc upstream.
+
+For some reason we endedup allocating sdw_stream_runtime for every cpu dai,
+this has two issues.
+1. we never set snd_soc_dai_set_stream for non soundwire dai, which
+ means there is no way that we can free this, resulting in memory leak
+2. startup and shutdown callbacks can be called without
+ hw_params callback called. This combination results in memory leak
+because machine driver sruntime array pointer is only set in hw_params
+callback.
+
+Fix this by
+ 1. adding a helper function to get sdw_runtime for substream
+which can be used by shutdown callback to get hold of sruntime to free.
+ 2. only allocate sdw_runtime for soundwire dais.
+
+Fixes: d32bac9cb09c ("ASoC: qcom: Add helper for allocating Soundwire stream runtime")
+Cc: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Cc: Stable@vger.kernel.org
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
+Tested-by: Steev Klimaszewski <threeway@gmail.com> # Thinkpad X13s
+Link: https://patch.msgid.link/20251022143349.1081513-2-srinivas.kandagatla@oss.qualcomm.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/qcom/sc7280.c | 2
+ sound/soc/qcom/sc8280xp.c | 2
+ sound/soc/qcom/sdw.c | 105 +++++++++++++++++++++++++---------------------
+ sound/soc/qcom/sdw.h | 1
+ sound/soc/qcom/sm8250.c | 2
+ sound/soc/qcom/x1e80100.c | 2
+ 6 files changed, 64 insertions(+), 50 deletions(-)
+
+--- a/sound/soc/qcom/sc7280.c
++++ b/sound/soc/qcom/sc7280.c
+@@ -317,7 +317,7 @@ static void sc7280_snd_shutdown(struct s
+ struct snd_soc_card *card = rtd->card;
+ struct sc7280_snd_data *data = snd_soc_card_get_drvdata(card);
+ struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+- struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
++ struct sdw_stream_runtime *sruntime = qcom_snd_sdw_get_stream(substream);
+
+ switch (cpu_dai->id) {
+ case MI2S_PRIMARY:
+--- a/sound/soc/qcom/sc8280xp.c
++++ b/sound/soc/qcom/sc8280xp.c
+@@ -73,7 +73,7 @@ static void sc8280xp_snd_shutdown(struct
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+ struct sc8280xp_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card);
+- struct sdw_stream_runtime *sruntime = pdata->sruntime[cpu_dai->id];
++ struct sdw_stream_runtime *sruntime = qcom_snd_sdw_get_stream(substream);
+
+ pdata->sruntime[cpu_dai->id] = NULL;
+ sdw_release_stream(sruntime);
+--- a/sound/soc/qcom/sdw.c
++++ b/sound/soc/qcom/sdw.c
+@@ -7,6 +7,37 @@
+ #include <sound/soc.h>
+ #include "sdw.h"
+
++static bool qcom_snd_is_sdw_dai(int id)
++{
++ switch (id) {
++ case WSA_CODEC_DMA_RX_0:
++ case WSA_CODEC_DMA_TX_0:
++ case WSA_CODEC_DMA_RX_1:
++ case WSA_CODEC_DMA_TX_1:
++ case WSA_CODEC_DMA_TX_2:
++ case RX_CODEC_DMA_RX_0:
++ case TX_CODEC_DMA_TX_0:
++ case RX_CODEC_DMA_RX_1:
++ case TX_CODEC_DMA_TX_1:
++ case RX_CODEC_DMA_RX_2:
++ case TX_CODEC_DMA_TX_2:
++ case RX_CODEC_DMA_RX_3:
++ case TX_CODEC_DMA_TX_3:
++ case RX_CODEC_DMA_RX_4:
++ case TX_CODEC_DMA_TX_4:
++ case RX_CODEC_DMA_RX_5:
++ case TX_CODEC_DMA_TX_5:
++ case RX_CODEC_DMA_RX_6:
++ case RX_CODEC_DMA_RX_7:
++ case SLIMBUS_0_RX...SLIMBUS_6_TX:
++ return true;
++ default:
++ break;
++ }
++
++ return false;
++}
++
+ /**
+ * qcom_snd_sdw_startup() - Helper to start Soundwire stream for SoC audio card
+ * @substream: The PCM substream from audio, as passed to snd_soc_ops->startup()
+@@ -29,6 +60,9 @@ int qcom_snd_sdw_startup(struct snd_pcm_
+ u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
+ int ret, i, j;
+
++ if (!qcom_snd_is_sdw_dai(cpu_dai->id))
++ return 0;
++
+ sruntime = sdw_alloc_stream(cpu_dai->name, SDW_STREAM_PCM);
+ if (!sruntime)
+ return -ENOMEM;
+@@ -89,19 +123,8 @@ int qcom_snd_sdw_prepare(struct snd_pcm_
+ if (!sruntime)
+ return 0;
+
+- switch (cpu_dai->id) {
+- case WSA_CODEC_DMA_RX_0:
+- case WSA_CODEC_DMA_RX_1:
+- case RX_CODEC_DMA_RX_0:
+- case RX_CODEC_DMA_RX_1:
+- case TX_CODEC_DMA_TX_0:
+- case TX_CODEC_DMA_TX_1:
+- case TX_CODEC_DMA_TX_2:
+- case TX_CODEC_DMA_TX_3:
+- break;
+- default:
++ if (!qcom_snd_is_sdw_dai(cpu_dai->id))
+ return 0;
+- }
+
+ if (*stream_prepared)
+ return 0;
+@@ -129,9 +152,7 @@ int qcom_snd_sdw_prepare(struct snd_pcm_
+ }
+ EXPORT_SYMBOL_GPL(qcom_snd_sdw_prepare);
+
+-int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
+- struct snd_pcm_hw_params *params,
+- struct sdw_stream_runtime **psruntime)
++struct sdw_stream_runtime *qcom_snd_sdw_get_stream(struct snd_pcm_substream *substream)
+ {
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct snd_soc_dai *codec_dai;
+@@ -139,21 +160,23 @@ int qcom_snd_sdw_hw_params(struct snd_pc
+ struct sdw_stream_runtime *sruntime;
+ int i;
+
+- switch (cpu_dai->id) {
+- case WSA_CODEC_DMA_RX_0:
+- case RX_CODEC_DMA_RX_0:
+- case RX_CODEC_DMA_RX_1:
+- case TX_CODEC_DMA_TX_0:
+- case TX_CODEC_DMA_TX_1:
+- case TX_CODEC_DMA_TX_2:
+- case TX_CODEC_DMA_TX_3:
+- for_each_rtd_codec_dais(rtd, i, codec_dai) {
+- sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream);
+- if (sruntime != ERR_PTR(-ENOTSUPP))
+- *psruntime = sruntime;
+- }
+- break;
++ if (!qcom_snd_is_sdw_dai(cpu_dai->id))
++ return NULL;
++
++ for_each_rtd_codec_dais(rtd, i, codec_dai) {
++ sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream);
++ if (sruntime != ERR_PTR(-ENOTSUPP))
++ return sruntime;
+ }
++ return NULL;
++}
++EXPORT_SYMBOL_GPL(qcom_snd_sdw_get_stream);
++
++int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params,
++ struct sdw_stream_runtime **psruntime)
++{
++ *psruntime = qcom_snd_sdw_get_stream(substream);
+
+ return 0;
+
+@@ -166,23 +189,13 @@ int qcom_snd_sdw_hw_free(struct snd_pcm_
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+
+- switch (cpu_dai->id) {
+- case WSA_CODEC_DMA_RX_0:
+- case WSA_CODEC_DMA_RX_1:
+- case RX_CODEC_DMA_RX_0:
+- case RX_CODEC_DMA_RX_1:
+- case TX_CODEC_DMA_TX_0:
+- case TX_CODEC_DMA_TX_1:
+- case TX_CODEC_DMA_TX_2:
+- case TX_CODEC_DMA_TX_3:
+- if (sruntime && *stream_prepared) {
+- sdw_disable_stream(sruntime);
+- sdw_deprepare_stream(sruntime);
+- *stream_prepared = false;
+- }
+- break;
+- default:
+- break;
++ if (!qcom_snd_is_sdw_dai(cpu_dai->id))
++ return 0;
++
++ if (sruntime && *stream_prepared) {
++ sdw_disable_stream(sruntime);
++ sdw_deprepare_stream(sruntime);
++ *stream_prepared = false;
+ }
+
+ return 0;
+--- a/sound/soc/qcom/sdw.h
++++ b/sound/soc/qcom/sdw.h
+@@ -10,6 +10,7 @@ int qcom_snd_sdw_startup(struct snd_pcm_
+ int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
+ struct sdw_stream_runtime *runtime,
+ bool *stream_prepared);
++struct sdw_stream_runtime *qcom_snd_sdw_get_stream(struct snd_pcm_substream *stream);
+ int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct sdw_stream_runtime **psruntime);
+--- a/sound/soc/qcom/sm8250.c
++++ b/sound/soc/qcom/sm8250.c
+@@ -117,7 +117,7 @@ static void sm8250_snd_shutdown(struct s
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+ struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
+- struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
++ struct sdw_stream_runtime *sruntime = qcom_snd_sdw_get_stream(substream);
+
+ data->sruntime[cpu_dai->id] = NULL;
+ sdw_release_stream(sruntime);
+--- a/sound/soc/qcom/x1e80100.c
++++ b/sound/soc/qcom/x1e80100.c
+@@ -55,7 +55,7 @@ static void x1e80100_snd_shutdown(struct
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+ struct x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
+- struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
++ struct sdw_stream_runtime *sruntime = qcom_snd_sdw_get_stream(substream);
+
+ data->sruntime[cpu_dai->id] = NULL;
+ sdw_release_stream(sruntime);
--- /dev/null
+From 52a525011cb8e293799a085436f026f2958403f9 Mon Sep 17 00:00:00 2001
+From: Biju Das <biju.das.jz@bp.renesas.com>
+Date: Fri, 14 Nov 2025 07:37:05 +0000
+Subject: ASoC: renesas: rz-ssi: Fix channel swap issue in full duplex mode
+
+From: Biju Das <biju.das.jz@bp.renesas.com>
+
+commit 52a525011cb8e293799a085436f026f2958403f9 upstream.
+
+The full duplex audio starts with half duplex mode and then switch to
+full duplex mode (another FIFO reset) when both playback/capture
+streams available leading to random audio left/right channel swap
+issue. Fix this channel swap issue by detecting the full duplex
+condition by populating struct dup variable in startup() callback
+and synchronize starting both the play and capture at the same time
+in rz_ssi_start().
+
+Cc: stable@kernel.org
+Fixes: 4f8cd05a4305 ("ASoC: sh: rz-ssi: Add full duplex support")
+Co-developed-by: Tony Tang <tony.tang.ks@renesas.com>
+Signed-off-by: Tony Tang <tony.tang.ks@renesas.com>
+Reviewed-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
+Link: https://patch.msgid.link/20251114073709.4376-2-biju.das.jz@bp.renesas.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/renesas/rz-ssi.c | 51 +++++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 43 insertions(+), 8 deletions(-)
+
+--- a/sound/soc/renesas/rz-ssi.c
++++ b/sound/soc/renesas/rz-ssi.c
+@@ -133,6 +133,12 @@ struct rz_ssi_priv {
+ bool bckp_rise; /* Bit clock polarity (SSICR.BCKP) */
+ bool dma_rt;
+
++ struct {
++ bool tx_active;
++ bool rx_active;
++ bool one_stream_triggered;
++ } dup;
++
+ /* Full duplex communication support */
+ struct {
+ unsigned int rate;
+@@ -332,13 +338,12 @@ static int rz_ssi_start(struct rz_ssi_pr
+ bool is_full_duplex;
+ u32 ssicr, ssifcr;
+
+- is_full_duplex = rz_ssi_is_stream_running(&ssi->playback) ||
+- rz_ssi_is_stream_running(&ssi->capture);
++ is_full_duplex = ssi->dup.tx_active && ssi->dup.rx_active;
+ ssicr = rz_ssi_reg_readl(ssi, SSICR);
+ ssifcr = rz_ssi_reg_readl(ssi, SSIFCR);
+ if (!is_full_duplex) {
+ ssifcr &= ~0xF;
+- } else {
++ } else if (ssi->dup.one_stream_triggered) {
+ rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TEN | SSICR_REN, 0);
+ rz_ssi_set_idle(ssi);
+ ssifcr &= ~SSIFCR_FIFO_RST;
+@@ -374,12 +379,16 @@ static int rz_ssi_start(struct rz_ssi_pr
+ SSISR_RUIRQ), 0);
+
+ strm->running = 1;
+- if (is_full_duplex)
+- ssicr |= SSICR_TEN | SSICR_REN;
+- else
++ if (!is_full_duplex) {
+ ssicr |= is_play ? SSICR_TEN : SSICR_REN;
+-
+- rz_ssi_reg_writel(ssi, SSICR, ssicr);
++ rz_ssi_reg_writel(ssi, SSICR, ssicr);
++ } else if (ssi->dup.one_stream_triggered) {
++ ssicr |= SSICR_TEN | SSICR_REN;
++ rz_ssi_reg_writel(ssi, SSICR, ssicr);
++ ssi->dup.one_stream_triggered = false;
++ } else {
++ ssi->dup.one_stream_triggered = true;
++ }
+
+ return 0;
+ }
+@@ -915,6 +924,30 @@ static int rz_ssi_dai_set_fmt(struct snd
+ return 0;
+ }
+
++static int rz_ssi_startup(struct snd_pcm_substream *substream,
++ struct snd_soc_dai *dai)
++{
++ struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
++
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ ssi->dup.tx_active = true;
++ else
++ ssi->dup.rx_active = true;
++
++ return 0;
++}
++
++static void rz_ssi_shutdown(struct snd_pcm_substream *substream,
++ struct snd_soc_dai *dai)
++{
++ struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
++
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ ssi->dup.tx_active = false;
++ else
++ ssi->dup.rx_active = false;
++}
++
+ static bool rz_ssi_is_valid_hw_params(struct rz_ssi_priv *ssi, unsigned int rate,
+ unsigned int channels,
+ unsigned int sample_width,
+@@ -985,6 +1018,8 @@ static int rz_ssi_dai_hw_params(struct s
+ }
+
+ static const struct snd_soc_dai_ops rz_ssi_dai_ops = {
++ .startup = rz_ssi_startup,
++ .shutdown = rz_ssi_shutdown,
+ .trigger = rz_ssi_dai_trigger,
+ .set_fmt = rz_ssi_dai_set_fmt,
+ .hw_params = rz_ssi_dai_hw_params,
--- /dev/null
+From 2bae7beda19f3b2dc6ab2062c94df19c27923712 Mon Sep 17 00:00:00 2001
+From: Biju Das <biju.das.jz@bp.renesas.com>
+Date: Fri, 14 Nov 2025 07:37:06 +0000
+Subject: ASoC: renesas: rz-ssi: Fix rz_ssi_priv::hw_params_cache::sample_width
+
+From: Biju Das <biju.das.jz@bp.renesas.com>
+
+commit 2bae7beda19f3b2dc6ab2062c94df19c27923712 upstream.
+
+The strm->sample_width is not filled during rz_ssi_dai_hw_params(). This
+wrong value is used for caching sample_width in struct hw_params_cache.
+Fix this issue by replacing 'strm->sample_width'->'params_width(params)'
+in rz_ssi_dai_hw_params(). After this drop the variable sample_width
+from struct rz_ssi_stream as it is unused.
+
+Cc: stable@kernel.org
+Fixes: 4f8cd05a4305 ("ASoC: sh: rz-ssi: Add full duplex support")
+Reviewed-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
+Link: https://patch.msgid.link/20251114073709.4376-3-biju.das.jz@bp.renesas.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/renesas/rz-ssi.c | 13 ++++---------
+ 1 file changed, 4 insertions(+), 9 deletions(-)
+
+--- a/sound/soc/renesas/rz-ssi.c
++++ b/sound/soc/renesas/rz-ssi.c
+@@ -13,6 +13,7 @@
+ #include <linux/module.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/reset.h>
++#include <sound/pcm_params.h>
+ #include <sound/soc.h>
+
+ /* REGISTER OFFSET */
+@@ -87,7 +88,6 @@ struct rz_ssi_stream {
+ int dma_buffer_pos; /* The address for the next DMA descriptor */
+ int completed_dma_buf_pos; /* The address of the last completed DMA descriptor. */
+ int period_counter; /* for keeping track of periods transferred */
+- int sample_width;
+ int buffer_pos; /* current frame position in the buffer */
+ int running; /* 0=stopped, 1=running */
+
+@@ -217,10 +217,7 @@ static inline bool rz_ssi_is_stream_runn
+ static void rz_ssi_stream_init(struct rz_ssi_stream *strm,
+ struct snd_pcm_substream *substream)
+ {
+- struct snd_pcm_runtime *runtime = substream->runtime;
+-
+ rz_ssi_set_substream(strm, substream);
+- strm->sample_width = samples_to_bytes(runtime, 1);
+ strm->dma_buffer_pos = 0;
+ strm->completed_dma_buf_pos = 0;
+ strm->period_counter = 0;
+@@ -978,9 +975,9 @@ static int rz_ssi_dai_hw_params(struct s
+ struct snd_soc_dai *dai)
+ {
+ struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
+- struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream);
+ unsigned int sample_bits = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min;
++ unsigned int sample_width = params_width(params);
+ unsigned int channels = params_channels(params);
+ unsigned int rate = params_rate(params);
+ int ret;
+@@ -999,16 +996,14 @@ static int rz_ssi_dai_hw_params(struct s
+
+ if (rz_ssi_is_stream_running(&ssi->playback) ||
+ rz_ssi_is_stream_running(&ssi->capture)) {
+- if (rz_ssi_is_valid_hw_params(ssi, rate, channels,
+- strm->sample_width, sample_bits))
++ if (rz_ssi_is_valid_hw_params(ssi, rate, channels, sample_width, sample_bits))
+ return 0;
+
+ dev_err(ssi->dev, "Full duplex needs same HW params\n");
+ return -EINVAL;
+ }
+
+- rz_ssi_cache_hw_params(ssi, rate, channels, strm->sample_width,
+- sample_bits);
++ rz_ssi_cache_hw_params(ssi, rate, channels, sample_width, sample_bits);
+
+ ret = rz_ssi_swreset(ssi);
+ if (ret)
--- /dev/null
+From 312ec2f0d9d1a5656f76d770bbf1d967e9289aa7 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Mon, 24 Nov 2025 11:49:06 +0100
+Subject: ASoC: stm32: sai: fix clk prepare imbalance on probe failure
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 312ec2f0d9d1a5656f76d770bbf1d967e9289aa7 upstream.
+
+Make sure to unprepare the parent clock also on probe failures (e.g.
+probe deferral).
+
+Fixes: a14bf98c045b ("ASoC: stm32: sai: fix possible circular locking")
+Cc: stable@vger.kernel.org # 5.5
+Cc: Olivier Moysan <olivier.moysan@st.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: olivier moysan <olivier.moysan@foss.st.com>
+Link: https://patch.msgid.link/20251124104908.15754-3-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/stm/stm32_sai_sub.c | 28 +++++++++++++++++++++-------
+ 1 file changed, 21 insertions(+), 7 deletions(-)
+
+--- a/sound/soc/stm/stm32_sai_sub.c
++++ b/sound/soc/stm/stm32_sai_sub.c
+@@ -1634,14 +1634,21 @@ static int stm32_sai_sub_parse_of(struct
+ if (of_property_present(np, "#clock-cells")) {
+ ret = stm32_sai_add_mclk_provider(sai);
+ if (ret < 0)
+- return ret;
++ goto err_unprepare_pclk;
+ } else {
+ sai->sai_mclk = devm_clk_get_optional(&pdev->dev, "MCLK");
+- if (IS_ERR(sai->sai_mclk))
+- return PTR_ERR(sai->sai_mclk);
++ if (IS_ERR(sai->sai_mclk)) {
++ ret = PTR_ERR(sai->sai_mclk);
++ goto err_unprepare_pclk;
++ }
+ }
+
+ return 0;
++
++err_unprepare_pclk:
++ clk_unprepare(sai->pdata->pclk);
++
++ return ret;
+ }
+
+ static int stm32_sai_sub_probe(struct platform_device *pdev)
+@@ -1688,26 +1695,33 @@ static int stm32_sai_sub_probe(struct pl
+ IRQF_SHARED, dev_name(&pdev->dev), sai);
+ if (ret) {
+ dev_err(&pdev->dev, "IRQ request returned %d\n", ret);
+- return ret;
++ goto err_unprepare_pclk;
+ }
+
+ if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
+ conf = &stm32_sai_pcm_config_spdif;
+
+ ret = snd_dmaengine_pcm_register(&pdev->dev, conf, 0);
+- if (ret)
+- return dev_err_probe(&pdev->dev, ret, "Could not register pcm dma\n");
++ if (ret) {
++ ret = dev_err_probe(&pdev->dev, ret, "Could not register pcm dma\n");
++ goto err_unprepare_pclk;
++ }
+
+ ret = snd_soc_register_component(&pdev->dev, &stm32_component,
+ &sai->cpu_dai_drv, 1);
+ if (ret) {
+ snd_dmaengine_pcm_unregister(&pdev->dev);
+- return ret;
++ goto err_unprepare_pclk;
+ }
+
+ pm_runtime_enable(&pdev->dev);
+
+ return 0;
++
++err_unprepare_pclk:
++ clk_unprepare(sai->pdata->pclk);
++
++ return ret;
+ }
+
+ static void stm32_sai_sub_remove(struct platform_device *pdev)
--- /dev/null
+From e26ff429eaf10c4ef1bc3dabd9bf27eb54b7e1f4 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Mon, 24 Nov 2025 11:49:05 +0100
+Subject: ASoC: stm32: sai: fix device leak on probe
+
+From: Johan Hovold <johan@kernel.org>
+
+commit e26ff429eaf10c4ef1bc3dabd9bf27eb54b7e1f4 upstream.
+
+Make sure to drop the reference taken when looking up the sync provider
+device and its driver data during DAI probe on probe failures and on
+unbind.
+
+Note that holding a reference to a device does not prevent its driver
+data from going away so there is no point in keeping the reference.
+
+Fixes: 7dd0d835582f ("ASoC: stm32: sai: simplify sync modes management")
+Fixes: 1c3816a19487 ("ASoC: stm32: sai: add missing put_device()")
+Cc: stable@vger.kernel.org # 4.16: 1c3816a19487
+Cc: olivier moysan <olivier.moysan@st.com>
+Cc: Wen Yang <yellowriver2010@hotmail.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: olivier moysan <olivier.moysan@foss.st.com>
+Link: https://patch.msgid.link/20251124104908.15754-2-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/stm/stm32_sai.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/soc/stm/stm32_sai.c
++++ b/sound/soc/stm/stm32_sai.c
+@@ -143,6 +143,7 @@ static int stm32_sai_set_sync(struct stm
+ }
+
+ sai_provider = platform_get_drvdata(pdev);
++ put_device(&pdev->dev);
+ if (!sai_provider) {
+ dev_err(&sai_client->pdev->dev,
+ "SAI sync provider data not found\n");
+@@ -159,7 +160,6 @@ static int stm32_sai_set_sync(struct stm
+ ret = stm32_sai_sync_conf_provider(sai_provider, synco);
+
+ error:
+- put_device(&pdev->dev);
+ of_node_put(np_provider);
+ return ret;
+ }
--- /dev/null
+From 23261f0de09427367e99f39f588e31e2856a690e Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Mon, 24 Nov 2025 11:49:07 +0100
+Subject: ASoC: stm32: sai: fix OF node leak on probe
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 23261f0de09427367e99f39f588e31e2856a690e upstream.
+
+The reference taken to the sync provider OF node when probing the
+platform device is currently only dropped if the set_sync() callback
+fails during DAI probe.
+
+Make sure to drop the reference on platform probe failures (e.g. probe
+deferral) and on driver unbind.
+
+This also avoids a potential use-after-free in case the DAI is ever
+reprobed without first rebinding the platform driver.
+
+Fixes: 5914d285f6b7 ("ASoC: stm32: sai: Add synchronization support")
+Fixes: d4180b4c02e7 ("ASoC: stm32: sai: fix set_sync service")
+Cc: Olivier Moysan <olivier.moysan@st.com>
+Cc: stable@vger.kernel.org # 4.16: d4180b4c02e7
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: olivier moysan <olivier.moysan@foss.st.com>
+Link: https://patch.msgid.link/20251124104908.15754-4-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/stm/stm32_sai.c | 12 +++---------
+ sound/soc/stm/stm32_sai_sub.c | 23 ++++++++++++++++-------
+ 2 files changed, 19 insertions(+), 16 deletions(-)
+
+--- a/sound/soc/stm/stm32_sai.c
++++ b/sound/soc/stm/stm32_sai.c
+@@ -138,7 +138,6 @@ static int stm32_sai_set_sync(struct stm
+ if (!pdev) {
+ dev_err(&sai_client->pdev->dev,
+ "Device not found for node %pOFn\n", np_provider);
+- of_node_put(np_provider);
+ return -ENODEV;
+ }
+
+@@ -147,21 +146,16 @@ static int stm32_sai_set_sync(struct stm
+ if (!sai_provider) {
+ dev_err(&sai_client->pdev->dev,
+ "SAI sync provider data not found\n");
+- ret = -EINVAL;
+- goto error;
++ return -EINVAL;
+ }
+
+ /* Configure sync client */
+ ret = stm32_sai_sync_conf_client(sai_client, synci);
+ if (ret < 0)
+- goto error;
++ return ret;
+
+ /* Configure sync provider */
+- ret = stm32_sai_sync_conf_provider(sai_provider, synco);
+-
+-error:
+- of_node_put(np_provider);
+- return ret;
++ return stm32_sai_sync_conf_provider(sai_provider, synco);
+ }
+
+ static int stm32_sai_get_parent_clk(struct stm32_sai_data *sai)
+--- a/sound/soc/stm/stm32_sai_sub.c
++++ b/sound/soc/stm/stm32_sai_sub.c
+@@ -1586,7 +1586,8 @@ static int stm32_sai_sub_parse_of(struct
+ dev_err(&pdev->dev,
+ "External synchro not supported\n");
+ of_node_put(args.np);
+- return -EINVAL;
++ ret = -EINVAL;
++ goto err_put_sync_provider;
+ }
+ sai->sync = SAI_SYNC_EXTERNAL;
+
+@@ -1595,7 +1596,8 @@ static int stm32_sai_sub_parse_of(struct
+ (sai->synci > (SAI_GCR_SYNCIN_MAX + 1))) {
+ dev_err(&pdev->dev, "Wrong SAI index\n");
+ of_node_put(args.np);
+- return -EINVAL;
++ ret = -EINVAL;
++ goto err_put_sync_provider;
+ }
+
+ if (of_property_match_string(args.np, "compatible",
+@@ -1609,7 +1611,8 @@ static int stm32_sai_sub_parse_of(struct
+ if (!sai->synco) {
+ dev_err(&pdev->dev, "Unknown SAI sub-block\n");
+ of_node_put(args.np);
+- return -EINVAL;
++ ret = -EINVAL;
++ goto err_put_sync_provider;
+ }
+ }
+
+@@ -1619,13 +1622,15 @@ static int stm32_sai_sub_parse_of(struct
+
+ of_node_put(args.np);
+ sai->sai_ck = devm_clk_get(&pdev->dev, "sai_ck");
+- if (IS_ERR(sai->sai_ck))
+- return dev_err_probe(&pdev->dev, PTR_ERR(sai->sai_ck),
+- "Missing kernel clock sai_ck\n");
++ if (IS_ERR(sai->sai_ck)) {
++ ret = dev_err_probe(&pdev->dev, PTR_ERR(sai->sai_ck),
++ "Missing kernel clock sai_ck\n");
++ goto err_put_sync_provider;
++ }
+
+ ret = clk_prepare(sai->pdata->pclk);
+ if (ret < 0)
+- return ret;
++ goto err_put_sync_provider;
+
+ if (STM_SAI_IS_F4(sai->pdata))
+ return 0;
+@@ -1647,6 +1652,8 @@ static int stm32_sai_sub_parse_of(struct
+
+ err_unprepare_pclk:
+ clk_unprepare(sai->pdata->pclk);
++err_put_sync_provider:
++ of_node_put(sai->np_sync_provider);
+
+ return ret;
+ }
+@@ -1720,6 +1727,7 @@ static int stm32_sai_sub_probe(struct pl
+
+ err_unprepare_pclk:
+ clk_unprepare(sai->pdata->pclk);
++ of_node_put(sai->np_sync_provider);
+
+ return ret;
+ }
+@@ -1732,6 +1740,7 @@ static void stm32_sai_sub_remove(struct
+ snd_dmaengine_pcm_unregister(&pdev->dev);
+ snd_soc_unregister_component(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
++ of_node_put(sai->np_sync_provider);
+ }
+
+ static int stm32_sai_sub_suspend(struct device *dev)
--- /dev/null
+From efae226c2ef19528ffd81d29ba0eecf1b0896ca2 Mon Sep 17 00:00:00 2001
+From: Damien Le Moal <dlemoal@kernel.org>
+Date: Wed, 5 Nov 2025 06:22:35 +0900
+Subject: block: handle zone management operations completions
+
+From: Damien Le Moal <dlemoal@kernel.org>
+
+commit efae226c2ef19528ffd81d29ba0eecf1b0896ca2 upstream.
+
+The functions blk_zone_wplug_handle_reset_or_finish() and
+blk_zone_wplug_handle_reset_all() both modify the zone write pointer
+offset of zone write plugs that are the target of a reset, reset all or
+finish zone management operation. However, these functions do this
+modification before the BIO is executed. So if the zone operation fails,
+the modified zone write pointer offsets become invalid.
+
+Avoid this by modifying the zone write pointer offset of a zone write
+plug that is the target of a zone management operation when the
+operation completes. To do so, modify blk_zone_bio_endio() to call the
+new function blk_zone_mgmt_bio_endio() which in turn calls the functions
+blk_zone_reset_all_bio_endio(), blk_zone_reset_bio_endio() or
+blk_zone_finish_bio_endio() depending on the operation of the completed
+BIO, to modify a zone write plug write pointer offset accordingly.
+These functions are called only if the BIO execution was successful.
+
+Fixes: dd291d77cc90 ("block: Introduce zone write plugging")
+Cc: stable@vger.kernel.org
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
+Reviewed-by: Hannes Reinecke <hare@suse.de>
+Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ block/blk-zoned.c | 139 ++++++++++++++++++++++++++++++++++--------------------
+ block/blk.h | 14 +++++
+ 2 files changed, 104 insertions(+), 49 deletions(-)
+
+--- a/block/blk-zoned.c
++++ b/block/blk-zoned.c
+@@ -71,6 +71,11 @@ struct blk_zone_wplug {
+ struct gendisk *disk;
+ };
+
++static inline unsigned int disk_zone_wplugs_hash_size(struct gendisk *disk)
++{
++ return 1U << disk->zone_wplugs_hash_bits;
++}
++
+ /*
+ * Zone write plug flags bits:
+ * - BLK_ZONE_WPLUG_PLUGGED: Indicates that the zone write plug is plugged,
+@@ -698,71 +703,91 @@ static int disk_zone_sync_wp_offset(stru
+ disk_report_zones_cb, &args);
+ }
+
+-static bool blk_zone_wplug_handle_reset_or_finish(struct bio *bio,
+- unsigned int wp_offset)
++static void blk_zone_reset_bio_endio(struct bio *bio)
+ {
+ struct gendisk *disk = bio->bi_bdev->bd_disk;
+- sector_t sector = bio->bi_iter.bi_sector;
+ struct blk_zone_wplug *zwplug;
+- unsigned long flags;
+-
+- /* Conventional zones cannot be reset nor finished. */
+- if (!bdev_zone_is_seq(bio->bi_bdev, sector)) {
+- bio_io_error(bio);
+- return true;
+- }
+-
+- /*
+- * No-wait reset or finish BIOs do not make much sense as the callers
+- * issue these as blocking operations in most cases. To avoid issues
+- * the BIO execution potentially failing with BLK_STS_AGAIN, warn about
+- * REQ_NOWAIT being set and ignore that flag.
+- */
+- if (WARN_ON_ONCE(bio->bi_opf & REQ_NOWAIT))
+- bio->bi_opf &= ~REQ_NOWAIT;
+
+ /*
+- * If we have a zone write plug, set its write pointer offset to 0
+- * (reset case) or to the zone size (finish case). This will abort all
+- * BIOs plugged for the target zone. It is fine as resetting or
+- * finishing zones while writes are still in-flight will result in the
++ * If we have a zone write plug, set its write pointer offset to 0.
++ * This will abort all BIOs plugged for the target zone. It is fine as
++ * resetting zones while writes are still in-flight will result in the
+ * writes failing anyway.
+ */
+- zwplug = disk_get_zone_wplug(disk, sector);
++ zwplug = disk_get_zone_wplug(disk, bio->bi_iter.bi_sector);
+ if (zwplug) {
++ unsigned long flags;
++
+ spin_lock_irqsave(&zwplug->lock, flags);
+- disk_zone_wplug_set_wp_offset(disk, zwplug, wp_offset);
++ disk_zone_wplug_set_wp_offset(disk, zwplug, 0);
+ spin_unlock_irqrestore(&zwplug->lock, flags);
+ disk_put_zone_wplug(zwplug);
+ }
+-
+- return false;
+ }
+
+-static bool blk_zone_wplug_handle_reset_all(struct bio *bio)
++static void blk_zone_reset_all_bio_endio(struct bio *bio)
+ {
+ struct gendisk *disk = bio->bi_bdev->bd_disk;
+ struct blk_zone_wplug *zwplug;
+ unsigned long flags;
+- sector_t sector;
++ unsigned int i;
+
+- /*
+- * Set the write pointer offset of all zone write plugs to 0. This will
+- * abort all plugged BIOs. It is fine as resetting zones while writes
+- * are still in-flight will result in the writes failing anyway.
+- */
+- for (sector = 0; sector < get_capacity(disk);
+- sector += disk->queue->limits.chunk_sectors) {
+- zwplug = disk_get_zone_wplug(disk, sector);
+- if (zwplug) {
++ /* Update the condition of all zone write plugs. */
++ rcu_read_lock();
++ for (i = 0; i < disk_zone_wplugs_hash_size(disk); i++) {
++ hlist_for_each_entry_rcu(zwplug, &disk->zone_wplugs_hash[i],
++ node) {
+ spin_lock_irqsave(&zwplug->lock, flags);
+ disk_zone_wplug_set_wp_offset(disk, zwplug, 0);
+ spin_unlock_irqrestore(&zwplug->lock, flags);
+- disk_put_zone_wplug(zwplug);
+ }
+ }
++ rcu_read_unlock();
++}
+
+- return false;
++static void blk_zone_finish_bio_endio(struct bio *bio)
++{
++ struct block_device *bdev = bio->bi_bdev;
++ struct gendisk *disk = bdev->bd_disk;
++ struct blk_zone_wplug *zwplug;
++
++ /*
++ * If we have a zone write plug, set its write pointer offset to the
++ * zone size. This will abort all BIOs plugged for the target zone. It
++ * is fine as resetting zones while writes are still in-flight will
++ * result in the writes failing anyway.
++ */
++ zwplug = disk_get_zone_wplug(disk, bio->bi_iter.bi_sector);
++ if (zwplug) {
++ unsigned long flags;
++
++ spin_lock_irqsave(&zwplug->lock, flags);
++ disk_zone_wplug_set_wp_offset(disk, zwplug,
++ bdev_zone_sectors(bdev));
++ spin_unlock_irqrestore(&zwplug->lock, flags);
++ disk_put_zone_wplug(zwplug);
++ }
++}
++
++void blk_zone_mgmt_bio_endio(struct bio *bio)
++{
++ /* If the BIO failed, we have nothing to do. */
++ if (bio->bi_status != BLK_STS_OK)
++ return;
++
++ switch (bio_op(bio)) {
++ case REQ_OP_ZONE_RESET:
++ blk_zone_reset_bio_endio(bio);
++ return;
++ case REQ_OP_ZONE_RESET_ALL:
++ blk_zone_reset_all_bio_endio(bio);
++ return;
++ case REQ_OP_ZONE_FINISH:
++ blk_zone_finish_bio_endio(bio);
++ return;
++ default:
++ return;
++ }
+ }
+
+ static void disk_zone_wplug_schedule_bio_work(struct gendisk *disk,
+@@ -1106,6 +1131,30 @@ static void blk_zone_wplug_handle_native
+ disk_put_zone_wplug(zwplug);
+ }
+
++static bool blk_zone_wplug_handle_zone_mgmt(struct bio *bio)
++{
++ if (bio_op(bio) != REQ_OP_ZONE_RESET_ALL &&
++ !bdev_zone_is_seq(bio->bi_bdev, bio->bi_iter.bi_sector)) {
++ /*
++ * Zone reset and zone finish operations do not apply to
++ * conventional zones.
++ */
++ bio_io_error(bio);
++ return true;
++ }
++
++ /*
++ * No-wait zone management BIOs do not make much sense as the callers
++ * issue these as blocking operations in most cases. To avoid issues
++ * with the BIO execution potentially failing with BLK_STS_AGAIN, warn
++ * about REQ_NOWAIT being set and ignore that flag.
++ */
++ if (WARN_ON_ONCE(bio->bi_opf & REQ_NOWAIT))
++ bio->bi_opf &= ~REQ_NOWAIT;
++
++ return false;
++}
++
+ /**
+ * blk_zone_plug_bio - Handle a zone write BIO with zone write plugging
+ * @bio: The BIO being submitted
+@@ -1153,12 +1202,9 @@ bool blk_zone_plug_bio(struct bio *bio,
+ case REQ_OP_WRITE_ZEROES:
+ return blk_zone_wplug_handle_write(bio, nr_segs);
+ case REQ_OP_ZONE_RESET:
+- return blk_zone_wplug_handle_reset_or_finish(bio, 0);
+ case REQ_OP_ZONE_FINISH:
+- return blk_zone_wplug_handle_reset_or_finish(bio,
+- bdev_zone_sectors(bdev));
+ case REQ_OP_ZONE_RESET_ALL:
+- return blk_zone_wplug_handle_reset_all(bio);
++ return blk_zone_wplug_handle_zone_mgmt(bio);
+ default:
+ return false;
+ }
+@@ -1332,11 +1378,6 @@ put_zwplug:
+ disk_put_zone_wplug(zwplug);
+ }
+
+-static inline unsigned int disk_zone_wplugs_hash_size(struct gendisk *disk)
+-{
+- return 1U << disk->zone_wplugs_hash_bits;
+-}
+-
+ void disk_init_zone_resources(struct gendisk *disk)
+ {
+ spin_lock_init(&disk->zone_wplugs_lock);
+--- a/block/blk.h
++++ b/block/blk.h
+@@ -488,10 +488,24 @@ static inline bool blk_req_bio_is_zone_a
+ void blk_zone_write_plug_bio_merged(struct bio *bio);
+ void blk_zone_write_plug_init_request(struct request *rq);
+ void blk_zone_append_update_request_bio(struct request *rq, struct bio *bio);
++void blk_zone_mgmt_bio_endio(struct bio *bio);
+ void blk_zone_write_plug_bio_endio(struct bio *bio);
+ static inline void blk_zone_bio_endio(struct bio *bio)
+ {
+ /*
++ * Zone management BIOs may impact zone write plugs (e.g. a zone reset
++ * changes a zone write plug zone write pointer offset), but these
++ * operation do not go through zone write plugging as they may operate
++ * on zones that do not have a zone write
++ * plug. blk_zone_mgmt_bio_endio() handles the potential changes to zone
++ * write plugs that are present.
++ */
++ if (op_is_zone_mgmt(bio_op(bio))) {
++ blk_zone_mgmt_bio_endio(bio);
++ return;
++ }
++
++ /*
+ * For write BIOs to zoned devices, signal the completion of the BIO so
+ * that the next write BIO can be submitted by zone write plugging.
+ */
--- /dev/null
+From ca389a55d8b2d86a817433bf82e0602b68c4d541 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <johannes.goede@oss.qualcomm.com>
+Date: Sat, 8 Nov 2025 22:03:18 +0100
+Subject: HID: logitech-dj: Remove duplicate error logging
+
+From: Hans de Goede <johannes.goede@oss.qualcomm.com>
+
+commit ca389a55d8b2d86a817433bf82e0602b68c4d541 upstream.
+
+logi_dj_recv_query_paired_devices() and logi_dj_recv_switch_to_dj_mode()
+both have 2 callers which all log an error if the function fails. Move
+the error logging to inside these 2 functions to remove the duplicated
+error logging in the callers.
+
+While at it also move the logi_dj_recv_send_report() call error handling
+in logi_dj_recv_switch_to_dj_mode() to directly after the call. That call
+only fails if the report cannot be found and in that case it does nothing,
+so the msleep() is not necessary on failures.
+
+Fixes: 6f20d3261265 ("HID: logitech-dj: Fix error handling in logi_dj_recv_switch_to_dj_mode()")
+Cc: stable@vger.kernel.org
+Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-logitech-dj.c | 56 +++++++++++++++++-------------------------
+ 1 file changed, 23 insertions(+), 33 deletions(-)
+
+--- a/drivers/hid/hid-logitech-dj.c
++++ b/drivers/hid/hid-logitech-dj.c
+@@ -805,7 +805,6 @@ static void delayedwork_callback(struct
+ struct dj_workitem workitem;
+ unsigned long flags;
+ int count;
+- int retval;
+
+ dbg_hid("%s\n", __func__);
+
+@@ -842,11 +841,7 @@ static void delayedwork_callback(struct
+ logi_dj_recv_destroy_djhid_device(djrcv_dev, &workitem);
+ break;
+ case WORKITEM_TYPE_UNKNOWN:
+- retval = logi_dj_recv_query_paired_devices(djrcv_dev);
+- if (retval) {
+- hid_err(djrcv_dev->hidpp, "%s: logi_dj_recv_query_paired_devices error: %d\n",
+- __func__, retval);
+- }
++ logi_dj_recv_query_paired_devices(djrcv_dev);
+ break;
+ case WORKITEM_TYPE_EMPTY:
+ dbg_hid("%s: device list is empty\n", __func__);
+@@ -1239,8 +1234,10 @@ static int logi_dj_recv_query_paired_dev
+
+ djrcv_dev->last_query = jiffies;
+
+- if (djrcv_dev->type != recvr_type_dj)
+- return logi_dj_recv_query_hidpp_devices(djrcv_dev);
++ if (djrcv_dev->type != recvr_type_dj) {
++ retval = logi_dj_recv_query_hidpp_devices(djrcv_dev);
++ goto out;
++ }
+
+ dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
+ if (!dj_report)
+@@ -1250,6 +1247,10 @@ static int logi_dj_recv_query_paired_dev
+ dj_report->report_type = REPORT_TYPE_CMD_GET_PAIRED_DEVICES;
+ retval = logi_dj_recv_send_report(djrcv_dev, dj_report);
+ kfree(dj_report);
++out:
++ if (retval < 0)
++ hid_err(djrcv_dev->hidpp, "%s error:%d\n", __func__, retval);
++
+ return retval;
+ }
+
+@@ -1275,6 +1276,8 @@ static int logi_dj_recv_switch_to_dj_mod
+ (u8)timeout;
+
+ retval = logi_dj_recv_send_report(djrcv_dev, dj_report);
++ if (retval)
++ goto out;
+
+ /*
+ * Ugly sleep to work around a USB 3.0 bug when the receiver is
+@@ -1283,11 +1286,6 @@ static int logi_dj_recv_switch_to_dj_mod
+ * 50 msec should gives enough time to the receiver to be ready.
+ */
+ msleep(50);
+-
+- if (retval) {
+- kfree(dj_report);
+- return retval;
+- }
+ }
+
+ /*
+@@ -1313,7 +1311,12 @@ static int logi_dj_recv_switch_to_dj_mod
+ HIDPP_REPORT_SHORT_LENGTH, HID_OUTPUT_REPORT,
+ HID_REQ_SET_REPORT);
+
++out:
+ kfree(dj_report);
++
++ if (retval < 0)
++ hid_err(hdev, "%s error:%d\n", __func__, retval);
++
+ return retval;
+ }
+
+@@ -1835,11 +1838,8 @@ static int logi_dj_probe(struct hid_devi
+
+ if (has_hidpp) {
+ retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
+- if (retval < 0) {
+- hid_err(hdev, "%s: logi_dj_recv_switch_to_dj_mode returned error:%d\n",
+- __func__, retval);
++ if (retval < 0)
+ goto switch_to_dj_mode_fail;
+- }
+ }
+
+ /* This is enabling the polling urb on the IN endpoint */
+@@ -1857,15 +1857,11 @@ static int logi_dj_probe(struct hid_devi
+ spin_lock_irqsave(&djrcv_dev->lock, flags);
+ djrcv_dev->ready = true;
+ spin_unlock_irqrestore(&djrcv_dev->lock, flags);
+- retval = logi_dj_recv_query_paired_devices(djrcv_dev);
+- if (retval < 0) {
+- hid_err(hdev, "%s: logi_dj_recv_query_paired_devices error:%d\n",
+- __func__, retval);
+- /*
+- * This can happen with a KVM, let the probe succeed,
+- * logi_dj_recv_queue_unknown_work will retry later.
+- */
+- }
++ /*
++ * This can fail with a KVM. Ignore errors to let the probe
++ * succeed, logi_dj_recv_queue_unknown_work will retry later.
++ */
++ logi_dj_recv_query_paired_devices(djrcv_dev);
+ }
+
+ return 0;
+@@ -1882,18 +1878,12 @@ hid_hw_start_fail:
+ #ifdef CONFIG_PM
+ static int logi_dj_reset_resume(struct hid_device *hdev)
+ {
+- int retval;
+ struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
+
+ if (!djrcv_dev || djrcv_dev->hidpp != hdev)
+ return 0;
+
+- retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
+- if (retval < 0) {
+- hid_err(hdev, "%s: logi_dj_recv_switch_to_dj_mode returned error:%d\n",
+- __func__, retval);
+- }
+-
++ logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
+ return 0;
+ }
+ #endif
--- /dev/null
+From 0ed3a30fd996cb0cac872432cf25185fda7e5316 Mon Sep 17 00:00:00 2001
+From: Raghavendra Rao Ananta <rananta@google.com>
+Date: Fri, 31 Oct 2025 17:06:03 +0000
+Subject: hisi_acc_vfio_pci: Add .match_token_uuid callback in hisi_acc_vfio_pci_migrn_ops
+
+From: Raghavendra Rao Ananta <rananta@google.com>
+
+commit 0ed3a30fd996cb0cac872432cf25185fda7e5316 upstream.
+
+The commit, <86624ba3b522> ("vfio/pci: Do vf_token checks for
+VFIO_DEVICE_BIND_IOMMUFD") accidentally ignored including the
+.match_token_uuid callback in the hisi_acc_vfio_pci_migrn_ops struct.
+Introduce the missed callback here.
+
+Fixes: 86624ba3b522 ("vfio/pci: Do vf_token checks for VFIO_DEVICE_BIND_IOMMUFD")
+Cc: stable@vger.kernel.org
+Suggested-by: Longfang Liu <liulongfang@huawei.com>
+Signed-off-by: Raghavendra Rao Ananta <rananta@google.com>
+Reviewed-by: Longfang Liu <liulongfang@huawei.com>
+Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
+Link: https://lore.kernel.org/r/20251031170603.2260022-3-rananta@google.com
+Signed-off-by: Alex Williamson <alex@shazbot.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
++++ b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
+@@ -1564,6 +1564,7 @@ static const struct vfio_device_ops hisi
+ .mmap = hisi_acc_vfio_pci_mmap,
+ .request = vfio_pci_core_request,
+ .match = vfio_pci_core_match,
++ .match_token_uuid = vfio_pci_core_match_token_uuid,
+ .bind_iommufd = vfio_iommufd_physical_bind,
+ .unbind_iommufd = vfio_iommufd_physical_unbind,
+ .attach_ioas = vfio_iommufd_physical_attach_ioas,
--- /dev/null
+From fae00a7186cecf90a57757a63b97a0cbcf384fe9 Mon Sep 17 00:00:00 2001
+From: Armin Wolf <W_Armin@gmx.de>
+Date: Wed, 3 Dec 2025 21:21:09 +0100
+Subject: hwmon: (dell-smm) Fix off-by-one error in dell_smm_is_visible()
+
+From: Armin Wolf <W_Armin@gmx.de>
+
+commit fae00a7186cecf90a57757a63b97a0cbcf384fe9 upstream.
+
+The documentation states that on machines supporting only global
+fan mode control, the pwmX_enable attributes should only be created
+for the first fan channel (pwm1_enable, aka channel 0).
+
+Fix the off-by-one error caused by the fact that fan channels have
+a zero-based index.
+
+Cc: stable@vger.kernel.org
+Fixes: 1c1658058c99 ("hwmon: (dell-smm) Add support for automatic fan mode")
+Signed-off-by: Armin Wolf <W_Armin@gmx.de>
+Link: https://lore.kernel.org/r/20251203202109.331528-1-W_Armin@gmx.de
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hwmon/dell-smm-hwmon.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/hwmon/dell-smm-hwmon.c
++++ b/drivers/hwmon/dell-smm-hwmon.c
+@@ -864,9 +864,9 @@ static umode_t dell_smm_is_visible(const
+ if (auto_fan) {
+ /*
+ * The setting affects all fans, so only create a
+- * single attribute.
++ * single attribute for the first fan channel.
+ */
+- if (channel != 1)
++ if (channel != 0)
+ return 0;
+
+ /*
--- /dev/null
+From 75ba146c2674ba49ed8a222c67f9abfb4a4f2a4f Mon Sep 17 00:00:00 2001
+From: Jinhui Guo <guojinhui.liam@bytedance.com>
+Date: Tue, 28 Oct 2025 00:50:17 +0800
+Subject: iommu/amd: Fix pci_segment memleak in alloc_pci_segment()
+
+From: Jinhui Guo <guojinhui.liam@bytedance.com>
+
+commit 75ba146c2674ba49ed8a222c67f9abfb4a4f2a4f upstream.
+
+Fix a memory leak of struct amd_iommu_pci_segment in alloc_pci_segment()
+when system memory (or contiguous memory) is insufficient.
+
+Fixes: 04230c119930 ("iommu/amd: Introduce per PCI segment device table")
+Fixes: eda797a27795 ("iommu/amd: Introduce per PCI segment rlookup table")
+Fixes: 99fc4ac3d297 ("iommu/amd: Introduce per PCI segment alias_table")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jinhui Guo <guojinhui.liam@bytedance.com>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/amd/init.c | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+--- a/drivers/iommu/amd/init.c
++++ b/drivers/iommu/amd/init.c
+@@ -1731,13 +1731,22 @@ static struct amd_iommu_pci_seg *__init
+ list_add_tail(&pci_seg->list, &amd_iommu_pci_seg_list);
+
+ if (alloc_dev_table(pci_seg))
+- return NULL;
++ goto err_free_pci_seg;
+ if (alloc_alias_table(pci_seg))
+- return NULL;
++ goto err_free_dev_table;
+ if (alloc_rlookup_table(pci_seg))
+- return NULL;
++ goto err_free_alias_table;
+
+ return pci_seg;
++
++err_free_alias_table:
++ free_alias_table(pci_seg);
++err_free_dev_table:
++ free_dev_table(pci_seg);
++err_free_pci_seg:
++ list_del(&pci_seg->list);
++ kfree(pci_seg);
++ return NULL;
+ }
+
+ static struct amd_iommu_pci_seg *__init get_pci_segment(u16 id,
--- /dev/null
+From 2381a1b40be4b286062fb3cf67dd7f005692aa2a Mon Sep 17 00:00:00 2001
+From: Jinhui Guo <guojinhui.liam@bytedance.com>
+Date: Thu, 20 Nov 2025 23:47:25 +0800
+Subject: iommu/amd: Propagate the error code returned by __modify_irte_ga() in modify_irte_ga()
+
+From: Jinhui Guo <guojinhui.liam@bytedance.com>
+
+commit 2381a1b40be4b286062fb3cf67dd7f005692aa2a upstream.
+
+The return type of __modify_irte_ga() is int, but modify_irte_ga()
+treats it as a bool. Casting the int to bool discards the error code.
+
+To fix the issue, change the type of ret to int in modify_irte_ga().
+
+Fixes: 57cdb720eaa5 ("iommu/amd: Do not flush IRTE when only updating isRun and destination fields")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jinhui Guo <guojinhui.liam@bytedance.com>
+Reviewed-by: Vasant Hegde <vasant.hegde@amd.com>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/amd/iommu.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/iommu/amd/iommu.c
++++ b/drivers/iommu/amd/iommu.c
+@@ -3354,7 +3354,7 @@ static int __modify_irte_ga(struct amd_i
+ static int modify_irte_ga(struct amd_iommu *iommu, u16 devid, int index,
+ struct irte_ga *irte)
+ {
+- bool ret;
++ int ret;
+
+ ret = __modify_irte_ga(iommu, devid, index, irte);
+ if (ret)
--- /dev/null
+From a6eaa872c52a181ae9a290fd4e40c9df91166d7a Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Mon, 20 Oct 2025 06:53:05 +0200
+Subject: iommu/apple-dart: fix device leak on of_xlate()
+
+From: Johan Hovold <johan@kernel.org>
+
+commit a6eaa872c52a181ae9a290fd4e40c9df91166d7a upstream.
+
+Make sure to drop the reference taken to the iommu platform device when
+looking up its driver data during of_xlate().
+
+Fixes: 46d1fb072e76 ("iommu/dart: Add DART iommu driver")
+Cc: stable@vger.kernel.org # 5.15
+Cc: Sven Peter <sven@kernel.org>
+Acked-by: Robin Murphy <robin.murphy@arm.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/apple-dart.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/iommu/apple-dart.c
++++ b/drivers/iommu/apple-dart.c
+@@ -802,6 +802,8 @@ static int apple_dart_of_xlate(struct de
+ struct apple_dart *cfg_dart;
+ int i, sid;
+
++ put_device(&iommu_pdev->dev);
++
+ if (args->args_count != 1)
+ return -EINVAL;
+ sid = args->args[0];
--- /dev/null
+From 72f98ef9a4be30d2a60136dd6faee376f780d06c Mon Sep 17 00:00:00 2001
+From: Lu Baolu <baolu.lu@linux.intel.com>
+Date: Wed, 22 Oct 2025 16:26:27 +0800
+Subject: iommu: disable SVA when CONFIG_X86 is set
+
+From: Lu Baolu <baolu.lu@linux.intel.com>
+
+commit 72f98ef9a4be30d2a60136dd6faee376f780d06c upstream.
+
+Patch series "Fix stale IOTLB entries for kernel address space", v7.
+
+This proposes a fix for a security vulnerability related to IOMMU Shared
+Virtual Addressing (SVA). In an SVA context, an IOMMU can cache kernel
+page table entries. When a kernel page table page is freed and
+reallocated for another purpose, the IOMMU might still hold stale,
+incorrect entries. This can be exploited to cause a use-after-free or
+write-after-free condition, potentially leading to privilege escalation or
+data corruption.
+
+This solution introduces a deferred freeing mechanism for kernel page
+table pages, which provides a safe window to notify the IOMMU to
+invalidate its caches before the page is reused.
+
+
+This patch (of 8):
+
+In the IOMMU Shared Virtual Addressing (SVA) context, the IOMMU hardware
+shares and walks the CPU's page tables. The x86 architecture maps the
+kernel's virtual address space into the upper portion of every process's
+page table. Consequently, in an SVA context, the IOMMU hardware can walk
+and cache kernel page table entries.
+
+The Linux kernel currently lacks a notification mechanism for kernel page
+table changes, specifically when page table pages are freed and reused.
+The IOMMU driver is only notified of changes to user virtual address
+mappings. This can cause the IOMMU's internal caches to retain stale
+entries for kernel VA.
+
+Use-After-Free (UAF) and Write-After-Free (WAF) conditions arise when
+kernel page table pages are freed and later reallocated. The IOMMU could
+misinterpret the new data as valid page table entries. The IOMMU might
+then walk into attacker-controlled memory, leading to arbitrary physical
+memory DMA access or privilege escalation. This is also a
+Write-After-Free issue, as the IOMMU will potentially continue to write
+Accessed and Dirty bits to the freed memory while attempting to walk the
+stale page tables.
+
+Currently, SVA contexts are unprivileged and cannot access kernel
+mappings. However, the IOMMU will still walk kernel-only page tables all
+the way down to the leaf entries, where it realizes the mapping is for the
+kernel and errors out. This means the IOMMU still caches these
+intermediate page table entries, making the described vulnerability a real
+concern.
+
+Disable SVA on x86 architecture until the IOMMU can receive notification
+to flush the paging cache before freeing the CPU kernel page table pages.
+
+Link: https://lkml.kernel.org/r/20251022082635.2462433-1-baolu.lu@linux.intel.com
+Link: https://lkml.kernel.org/r/20251022082635.2462433-2-baolu.lu@linux.intel.com
+Fixes: 26b25a2b98e4 ("iommu: Bind process address spaces to devices")
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
+Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
+Cc: Alistair Popple <apopple@nvidia.com>
+Cc: Andy Lutomirski <luto@kernel.org>
+Cc: Borislav Betkov <bp@alien8.de>
+Cc: Dave Hansen <dave.hansen@intel.com>
+Cc: David Hildenbrand <david@redhat.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Jann Horn <jannh@google.com>
+Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
+Cc: Joerg Roedel <joro@8bytes.org>
+Cc: Kevin Tian <kevin.tian@intel.com>
+Cc: Liam Howlett <liam.howlett@oracle.com>
+Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
+Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
+Cc: Michal Hocko <mhocko@kernel.org>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Robin Murohy <robin.murphy@arm.com>
+Cc: Thomas Gleinxer <tglx@linutronix.de>
+Cc: "Uladzislau Rezki (Sony)" <urezki@gmail.com>
+Cc: Vasant Hegde <vasant.hegde@amd.com>
+Cc: Vinicius Costa Gomes <vinicius.gomes@intel.com>
+Cc: Vlastimil Babka <vbabka@suse.cz>
+Cc: Will Deacon <will@kernel.org>
+Cc: Yi Lai <yi1.lai@intel.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/iommu-sva.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/iommu/iommu-sva.c
++++ b/drivers/iommu/iommu-sva.c
+@@ -77,6 +77,9 @@ struct iommu_sva *iommu_sva_bind_device(
+ if (!group)
+ return ERR_PTR(-ENODEV);
+
++ if (IS_ENABLED(CONFIG_X86))
++ return ERR_PTR(-EOPNOTSUPP);
++
+ mutex_lock(&iommu_sva_lock);
+
+ /* Allocate mm->pasid if necessary. */
--- /dev/null
+From 05913cc43cb122f9afecdbe775115c058b906e1b Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Mon, 20 Oct 2025 06:53:07 +0200
+Subject: iommu/exynos: fix device leak on of_xlate()
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 05913cc43cb122f9afecdbe775115c058b906e1b upstream.
+
+Make sure to drop the reference taken to the iommu platform device when
+looking up its driver data during of_xlate().
+
+Note that commit 1a26044954a6 ("iommu/exynos: add missing put_device()
+call in exynos_iommu_of_xlate()") fixed the leak in a couple of error
+paths, but the reference is still leaking on success.
+
+Fixes: aa759fd376fb ("iommu/exynos: Add callback for initializing devices from device tree")
+Cc: stable@vger.kernel.org # 4.2: 1a26044954a6
+Cc: Yu Kuai <yukuai3@huawei.com>
+Acked-by: Robin Murphy <robin.murphy@arm.com>
+Acked-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/exynos-iommu.c | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+--- a/drivers/iommu/exynos-iommu.c
++++ b/drivers/iommu/exynos-iommu.c
+@@ -1446,17 +1446,14 @@ static int exynos_iommu_of_xlate(struct
+ return -ENODEV;
+
+ data = platform_get_drvdata(sysmmu);
+- if (!data) {
+- put_device(&sysmmu->dev);
++ put_device(&sysmmu->dev);
++ if (!data)
+ return -ENODEV;
+- }
+
+ if (!owner) {
+ owner = kzalloc(sizeof(*owner), GFP_KERNEL);
+- if (!owner) {
+- put_device(&sysmmu->dev);
++ if (!owner)
+ return -ENOMEM;
+- }
+
+ INIT_LIST_HEAD(&owner->controllers);
+ mutex_init(&owner->rpm_lock);
--- /dev/null
+From 80aa518452c4aceb9459f9a8e3184db657d1b441 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Mon, 20 Oct 2025 06:53:08 +0200
+Subject: iommu/ipmmu-vmsa: fix device leak on of_xlate()
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 80aa518452c4aceb9459f9a8e3184db657d1b441 upstream.
+
+Make sure to drop the reference taken to the iommu platform device when
+looking up its driver data during of_xlate().
+
+Fixes: 7b2d59611fef ("iommu/ipmmu-vmsa: Replace local utlb code with fwspec ids")
+Cc: stable@vger.kernel.org # 4.14
+Cc: Magnus Damm <damm+renesas@opensource.se>
+Acked-by: Robin Murphy <robin.murphy@arm.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/ipmmu-vmsa.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/iommu/ipmmu-vmsa.c
++++ b/drivers/iommu/ipmmu-vmsa.c
+@@ -720,6 +720,8 @@ static int ipmmu_init_platform_device(st
+
+ dev_iommu_priv_set(dev, platform_get_drvdata(ipmmu_pdev));
+
++ put_device(&ipmmu_pdev->dev);
++
+ return 0;
+ }
+
--- /dev/null
+From b3f1ee18280363ef17f82b564fc379ceba9ec86f Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Mon, 20 Oct 2025 06:53:09 +0200
+Subject: iommu/mediatek: fix device leak on of_xlate()
+
+From: Johan Hovold <johan@kernel.org>
+
+commit b3f1ee18280363ef17f82b564fc379ceba9ec86f upstream.
+
+Make sure to drop the reference taken to the iommu platform device when
+looking up its driver data during of_xlate().
+
+Fixes: 0df4fabe208d ("iommu/mediatek: Add mt8173 IOMMU driver")
+Cc: stable@vger.kernel.org # 4.6
+Acked-by: Robin Murphy <robin.murphy@arm.com>
+Reviewed-by: Yong Wu <yong.wu@mediatek.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/mtk_iommu.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/iommu/mtk_iommu.c
++++ b/drivers/iommu/mtk_iommu.c
+@@ -974,6 +974,8 @@ static int mtk_iommu_of_xlate(struct dev
+ return -EINVAL;
+
+ dev_iommu_priv_set(dev, platform_get_drvdata(m4updev));
++
++ put_device(&m4updev->dev);
+ }
+
+ return iommu_fwspec_add_ids(dev, args->args, 1);
--- /dev/null
+From c77ad28bfee0df9cbc719eb5adc9864462cfb65b Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Mon, 20 Oct 2025 06:53:12 +0200
+Subject: iommu/mediatek-v1: fix device leak on probe_device()
+
+From: Johan Hovold <johan@kernel.org>
+
+commit c77ad28bfee0df9cbc719eb5adc9864462cfb65b upstream.
+
+Make sure to drop the reference taken to the iommu platform device when
+looking up its driver data during probe_device().
+
+Fixes: b17336c55d89 ("iommu/mediatek: add support for mtk iommu generation one HW")
+Cc: stable@vger.kernel.org # 4.8
+Cc: Honghui Zhang <honghui.zhang@mediatek.com>
+Acked-by: Robin Murphy <robin.murphy@arm.com>
+Reviewed-by: Yong Wu <yong.wu@mediatek.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/mtk_iommu_v1.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/iommu/mtk_iommu_v1.c
++++ b/drivers/iommu/mtk_iommu_v1.c
+@@ -435,6 +435,8 @@ static int mtk_iommu_v1_create_mapping(s
+ return -EINVAL;
+
+ dev_iommu_priv_set(dev, platform_get_drvdata(m4updev));
++
++ put_device(&m4updev->dev);
+ }
+
+ ret = iommu_fwspec_add_ids(dev, args->args, 1);
--- /dev/null
+From 46207625c9f33da0e43bb4ae1e91f0791b6ed633 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Mon, 20 Oct 2025 06:53:13 +0200
+Subject: iommu/mediatek-v1: fix device leaks on probe()
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 46207625c9f33da0e43bb4ae1e91f0791b6ed633 upstream.
+
+Make sure to drop the references taken to the larb devices during
+probe on probe failure (e.g. probe deferral) and on driver unbind.
+
+Fixes: b17336c55d89 ("iommu/mediatek: add support for mtk iommu generation one HW")
+Cc: stable@vger.kernel.org # 4.8
+Cc: Honghui Zhang <honghui.zhang@mediatek.com>
+Acked-by: Robin Murphy <robin.murphy@arm.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/mtk_iommu_v1.c | 23 ++++++++++++++++++-----
+ 1 file changed, 18 insertions(+), 5 deletions(-)
+
+--- a/drivers/iommu/mtk_iommu_v1.c
++++ b/drivers/iommu/mtk_iommu_v1.c
+@@ -648,8 +648,10 @@ static int mtk_iommu_v1_probe(struct pla
+ struct platform_device *plarbdev;
+
+ larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i);
+- if (!larbnode)
+- return -EINVAL;
++ if (!larbnode) {
++ ret = -EINVAL;
++ goto out_put_larbs;
++ }
+
+ if (!of_device_is_available(larbnode)) {
+ of_node_put(larbnode);
+@@ -659,11 +661,14 @@ static int mtk_iommu_v1_probe(struct pla
+ plarbdev = of_find_device_by_node(larbnode);
+ if (!plarbdev) {
+ of_node_put(larbnode);
+- return -ENODEV;
++ ret = -ENODEV;
++ goto out_put_larbs;
+ }
+ if (!plarbdev->dev.driver) {
+ of_node_put(larbnode);
+- return -EPROBE_DEFER;
++ put_device(&plarbdev->dev);
++ ret = -EPROBE_DEFER;
++ goto out_put_larbs;
+ }
+ data->larb_imu[i].dev = &plarbdev->dev;
+
+@@ -675,7 +680,7 @@ static int mtk_iommu_v1_probe(struct pla
+
+ ret = mtk_iommu_v1_hw_init(data);
+ if (ret)
+- return ret;
++ goto out_put_larbs;
+
+ ret = iommu_device_sysfs_add(&data->iommu, &pdev->dev, NULL,
+ dev_name(&pdev->dev));
+@@ -697,12 +702,17 @@ out_sysfs_remove:
+ iommu_device_sysfs_remove(&data->iommu);
+ out_clk_unprepare:
+ clk_disable_unprepare(data->bclk);
++out_put_larbs:
++ for (i = 0; i < MTK_LARB_NR_MAX; i++)
++ put_device(data->larb_imu[i].dev);
++
+ return ret;
+ }
+
+ static void mtk_iommu_v1_remove(struct platform_device *pdev)
+ {
+ struct mtk_iommu_v1_data *data = platform_get_drvdata(pdev);
++ int i;
+
+ iommu_device_sysfs_remove(&data->iommu);
+ iommu_device_unregister(&data->iommu);
+@@ -710,6 +720,9 @@ static void mtk_iommu_v1_remove(struct p
+ clk_disable_unprepare(data->bclk);
+ devm_free_irq(&pdev->dev, data->irq, data);
+ component_master_del(&pdev->dev, &mtk_iommu_v1_com_ops);
++
++ for (i = 0; i < MTK_LARB_NR_MAX; i++)
++ put_device(data->larb_imu[i].dev);
+ }
+
+ static int __maybe_unused mtk_iommu_v1_suspend(struct device *dev)
--- /dev/null
+From b5870691065e6bbe6ba0650c0412636c6a239c5a Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Mon, 20 Oct 2025 06:53:15 +0200
+Subject: iommu/omap: fix device leaks on probe_device()
+
+From: Johan Hovold <johan@kernel.org>
+
+commit b5870691065e6bbe6ba0650c0412636c6a239c5a upstream.
+
+Make sure to drop the references taken to the iommu platform devices
+when looking up their driver data during probe_device().
+
+Note that the arch data device pointer added by commit 604629bcb505
+("iommu/omap: add support for late attachment of iommu devices") has
+never been used. Remove it to underline that the references are not
+needed.
+
+Fixes: 9d5018deec86 ("iommu/omap: Add support to program multiple iommus")
+Fixes: 7d6827748d54 ("iommu/omap: Fix iommu archdata name for DT-based devices")
+Cc: stable@vger.kernel.org # 3.18
+Cc: Suman Anna <s-anna@ti.com>
+Acked-by: Robin Murphy <robin.murphy@arm.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/omap-iommu.c | 2 +-
+ drivers/iommu/omap-iommu.h | 2 --
+ 2 files changed, 1 insertion(+), 3 deletions(-)
+
+--- a/drivers/iommu/omap-iommu.c
++++ b/drivers/iommu/omap-iommu.c
+@@ -1675,6 +1675,7 @@ static struct iommu_device *omap_iommu_p
+ }
+
+ oiommu = platform_get_drvdata(pdev);
++ put_device(&pdev->dev);
+ if (!oiommu) {
+ of_node_put(np);
+ kfree(arch_data);
+@@ -1682,7 +1683,6 @@ static struct iommu_device *omap_iommu_p
+ }
+
+ tmp->iommu_dev = oiommu;
+- tmp->dev = &pdev->dev;
+
+ of_node_put(np);
+ }
+--- a/drivers/iommu/omap-iommu.h
++++ b/drivers/iommu/omap-iommu.h
+@@ -88,7 +88,6 @@ struct omap_iommu {
+ /**
+ * struct omap_iommu_arch_data - omap iommu private data
+ * @iommu_dev: handle of the OMAP iommu device
+- * @dev: handle of the iommu device
+ *
+ * This is an omap iommu private data object, which binds an iommu user
+ * to its iommu device. This object should be placed at the iommu user's
+@@ -97,7 +96,6 @@ struct omap_iommu {
+ */
+ struct omap_iommu_arch_data {
+ struct omap_iommu *iommu_dev;
+- struct device *dev;
+ };
+
+ struct cr_regs {
--- /dev/null
+From 6a3908ce56e6879920b44ef136252b2f0c954194 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Mon, 20 Oct 2025 06:53:06 +0200
+Subject: iommu/qcom: fix device leak on of_xlate()
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 6a3908ce56e6879920b44ef136252b2f0c954194 upstream.
+
+Make sure to drop the reference taken to the iommu platform device when
+looking up its driver data during of_xlate().
+
+Note that commit e2eae09939a8 ("iommu/qcom: add missing put_device()
+call in qcom_iommu_of_xlate()") fixed the leak in a couple of error
+paths, but the reference is still leaking on success and late failures.
+
+Fixes: 0ae349a0f33f ("iommu/qcom: Add qcom_iommu")
+Cc: stable@vger.kernel.org # 4.14: e2eae09939a8
+Cc: Rob Clark <robin.clark@oss.qualcomm.com>
+Cc: Yu Kuai <yukuai3@huawei.com>
+Acked-by: Robin Murphy <robin.murphy@arm.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/arm/arm-smmu/qcom_iommu.c | 10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+--- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c
++++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
+@@ -565,14 +565,14 @@ static int qcom_iommu_of_xlate(struct de
+
+ qcom_iommu = platform_get_drvdata(iommu_pdev);
+
++ put_device(&iommu_pdev->dev);
++
+ /* make sure the asid specified in dt is valid, so we don't have
+ * to sanity check this elsewhere:
+ */
+ if (WARN_ON(asid > qcom_iommu->max_asid) ||
+- WARN_ON(qcom_iommu->ctxs[asid] == NULL)) {
+- put_device(&iommu_pdev->dev);
++ WARN_ON(qcom_iommu->ctxs[asid] == NULL))
+ return -EINVAL;
+- }
+
+ if (!dev_iommu_priv_get(dev)) {
+ dev_iommu_priv_set(dev, qcom_iommu);
+@@ -581,10 +581,8 @@ static int qcom_iommu_of_xlate(struct de
+ * multiple different iommu devices. Multiple context
+ * banks are ok, but multiple devices are not:
+ */
+- if (WARN_ON(qcom_iommu != dev_iommu_priv_get(dev))) {
+- put_device(&iommu_pdev->dev);
++ if (WARN_ON(qcom_iommu != dev_iommu_priv_get(dev)))
+ return -EINVAL;
+- }
+ }
+
+ return iommu_fwspec_add_ids(dev, &asid, 1);
--- /dev/null
+From f916109bf53864605d10bf6f4215afa023a80406 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Mon, 20 Oct 2025 06:53:17 +0200
+Subject: iommu/sun50i: fix device leak on of_xlate()
+
+From: Johan Hovold <johan@kernel.org>
+
+commit f916109bf53864605d10bf6f4215afa023a80406 upstream.
+
+Make sure to drop the reference taken to the iommu platform device when
+looking up its driver data during of_xlate().
+
+Fixes: 4100b8c229b3 ("iommu: Add Allwinner H6 IOMMU driver")
+Cc: stable@vger.kernel.org # 5.8
+Cc: Maxime Ripard <mripard@kernel.org>
+Acked-by: Robin Murphy <robin.murphy@arm.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/sun50i-iommu.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/iommu/sun50i-iommu.c
++++ b/drivers/iommu/sun50i-iommu.c
+@@ -839,6 +839,8 @@ static int sun50i_iommu_of_xlate(struct
+
+ dev_iommu_priv_set(dev, platform_get_drvdata(iommu_pdev));
+
++ put_device(&iommu_pdev->dev);
++
+ return iommu_fwspec_add_ids(dev, &id, 1);
+ }
+
--- /dev/null
+From c08934a61201db8f1d1c66fcc63fb2eb526b656d Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Mon, 20 Oct 2025 06:53:18 +0200
+Subject: iommu/tegra: fix device leak on probe_device()
+
+From: Johan Hovold <johan@kernel.org>
+
+commit c08934a61201db8f1d1c66fcc63fb2eb526b656d upstream.
+
+Make sure to drop the reference taken to the iommu platform device when
+looking up its driver data during probe_device().
+
+Note that commit 9826e393e4a8 ("iommu/tegra-smmu: Fix missing
+put_device() call in tegra_smmu_find") fixed the leak in an error path,
+but the reference is still leaking on success.
+
+Fixes: 891846516317 ("memory: Add NVIDIA Tegra memory controller support")
+Cc: stable@vger.kernel.org # 3.19: 9826e393e4a8
+Cc: Miaoqian Lin <linmq006@gmail.com>
+Acked-by: Robin Murphy <robin.murphy@arm.com>
+Acked-by: Thierry Reding <treding@nvidia.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/tegra-smmu.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/drivers/iommu/tegra-smmu.c
++++ b/drivers/iommu/tegra-smmu.c
+@@ -830,10 +830,9 @@ static struct tegra_smmu *tegra_smmu_fin
+ return NULL;
+
+ mc = platform_get_drvdata(pdev);
+- if (!mc) {
+- put_device(&pdev->dev);
++ put_device(&pdev->dev);
++ if (!mc)
+ return NULL;
+- }
+
+ return mc->smmu;
+ }
--- /dev/null
+From 68f6bd128e75a032432eda9d16676ed2969a1096 Mon Sep 17 00:00:00 2001
+From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
+Date: Fri, 18 Jul 2025 20:53:58 +0100
+Subject: ntfs: Do not overwrite uptodate pages
+
+From: Matthew Wilcox (Oracle) <willy@infradead.org>
+
+commit 68f6bd128e75a032432eda9d16676ed2969a1096 upstream.
+
+When reading a compressed file, we may read several pages in addition to
+the one requested. The current code will overwrite pages in the page
+cache with the data from disc which can definitely result in changes
+that have been made being lost.
+
+For example if we have four consecutie pages ABCD in the file compressed
+into a single extent, on first access, we'll bring in ABCD. Then we
+write to page B. Memory pressure results in the eviction of ACD.
+When we attempt to write to page C, we will overwrite the data in page
+B with the data currently on disk.
+
+I haven't investigated the decompression code to check whether it's
+OK to overwrite a clean page or whether it might be possible to see
+corrupt data. Out of an abundance of caution, decline to overwrite
+uptodate pages, not just dirty pages.
+
+Fixes: 4342306f0f0d (fs/ntfs3: Add file operations and implementation)
+Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ntfs3/frecord.c | 35 +++++++++++++++++++++++++++++------
+ 1 file changed, 29 insertions(+), 6 deletions(-)
+
+--- a/fs/ntfs3/frecord.c
++++ b/fs/ntfs3/frecord.c
+@@ -2022,6 +2022,29 @@ out:
+ return err;
+ }
+
++static struct page *ntfs_lock_new_page(struct address_space *mapping,
++ pgoff_t index, gfp_t gfp)
++{
++ struct folio *folio = __filemap_get_folio(mapping, index,
++ FGP_LOCK | FGP_ACCESSED | FGP_CREAT, gfp);
++ struct page *page;
++
++ if (IS_ERR(folio))
++ return ERR_CAST(folio);
++
++ if (!folio_test_uptodate(folio))
++ return folio_file_page(folio, index);
++
++ /* Use a temporary page to avoid data corruption */
++ folio_unlock(folio);
++ folio_put(folio);
++ page = alloc_page(gfp);
++ if (!page)
++ return ERR_PTR(-ENOMEM);
++ __SetPageLocked(page);
++ return page;
++}
++
+ /*
+ * ni_readpage_cmpr
+ *
+@@ -2076,9 +2099,9 @@ int ni_readpage_cmpr(struct ntfs_inode *
+ if (i == idx)
+ continue;
+
+- pg = find_or_create_page(mapping, index, gfp_mask);
+- if (!pg) {
+- err = -ENOMEM;
++ pg = ntfs_lock_new_page(mapping, index, gfp_mask);
++ if (IS_ERR(pg)) {
++ err = PTR_ERR(pg);
+ goto out1;
+ }
+ pages[i] = pg;
+@@ -2177,13 +2200,13 @@ int ni_decompress_file(struct ntfs_inode
+ for (i = 0; i < pages_per_frame; i++, index++) {
+ struct page *pg;
+
+- pg = find_or_create_page(mapping, index, gfp_mask);
+- if (!pg) {
++ pg = ntfs_lock_new_page(mapping, index, gfp_mask);
++ if (IS_ERR(pg)) {
+ while (i--) {
+ unlock_page(pages[i]);
+ put_page(pages[i]);
+ }
+- err = -ENOMEM;
++ err = PTR_ERR(pg);
+ goto out;
+ }
+ pages[i] = pg;
rdma-bnxt_re-fix-dma_free_coherent-pointer.patch
blk-mq-skip-cpu-offline-notify-on-unmapped-hctx.patch
selftests-ftrace-traceonoff_triggers-strip-off-names.patch
+block-handle-zone-management-operations-completions.patch
+ntfs-do-not-overwrite-uptodate-pages.patch
+asoc-codecs-wcd939x-fix-regmap-leak-on-probe-failure.patch
+asoc-stm32-sai-fix-device-leak-on-probe.patch
+asoc-stm32-sai-fix-clk-prepare-imbalance-on-probe-failure.patch
+asoc-stm32-sai-fix-of-node-leak-on-probe.patch
+asoc-renesas-rz-ssi-fix-channel-swap-issue-in-full-duplex-mode.patch
+asoc-renesas-rz-ssi-fix-rz_ssi_priv-hw_params_cache-sample_width.patch
+asoc-codecs-wcd937x-fix-error-handling-in-wcd937x-codec-driver.patch
+asoc-codecs-pm4125-fix-potential-conflict-when-probing-two-devices.patch
+asoc-codecs-pm4125-remove-irq_chip-on-component-unbind.patch
+asoc-codecs-lpass-tx-macro-fix-sm6115-support.patch
+asoc-qcom-sdw-fix-memory-leak-for-sdw_stream_runtime.patch
+asoc-cs35l41-always-return-0-when-a-subsystem-id-is-found.patch
+asoc-codecs-fix-error-handling-in-pm4125-audio-codec-driver.patch
+asoc-qcom-q6apm-dai-set-flags-to-reflect-correct-operation-of-appl_ptr.patch
+asoc-qcom-q6asm-dai-perform-correct-state-check-before-closing.patch
+asoc-qcom-q6adm-the-the-copp-device-only-during-last-instance.patch
+asoc-qcom-qdsp6-q6asm-dai-set-10-ms-period-and-buffer-alignment.patch
+iommu-amd-fix-pci_segment-memleak-in-alloc_pci_segment.patch
+iommu-amd-propagate-the-error-code-returned-by-__modify_irte_ga-in-modify_irte_ga.patch
+iommu-apple-dart-fix-device-leak-on-of_xlate.patch
+iommu-exynos-fix-device-leak-on-of_xlate.patch
+iommu-ipmmu-vmsa-fix-device-leak-on-of_xlate.patch
+iommu-mediatek-v1-fix-device-leak-on-probe_device.patch
+iommu-mediatek-v1-fix-device-leaks-on-probe.patch
+iommu-mediatek-fix-device-leak-on-of_xlate.patch
+iommu-omap-fix-device-leaks-on-probe_device.patch
+iommu-qcom-fix-device-leak-on-of_xlate.patch
+iommu-sun50i-fix-device-leak-on-of_xlate.patch
+iommu-tegra-fix-device-leak-on-probe_device.patch
+iommu-disable-sva-when-config_x86-is-set.patch
+hwmon-dell-smm-fix-off-by-one-error-in-dell_smm_is_visible.patch
+hid-logitech-dj-remove-duplicate-error-logging.patch
+hisi_acc_vfio_pci-add-.match_token_uuid-callback-in-hisi_acc_vfio_pci_migrn_ops.patch