From: Greg Kroah-Hartman Date: Mon, 5 Jan 2026 09:42:01 +0000 (+0100) Subject: 6.18-stable patches X-Git-Tag: v6.12.64~42 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9db2c1b0c24f989d28c2a371fdbb867b98784749;p=thirdparty%2Fkernel%2Fstable-queue.git 6.18-stable patches added patches: asoc-codecs-fix-error-handling-in-pm4125-audio-codec-driver.patch asoc-codecs-lpass-tx-macro-fix-sm6115-support.patch asoc-codecs-pm4125-fix-potential-conflict-when-probing-two-devices.patch asoc-codecs-pm4125-remove-irq_chip-on-component-unbind.patch asoc-codecs-wcd937x-fix-error-handling-in-wcd937x-codec-driver.patch asoc-codecs-wcd939x-fix-regmap-leak-on-probe-failure.patch asoc-cs35l41-always-return-0-when-a-subsystem-id-is-found.patch asoc-qcom-q6adm-the-the-copp-device-only-during-last-instance.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-qdsp6-q6asm-dai-set-10-ms-period-and-buffer-alignment.patch asoc-qcom-sdw-fix-memory-leak-for-sdw_stream_runtime.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-stm32-sai-fix-clk-prepare-imbalance-on-probe-failure.patch asoc-stm32-sai-fix-device-leak-on-probe.patch asoc-stm32-sai-fix-of-node-leak-on-probe.patch block-handle-zone-management-operations-completions.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 hwmon-dell-smm-fix-off-by-one-error-in-dell_smm_is_visible.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-disable-sva-when-config_x86-is-set.patch iommu-exynos-fix-device-leak-on-of_xlate.patch iommu-ipmmu-vmsa-fix-device-leak-on-of_xlate.patch iommu-mediatek-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-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 ntfs-do-not-overwrite-uptodate-pages.patch --- diff --git a/queue-6.18/asoc-codecs-fix-error-handling-in-pm4125-audio-codec-driver.patch b/queue-6.18/asoc-codecs-fix-error-handling-in-pm4125-audio-codec-driver.patch new file mode 100644 index 0000000000..dafa6342a8 --- /dev/null +++ b/queue-6.18/asoc-codecs-fix-error-handling-in-pm4125-audio-codec-driver.patch @@ -0,0 +1,96 @@ +From 2196e8172bee2002e9baaa0d02b2f9f2dd213949 Mon Sep 17 00:00:00 2001 +From: Ma Ke +Date: Sun, 16 Nov 2025 11:37:16 +0800 +Subject: ASoC: codecs: Fix error handling in pm4125 audio codec driver + +From: Ma Ke + +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 +Reviewed-by: Dmitry Baryshkov +Link: https://patch.msgid.link/20251116033716.29369-1-make24@iscas.ac.cn +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + 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); + } + diff --git a/queue-6.18/asoc-codecs-lpass-tx-macro-fix-sm6115-support.patch b/queue-6.18/asoc-codecs-lpass-tx-macro-fix-sm6115-support.patch new file mode 100644 index 0000000000..711e37915c --- /dev/null +++ b/queue-6.18/asoc-codecs-lpass-tx-macro-fix-sm6115-support.patch @@ -0,0 +1,36 @@ +From 7c63b5a8ed972a2c8c03d984f6a43349007cea93 Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla +Date: Fri, 31 Oct 2025 12:06:58 +0000 +Subject: ASoC: codecs: lpass-tx-macro: fix SM6115 support + +From: Srinivas Kandagatla + +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 +Link: https://patch.msgid.link/20251031120703.590201-2-srinivas.kandagatla@oss.qualcomm.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + 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), diff --git a/queue-6.18/asoc-codecs-pm4125-fix-potential-conflict-when-probing-two-devices.patch b/queue-6.18/asoc-codecs-pm4125-fix-potential-conflict-when-probing-two-devices.patch new file mode 100644 index 0000000000..c274b3a4aa --- /dev/null +++ b/queue-6.18/asoc-codecs-pm4125-fix-potential-conflict-when-probing-two-devices.patch @@ -0,0 +1,89 @@ +From fd94857a934cbe613353810a024c84d54826ead3 Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Thu, 23 Oct 2025 11:02:50 +0200 +Subject: ASoC: codecs: pm4125: Fix potential conflict when probing two devices + +From: Krzysztof Kozlowski + +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 +Link: https://patch.msgid.link/20251023-asoc-regmap-irq-chip-v1-1-17ad32680913@linaro.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + 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) diff --git a/queue-6.18/asoc-codecs-pm4125-remove-irq_chip-on-component-unbind.patch b/queue-6.18/asoc-codecs-pm4125-remove-irq_chip-on-component-unbind.patch new file mode 100644 index 0000000000..21e3718f85 --- /dev/null +++ b/queue-6.18/asoc-codecs-pm4125-remove-irq_chip-on-component-unbind.patch @@ -0,0 +1,36 @@ +From e65b871c9b5af9265aefc5b8cd34993586d93aab Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Thu, 23 Oct 2025 11:02:51 +0200 +Subject: ASoC: codecs: pm4125: Remove irq_chip on component unbind + +From: Krzysztof Kozlowski + +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 +Link: https://patch.msgid.link/20251023-asoc-regmap-irq-chip-v1-2-17ad32680913@linaro.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-6.18/asoc-codecs-wcd937x-fix-error-handling-in-wcd937x-codec-driver.patch b/queue-6.18/asoc-codecs-wcd937x-fix-error-handling-in-wcd937x-codec-driver.patch new file mode 100644 index 0000000000..e6f2c7b02f --- /dev/null +++ b/queue-6.18/asoc-codecs-wcd937x-fix-error-handling-in-wcd937x-codec-driver.patch @@ -0,0 +1,140 @@ +From 578ccfe344c5f421c2c6343b872995b397ffd3ff Mon Sep 17 00:00:00 2001 +From: Ma Ke +Date: Sun, 16 Nov 2025 14:16:23 +0800 +Subject: ASoC: codecs: wcd937x: Fix error handling in wcd937x codec driver + +From: Ma Ke + +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 +Reviewed-by: David Heidelberg +Link: https://patch.msgid.link/20251116061623.11830-1-make24@iscas.ac.cn +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + 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 = { diff --git a/queue-6.18/asoc-codecs-wcd939x-fix-regmap-leak-on-probe-failure.patch b/queue-6.18/asoc-codecs-wcd939x-fix-regmap-leak-on-probe-failure.patch new file mode 100644 index 0000000000..f18df7a8e9 --- /dev/null +++ b/queue-6.18/asoc-codecs-wcd939x-fix-regmap-leak-on-probe-failure.patch @@ -0,0 +1,47 @@ +From 86dc090f737953f16f8dc60c546ae7854690d4f6 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Thu, 27 Nov 2025 14:50:57 +0100 +Subject: ASoC: codecs: wcd939x: fix regmap leak on probe failure + +From: Johan Hovold + +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 +Signed-off-by: Johan Hovold +Link: https://patch.msgid.link/20251127135057.2216-1-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + 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) diff --git a/queue-6.18/asoc-cs35l41-always-return-0-when-a-subsystem-id-is-found.patch b/queue-6.18/asoc-cs35l41-always-return-0-when-a-subsystem-id-is-found.patch new file mode 100644 index 0000000000..6144163434 --- /dev/null +++ b/queue-6.18/asoc-cs35l41-always-return-0-when-a-subsystem-id-is-found.patch @@ -0,0 +1,56 @@ +From b0ff70e9d4fe46cece25eb97b9b9b0166624af95 Mon Sep 17 00:00:00 2001 +From: Eric Naim +Date: Sun, 7 Dec 2025 03:38:12 +0800 +Subject: ASoC: cs35l41: Always return 0 when a subsystem ID is found + +From: Eric Naim + +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 +Reviewed-by: Richard Fitzgerald +Link: https://patch.msgid.link/20251206193813.56955-1-dnaim@cachyos.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + 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 + diff --git a/queue-6.18/asoc-qcom-q6adm-the-the-copp-device-only-during-last-instance.patch b/queue-6.18/asoc-qcom-q6adm-the-the-copp-device-only-during-last-instance.patch new file mode 100644 index 0000000000..2797032c60 --- /dev/null +++ b/queue-6.18/asoc-qcom-q6adm-the-the-copp-device-only-during-last-instance.patch @@ -0,0 +1,223 @@ +From 74cc4f3ea4e99262ba0d619c6a4ee33e2cd47f65 Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla +Date: Thu, 23 Oct 2025 11:24:26 +0100 +Subject: ASoC: qcom: q6adm: the the copp device only during last instance + +From: Srinivas Kandagatla + +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 +Signed-off-by: Srinivas Kandagatla +Tested-by: Alexey Klimov # RB5, RB3 +Link: https://patch.msgid.link/20251023102444.88158-3-srinivas.kandagatla@oss.qualcomm.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + 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; diff --git a/queue-6.18/asoc-qcom-q6apm-dai-set-flags-to-reflect-correct-operation-of-appl_ptr.patch b/queue-6.18/asoc-qcom-q6apm-dai-set-flags-to-reflect-correct-operation-of-appl_ptr.patch new file mode 100644 index 0000000000..a251d36e70 --- /dev/null +++ b/queue-6.18/asoc-qcom-q6apm-dai-set-flags-to-reflect-correct-operation-of-appl_ptr.patch @@ -0,0 +1,45 @@ +From 950a4e5788fc7dc6e8e93614a7d4d0449c39fb8d Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla +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 + +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 +Tested-by: Alexey Klimov # RB5, RB3 +Link: https://patch.msgid.link/20251023102444.88158-2-srinivas.kandagatla@oss.qualcomm.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + 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, diff --git a/queue-6.18/asoc-qcom-q6asm-dai-perform-correct-state-check-before-closing.patch b/queue-6.18/asoc-qcom-q6asm-dai-perform-correct-state-check-before-closing.patch new file mode 100644 index 0000000000..6f7a4b1e43 --- /dev/null +++ b/queue-6.18/asoc-qcom-q6asm-dai-perform-correct-state-check-before-closing.patch @@ -0,0 +1,45 @@ +From bfbb12dfa144d45575bcfe139a71360b3ce80237 Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla +Date: Thu, 23 Oct 2025 11:24:28 +0100 +Subject: ASoC: qcom: q6asm-dai: perform correct state check before closing + +From: Srinivas Kandagatla + +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 +Tested-by: Alexey Klimov # RB5, RB3 +Link: https://patch.msgid.link/20251023102444.88158-5-srinivas.kandagatla@oss.qualcomm.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + 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, diff --git a/queue-6.18/asoc-qcom-qdsp6-q6asm-dai-set-10-ms-period-and-buffer-alignment.patch b/queue-6.18/asoc-qcom-qdsp6-q6asm-dai-set-10-ms-period-and-buffer-alignment.patch new file mode 100644 index 0000000000..15a01eeb76 --- /dev/null +++ b/queue-6.18/asoc-qcom-qdsp6-q6asm-dai-set-10-ms-period-and-buffer-alignment.patch @@ -0,0 +1,46 @@ +From 81c53b52de21b8d5a3de55ebd06b6bf188bf7efd Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla +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 + +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 +Tested-by: Alexey Klimov # RB5, RB3 +Link: https://patch.msgid.link/20251023102444.88158-4-srinivas.kandagatla@oss.qualcomm.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-6.18/asoc-qcom-sdw-fix-memory-leak-for-sdw_stream_runtime.patch b/queue-6.18/asoc-qcom-sdw-fix-memory-leak-for-sdw_stream_runtime.patch new file mode 100644 index 0000000000..f20f250e2c --- /dev/null +++ b/queue-6.18/asoc-qcom-sdw-fix-memory-leak-for-sdw_stream_runtime.patch @@ -0,0 +1,245 @@ +From bcba17279327c6e85dee6a97014dc642e2dc93cc Mon Sep 17 00:00:00 2001 +From: Srinivas Kandagatla +Date: Wed, 22 Oct 2025 15:33:46 +0100 +Subject: ASoC: qcom: sdw: fix memory leak for sdw_stream_runtime + +From: Srinivas Kandagatla + +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 +Cc: Stable@vger.kernel.org +Signed-off-by: Srinivas Kandagatla +Tested-by: Steev Klimaszewski # Thinkpad X13s +Link: https://patch.msgid.link/20251022143349.1081513-2-srinivas.kandagatla@oss.qualcomm.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #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); diff --git a/queue-6.18/asoc-renesas-rz-ssi-fix-channel-swap-issue-in-full-duplex-mode.patch b/queue-6.18/asoc-renesas-rz-ssi-fix-channel-swap-issue-in-full-duplex-mode.patch new file mode 100644 index 0000000000..de359aa397 --- /dev/null +++ b/queue-6.18/asoc-renesas-rz-ssi-fix-channel-swap-issue-in-full-duplex-mode.patch @@ -0,0 +1,123 @@ +From 52a525011cb8e293799a085436f026f2958403f9 Mon Sep 17 00:00:00 2001 +From: Biju Das +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 + +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 +Signed-off-by: Tony Tang +Reviewed-by: Kuninori Morimoto +Signed-off-by: Biju Das +Link: https://patch.msgid.link/20251114073709.4376-2-biju.das.jz@bp.renesas.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + 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, diff --git a/queue-6.18/asoc-renesas-rz-ssi-fix-rz_ssi_priv-hw_params_cache-sample_width.patch b/queue-6.18/asoc-renesas-rz-ssi-fix-rz_ssi_priv-hw_params_cache-sample_width.patch new file mode 100644 index 0000000000..90ba6a4418 --- /dev/null +++ b/queue-6.18/asoc-renesas-rz-ssi-fix-rz_ssi_priv-hw_params_cache-sample_width.patch @@ -0,0 +1,85 @@ +From 2bae7beda19f3b2dc6ab2062c94df19c27923712 Mon Sep 17 00:00:00 2001 +From: Biju Das +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 + +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 +Signed-off-by: Biju Das +Link: https://patch.msgid.link/20251114073709.4376-3-biju.das.jz@bp.renesas.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include + #include + + /* 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) diff --git a/queue-6.18/asoc-stm32-sai-fix-clk-prepare-imbalance-on-probe-failure.patch b/queue-6.18/asoc-stm32-sai-fix-clk-prepare-imbalance-on-probe-failure.patch new file mode 100644 index 0000000000..cfaec8710e --- /dev/null +++ b/queue-6.18/asoc-stm32-sai-fix-clk-prepare-imbalance-on-probe-failure.patch @@ -0,0 +1,89 @@ +From 312ec2f0d9d1a5656f76d770bbf1d967e9289aa7 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 24 Nov 2025 11:49:06 +0100 +Subject: ASoC: stm32: sai: fix clk prepare imbalance on probe failure + +From: Johan Hovold + +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 +Signed-off-by: Johan Hovold +Reviewed-by: olivier moysan +Link: https://patch.msgid.link/20251124104908.15754-3-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + 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) diff --git a/queue-6.18/asoc-stm32-sai-fix-device-leak-on-probe.patch b/queue-6.18/asoc-stm32-sai-fix-device-leak-on-probe.patch new file mode 100644 index 0000000000..91cf50a1da --- /dev/null +++ b/queue-6.18/asoc-stm32-sai-fix-device-leak-on-probe.patch @@ -0,0 +1,48 @@ +From e26ff429eaf10c4ef1bc3dabd9bf27eb54b7e1f4 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 24 Nov 2025 11:49:05 +0100 +Subject: ASoC: stm32: sai: fix device leak on probe + +From: Johan Hovold + +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 +Cc: Wen Yang +Signed-off-by: Johan Hovold +Reviewed-by: olivier moysan +Link: https://patch.msgid.link/20251124104908.15754-2-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + 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; + } diff --git a/queue-6.18/asoc-stm32-sai-fix-of-node-leak-on-probe.patch b/queue-6.18/asoc-stm32-sai-fix-of-node-leak-on-probe.patch new file mode 100644 index 0000000000..e56952e0e1 --- /dev/null +++ b/queue-6.18/asoc-stm32-sai-fix-of-node-leak-on-probe.patch @@ -0,0 +1,145 @@ +From 23261f0de09427367e99f39f588e31e2856a690e Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 24 Nov 2025 11:49:07 +0100 +Subject: ASoC: stm32: sai: fix OF node leak on probe + +From: Johan Hovold + +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 +Cc: stable@vger.kernel.org # 4.16: d4180b4c02e7 +Signed-off-by: Johan Hovold +Reviewed-by: olivier moysan +Link: https://patch.msgid.link/20251124104908.15754-4-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + 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) diff --git a/queue-6.18/block-handle-zone-management-operations-completions.patch b/queue-6.18/block-handle-zone-management-operations-completions.patch new file mode 100644 index 0000000000..bb2d51727a --- /dev/null +++ b/queue-6.18/block-handle-zone-management-operations-completions.patch @@ -0,0 +1,270 @@ +From efae226c2ef19528ffd81d29ba0eecf1b0896ca2 Mon Sep 17 00:00:00 2001 +From: Damien Le Moal +Date: Wed, 5 Nov 2025 06:22:35 +0900 +Subject: block: handle zone management operations completions + +From: Damien Le Moal + +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 +Reviewed-by: Christoph Hellwig +Reviewed-by: Johannes Thumshirn +Reviewed-by: Chaitanya Kulkarni +Reviewed-by: Hannes Reinecke +Reviewed-by: Martin K. Petersen +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + 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. + */ diff --git a/queue-6.18/hid-logitech-dj-remove-duplicate-error-logging.patch b/queue-6.18/hid-logitech-dj-remove-duplicate-error-logging.patch new file mode 100644 index 0000000000..b749316118 --- /dev/null +++ b/queue-6.18/hid-logitech-dj-remove-duplicate-error-logging.patch @@ -0,0 +1,163 @@ +From ca389a55d8b2d86a817433bf82e0602b68c4d541 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sat, 8 Nov 2025 22:03:18 +0100 +Subject: HID: logitech-dj: Remove duplicate error logging + +From: Hans de Goede + +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 +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman +--- + 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 diff --git a/queue-6.18/hisi_acc_vfio_pci-add-.match_token_uuid-callback-in-hisi_acc_vfio_pci_migrn_ops.patch b/queue-6.18/hisi_acc_vfio_pci-add-.match_token_uuid-callback-in-hisi_acc_vfio_pci_migrn_ops.patch new file mode 100644 index 0000000000..2f12f43c24 --- /dev/null +++ b/queue-6.18/hisi_acc_vfio_pci-add-.match_token_uuid-callback-in-hisi_acc_vfio_pci_migrn_ops.patch @@ -0,0 +1,37 @@ +From 0ed3a30fd996cb0cac872432cf25185fda7e5316 Mon Sep 17 00:00:00 2001 +From: Raghavendra Rao Ananta +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 + +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 +Signed-off-by: Raghavendra Rao Ananta +Reviewed-by: Longfang Liu +Reviewed-by: Jason Gunthorpe +Link: https://lore.kernel.org/r/20251031170603.2260022-3-rananta@google.com +Signed-off-by: Alex Williamson +Signed-off-by: Greg Kroah-Hartman +--- + 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, diff --git a/queue-6.18/hwmon-dell-smm-fix-off-by-one-error-in-dell_smm_is_visible.patch b/queue-6.18/hwmon-dell-smm-fix-off-by-one-error-in-dell_smm_is_visible.patch new file mode 100644 index 0000000000..4a8c75b1bd --- /dev/null +++ b/queue-6.18/hwmon-dell-smm-fix-off-by-one-error-in-dell_smm_is_visible.patch @@ -0,0 +1,40 @@ +From fae00a7186cecf90a57757a63b97a0cbcf384fe9 Mon Sep 17 00:00:00 2001 +From: Armin Wolf +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 + +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 +Link: https://lore.kernel.org/r/20251203202109.331528-1-W_Armin@gmx.de +Signed-off-by: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman +--- + 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; + + /* diff --git a/queue-6.18/iommu-amd-fix-pci_segment-memleak-in-alloc_pci_segment.patch b/queue-6.18/iommu-amd-fix-pci_segment-memleak-in-alloc_pci_segment.patch new file mode 100644 index 0000000000..7eeb57fa2c --- /dev/null +++ b/queue-6.18/iommu-amd-fix-pci_segment-memleak-in-alloc_pci_segment.patch @@ -0,0 +1,51 @@ +From 75ba146c2674ba49ed8a222c67f9abfb4a4f2a4f Mon Sep 17 00:00:00 2001 +From: Jinhui Guo +Date: Tue, 28 Oct 2025 00:50:17 +0800 +Subject: iommu/amd: Fix pci_segment memleak in alloc_pci_segment() + +From: Jinhui Guo + +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 +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman +--- + 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, diff --git a/queue-6.18/iommu-amd-propagate-the-error-code-returned-by-__modify_irte_ga-in-modify_irte_ga.patch b/queue-6.18/iommu-amd-propagate-the-error-code-returned-by-__modify_irte_ga-in-modify_irte_ga.patch new file mode 100644 index 0000000000..56aea6385e --- /dev/null +++ b/queue-6.18/iommu-amd-propagate-the-error-code-returned-by-__modify_irte_ga-in-modify_irte_ga.patch @@ -0,0 +1,35 @@ +From 2381a1b40be4b286062fb3cf67dd7f005692aa2a Mon Sep 17 00:00:00 2001 +From: Jinhui Guo +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 + +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 +Reviewed-by: Vasant Hegde +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman +--- + 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) diff --git a/queue-6.18/iommu-apple-dart-fix-device-leak-on-of_xlate.patch b/queue-6.18/iommu-apple-dart-fix-device-leak-on-of_xlate.patch new file mode 100644 index 0000000000..68eb07797d --- /dev/null +++ b/queue-6.18/iommu-apple-dart-fix-device-leak-on-of_xlate.patch @@ -0,0 +1,34 @@ +From a6eaa872c52a181ae9a290fd4e40c9df91166d7a Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 20 Oct 2025 06:53:05 +0200 +Subject: iommu/apple-dart: fix device leak on of_xlate() + +From: Johan Hovold + +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 +Acked-by: Robin Murphy +Signed-off-by: Johan Hovold +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman +--- + 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]; diff --git a/queue-6.18/iommu-disable-sva-when-config_x86-is-set.patch b/queue-6.18/iommu-disable-sva-when-config_x86-is-set.patch new file mode 100644 index 0000000000..8692c5d0c6 --- /dev/null +++ b/queue-6.18/iommu-disable-sva-when-config_x86-is-set.patch @@ -0,0 +1,106 @@ +From 72f98ef9a4be30d2a60136dd6faee376f780d06c Mon Sep 17 00:00:00 2001 +From: Lu Baolu +Date: Wed, 22 Oct 2025 16:26:27 +0800 +Subject: iommu: disable SVA when CONFIG_X86 is set + +From: Lu Baolu + +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 +Suggested-by: Jason Gunthorpe +Reviewed-by: Jason Gunthorpe +Cc: Alistair Popple +Cc: Andy Lutomirski +Cc: Borislav Betkov +Cc: Dave Hansen +Cc: David Hildenbrand +Cc: Ingo Molnar +Cc: Jann Horn +Cc: Jean-Philippe Brucker +Cc: Joerg Roedel +Cc: Kevin Tian +Cc: Liam Howlett +Cc: Lorenzo Stoakes +Cc: Matthew Wilcox (Oracle) +Cc: Michal Hocko +Cc: Mike Rapoport +Cc: Peter Zijlstra +Cc: Robin Murohy +Cc: Thomas Gleinxer +Cc: "Uladzislau Rezki (Sony)" +Cc: Vasant Hegde +Cc: Vinicius Costa Gomes +Cc: Vlastimil Babka +Cc: Will Deacon +Cc: Yi Lai +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + 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. */ diff --git a/queue-6.18/iommu-exynos-fix-device-leak-on-of_xlate.patch b/queue-6.18/iommu-exynos-fix-device-leak-on-of_xlate.patch new file mode 100644 index 0000000000..696e440573 --- /dev/null +++ b/queue-6.18/iommu-exynos-fix-device-leak-on-of_xlate.patch @@ -0,0 +1,51 @@ +From 05913cc43cb122f9afecdbe775115c058b906e1b Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 20 Oct 2025 06:53:07 +0200 +Subject: iommu/exynos: fix device leak on of_xlate() + +From: Johan Hovold + +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 +Acked-by: Robin Murphy +Acked-by: Marek Szyprowski +Signed-off-by: Johan Hovold +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-6.18/iommu-ipmmu-vmsa-fix-device-leak-on-of_xlate.patch b/queue-6.18/iommu-ipmmu-vmsa-fix-device-leak-on-of_xlate.patch new file mode 100644 index 0000000000..b24d45dbd4 --- /dev/null +++ b/queue-6.18/iommu-ipmmu-vmsa-fix-device-leak-on-of_xlate.patch @@ -0,0 +1,34 @@ +From 80aa518452c4aceb9459f9a8e3184db657d1b441 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 20 Oct 2025 06:53:08 +0200 +Subject: iommu/ipmmu-vmsa: fix device leak on of_xlate() + +From: Johan Hovold + +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 +Acked-by: Robin Murphy +Signed-off-by: Johan Hovold +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman +--- + 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; + } + diff --git a/queue-6.18/iommu-mediatek-fix-device-leak-on-of_xlate.patch b/queue-6.18/iommu-mediatek-fix-device-leak-on-of_xlate.patch new file mode 100644 index 0000000000..984caab5de --- /dev/null +++ b/queue-6.18/iommu-mediatek-fix-device-leak-on-of_xlate.patch @@ -0,0 +1,35 @@ +From b3f1ee18280363ef17f82b564fc379ceba9ec86f Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 20 Oct 2025 06:53:09 +0200 +Subject: iommu/mediatek: fix device leak on of_xlate() + +From: Johan Hovold + +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 +Reviewed-by: Yong Wu +Signed-off-by: Johan Hovold +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-6.18/iommu-mediatek-v1-fix-device-leak-on-probe_device.patch b/queue-6.18/iommu-mediatek-v1-fix-device-leak-on-probe_device.patch new file mode 100644 index 0000000000..77d4eb5246 --- /dev/null +++ b/queue-6.18/iommu-mediatek-v1-fix-device-leak-on-probe_device.patch @@ -0,0 +1,36 @@ +From c77ad28bfee0df9cbc719eb5adc9864462cfb65b Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 20 Oct 2025 06:53:12 +0200 +Subject: iommu/mediatek-v1: fix device leak on probe_device() + +From: Johan Hovold + +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 +Acked-by: Robin Murphy +Reviewed-by: Yong Wu +Signed-off-by: Johan Hovold +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-6.18/iommu-mediatek-v1-fix-device-leaks-on-probe.patch b/queue-6.18/iommu-mediatek-v1-fix-device-leaks-on-probe.patch new file mode 100644 index 0000000000..043ab7c77e --- /dev/null +++ b/queue-6.18/iommu-mediatek-v1-fix-device-leaks-on-probe.patch @@ -0,0 +1,93 @@ +From 46207625c9f33da0e43bb4ae1e91f0791b6ed633 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 20 Oct 2025 06:53:13 +0200 +Subject: iommu/mediatek-v1: fix device leaks on probe() + +From: Johan Hovold + +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 +Acked-by: Robin Murphy +Signed-off-by: Johan Hovold +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman +--- + 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) diff --git a/queue-6.18/iommu-omap-fix-device-leaks-on-probe_device.patch b/queue-6.18/iommu-omap-fix-device-leaks-on-probe_device.patch new file mode 100644 index 0000000000..6f5f3ca7c5 --- /dev/null +++ b/queue-6.18/iommu-omap-fix-device-leaks-on-probe_device.patch @@ -0,0 +1,66 @@ +From b5870691065e6bbe6ba0650c0412636c6a239c5a Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 20 Oct 2025 06:53:15 +0200 +Subject: iommu/omap: fix device leaks on probe_device() + +From: Johan Hovold + +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 +Acked-by: Robin Murphy +Signed-off-by: Johan Hovold +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman +--- + 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 { diff --git a/queue-6.18/iommu-qcom-fix-device-leak-on-of_xlate.patch b/queue-6.18/iommu-qcom-fix-device-leak-on-of_xlate.patch new file mode 100644 index 0000000000..7be37157f5 --- /dev/null +++ b/queue-6.18/iommu-qcom-fix-device-leak-on-of_xlate.patch @@ -0,0 +1,60 @@ +From 6a3908ce56e6879920b44ef136252b2f0c954194 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 20 Oct 2025 06:53:06 +0200 +Subject: iommu/qcom: fix device leak on of_xlate() + +From: Johan Hovold + +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 +Cc: Yu Kuai +Acked-by: Robin Murphy +Signed-off-by: Johan Hovold +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-6.18/iommu-sun50i-fix-device-leak-on-of_xlate.patch b/queue-6.18/iommu-sun50i-fix-device-leak-on-of_xlate.patch new file mode 100644 index 0000000000..27a61cc73d --- /dev/null +++ b/queue-6.18/iommu-sun50i-fix-device-leak-on-of_xlate.patch @@ -0,0 +1,34 @@ +From f916109bf53864605d10bf6f4215afa023a80406 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 20 Oct 2025 06:53:17 +0200 +Subject: iommu/sun50i: fix device leak on of_xlate() + +From: Johan Hovold + +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 +Acked-by: Robin Murphy +Signed-off-by: Johan Hovold +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman +--- + 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); + } + diff --git a/queue-6.18/iommu-tegra-fix-device-leak-on-probe_device.patch b/queue-6.18/iommu-tegra-fix-device-leak-on-probe_device.patch new file mode 100644 index 0000000000..06245de36b --- /dev/null +++ b/queue-6.18/iommu-tegra-fix-device-leak-on-probe_device.patch @@ -0,0 +1,43 @@ +From c08934a61201db8f1d1c66fcc63fb2eb526b656d Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 20 Oct 2025 06:53:18 +0200 +Subject: iommu/tegra: fix device leak on probe_device() + +From: Johan Hovold + +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 +Acked-by: Robin Murphy +Acked-by: Thierry Reding +Signed-off-by: Johan Hovold +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman +--- + 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; + } diff --git a/queue-6.18/ntfs-do-not-overwrite-uptodate-pages.patch b/queue-6.18/ntfs-do-not-overwrite-uptodate-pages.patch new file mode 100644 index 0000000000..80f0a3cef9 --- /dev/null +++ b/queue-6.18/ntfs-do-not-overwrite-uptodate-pages.patch @@ -0,0 +1,96 @@ +From 68f6bd128e75a032432eda9d16676ed2969a1096 Mon Sep 17 00:00:00 2001 +From: "Matthew Wilcox (Oracle)" +Date: Fri, 18 Jul 2025 20:53:58 +0100 +Subject: ntfs: Do not overwrite uptodate pages + +From: Matthew Wilcox (Oracle) + +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) +Cc: stable@vger.kernel.org +Signed-off-by: Konstantin Komarov +Signed-off-by: Greg Kroah-Hartman +--- + 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; diff --git a/queue-6.18/series b/queue-6.18/series index 8b2d586218..29c3d08f2d 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -86,3 +86,38 @@ rdma-rtrs-fix-clt_path-max_pages_per_mr-calculation.patch 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