From: Greg Kroah-Hartman Date: Mon, 28 Oct 2024 00:48:35 +0000 (+0100) Subject: 6.11-stable patches X-Git-Tag: v5.15.170~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=256ccf8ecb551cef390cec349dba7b7d415ebe70;p=thirdparty%2Fkernel%2Fstable-queue.git 6.11-stable patches added patches: asoc-dapm-avoid-container_of-to-get-component.patch asoc-qcom-fix-null-dereference-in-asoc_qcom_lpass_cpu_platform_probe.patch asoc-qcom-sc7280-fix-missing-soundwire-runtime-stream-alloc.patch asoc-qcom-sdm845-add-missing-soundwire-runtime-stream-alloc.patch asoc-sof-intel-hda-always-clean-up-link-dma-during-stop.patch asoc-sof-intel-hda-handle-prepare-without-close-for-non-hda-dai-s.patch asoc-sof-intel-hda-loader-do-not-wait-for-hdaudio-ioc.patch asoc-sof-ipc4-topology-do-not-set-alh-node_id-for-aggregated-dais.patch ata-libata-set-did_time_out-for-commands-that-actually-timed-out.patch block-fix-sanity-checks-in-blk_rq_map_user_bvec.patch drm-amd-display-temp-w-a-for-dp-link-layer-compliance.patch net-phy-dp83822-fix-reset-pin-definitions.patch nfsd-fix-race-between-laundromat-and-free_stateid.patch revert-fs-9p-fix-uaf-in-in-v9fs_stat2inode_dotl.patch revert-fs-9p-mitigate-inode-collisions.patch revert-fs-9p-remove-redundant-pointer-v9ses.patch revert-fs-9p-simplify-iget-to-remove-unnecessary-paths.patch soundwire-intel_ace2x-send-pdi-stream-number-during-prepare.patch --- diff --git a/queue-6.11/asoc-dapm-avoid-container_of-to-get-component.patch b/queue-6.11/asoc-dapm-avoid-container_of-to-get-component.patch new file mode 100644 index 00000000000..1d513536fb2 --- /dev/null +++ b/queue-6.11/asoc-dapm-avoid-container_of-to-get-component.patch @@ -0,0 +1,41 @@ +From 3fe9f5882cf71573516749b0bb687ef88f470d1d Mon Sep 17 00:00:00 2001 +From: Benjamin Bara +Date: Tue, 8 Oct 2024 13:36:14 +0200 +Subject: ASoC: dapm: avoid container_of() to get component + +From: Benjamin Bara + +commit 3fe9f5882cf71573516749b0bb687ef88f470d1d upstream. + +The current implementation does not work for widgets of DAPMs without +component, as snd_soc_dapm_to_component() requires it. If the widget is +directly owned by the card, e.g. as it is the case for the tegra +implementation, the call leads to UB. Therefore directly access the +component of the widget's DAPM to be able to check if a component is +available. + +Fixes: f82eb06a40c8 ("ASoC: tegra: machine: Handle component name prefix") +Cc: stable@vger.kernel.org # v6.7+ +Signed-off-by: Benjamin Bara +Link: https://patch.msgid.link/20241008-tegra-dapm-v2-1-5e999cb5f0e7@skidata.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + sound/soc/soc-dapm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/sound/soc/soc-dapm.c ++++ b/sound/soc/soc-dapm.c +@@ -2786,10 +2786,10 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_update_da + + int snd_soc_dapm_widget_name_cmp(struct snd_soc_dapm_widget *widget, const char *s) + { +- struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm); ++ struct snd_soc_component *component = widget->dapm->component; + const char *wname = widget->name; + +- if (component->name_prefix) ++ if (component && component->name_prefix) + wname += strlen(component->name_prefix) + 1; /* plus space */ + + return strcmp(wname, s); diff --git a/queue-6.11/asoc-qcom-fix-null-dereference-in-asoc_qcom_lpass_cpu_platform_probe.patch b/queue-6.11/asoc-qcom-fix-null-dereference-in-asoc_qcom_lpass_cpu_platform_probe.patch new file mode 100644 index 00000000000..802e8008ba9 --- /dev/null +++ b/queue-6.11/asoc-qcom-fix-null-dereference-in-asoc_qcom_lpass_cpu_platform_probe.patch @@ -0,0 +1,35 @@ +From 49da1463c9e3d2082276c3e0e2a8b65a88711cd2 Mon Sep 17 00:00:00 2001 +From: Zichen Xie +Date: Sun, 6 Oct 2024 15:57:37 -0500 +Subject: ASoC: qcom: Fix NULL Dereference in asoc_qcom_lpass_cpu_platform_probe() + +From: Zichen Xie + +commit 49da1463c9e3d2082276c3e0e2a8b65a88711cd2 upstream. + +A devm_kzalloc() in asoc_qcom_lpass_cpu_platform_probe() could +possibly return NULL pointer. NULL Pointer Dereference may be +triggerred without addtional check. +Add a NULL check for the returned pointer. + +Fixes: b5022a36d28f ("ASoC: qcom: lpass: Use regmap_field for i2sctl and dmactl registers") +Cc: stable@vger.kernel.org +Signed-off-by: Zichen Xie +Link: https://patch.msgid.link/20241006205737.8829-1-zichenxie0106@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + sound/soc/qcom/lpass-cpu.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/sound/soc/qcom/lpass-cpu.c ++++ b/sound/soc/qcom/lpass-cpu.c +@@ -1242,6 +1242,8 @@ int asoc_qcom_lpass_cpu_platform_probe(s + /* Allocation for i2sctl regmap fields */ + drvdata->i2sctl = devm_kzalloc(&pdev->dev, sizeof(struct lpaif_i2sctl), + GFP_KERNEL); ++ if (!drvdata->i2sctl) ++ return -ENOMEM; + + /* Initialize bitfields for dai I2SCTL register */ + ret = lpass_cpu_init_i2sctl_bitfields(dev, drvdata->i2sctl, diff --git a/queue-6.11/asoc-qcom-sc7280-fix-missing-soundwire-runtime-stream-alloc.patch b/queue-6.11/asoc-qcom-sc7280-fix-missing-soundwire-runtime-stream-alloc.patch new file mode 100644 index 00000000000..11f70249efd --- /dev/null +++ b/queue-6.11/asoc-qcom-sc7280-fix-missing-soundwire-runtime-stream-alloc.patch @@ -0,0 +1,91 @@ +From db7e59e6a39a4d3d54ca8197c796557e6d480b0d Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Sat, 12 Oct 2024 12:11:08 +0200 +Subject: ASoC: qcom: sc7280: Fix missing Soundwire runtime stream alloc + +From: Krzysztof Kozlowski + +commit db7e59e6a39a4d3d54ca8197c796557e6d480b0d upstream. + +Commit 15c7fab0e047 ("ASoC: qcom: Move Soundwire runtime stream alloc to +soundcards") moved the allocation of Soundwire stream runtime from the +Qualcomm Soundwire driver to each individual machine sound card driver, +except that it forgot to update SC7280 card. + +Just like for other Qualcomm sound cards using Soundwire, the card +driver should allocate and release the runtime. Otherwise sound +playback will result in a NULL pointer dereference or other effect of +uninitialized memory accesses (which was confirmed on SDM845 having +similar issue). + +Cc: stable@vger.kernel.org +Cc: Alexey Klimov +Cc: Steev Klimaszewski +Fixes: 15c7fab0e047 ("ASoC: qcom: Move Soundwire runtime stream alloc to soundcards") +Link: https://lore.kernel.org/r/20241010054109.16938-1-krzysztof.kozlowski@linaro.org +Signed-off-by: Krzysztof Kozlowski +Link: https://patch.msgid.link/20241012101108.129476-1-krzysztof.kozlowski@linaro.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + sound/soc/qcom/Kconfig | 1 + + sound/soc/qcom/sc7280.c | 10 +++++++++- + 2 files changed, 10 insertions(+), 1 deletion(-) + +--- a/sound/soc/qcom/Kconfig ++++ b/sound/soc/qcom/Kconfig +@@ -208,6 +208,7 @@ config SND_SOC_SC7280 + tristate "SoC Machine driver for SC7280 boards" + depends on I2C && SOUNDWIRE + select SND_SOC_QCOM_COMMON ++ select SND_SOC_QCOM_SDW + select SND_SOC_LPASS_SC7280 + select SND_SOC_MAX98357A + select SND_SOC_WCD938X_SDW +--- a/sound/soc/qcom/sc7280.c ++++ b/sound/soc/qcom/sc7280.c +@@ -23,6 +23,7 @@ + #include "common.h" + #include "lpass.h" + #include "qdsp6/q6afe.h" ++#include "sdw.h" + + #define DEFAULT_MCLK_RATE 19200000 + #define RT5682_PLL_FREQ (48000 * 512) +@@ -316,6 +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]; + + switch (cpu_dai->id) { + case MI2S_PRIMARY: +@@ -333,6 +335,9 @@ static void sc7280_snd_shutdown(struct s + default: + break; + } ++ ++ data->sruntime[cpu_dai->id] = NULL; ++ sdw_release_stream(sruntime); + } + + static int sc7280_snd_startup(struct snd_pcm_substream *substream) +@@ -347,6 +352,8 @@ static int sc7280_snd_startup(struct snd + switch (cpu_dai->id) { + case MI2S_PRIMARY: + ret = sc7280_rt5682_init(rtd); ++ if (ret) ++ return ret; + break; + case SECONDARY_MI2S_RX: + codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S; +@@ -360,7 +367,8 @@ static int sc7280_snd_startup(struct snd + default: + break; + } +- return ret; ++ ++ return qcom_snd_sdw_startup(substream); + } + + static const struct snd_soc_ops sc7280_ops = { diff --git a/queue-6.11/asoc-qcom-sdm845-add-missing-soundwire-runtime-stream-alloc.patch b/queue-6.11/asoc-qcom-sdm845-add-missing-soundwire-runtime-stream-alloc.patch new file mode 100644 index 00000000000..e776522101e --- /dev/null +++ b/queue-6.11/asoc-qcom-sdm845-add-missing-soundwire-runtime-stream-alloc.patch @@ -0,0 +1,173 @@ +From d0e806b0cc6260b59c65e606034a63145169c04c Mon Sep 17 00:00:00 2001 +From: Alexey Klimov +Date: Wed, 9 Oct 2024 22:39:22 +0100 +Subject: ASoC: qcom: sdm845: add missing soundwire runtime stream alloc + +From: Alexey Klimov + +commit d0e806b0cc6260b59c65e606034a63145169c04c upstream. + +During the migration of Soundwire runtime stream allocation from +the Qualcomm Soundwire controller to SoC's soundcard drivers the sdm845 +soundcard was forgotten. + +At this point any playback attempt or audio daemon startup, for instance +on sdm845-db845c (Qualcomm RB3 board), will result in stream pointer +NULL dereference: + + Unable to handle kernel NULL pointer dereference at virtual + address 0000000000000020 + Mem abort info: + ESR = 0x0000000096000004 + EC = 0x25: DABT (current EL), IL = 32 bits + SET = 0, FnV = 0 + EA = 0, S1PTW = 0 + FSC = 0x04: level 0 translation fault + Data abort info: + ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000 + CM = 0, WnR = 0, TnD = 0, TagAccess = 0 + GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 + user pgtable: 4k pages, 48-bit VAs, pgdp=0000000101ecf000 + [0000000000000020] pgd=0000000000000000, p4d=0000000000000000 + Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP + Modules linked in: ... + CPU: 5 UID: 0 PID: 1198 Comm: aplay + Not tainted 6.12.0-rc2-qcomlt-arm64-00059-g9d78f315a362-dirty #18 + Hardware name: Thundercomm Dragonboard 845c (DT) + pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) + pc : sdw_stream_add_slave+0x44/0x380 [soundwire_bus] + lr : sdw_stream_add_slave+0x44/0x380 [soundwire_bus] + sp : ffff80008a2035c0 + x29: ffff80008a2035c0 x28: ffff80008a203978 x27: 0000000000000000 + x26: 00000000000000c0 x25: 0000000000000000 x24: ffff1676025f4800 + x23: ffff167600ff1cb8 x22: ffff167600ff1c98 x21: 0000000000000003 + x20: ffff167607316000 x19: ffff167604e64e80 x18: 0000000000000000 + x17: 0000000000000000 x16: ffffcec265074160 x15: 0000000000000000 + x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000 + x11: 0000000000000000 x10: 0000000000000000 x9 : 0000000000000000 + x8 : 0000000000000000 x7 : 0000000000000000 x6 : ffff167600ff1cec + x5 : ffffcec22cfa2010 x4 : 0000000000000000 x3 : 0000000000000003 + x2 : ffff167613f836c0 x1 : 0000000000000000 x0 : ffff16761feb60b8 + Call trace: + sdw_stream_add_slave+0x44/0x380 [soundwire_bus] + wsa881x_hw_params+0x68/0x80 [snd_soc_wsa881x] + snd_soc_dai_hw_params+0x3c/0xa4 + __soc_pcm_hw_params+0x230/0x660 + dpcm_be_dai_hw_params+0x1d0/0x3f8 + dpcm_fe_dai_hw_params+0x98/0x268 + snd_pcm_hw_params+0x124/0x460 + snd_pcm_common_ioctl+0x998/0x16e8 + snd_pcm_ioctl+0x34/0x58 + __arm64_sys_ioctl+0xac/0xf8 + invoke_syscall+0x48/0x104 + el0_svc_common.constprop.0+0x40/0xe0 + do_el0_svc+0x1c/0x28 + el0_svc+0x34/0xe0 + el0t_64_sync_handler+0x120/0x12c + el0t_64_sync+0x190/0x194 + Code: aa0403fb f9418400 9100e000 9400102f (f8420f22) + ---[ end trace 0000000000000000 ]--- + +0000000000006108 : + 6108: d503233f paciasp + 610c: a9b97bfd stp x29, x30, [sp, #-112]! + 6110: 910003fd mov x29, sp + 6114: a90153f3 stp x19, x20, [sp, #16] + 6118: a9025bf5 stp x21, x22, [sp, #32] + 611c: aa0103f6 mov x22, x1 + 6120: 2a0303f5 mov w21, w3 + 6124: a90363f7 stp x23, x24, [sp, #48] + 6128: aa0003f8 mov x24, x0 + 612c: aa0203f7 mov x23, x2 + 6130: a9046bf9 stp x25, x26, [sp, #64] + 6134: aa0403f9 mov x25, x4 <-- x4 copied to x25 + 6138: a90573fb stp x27, x28, [sp, #80] + 613c: aa0403fb mov x27, x4 + 6140: f9418400 ldr x0, [x0, #776] + 6144: 9100e000 add x0, x0, #0x38 + 6148: 94000000 bl 0 + 614c: f8420f22 ldr x2, [x25, #32]! <-- offset 0x44 + ^^^ +This is 0x6108 + offset 0x44 from the beginning of sdw_stream_add_slave() +where data abort happens. +wsa881x_hw_params() is called with stream = NULL and passes it further +in register x4 (5th argument) to sdw_stream_add_slave() without any checks. +Value from x4 is copied to x25 and finally it aborts on trying to load +a value from address in x25 plus offset 32 (in dec) which corresponds +to master_list member in struct sdw_stream_runtime: + +struct sdw_stream_runtime { + const char * name; /* 0 8 */ + struct sdw_stream_params params; /* 8 12 */ + enum sdw_stream_state state; /* 20 4 */ + enum sdw_stream_type type; /* 24 4 */ + /* XXX 4 bytes hole, try to pack */ + here-> struct list_head master_list; /* 32 16 */ + int m_rt_count; /* 48 4 */ + /* size: 56, cachelines: 1, members: 6 */ + /* sum members: 48, holes: 1, sum holes: 4 */ + /* padding: 4 */ + /* last cacheline: 56 bytes */ + +Fix this by adding required calls to qcom_snd_sdw_startup() and +sdw_release_stream() to startup and shutdown routines which restores +the previous correct behaviour when ->set_stream() method is called to +set a valid stream runtime pointer on playback startup. + +Reproduced and then fix was tested on db845c RB3 board. + +Reported-by: Dmitry Baryshkov +Cc: stable@vger.kernel.org +Fixes: 15c7fab0e047 ("ASoC: qcom: Move Soundwire runtime stream alloc to soundcards") +Cc: Srinivas Kandagatla +Cc: Dmitry Baryshkov +Cc: Krzysztof Kozlowski +Cc: Pierre-Louis Bossart +Signed-off-by: Alexey Klimov +Tested-by: Steev Klimaszewski # Lenovo Yoga C630 +Reviewed-by: Krzysztof Kozlowski +Reviewed-by: Srinivas Kandagatla +Link: https://patch.msgid.link/20241009213922.999355-1-alexey.klimov@linaro.org +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + sound/soc/qcom/sdm845.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/sound/soc/qcom/sdm845.c ++++ b/sound/soc/qcom/sdm845.c +@@ -15,6 +15,7 @@ + #include + #include "common.h" + #include "qdsp6/q6afe.h" ++#include "sdw.h" + #include "../codecs/rt5663.h" + + #define DRIVER_NAME "sdm845" +@@ -416,7 +417,7 @@ static int sdm845_snd_startup(struct snd + pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id); + break; + } +- return 0; ++ return qcom_snd_sdw_startup(substream); + } + + static void sdm845_snd_shutdown(struct snd_pcm_substream *substream) +@@ -425,6 +426,7 @@ static void sdm845_snd_shutdown(struct + struct snd_soc_card *card = rtd->card; + struct sdm845_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]; + + switch (cpu_dai->id) { + case PRIMARY_MI2S_RX: +@@ -463,6 +465,9 @@ static void sdm845_snd_shutdown(struct + pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id); + break; + } ++ ++ data->sruntime[cpu_dai->id] = NULL; ++ sdw_release_stream(sruntime); + } + + static int sdm845_snd_prepare(struct snd_pcm_substream *substream) diff --git a/queue-6.11/asoc-sof-intel-hda-always-clean-up-link-dma-during-stop.patch b/queue-6.11/asoc-sof-intel-hda-always-clean-up-link-dma-during-stop.patch new file mode 100644 index 00000000000..0342ad2afb8 --- /dev/null +++ b/queue-6.11/asoc-sof-intel-hda-always-clean-up-link-dma-during-stop.patch @@ -0,0 +1,92 @@ +From ab5593793e9088abcddce30ba8e376e31b7285fd Mon Sep 17 00:00:00 2001 +From: Ranjani Sridharan +Date: Wed, 16 Oct 2024 11:29:10 +0800 +Subject: ASoC: SOF: Intel: hda: Always clean up link DMA during stop +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ranjani Sridharan + +commit ab5593793e9088abcddce30ba8e376e31b7285fd upstream. + +This is required to reset the DMA read/write pointers when the stream is +prepared and restarted after a call to snd_pcm_drain()/snd_pcm_drop(). +Also, now that the stream is reset during stop, do not save LLP registers +in the case of STOP/suspend to avoid erroneous delay reporting. + +Link: https://github.com/thesofproject/sof/issues/9502 +Signed-off-by: Ranjani Sridharan +Reviewed-by: Péter Ujfalusi +Reviewed-by: Kai Vehmanen +Signed-off-by: Bard Liao +All: stable@vger.kernel.org # 6.10.x 6.11.x +Link: https://patch.msgid.link/20241016032910.14601-5-yung-chuan.liao@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + sound/soc/sof/intel/hda-dai-ops.c | 23 ++++++++++------------- + sound/soc/sof/intel/hda-dai.c | 1 + + 2 files changed, 11 insertions(+), 13 deletions(-) + +--- a/sound/soc/sof/intel/hda-dai-ops.c ++++ b/sound/soc/sof/intel/hda-dai-ops.c +@@ -346,20 +346,21 @@ static int hda_trigger(struct snd_sof_de + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + snd_hdac_ext_stream_start(hext_stream); + break; +- case SNDRV_PCM_TRIGGER_SUSPEND: +- case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: +- snd_hdac_ext_stream_clear(hext_stream); +- + /* +- * Save the LLP registers in case the stream is +- * restarting due PAUSE_RELEASE, or START without a pcm +- * close/open since in this case the LLP register is not reset +- * to 0 and the delay calculation will return with invalid +- * results. ++ * Save the LLP registers since in case of PAUSE the LLP ++ * register are not reset to 0, the delay calculation will use ++ * the saved offsets for compensating the delay calculation. + */ + hext_stream->pplcllpl = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPL); + hext_stream->pplcllpu = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPU); ++ snd_hdac_ext_stream_clear(hext_stream); ++ break; ++ case SNDRV_PCM_TRIGGER_SUSPEND: ++ case SNDRV_PCM_TRIGGER_STOP: ++ hext_stream->pplcllpl = 0; ++ hext_stream->pplcllpu = 0; ++ snd_hdac_ext_stream_clear(hext_stream); + break; + default: + dev_err(sdev->dev, "unknown trigger command %d\n", cmd); +@@ -512,7 +513,6 @@ static const struct hda_dai_widget_dma_o + static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, + struct snd_pcm_substream *substream, int cmd) + { +- struct hdac_ext_stream *hext_stream = hda_get_hext_stream(sdev, cpu_dai, substream); + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); + + switch (cmd) { +@@ -527,9 +527,6 @@ static int hda_ipc3_post_trigger(struct + if (ret < 0) + return ret; + +- if (cmd == SNDRV_PCM_TRIGGER_STOP) +- return hda_link_dma_cleanup(substream, hext_stream, cpu_dai); +- + break; + } + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: +--- a/sound/soc/sof/intel/hda-dai.c ++++ b/sound/soc/sof/intel/hda-dai.c +@@ -302,6 +302,7 @@ static int __maybe_unused hda_dai_trigge + } + + switch (cmd) { ++ case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + ret = hda_link_dma_cleanup(substream, hext_stream, dai); + if (ret < 0) { diff --git a/queue-6.11/asoc-sof-intel-hda-handle-prepare-without-close-for-non-hda-dai-s.patch b/queue-6.11/asoc-sof-intel-hda-handle-prepare-without-close-for-non-hda-dai-s.patch new file mode 100644 index 00000000000..875e0d52db2 --- /dev/null +++ b/queue-6.11/asoc-sof-intel-hda-handle-prepare-without-close-for-non-hda-dai-s.patch @@ -0,0 +1,104 @@ +From 6e38a7e098d32d128b00b42a536151de9ea1340b Mon Sep 17 00:00:00 2001 +From: Ranjani Sridharan +Date: Wed, 16 Oct 2024 11:29:08 +0800 +Subject: ASoC: SOF: Intel: hda: Handle prepare without close for non-HDA DAI's +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ranjani Sridharan + +commit 6e38a7e098d32d128b00b42a536151de9ea1340b upstream. + +When a PCM is restarted after a snd_pcm_drain/snd_pcm_drop(), the prepare +callback will be invoked and the hw_params will be set again. For the +HDA DAI's, the hw_params function handles this case already but not for +the non-HDA DAI's. So, add the check for link_prepared to verify if the +hw_params should be done again or not. Additionally, for SDW DAI's reset +the PCMSyCM registers as would be done in the case of a start after a +hw_free. + +Signed-off-by: Ranjani Sridharan +Reviewed-by: Péter Ujfalusi +Reviewed-by: Kai Vehmanen +Signed-off-by: Bard Liao +All: stable@vger.kernel.org # 6.10.x 6.11.x +Link: https://patch.msgid.link/20241016032910.14601-3-yung-chuan.liao@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + sound/soc/sof/intel/hda-dai.c | 36 +++++++++++++++++++++++++++++++---- + 1 file changed, 32 insertions(+), 4 deletions(-) + +diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c +index 1c823f9eea57..8cccf38967e7 100644 +--- a/sound/soc/sof/intel/hda-dai.c ++++ b/sound/soc/sof/intel/hda-dai.c +@@ -370,6 +370,13 @@ static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream, + return -EINVAL; + } + ++ sdev = widget_to_sdev(w); ++ hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); ++ ++ /* nothing more to do if the link is already prepared */ ++ if (hext_stream && hext_stream->link_prepared) ++ return 0; ++ + /* use HDaudio stream handling */ + ret = hda_dai_hw_params_data(substream, params, cpu_dai, data, flags); + if (ret < 0) { +@@ -377,7 +384,6 @@ static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream, + return ret; + } + +- sdev = widget_to_sdev(w); + if (sdev->dspless_mode_selected) + return 0; + +@@ -482,6 +488,31 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, + int ret; + int i; + ++ ops = hda_dai_get_ops(substream, cpu_dai); ++ if (!ops) { ++ dev_err(cpu_dai->dev, "DAI widget ops not set\n"); ++ return -EINVAL; ++ } ++ ++ sdev = widget_to_sdev(w); ++ hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); ++ ++ /* nothing more to do if the link is already prepared */ ++ if (hext_stream && hext_stream->link_prepared) ++ return 0; ++ ++ /* ++ * reset the PCMSyCM registers to handle a prepare callback when the PCM is restarted ++ * due to xruns or after a call to snd_pcm_drain/drop() ++ */ ++ ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id, cpu_dai->id, ++ 0, 0, substream->stream); ++ if (ret < 0) { ++ dev_err(cpu_dai->dev, "%s: hdac_bus_eml_sdw_map_stream_ch failed %d\n", ++ __func__, ret); ++ return ret; ++ } ++ + data.dai_index = (link_id << 8) | cpu_dai->id; + data.dai_node_id = intel_alh_id; + ret = non_hda_dai_hw_params_data(substream, params, cpu_dai, &data, flags); +@@ -490,10 +521,7 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, + return ret; + } + +- ops = hda_dai_get_ops(substream, cpu_dai); +- sdev = widget_to_sdev(w); + hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); +- + if (!hext_stream) + return -ENODEV; + +-- +2.47.0 + diff --git a/queue-6.11/asoc-sof-intel-hda-loader-do-not-wait-for-hdaudio-ioc.patch b/queue-6.11/asoc-sof-intel-hda-loader-do-not-wait-for-hdaudio-ioc.patch new file mode 100644 index 00000000000..36073d59036 --- /dev/null +++ b/queue-6.11/asoc-sof-intel-hda-loader-do-not-wait-for-hdaudio-ioc.patch @@ -0,0 +1,75 @@ +From 9814c1447f9cc67c9e88e0a4423de3a496078360 Mon Sep 17 00:00:00 2001 +From: Kai Vehmanen +Date: Tue, 8 Oct 2024 09:07:10 +0300 +Subject: ASoC: SOF: Intel: hda-loader: do not wait for HDaudio IOC +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Kai Vehmanen + +commit 9814c1447f9cc67c9e88e0a4423de3a496078360 upstream. + +Commit 9ee3f0d8c999 ("ASOC: SOF: Intel: hda-loader: only wait for +HDaudio IOC for IPC4 devices") removed DMA wait for IPC3 case. +Proceed and remove the wait for IPC4 devices as well. + +There is no dependency to IPC version in the load logic and +checking the firmware status is a sufficient check in case of +errors. + +The removed code also had a bug in that -ETIMEDOUT is returned +without stopping the DMA transfer. + +Cc: stable@vger.kernel.org +Link: https://github.com/thesofproject/linux/issues/5135 +Fixes: 9ee3f0d8c999 ("ASOC: SOF: Intel: hda-loader: only wait for HDaudio IOC for IPC4 devices") +Suggested-by: Peter Ujfalusi +Signed-off-by: Kai Vehmanen +Reviewed-by: Péter Ujfalusi +Reviewed-by: Pierre-Louis Bossart +Reviewed-by: Ranjani Sridharan +Signed-off-by: Peter Ujfalusi +Link: https://patch.msgid.link/20241008060710.15409-1-peter.ujfalusi@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + sound/soc/sof/intel/hda-loader.c | 17 ----------------- + 1 file changed, 17 deletions(-) + +--- a/sound/soc/sof/intel/hda-loader.c ++++ b/sound/soc/sof/intel/hda-loader.c +@@ -294,14 +294,9 @@ int hda_cl_copy_fw(struct snd_sof_dev *s + { + struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; + const struct sof_intel_dsp_desc *chip = hda->desc; +- struct sof_intel_hda_stream *hda_stream; +- unsigned long time_left; + unsigned int reg; + int ret, status; + +- hda_stream = container_of(hext_stream, struct sof_intel_hda_stream, +- hext_stream); +- + dev_dbg(sdev->dev, "Code loader DMA starting\n"); + + ret = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_START); +@@ -310,18 +305,6 @@ int hda_cl_copy_fw(struct snd_sof_dev *s + return ret; + } + +- if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) { +- /* Wait for completion of transfer */ +- time_left = wait_for_completion_timeout(&hda_stream->ioc, +- msecs_to_jiffies(HDA_CL_DMA_IOC_TIMEOUT_MS)); +- +- if (!time_left) { +- dev_err(sdev->dev, "Code loader DMA did not complete\n"); +- return -ETIMEDOUT; +- } +- dev_dbg(sdev->dev, "Code loader DMA done\n"); +- } +- + dev_dbg(sdev->dev, "waiting for FW_ENTERED status\n"); + + status = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, diff --git a/queue-6.11/asoc-sof-ipc4-topology-do-not-set-alh-node_id-for-aggregated-dais.patch b/queue-6.11/asoc-sof-ipc4-topology-do-not-set-alh-node_id-for-aggregated-dais.patch new file mode 100644 index 00000000000..76c66d68196 --- /dev/null +++ b/queue-6.11/asoc-sof-ipc4-topology-do-not-set-alh-node_id-for-aggregated-dais.patch @@ -0,0 +1,62 @@ +From 9822b4c90d77e3c6555fb21c459c4a61c6a8619f Mon Sep 17 00:00:00 2001 +From: Ranjani Sridharan +Date: Wed, 16 Oct 2024 11:29:07 +0800 +Subject: ASoC: SOF: ipc4-topology: Do not set ALH node_id for aggregated DAIs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ranjani Sridharan + +commit 9822b4c90d77e3c6555fb21c459c4a61c6a8619f upstream. + +For aggregated DAIs, the node ID is set to the group_id during the DAI +widget's ipc_prepare op. With the current logic, setting the dai_index +for node_id in the dai_config is redundant as it will be overwritten +with the group_id anyway. Removing it will also prevent any accidental +clearing/resetting of the group_id for aggregated DAIs due to the +dai_config calls could that happen before the allocated group_id is +freed. + +Signed-off-by: Ranjani Sridharan +Reviewed-by: Péter Ujfalusi +Reviewed-by: Kai Vehmanen +Signed-off-by: Bard Liao +All: stable@vger.kernel.org # 6.10.x 6.11.x +Link: https://patch.msgid.link/20241016032910.14601-2-yung-chuan.liao@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + sound/soc/sof/ipc4-topology.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c +index 87be7f16e8c2..240fee2166d1 100644 +--- a/sound/soc/sof/ipc4-topology.c ++++ b/sound/soc/sof/ipc4-topology.c +@@ -3129,9 +3129,20 @@ static int sof_ipc4_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget * + * group_id during copier's ipc_prepare op. + */ + if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) { ++ struct sof_ipc4_alh_configuration_blob *blob; ++ ++ blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config; + ipc4_copier->dai_index = data->dai_node_id; +- copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; +- copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_node_id); ++ ++ /* ++ * no need to set the node_id for aggregated DAI's. These will be assigned ++ * a group_id during widget ipc_prepare ++ */ ++ if (blob->alh_cfg.device_count == 1) { ++ copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; ++ copier_data->gtw_cfg.node_id |= ++ SOF_IPC4_NODE_INDEX(data->dai_node_id); ++ } + } + + break; +-- +2.47.0 + diff --git a/queue-6.11/ata-libata-set-did_time_out-for-commands-that-actually-timed-out.patch b/queue-6.11/ata-libata-set-did_time_out-for-commands-that-actually-timed-out.patch new file mode 100644 index 00000000000..f58e8002181 --- /dev/null +++ b/queue-6.11/ata-libata-set-did_time_out-for-commands-that-actually-timed-out.patch @@ -0,0 +1,72 @@ +From 8e59a2a5459fd9840dbe2cbde85fe154b11e1727 Mon Sep 17 00:00:00 2001 +From: Niklas Cassel +Date: Wed, 23 Oct 2024 12:55:41 +0200 +Subject: ata: libata: Set DID_TIME_OUT for commands that actually timed out + +From: Niklas Cassel + +commit 8e59a2a5459fd9840dbe2cbde85fe154b11e1727 upstream. + +When ata_qc_complete() schedules a command for EH using +ata_qc_schedule_eh(), blk_abort_request() will be called, which leads to +req->q->mq_ops->timeout() / scsi_timeout() being called. + +scsi_timeout(), if the LLDD has no abort handler (libata has no abort +handler), will set host byte to DID_TIME_OUT, and then call +scsi_eh_scmd_add() to add the command to EH. + +Thus, when commands first enter libata's EH strategy_handler, all the +commands that have been added to EH will have DID_TIME_OUT set. + +Commit e5dd410acb34 ("ata: libata: Clear DID_TIME_OUT for ATA PT commands +with sense data") clears this bogus DID_TIME_OUT flag for all commands +that reached libata's EH strategy_handler. + +libata has its own flag (AC_ERR_TIMEOUT), that it sets for commands that +have not received a completion at the time of entering EH. + +ata_eh_worth_retry() has no special handling for AC_ERR_TIMEOUT, so by +default timed out commands will get flag ATA_QCFLAG_RETRY set, and will be +retried after the port has been reset (ata_eh_link_autopsy() always +triggers a port reset if any command has AC_ERR_TIMEOUT set). + +For a command that has ATA_QCFLAG_RETRY set, while also having an error +flag set (e.g. AC_ERR_TIMEOUT), ata_eh_finish() will not increment +scmd->allowed, so the command will at most be retried scmd->allowed number +of times (which by default is set to 3). + +However, scsi_eh_flush_done_q() will only retry commands for which +scsi_noretry_cmd() returns false. + +For a command that has DID_TIME_OUT set, while also having either the +FAILFAST flag set, or the command being a passthrough command, +scsi_noretry_cmd() will return true. Thus, such a command will never be +retried. + +Thus, make sure that libata sets SCSI's DID_TIME_OUT flag for commands that +actually timed out (libata's AC_ERR_TIMEOUT flag), such that timed out +commands will once again not be retried if they are also a FAILFAST or +passthrough command. + +Cc: stable@vger.kernel.org +Fixes: e5dd410acb34 ("ata: libata: Clear DID_TIME_OUT for ATA PT commands with sense data") +Reported-by: Lai, Yi +Closes: https://lore.kernel.org/linux-ide/ZxYz871I3Blsi30F@ly-workstation/ +Reviewed-by: Damien Le Moal +Link: https://lore.kernel.org/r/20241023105540.1070012-2-cassel@kernel.org +Signed-off-by: Niklas Cassel +Signed-off-by: Greg Kroah-Hartman +--- + drivers/ata/libata-eh.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/ata/libata-eh.c ++++ b/drivers/ata/libata-eh.c +@@ -648,6 +648,7 @@ void ata_scsi_cmd_error_handler(struct S + /* the scmd has an associated qc */ + if (!(qc->flags & ATA_QCFLAG_EH)) { + /* which hasn't failed yet, timeout */ ++ set_host_byte(scmd, DID_TIME_OUT); + qc->err_mask |= AC_ERR_TIMEOUT; + qc->flags |= ATA_QCFLAG_EH; + nr_timedout++; diff --git a/queue-6.11/block-fix-sanity-checks-in-blk_rq_map_user_bvec.patch b/queue-6.11/block-fix-sanity-checks-in-blk_rq_map_user_bvec.patch new file mode 100644 index 00000000000..b6b39e47c25 --- /dev/null +++ b/queue-6.11/block-fix-sanity-checks-in-blk_rq_map_user_bvec.patch @@ -0,0 +1,54 @@ +From 2ff949441802a8d076d9013c7761f63e8ae5a9bd Mon Sep 17 00:00:00 2001 +From: Xinyu Zhang +Date: Wed, 23 Oct 2024 15:15:19 -0600 +Subject: block: fix sanity checks in blk_rq_map_user_bvec + +From: Xinyu Zhang + +commit 2ff949441802a8d076d9013c7761f63e8ae5a9bd upstream. + +blk_rq_map_user_bvec contains a check bytes + bv->bv_len > nr_iter which +causes unnecessary failures in NVMe passthrough I/O, reproducible as +follows: + +- register a 2 page, page-aligned buffer against a ring +- use that buffer to do a 1 page io_uring NVMe passthrough read + +The second (i = 1) iteration of the loop in blk_rq_map_user_bvec will +then have nr_iter == 1 page, bytes == 1 page, bv->bv_len == 1 page, so +the check bytes + bv->bv_len > nr_iter will succeed, causing the I/O to +fail. This failure is unnecessary, as when the check succeeds, it means +we've checked the entire buffer that will be used by the request - i.e. +blk_rq_map_user_bvec should complete successfully. Therefore, terminate +the loop early and return successfully when the check bytes + bv->bv_len +> nr_iter succeeds. + +While we're at it, also remove the check that all segments in the bvec +are single-page. While this seems to be true for all users of the +function, it doesn't appear to be required anywhere downstream. + +CC: stable@vger.kernel.org +Signed-off-by: Xinyu Zhang +Co-developed-by: Uday Shankar +Signed-off-by: Uday Shankar +Fixes: 37987547932c ("block: extend functionality to map bvec iterator") +Link: https://lore.kernel.org/r/20241023211519.4177873-1-ushankar@purestorage.com +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + block/blk-map.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/block/blk-map.c ++++ b/block/blk-map.c +@@ -600,9 +600,7 @@ static int blk_rq_map_user_bvec(struct r + if (nsegs >= nr_segs || bytes > UINT_MAX - bv->bv_len) + goto put_bio; + if (bytes + bv->bv_len > nr_iter) +- goto put_bio; +- if (bv->bv_offset + bv->bv_len > PAGE_SIZE) +- goto put_bio; ++ break; + + nsegs++; + bytes += bv->bv_len; diff --git a/queue-6.11/drm-amd-display-temp-w-a-for-dp-link-layer-compliance.patch b/queue-6.11/drm-amd-display-temp-w-a-for-dp-link-layer-compliance.patch new file mode 100644 index 00000000000..aafa88b0e75 --- /dev/null +++ b/queue-6.11/drm-amd-display-temp-w-a-for-dp-link-layer-compliance.patch @@ -0,0 +1,70 @@ +From 63feb35cd26557572ad95fc062ede344bb61d9ad Mon Sep 17 00:00:00 2001 +From: Aurabindo Pillai +Date: Mon, 7 Oct 2024 14:19:32 -0400 +Subject: drm/amd/display: temp w/a for DP Link Layer compliance + +From: Aurabindo Pillai + +commit 63feb35cd26557572ad95fc062ede344bb61d9ad upstream. + +[Why&How] +Disabling P-State support on full updates for DCN401 results in +introducing additional communication with SMU. A UCLK hard min message +to SMU takes 4 seconds to go through, which was due to DCN not allowing +pstate switch, which was caused by incorrect value for TTU watermark +before blanking the HUBP prior to DPG on for servicing the test request. + +Fix the issue temporarily by disallowing pstate changes for compliance +test while test request handler is reworked for a proper fix. + +Fixes: 67ea53a4bd9d ("drm/amd/display: Disable DCN401 UCLK P-State support on full updates") +Cc: Mario Limonciello +Cc: Alex Deucher +Reviewed-by: Dillon Varone +Signed-off-by: Aurabindo Pillai +Signed-off-by: Wayne Lin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +(cherry picked from commit 8a79f7cdbb41bb0ddfd4d7662b4428d4a9d5306d) +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +@@ -44,6 +44,7 @@ + + #include "dm_helpers.h" + #include "ddc_service_types.h" ++#include "clk_mgr.h" + + static u32 edid_extract_panel_id(struct edid *edid) + { +@@ -1121,6 +1122,8 @@ bool dm_helpers_dp_handle_test_pattern_r + struct pipe_ctx *pipe_ctx = NULL; + struct amdgpu_dm_connector *aconnector = link->priv; + struct drm_device *dev = aconnector->base.dev; ++ struct dc_state *dc_state = ctx->dc->current_state; ++ struct clk_mgr *clk_mgr = ctx->dc->clk_mgr; + int i; + + for (i = 0; i < MAX_PIPES; i++) { +@@ -1221,6 +1224,16 @@ bool dm_helpers_dp_handle_test_pattern_r + pipe_ctx->stream->test_pattern.type = test_pattern; + pipe_ctx->stream->test_pattern.color_space = test_pattern_color_space; + ++ /* Temp W/A for compliance test failure */ ++ dc_state->bw_ctx.bw.dcn.clk.p_state_change_support = false; ++ dc_state->bw_ctx.bw.dcn.clk.dramclk_khz = clk_mgr->dc_mode_softmax_enabled ? ++ clk_mgr->bw_params->dc_mode_softmax_memclk : clk_mgr->bw_params->max_memclk_mhz; ++ dc_state->bw_ctx.bw.dcn.clk.idle_dramclk_khz = dc_state->bw_ctx.bw.dcn.clk.dramclk_khz; ++ ctx->dc->clk_mgr->funcs->update_clocks( ++ ctx->dc->clk_mgr, ++ dc_state, ++ false); ++ + dc_link_dp_set_test_pattern( + (struct dc_link *) link, + test_pattern, diff --git a/queue-6.11/net-phy-dp83822-fix-reset-pin-definitions.patch b/queue-6.11/net-phy-dp83822-fix-reset-pin-definitions.patch new file mode 100644 index 00000000000..1463afbc3f6 --- /dev/null +++ b/queue-6.11/net-phy-dp83822-fix-reset-pin-definitions.patch @@ -0,0 +1,50 @@ +From de96f6a3003513c796bbe4e23210a446913f5c00 Mon Sep 17 00:00:00 2001 +From: Michel Alex +Date: Wed, 16 Oct 2024 12:11:15 +0000 +Subject: net: phy: dp83822: Fix reset pin definitions + +From: Michel Alex + +commit de96f6a3003513c796bbe4e23210a446913f5c00 upstream. + +This change fixes a rare issue where the PHY fails to detect a link +due to incorrect reset behavior. + +The SW_RESET definition was incorrectly assigned to bit 14, which is the +Digital Restart bit according to the datasheet. This commit corrects +SW_RESET to bit 15 and assigns DIG_RESTART to bit 14 as per the +datasheet specifications. + +The SW_RESET define is only used in the phy_reset function, which fully +re-initializes the PHY after the reset is performed. The change in the +bit definitions should not have any negative impact on the functionality +of the PHY. + +v2: +- added Fixes tag +- improved commit message + +Cc: stable@vger.kernel.org +Fixes: 5dc39fd5ef35 ("net: phy: DP83822: Add ability to advertise Fiber connection") +Signed-off-by: Alex Michel +Reviewed-by: Andrew Lunn +Message-ID: +Signed-off-by: Andrew Lunn +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/phy/dp83822.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/phy/dp83822.c ++++ b/drivers/net/phy/dp83822.c +@@ -45,8 +45,8 @@ + /* Control Register 2 bits */ + #define DP83822_FX_ENABLE BIT(14) + +-#define DP83822_HW_RESET BIT(15) +-#define DP83822_SW_RESET BIT(14) ++#define DP83822_SW_RESET BIT(15) ++#define DP83822_DIG_RESTART BIT(14) + + /* PHY STS bits */ + #define DP83822_PHYSTS_DUPLEX BIT(2) diff --git a/queue-6.11/nfsd-fix-race-between-laundromat-and-free_stateid.patch b/queue-6.11/nfsd-fix-race-between-laundromat-and-free_stateid.patch new file mode 100644 index 00000000000..3ad52599871 --- /dev/null +++ b/queue-6.11/nfsd-fix-race-between-laundromat-and-free_stateid.patch @@ -0,0 +1,194 @@ +From 8dd91e8d31febf4d9cca3ae1bb4771d33ae7ee5a Mon Sep 17 00:00:00 2001 +From: Olga Kornievskaia +Date: Fri, 18 Oct 2024 15:24:58 -0400 +Subject: nfsd: fix race between laundromat and free_stateid + +From: Olga Kornievskaia + +commit 8dd91e8d31febf4d9cca3ae1bb4771d33ae7ee5a upstream. + +There is a race between laundromat handling of revoked delegations +and a client sending free_stateid operation. Laundromat thread +finds that delegation has expired and needs to be revoked so it +marks the delegation stid revoked and it puts it on a reaper list +but then it unlock the state lock and the actual delegation revocation +happens without the lock. Once the stid is marked revoked a racing +free_stateid processing thread does the following (1) it calls +list_del_init() which removes it from the reaper list and (2) frees +the delegation stid structure. The laundromat thread ends up not +calling the revoke_delegation() function for this particular delegation +but that means it will no release the lock lease that exists on +the file. + +Now, a new open for this file comes in and ends up finding that +lease list isn't empty and calls nfsd_breaker_owns_lease() which ends +up trying to derefence a freed delegation stateid. Leading to the +followint use-after-free KASAN warning: + +kernel: ================================================================== +kernel: BUG: KASAN: slab-use-after-free in nfsd_breaker_owns_lease+0x140/0x160 [nfsd] +kernel: Read of size 8 at addr ffff0000e73cd0c8 by task nfsd/6205 +kernel: +kernel: CPU: 2 UID: 0 PID: 6205 Comm: nfsd Kdump: loaded Not tainted 6.11.0-rc7+ #9 +kernel: Hardware name: Apple Inc. Apple Virtualization Generic Platform, BIOS 2069.0.0.0.0 08/03/2024 +kernel: Call trace: +kernel: dump_backtrace+0x98/0x120 +kernel: show_stack+0x1c/0x30 +kernel: dump_stack_lvl+0x80/0xe8 +kernel: print_address_description.constprop.0+0x84/0x390 +kernel: print_report+0xa4/0x268 +kernel: kasan_report+0xb4/0xf8 +kernel: __asan_report_load8_noabort+0x1c/0x28 +kernel: nfsd_breaker_owns_lease+0x140/0x160 [nfsd] +kernel: nfsd_file_do_acquire+0xb3c/0x11d0 [nfsd] +kernel: nfsd_file_acquire_opened+0x84/0x110 [nfsd] +kernel: nfs4_get_vfs_file+0x634/0x958 [nfsd] +kernel: nfsd4_process_open2+0xa40/0x1a40 [nfsd] +kernel: nfsd4_open+0xa08/0xe80 [nfsd] +kernel: nfsd4_proc_compound+0xb8c/0x2130 [nfsd] +kernel: nfsd_dispatch+0x22c/0x718 [nfsd] +kernel: svc_process_common+0x8e8/0x1960 [sunrpc] +kernel: svc_process+0x3d4/0x7e0 [sunrpc] +kernel: svc_handle_xprt+0x828/0xe10 [sunrpc] +kernel: svc_recv+0x2cc/0x6a8 [sunrpc] +kernel: nfsd+0x270/0x400 [nfsd] +kernel: kthread+0x288/0x310 +kernel: ret_from_fork+0x10/0x20 + +This patch proposes a fixed that's based on adding 2 new additional +stid's sc_status values that help coordinate between the laundromat +and other operations (nfsd4_free_stateid() and nfsd4_delegreturn()). + +First to make sure, that once the stid is marked revoked, it is not +removed by the nfsd4_free_stateid(), the laundromat take a reference +on the stateid. Then, coordinating whether the stid has been put +on the cl_revoked list or we are processing FREE_STATEID and need to +make sure to remove it from the list, each check that state and act +accordingly. If laundromat has added to the cl_revoke list before +the arrival of FREE_STATEID, then nfsd4_free_stateid() knows to remove +it from the list. If nfsd4_free_stateid() finds that operations arrived +before laundromat has placed it on cl_revoke list, it marks the state +freed and then laundromat will no longer add it to the list. + +Also, for nfsd4_delegreturn() when looking for the specified stid, +we need to access stid that are marked removed or freeable, it means +the laundromat has started processing it but hasn't finished and this +delegreturn needs to return nfserr_deleg_revoked and not +nfserr_bad_stateid. The latter will not trigger a FREE_STATEID and the +lack of it will leave this stid on the cl_revoked list indefinitely. + +Fixes: 2d4a532d385f ("nfsd: ensure that clp->cl_revoked list is protected by clp->cl_lock") +CC: stable@vger.kernel.org +Signed-off-by: Olga Kornievskaia +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/nfs4state.c | 48 ++++++++++++++++++++++++++++++++++++++++-------- + fs/nfsd/state.h | 2 ++ + 2 files changed, 42 insertions(+), 8 deletions(-) + +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -1358,21 +1358,47 @@ static void destroy_delegation(struct nf + destroy_unhashed_deleg(dp); + } + ++/** ++ * revoke_delegation - perform nfs4 delegation structure cleanup ++ * @dp: pointer to the delegation ++ * ++ * This function assumes that it's called either from the administrative ++ * interface (nfsd4_revoke_states()) that's revoking a specific delegation ++ * stateid or it's called from a laundromat thread (nfsd4_landromat()) that ++ * determined that this specific state has expired and needs to be revoked ++ * (both mark state with the appropriate stid sc_status mode). It is also ++ * assumed that a reference was taken on the @dp state. ++ * ++ * If this function finds that the @dp state is SC_STATUS_FREED it means ++ * that a FREE_STATEID operation for this stateid has been processed and ++ * we can proceed to removing it from recalled list. However, if @dp state ++ * isn't marked SC_STATUS_FREED, it means we need place it on the cl_revoked ++ * list and wait for the FREE_STATEID to arrive from the client. At the same ++ * time, we need to mark it as SC_STATUS_FREEABLE to indicate to the ++ * nfsd4_free_stateid() function that this stateid has already been added ++ * to the cl_revoked list and that nfsd4_free_stateid() is now responsible ++ * for removing it from the list. Inspection of where the delegation state ++ * in the revocation process is protected by the clp->cl_lock. ++ */ + static void revoke_delegation(struct nfs4_delegation *dp) + { + struct nfs4_client *clp = dp->dl_stid.sc_client; + + WARN_ON(!list_empty(&dp->dl_recall_lru)); ++ WARN_ON_ONCE(!(dp->dl_stid.sc_status & ++ (SC_STATUS_REVOKED | SC_STATUS_ADMIN_REVOKED))); + + trace_nfsd_stid_revoke(&dp->dl_stid); + +- if (dp->dl_stid.sc_status & +- (SC_STATUS_REVOKED | SC_STATUS_ADMIN_REVOKED)) { +- spin_lock(&clp->cl_lock); +- refcount_inc(&dp->dl_stid.sc_count); +- list_add(&dp->dl_recall_lru, &clp->cl_revoked); +- spin_unlock(&clp->cl_lock); ++ spin_lock(&clp->cl_lock); ++ if (dp->dl_stid.sc_status & SC_STATUS_FREED) { ++ list_del_init(&dp->dl_recall_lru); ++ goto out; + } ++ list_add(&dp->dl_recall_lru, &clp->cl_revoked); ++ dp->dl_stid.sc_status |= SC_STATUS_FREEABLE; ++out: ++ spin_unlock(&clp->cl_lock); + destroy_unhashed_deleg(dp); + } + +@@ -1781,6 +1807,7 @@ void nfsd4_revoke_states(struct net *net + mutex_unlock(&stp->st_mutex); + break; + case SC_TYPE_DELEG: ++ refcount_inc(&stid->sc_count); + dp = delegstateid(stid); + spin_lock(&state_lock); + if (!unhash_delegation_locked( +@@ -6544,6 +6571,7 @@ nfs4_laundromat(struct nfsd_net *nn) + dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru); + if (!state_expired(<, dp->dl_time)) + break; ++ refcount_inc(&dp->dl_stid.sc_count); + unhash_delegation_locked(dp, SC_STATUS_REVOKED); + list_add(&dp->dl_recall_lru, &reaplist); + } +@@ -7161,7 +7189,9 @@ nfsd4_free_stateid(struct svc_rqst *rqst + s->sc_status |= SC_STATUS_CLOSED; + spin_unlock(&s->sc_lock); + dp = delegstateid(s); +- list_del_init(&dp->dl_recall_lru); ++ if (s->sc_status & SC_STATUS_FREEABLE) ++ list_del_init(&dp->dl_recall_lru); ++ s->sc_status |= SC_STATUS_FREED; + spin_unlock(&cl->cl_lock); + nfs4_put_stid(s); + ret = nfs_ok; +@@ -7491,7 +7521,9 @@ nfsd4_delegreturn(struct svc_rqst *rqstp + if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0))) + return status; + +- status = nfsd4_lookup_stateid(cstate, stateid, SC_TYPE_DELEG, 0, &s, nn); ++ status = nfsd4_lookup_stateid(cstate, stateid, SC_TYPE_DELEG, ++ SC_STATUS_REVOKED | SC_STATUS_FREEABLE, ++ &s, nn); + if (status) + goto out; + dp = delegstateid(s); +--- a/fs/nfsd/state.h ++++ b/fs/nfsd/state.h +@@ -113,6 +113,8 @@ struct nfs4_stid { + /* For a deleg stateid kept around only to process free_stateid's: */ + #define SC_STATUS_REVOKED BIT(1) + #define SC_STATUS_ADMIN_REVOKED BIT(2) ++#define SC_STATUS_FREEABLE BIT(3) ++#define SC_STATUS_FREED BIT(4) + unsigned short sc_status; + + struct list_head sc_cp_list; diff --git a/queue-6.11/revert-fs-9p-fix-uaf-in-in-v9fs_stat2inode_dotl.patch b/queue-6.11/revert-fs-9p-fix-uaf-in-in-v9fs_stat2inode_dotl.patch new file mode 100644 index 00000000000..f3b2a47e60d --- /dev/null +++ b/queue-6.11/revert-fs-9p-fix-uaf-in-in-v9fs_stat2inode_dotl.patch @@ -0,0 +1,45 @@ +From 26f8dd2dde6864558782d91542f89483bd59a3c2 Mon Sep 17 00:00:00 2001 +From: Dominique Martinet +Date: Thu, 24 Oct 2024 08:52:12 +0900 +Subject: Revert "fs/9p: fix uaf in in v9fs_stat2inode_dotl" + +From: Dominique Martinet + +commit 26f8dd2dde6864558782d91542f89483bd59a3c2 upstream. + +This reverts commit 11763a8598f888dec631a8a903f7ada32181001f. + +This is a requirement to revert commit 724a08450f74 ("fs/9p: simplify +iget to remove unnecessary paths"), see that revert for details. + +Fixes: 724a08450f74 ("fs/9p: simplify iget to remove unnecessary paths") +Reported-by: Will Deacon +Link: https://lkml.kernel.org/r/20240923100508.GA32066@willie-the-truck +Cc: stable@vger.kernel.org # v6.9+ +Message-ID: <20241024-revert_iget-v1-3-4cac63d25f72@codewreck.org> +Signed-off-by: Dominique Martinet +Signed-off-by: Greg Kroah-Hartman +--- + fs/9p/vfs_inode_dotl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c +index 2b313fe7003e..ef9db3e03506 100644 +--- a/fs/9p/vfs_inode_dotl.c ++++ b/fs/9p/vfs_inode_dotl.c +@@ -78,11 +78,11 @@ struct inode *v9fs_fid_iget_dotl(struct super_block *sb, struct p9_fid *fid) + + retval = v9fs_init_inode(v9ses, inode, &fid->qid, + st->st_mode, new_decode_dev(st->st_rdev)); +- v9fs_stat2inode_dotl(st, inode, 0); + kfree(st); + if (retval) + goto error; + ++ v9fs_stat2inode_dotl(st, inode, 0); + v9fs_set_netfs_context(inode); + v9fs_cache_inode_get_cookie(inode); + retval = v9fs_get_acl(inode, fid); +-- +2.47.0 + diff --git a/queue-6.11/revert-fs-9p-mitigate-inode-collisions.patch b/queue-6.11/revert-fs-9p-mitigate-inode-collisions.patch new file mode 100644 index 00000000000..264ce704883 --- /dev/null +++ b/queue-6.11/revert-fs-9p-mitigate-inode-collisions.patch @@ -0,0 +1,242 @@ +From f69999b5f9b444a2443ca2b9e5976e78bb5b7c69 Mon Sep 17 00:00:00 2001 +From: Dominique Martinet +Date: Thu, 24 Oct 2024 08:52:10 +0900 +Subject: Revert " fs/9p: mitigate inode collisions" + +From: Dominique Martinet + +commit f69999b5f9b444a2443ca2b9e5976e78bb5b7c69 upstream. + +This reverts commit d05dcfdf5e1659b2949d13060284eff3888b644e. + +This is a requirement to revert commit 724a08450f74 ("fs/9p: simplify +iget to remove unnecessary paths"), see that revert for details. + +Fixes: 724a08450f74 ("fs/9p: simplify iget to remove unnecessary paths") +Reported-by: Will Deacon +Link: https://lkml.kernel.org/r/20240923100508.GA32066@willie-the-truck +Cc: stable@vger.kernel.org # v6.9+ +Message-ID: <20241024-revert_iget-v1-1-4cac63d25f72@codewreck.org> +Signed-off-by: Dominique Martinet +Signed-off-by: Greg Kroah-Hartman +--- + fs/9p/v9fs.h | 11 +++++------ + fs/9p/vfs_inode.c | 37 ++++++++----------------------------- + fs/9p/vfs_inode_dotl.c | 28 ++++++++-------------------- + fs/9p/vfs_super.c | 2 +- + 4 files changed, 22 insertions(+), 56 deletions(-) + +--- a/fs/9p/v9fs.h ++++ b/fs/9p/v9fs.h +@@ -179,14 +179,13 @@ extern int v9fs_vfs_rename(struct mnt_id + struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry, + unsigned int flags); +-extern struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid, +- bool new); ++extern struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid); + extern const struct inode_operations v9fs_dir_inode_operations_dotl; + extern const struct inode_operations v9fs_file_inode_operations_dotl; + extern const struct inode_operations v9fs_symlink_inode_operations_dotl; + extern const struct netfs_request_ops v9fs_req_ops; + extern struct inode *v9fs_fid_iget_dotl(struct super_block *sb, +- struct p9_fid *fid, bool new); ++ struct p9_fid *fid); + + /* other default globals */ + #define V9FS_PORT 564 +@@ -225,12 +224,12 @@ static inline int v9fs_proto_dotl(struct + */ + static inline struct inode * + v9fs_get_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, +- struct super_block *sb, bool new) ++ struct super_block *sb) + { + if (v9fs_proto_dotl(v9ses)) +- return v9fs_fid_iget_dotl(sb, fid, new); ++ return v9fs_fid_iget_dotl(sb, fid); + else +- return v9fs_fid_iget(sb, fid, new); ++ return v9fs_fid_iget(sb, fid); + } + + #endif +--- a/fs/9p/vfs_inode.c ++++ b/fs/9p/vfs_inode.c +@@ -365,8 +365,7 @@ void v9fs_evict_inode(struct inode *inod + clear_inode(inode); + } + +-struct inode * +-v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid, bool new) ++struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid) + { + dev_t rdev; + int retval; +@@ -378,18 +377,8 @@ v9fs_fid_iget(struct super_block *sb, st + inode = iget_locked(sb, QID2INO(&fid->qid)); + if (unlikely(!inode)) + return ERR_PTR(-ENOMEM); +- if (!(inode->i_state & I_NEW)) { +- if (!new) { +- goto done; +- } else { +- p9_debug(P9_DEBUG_VFS, "WARNING: Inode collision %ld\n", +- inode->i_ino); +- iput(inode); +- remove_inode_hash(inode); +- inode = iget_locked(sb, QID2INO(&fid->qid)); +- WARN_ON(!(inode->i_state & I_NEW)); +- } +- } ++ if (!(inode->i_state & I_NEW)) ++ return inode; + + /* + * initialize the inode with the stat info +@@ -413,11 +402,11 @@ v9fs_fid_iget(struct super_block *sb, st + v9fs_set_netfs_context(inode); + v9fs_cache_inode_get_cookie(inode); + unlock_new_inode(inode); +-done: + return inode; + error: + iget_failed(inode); + return ERR_PTR(retval); ++ + } + + /** +@@ -449,15 +438,8 @@ static int v9fs_at_to_dotl_flags(int fla + */ + static void v9fs_dec_count(struct inode *inode) + { +- if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2) { +- if (inode->i_nlink) { +- drop_nlink(inode); +- } else { +- p9_debug(P9_DEBUG_VFS, +- "WARNING: unexpected i_nlink zero %d inode %ld\n", +- inode->i_nlink, inode->i_ino); +- } +- } ++ if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2) ++ drop_nlink(inode); + } + + /** +@@ -508,9 +490,6 @@ static int v9fs_remove(struct inode *dir + } else + v9fs_dec_count(inode); + +- if (inode->i_nlink <= 0) /* no more refs unhash it */ +- remove_inode_hash(inode); +- + v9fs_invalidate_inode_attr(inode); + v9fs_invalidate_inode_attr(dir); + +@@ -576,7 +555,7 @@ v9fs_create(struct v9fs_session_info *v9 + /* + * instantiate inode and assign the unopened fid to the dentry + */ +- inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb, true); ++ inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + p9_debug(P9_DEBUG_VFS, +@@ -705,7 +684,7 @@ struct dentry *v9fs_vfs_lookup(struct in + else if (IS_ERR(fid)) + inode = ERR_CAST(fid); + else +- inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb, false); ++ inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb); + /* + * If we had a rename on the server and a parallel lookup + * for the new name, then make sure we instantiate with +--- a/fs/9p/vfs_inode_dotl.c ++++ b/fs/9p/vfs_inode_dotl.c +@@ -52,10 +52,7 @@ static kgid_t v9fs_get_fsgid_for_create( + return current_fsgid(); + } + +- +- +-struct inode * +-v9fs_fid_iget_dotl(struct super_block *sb, struct p9_fid *fid, bool new) ++struct inode *v9fs_fid_iget_dotl(struct super_block *sb, struct p9_fid *fid) + { + int retval; + struct inode *inode; +@@ -65,18 +62,8 @@ v9fs_fid_iget_dotl(struct super_block *s + inode = iget_locked(sb, QID2INO(&fid->qid)); + if (unlikely(!inode)) + return ERR_PTR(-ENOMEM); +- if (!(inode->i_state & I_NEW)) { +- if (!new) { +- goto done; +- } else { /* deal with race condition in inode number reuse */ +- p9_debug(P9_DEBUG_ERROR, "WARNING: Inode collision %lx\n", +- inode->i_ino); +- iput(inode); +- remove_inode_hash(inode); +- inode = iget_locked(sb, QID2INO(&fid->qid)); +- WARN_ON(!(inode->i_state & I_NEW)); +- } +- } ++ if (!(inode->i_state & I_NEW)) ++ return inode; + + /* + * initialize the inode with the stat info +@@ -103,11 +90,12 @@ v9fs_fid_iget_dotl(struct super_block *s + goto error; + + unlock_new_inode(inode); +-done: ++ + return inode; + error: + iget_failed(inode); + return ERR_PTR(retval); ++ + } + + struct dotl_openflag_map { +@@ -259,7 +247,7 @@ v9fs_vfs_atomic_open_dotl(struct inode * + p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); + goto out; + } +- inode = v9fs_fid_iget_dotl(dir->i_sb, fid, true); ++ inode = v9fs_fid_iget_dotl(dir->i_sb, fid); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", err); +@@ -352,7 +340,7 @@ static int v9fs_vfs_mkdir_dotl(struct mn + } + + /* instantiate inode and assign the unopened fid to the dentry */ +- inode = v9fs_fid_iget_dotl(dir->i_sb, fid, true); ++ inode = v9fs_fid_iget_dotl(dir->i_sb, fid); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", +@@ -788,7 +776,7 @@ v9fs_vfs_mknod_dotl(struct mnt_idmap *id + err); + goto error; + } +- inode = v9fs_fid_iget_dotl(dir->i_sb, fid, true); ++ inode = v9fs_fid_iget_dotl(dir->i_sb, fid); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", +--- a/fs/9p/vfs_super.c ++++ b/fs/9p/vfs_super.c +@@ -139,7 +139,7 @@ static struct dentry *v9fs_mount(struct + else + sb->s_d_op = &v9fs_dentry_operations; + +- inode = v9fs_get_inode_from_fid(v9ses, fid, sb, true); ++ inode = v9fs_get_inode_from_fid(v9ses, fid, sb); + if (IS_ERR(inode)) { + retval = PTR_ERR(inode); + goto release_sb; diff --git a/queue-6.11/revert-fs-9p-remove-redundant-pointer-v9ses.patch b/queue-6.11/revert-fs-9p-remove-redundant-pointer-v9ses.patch new file mode 100644 index 00000000000..c46a2d8bb3e --- /dev/null +++ b/queue-6.11/revert-fs-9p-remove-redundant-pointer-v9ses.patch @@ -0,0 +1,64 @@ +From fedd06210b14febfa69e09d0721746749ea9ea20 Mon Sep 17 00:00:00 2001 +From: Dominique Martinet +Date: Thu, 24 Oct 2024 08:52:11 +0900 +Subject: Revert "fs/9p: remove redundant pointer v9ses" + +From: Dominique Martinet + +commit fedd06210b14febfa69e09d0721746749ea9ea20 upstream. + +This reverts commit 10211b4a23cf4a3df5c11a10e5b3d371f16a906f. + +This is a requirement to revert commit 724a08450f74 ("fs/9p: simplify +iget to remove unnecessary paths"), see that revert for details. + +Fixes: 724a08450f74 ("fs/9p: simplify iget to remove unnecessary paths") +Reported-by: Will Deacon +Link: https://lkml.kernel.org/r/20240923100508.GA32066@willie-the-truck +Cc: stable@vger.kernel.org # v6.9+ +Message-ID: <20241024-revert_iget-v1-2-4cac63d25f72@codewreck.org> +Signed-off-by: Dominique Martinet +Signed-off-by: Greg Kroah-Hartman +--- + fs/9p/vfs_inode_dotl.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c +index 55dde186041a..2b313fe7003e 100644 +--- a/fs/9p/vfs_inode_dotl.c ++++ b/fs/9p/vfs_inode_dotl.c +@@ -297,6 +297,7 @@ static int v9fs_vfs_mkdir_dotl(struct mnt_idmap *idmap, + umode_t omode) + { + int err; ++ struct v9fs_session_info *v9ses; + struct p9_fid *fid = NULL, *dfid = NULL; + kgid_t gid; + const unsigned char *name; +@@ -306,6 +307,7 @@ static int v9fs_vfs_mkdir_dotl(struct mnt_idmap *idmap, + struct posix_acl *dacl = NULL, *pacl = NULL; + + p9_debug(P9_DEBUG_VFS, "name %pd\n", dentry); ++ v9ses = v9fs_inode2v9ses(dir); + + omode |= S_IFDIR; + if (dir->i_mode & S_ISGID) +@@ -737,6 +739,7 @@ v9fs_vfs_mknod_dotl(struct mnt_idmap *idmap, struct inode *dir, + kgid_t gid; + const unsigned char *name; + umode_t mode; ++ struct v9fs_session_info *v9ses; + struct p9_fid *fid = NULL, *dfid = NULL; + struct inode *inode; + struct p9_qid qid; +@@ -746,6 +749,7 @@ v9fs_vfs_mknod_dotl(struct mnt_idmap *idmap, struct inode *dir, + dir->i_ino, dentry, omode, + MAJOR(rdev), MINOR(rdev)); + ++ v9ses = v9fs_inode2v9ses(dir); + dfid = v9fs_parent_fid(dentry); + if (IS_ERR(dfid)) { + err = PTR_ERR(dfid); +-- +2.47.0 + diff --git a/queue-6.11/revert-fs-9p-simplify-iget-to-remove-unnecessary-paths.patch b/queue-6.11/revert-fs-9p-simplify-iget-to-remove-unnecessary-paths.patch new file mode 100644 index 00000000000..105e9ca7897 --- /dev/null +++ b/queue-6.11/revert-fs-9p-simplify-iget-to-remove-unnecessary-paths.patch @@ -0,0 +1,458 @@ +From be2ca3825372085d669d322dccd0542a90e5b434 Mon Sep 17 00:00:00 2001 +From: Dominique Martinet +Date: Thu, 24 Oct 2024 08:52:13 +0900 +Subject: Revert "fs/9p: simplify iget to remove unnecessary paths" + +From: Dominique Martinet + +commit be2ca3825372085d669d322dccd0542a90e5b434 upstream. + +This reverts commit 724a08450f74b02bd89078a596fd24857827c012. + +This code simplification introduced significant regressions on servers +that do not remap inode numbers when exporting multiple underlying +filesystems with colliding inodes, as can be illustrated with simple +tmpfs exports in qemu with remapping disabled: +``` +# host side +cd /tmp/linux-test +mkdir m1 m2 +mount -t tmpfs tmpfs m1 +mount -t tmpfs tmpfs m2 +mkdir m1/dir m2/dir +echo foo > m1/dir/foo +echo bar > m2/dir/bar + +# guest side +# started with -virtfs local,path=/tmp/linux-test,mount_tag=tmp,security_model=mapped-file +mount -t 9p -o trans=virtio,debug=1 tmp /mnt/t + +ls /mnt/t/m1/dir +# foo +ls /mnt/t/m2/dir +# bar (works ok if directry isn't open) + +# cd to keep first dir's inode alive +cd /mnt/t/m1/dir +ls /mnt/t/m2/dir +# foo (should be bar) +``` +Other examples can be crafted with regular files with fscache enabled, +in which case I/Os just happen to the wrong file leading to +corruptions, or guest failing to boot with: + | VFS: Lookup of 'com.android.runtime' in 9p 9p would have caused loop + +In theory, we'd want the servers to be smart enough and ensure they +never send us two different files with the same 'qid.path', but while +qemu has an option to remap that is recommended (and qemu prints a +warning if this case happens), there are many other servers which do +not (kvmtool, nfs-ganesha, probably diod...), we should at least ensure +we don't cause regressions on this: +- assume servers can't be trusted and operations that should get a 'new' +inode properly do so. commit d05dcfdf5e16 (" fs/9p: mitigate inode +collisions") attempted to do this, but v9fs_fid_iget_dotl() was not +called so some higher level of caching got in the way; this needs to be +fixed properly before we can re-apply the patches. +- if we ever want to really simplify this code, we will need to add some +negotiation with the server at mount time where the server could claim +they handle this properly, at which point we could optimize this out. +(but that might not be needed at all if we properly handle the 'new' +check?) + +Fixes: 724a08450f74 ("fs/9p: simplify iget to remove unnecessary paths") +Reported-by: Will Deacon +Link: https://lore.kernel.org/all/20240408141436.GA17022@redhat.com/ +Link: https://lkml.kernel.org/r/20240923100508.GA32066@willie-the-truck +Cc: stable@vger.kernel.org # v6.9+ +Message-ID: <20241024-revert_iget-v1-4-4cac63d25f72@codewreck.org> +Signed-off-by: Dominique Martinet +Signed-off-by: Greg Kroah-Hartman +--- + fs/9p/v9fs.h | 31 +++++++++++++-- + fs/9p/v9fs_vfs.h | 2 - + fs/9p/vfs_inode.c | 98 ++++++++++++++++++++++++++++++++++++++----------- + fs/9p/vfs_inode_dotl.c | 92 +++++++++++++++++++++++++++++++++++++--------- + fs/9p/vfs_super.c | 2 - + 5 files changed, 180 insertions(+), 45 deletions(-) + +--- a/fs/9p/v9fs.h ++++ b/fs/9p/v9fs.h +@@ -179,13 +179,16 @@ extern int v9fs_vfs_rename(struct mnt_id + struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry, + unsigned int flags); +-extern struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid); ++extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses, ++ struct p9_fid *fid, ++ struct super_block *sb, int new); + extern const struct inode_operations v9fs_dir_inode_operations_dotl; + extern const struct inode_operations v9fs_file_inode_operations_dotl; + extern const struct inode_operations v9fs_symlink_inode_operations_dotl; + extern const struct netfs_request_ops v9fs_req_ops; +-extern struct inode *v9fs_fid_iget_dotl(struct super_block *sb, +- struct p9_fid *fid); ++extern struct inode *v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, ++ struct p9_fid *fid, ++ struct super_block *sb, int new); + + /* other default globals */ + #define V9FS_PORT 564 +@@ -227,9 +230,27 @@ v9fs_get_inode_from_fid(struct v9fs_sess + struct super_block *sb) + { + if (v9fs_proto_dotl(v9ses)) +- return v9fs_fid_iget_dotl(sb, fid); ++ return v9fs_inode_from_fid_dotl(v9ses, fid, sb, 0); + else +- return v9fs_fid_iget(sb, fid); ++ return v9fs_inode_from_fid(v9ses, fid, sb, 0); ++} ++ ++/** ++ * v9fs_get_new_inode_from_fid - Helper routine to populate an inode by ++ * issuing a attribute request ++ * @v9ses: session information ++ * @fid: fid to issue attribute request for ++ * @sb: superblock on which to create inode ++ * ++ */ ++static inline struct inode * ++v9fs_get_new_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, ++ struct super_block *sb) ++{ ++ if (v9fs_proto_dotl(v9ses)) ++ return v9fs_inode_from_fid_dotl(v9ses, fid, sb, 1); ++ else ++ return v9fs_inode_from_fid(v9ses, fid, sb, 1); + } + + #endif +--- a/fs/9p/v9fs_vfs.h ++++ b/fs/9p/v9fs_vfs.h +@@ -42,7 +42,7 @@ struct inode *v9fs_alloc_inode(struct su + void v9fs_free_inode(struct inode *inode); + void v9fs_set_netfs_context(struct inode *inode); + int v9fs_init_inode(struct v9fs_session_info *v9ses, +- struct inode *inode, struct p9_qid *qid, umode_t mode, dev_t rdev); ++ struct inode *inode, umode_t mode, dev_t rdev); + void v9fs_evict_inode(struct inode *inode); + #if (BITS_PER_LONG == 32) + #define QID2INO(q) ((ino_t) (((q)->path+2) ^ (((q)->path) >> 32))) +--- a/fs/9p/vfs_inode.c ++++ b/fs/9p/vfs_inode.c +@@ -256,12 +256,9 @@ void v9fs_set_netfs_context(struct inode + } + + int v9fs_init_inode(struct v9fs_session_info *v9ses, +- struct inode *inode, struct p9_qid *qid, umode_t mode, dev_t rdev) ++ struct inode *inode, umode_t mode, dev_t rdev) + { + int err = 0; +- struct v9fs_inode *v9inode = V9FS_I(inode); +- +- memcpy(&v9inode->qid, qid, sizeof(struct p9_qid)); + + inode_init_owner(&nop_mnt_idmap, inode, NULL, mode); + inode->i_blocks = 0; +@@ -365,40 +362,80 @@ void v9fs_evict_inode(struct inode *inod + clear_inode(inode); + } + +-struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid) ++static int v9fs_test_inode(struct inode *inode, void *data) ++{ ++ int umode; ++ dev_t rdev; ++ struct v9fs_inode *v9inode = V9FS_I(inode); ++ struct p9_wstat *st = (struct p9_wstat *)data; ++ struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); ++ ++ umode = p9mode2unixmode(v9ses, st, &rdev); ++ /* don't match inode of different type */ ++ if (inode_wrong_type(inode, umode)) ++ return 0; ++ ++ /* compare qid details */ ++ if (memcmp(&v9inode->qid.version, ++ &st->qid.version, sizeof(v9inode->qid.version))) ++ return 0; ++ ++ if (v9inode->qid.type != st->qid.type) ++ return 0; ++ ++ if (v9inode->qid.path != st->qid.path) ++ return 0; ++ return 1; ++} ++ ++static int v9fs_test_new_inode(struct inode *inode, void *data) ++{ ++ return 0; ++} ++ ++static int v9fs_set_inode(struct inode *inode, void *data) ++{ ++ struct v9fs_inode *v9inode = V9FS_I(inode); ++ struct p9_wstat *st = (struct p9_wstat *)data; ++ ++ memcpy(&v9inode->qid, &st->qid, sizeof(st->qid)); ++ return 0; ++} ++ ++static struct inode *v9fs_qid_iget(struct super_block *sb, ++ struct p9_qid *qid, ++ struct p9_wstat *st, ++ int new) + { + dev_t rdev; + int retval; + umode_t umode; + struct inode *inode; +- struct p9_wstat *st; + struct v9fs_session_info *v9ses = sb->s_fs_info; ++ int (*test)(struct inode *inode, void *data); ++ ++ if (new) ++ test = v9fs_test_new_inode; ++ else ++ test = v9fs_test_inode; + +- inode = iget_locked(sb, QID2INO(&fid->qid)); +- if (unlikely(!inode)) ++ inode = iget5_locked(sb, QID2INO(qid), test, v9fs_set_inode, st); ++ if (!inode) + return ERR_PTR(-ENOMEM); + if (!(inode->i_state & I_NEW)) + return inode; +- + /* + * initialize the inode with the stat info + * FIXME!! we may need support for stale inodes + * later. + */ +- st = p9_client_stat(fid); +- if (IS_ERR(st)) { +- retval = PTR_ERR(st); +- goto error; +- } +- ++ inode->i_ino = QID2INO(qid); + umode = p9mode2unixmode(v9ses, st, &rdev); +- retval = v9fs_init_inode(v9ses, inode, &fid->qid, umode, rdev); +- v9fs_stat2inode(st, inode, sb, 0); +- p9stat_free(st); +- kfree(st); ++ retval = v9fs_init_inode(v9ses, inode, umode, rdev); + if (retval) + goto error; + ++ v9fs_stat2inode(st, inode, sb, 0); + v9fs_set_netfs_context(inode); + v9fs_cache_inode_get_cookie(inode); + unlock_new_inode(inode); +@@ -409,6 +446,23 @@ error: + + } + ++struct inode * ++v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, ++ struct super_block *sb, int new) ++{ ++ struct p9_wstat *st; ++ struct inode *inode = NULL; ++ ++ st = p9_client_stat(fid); ++ if (IS_ERR(st)) ++ return ERR_CAST(st); ++ ++ inode = v9fs_qid_iget(sb, &st->qid, st, new); ++ p9stat_free(st); ++ kfree(st); ++ return inode; ++} ++ + /** + * v9fs_at_to_dotl_flags- convert Linux specific AT flags to + * plan 9 AT flag. +@@ -555,7 +609,7 @@ v9fs_create(struct v9fs_session_info *v9 + /* + * instantiate inode and assign the unopened fid to the dentry + */ +- inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb); ++ inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + p9_debug(P9_DEBUG_VFS, +@@ -683,8 +737,10 @@ struct dentry *v9fs_vfs_lookup(struct in + inode = NULL; + else if (IS_ERR(fid)) + inode = ERR_CAST(fid); +- else ++ else if (v9ses->cache & (CACHE_META|CACHE_LOOSE)) + inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb); ++ else ++ inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); + /* + * If we had a rename on the server and a parallel lookup + * for the new name, then make sure we instantiate with +--- a/fs/9p/vfs_inode_dotl.c ++++ b/fs/9p/vfs_inode_dotl.c +@@ -52,33 +52,76 @@ static kgid_t v9fs_get_fsgid_for_create( + return current_fsgid(); + } + +-struct inode *v9fs_fid_iget_dotl(struct super_block *sb, struct p9_fid *fid) ++static int v9fs_test_inode_dotl(struct inode *inode, void *data) ++{ ++ struct v9fs_inode *v9inode = V9FS_I(inode); ++ struct p9_stat_dotl *st = (struct p9_stat_dotl *)data; ++ ++ /* don't match inode of different type */ ++ if (inode_wrong_type(inode, st->st_mode)) ++ return 0; ++ ++ if (inode->i_generation != st->st_gen) ++ return 0; ++ ++ /* compare qid details */ ++ if (memcmp(&v9inode->qid.version, ++ &st->qid.version, sizeof(v9inode->qid.version))) ++ return 0; ++ ++ if (v9inode->qid.type != st->qid.type) ++ return 0; ++ ++ if (v9inode->qid.path != st->qid.path) ++ return 0; ++ return 1; ++} ++ ++/* Always get a new inode */ ++static int v9fs_test_new_inode_dotl(struct inode *inode, void *data) ++{ ++ return 0; ++} ++ ++static int v9fs_set_inode_dotl(struct inode *inode, void *data) ++{ ++ struct v9fs_inode *v9inode = V9FS_I(inode); ++ struct p9_stat_dotl *st = (struct p9_stat_dotl *)data; ++ ++ memcpy(&v9inode->qid, &st->qid, sizeof(st->qid)); ++ inode->i_generation = st->st_gen; ++ return 0; ++} ++ ++static struct inode *v9fs_qid_iget_dotl(struct super_block *sb, ++ struct p9_qid *qid, ++ struct p9_fid *fid, ++ struct p9_stat_dotl *st, ++ int new) + { + int retval; + struct inode *inode; +- struct p9_stat_dotl *st; + struct v9fs_session_info *v9ses = sb->s_fs_info; ++ int (*test)(struct inode *inode, void *data); + +- inode = iget_locked(sb, QID2INO(&fid->qid)); +- if (unlikely(!inode)) ++ if (new) ++ test = v9fs_test_new_inode_dotl; ++ else ++ test = v9fs_test_inode_dotl; ++ ++ inode = iget5_locked(sb, QID2INO(qid), test, v9fs_set_inode_dotl, st); ++ if (!inode) + return ERR_PTR(-ENOMEM); + if (!(inode->i_state & I_NEW)) + return inode; +- + /* + * initialize the inode with the stat info + * FIXME!! we may need support for stale inodes + * later. + */ +- st = p9_client_getattr_dotl(fid, P9_STATS_BASIC | P9_STATS_GEN); +- if (IS_ERR(st)) { +- retval = PTR_ERR(st); +- goto error; +- } +- +- retval = v9fs_init_inode(v9ses, inode, &fid->qid, ++ inode->i_ino = QID2INO(qid); ++ retval = v9fs_init_inode(v9ses, inode, + st->st_mode, new_decode_dev(st->st_rdev)); +- kfree(st); + if (retval) + goto error; + +@@ -90,7 +133,6 @@ struct inode *v9fs_fid_iget_dotl(struct + goto error; + + unlock_new_inode(inode); +- + return inode; + error: + iget_failed(inode); +@@ -98,6 +140,22 @@ error: + + } + ++struct inode * ++v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid, ++ struct super_block *sb, int new) ++{ ++ struct p9_stat_dotl *st; ++ struct inode *inode = NULL; ++ ++ st = p9_client_getattr_dotl(fid, P9_STATS_BASIC | P9_STATS_GEN); ++ if (IS_ERR(st)) ++ return ERR_CAST(st); ++ ++ inode = v9fs_qid_iget_dotl(sb, &st->qid, fid, st, new); ++ kfree(st); ++ return inode; ++} ++ + struct dotl_openflag_map { + int open_flag; + int dotl_flag; +@@ -247,7 +305,7 @@ v9fs_vfs_atomic_open_dotl(struct inode * + p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); + goto out; + } +- inode = v9fs_fid_iget_dotl(dir->i_sb, fid); ++ inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", err); +@@ -342,7 +400,7 @@ static int v9fs_vfs_mkdir_dotl(struct mn + } + + /* instantiate inode and assign the unopened fid to the dentry */ +- inode = v9fs_fid_iget_dotl(dir->i_sb, fid); ++ inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", +@@ -780,7 +838,7 @@ v9fs_vfs_mknod_dotl(struct mnt_idmap *id + err); + goto error; + } +- inode = v9fs_fid_iget_dotl(dir->i_sb, fid); ++ inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", +--- a/fs/9p/vfs_super.c ++++ b/fs/9p/vfs_super.c +@@ -139,7 +139,7 @@ static struct dentry *v9fs_mount(struct + else + sb->s_d_op = &v9fs_dentry_operations; + +- inode = v9fs_get_inode_from_fid(v9ses, fid, sb); ++ inode = v9fs_get_new_inode_from_fid(v9ses, fid, sb); + if (IS_ERR(inode)) { + retval = PTR_ERR(inode); + goto release_sb; diff --git a/queue-6.11/series b/queue-6.11/series index 9247e4298f3..6d47cd3e415 100644 --- a/queue-6.11/series +++ b/queue-6.11/series @@ -233,3 +233,21 @@ drm-amd-display-disable-psr-su-on-parade-08-01-tcon-too.patch platform-x86-intel-pmc-fix-pmc_core_iounmap-to-call-.patch fgraph-fix-missing-unlock-in-register_ftrace_graph.patch fgraph-change-the-name-of-cpuhp-state-to-fgraph-onli.patch +net-phy-dp83822-fix-reset-pin-definitions.patch +nfsd-fix-race-between-laundromat-and-free_stateid.patch +block-fix-sanity-checks-in-blk_rq_map_user_bvec.patch +drm-amd-display-temp-w-a-for-dp-link-layer-compliance.patch +ata-libata-set-did_time_out-for-commands-that-actually-timed-out.patch +asoc-sof-intel-hda-loader-do-not-wait-for-hdaudio-ioc.patch +asoc-sof-intel-hda-handle-prepare-without-close-for-non-hda-dai-s.patch +asoc-sof-intel-hda-always-clean-up-link-dma-during-stop.patch +asoc-sof-ipc4-topology-do-not-set-alh-node_id-for-aggregated-dais.patch +asoc-dapm-avoid-container_of-to-get-component.patch +asoc-qcom-sc7280-fix-missing-soundwire-runtime-stream-alloc.patch +asoc-qcom-sdm845-add-missing-soundwire-runtime-stream-alloc.patch +asoc-qcom-fix-null-dereference-in-asoc_qcom_lpass_cpu_platform_probe.patch +revert-fs-9p-mitigate-inode-collisions.patch +revert-fs-9p-remove-redundant-pointer-v9ses.patch +revert-fs-9p-fix-uaf-in-in-v9fs_stat2inode_dotl.patch +revert-fs-9p-simplify-iget-to-remove-unnecessary-paths.patch +soundwire-intel_ace2x-send-pdi-stream-number-during-prepare.patch diff --git a/queue-6.11/soundwire-intel_ace2x-send-pdi-stream-number-during-prepare.patch b/queue-6.11/soundwire-intel_ace2x-send-pdi-stream-number-during-prepare.patch new file mode 100644 index 00000000000..0ea16058063 --- /dev/null +++ b/queue-6.11/soundwire-intel_ace2x-send-pdi-stream-number-during-prepare.patch @@ -0,0 +1,87 @@ +From c78f1e15e46ac82607eed593b22992fd08644d96 Mon Sep 17 00:00:00 2001 +From: Ranjani Sridharan +Date: Wed, 16 Oct 2024 11:29:09 +0800 +Subject: soundwire: intel_ace2x: Send PDI stream number during prepare +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ranjani Sridharan + +commit c78f1e15e46ac82607eed593b22992fd08644d96 upstream. + +In the case of a prepare callback after an xrun or when the PCM is +restarted after a call to snd_pcm_drain/snd_pcm_drop, avoid +reprogramming the SHIM registers but send the PDI stream number so that +the link DMA data can be set. This is needed for the case that the DMA +data is cleared when the PCM is stopped and restarted without being +closed. + +Link: https://github.com/thesofproject/sof/issues/9502 +Signed-off-by: Ranjani Sridharan +Reviewed-by: Péter Ujfalusi +Reviewed-by: Kai Vehmanen +Signed-off-by: Bard Liao +Acked-by: Vinod Koul +All: stable@vger.kernel.org # 6.10.x 6.11.x +Link: https://patch.msgid.link/20241016032910.14601-4-yung-chuan.liao@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/soundwire/intel_ace2x.c | 19 ++++++------------- + 1 file changed, 6 insertions(+), 13 deletions(-) + +diff --git a/drivers/soundwire/intel_ace2x.c b/drivers/soundwire/intel_ace2x.c +index fff312c6968d..4f3dd70d6a1a 100644 +--- a/drivers/soundwire/intel_ace2x.c ++++ b/drivers/soundwire/intel_ace2x.c +@@ -376,11 +376,12 @@ static int intel_hw_params(struct snd_pcm_substream *substream, + static int intel_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) + { ++ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai); + struct sdw_intel *sdw = cdns_to_intel(cdns); + struct sdw_cdns_dai_runtime *dai_runtime; ++ struct snd_pcm_hw_params *hw_params; + int ch, dir; +- int ret = 0; + + dai_runtime = cdns->dai_runtime_array[dai->id]; + if (!dai_runtime) { +@@ -389,12 +390,8 @@ static int intel_prepare(struct snd_pcm_substream *substream, + return -EIO; + } + ++ hw_params = &rtd->dpcm[substream->stream].hw_params; + if (dai_runtime->suspended) { +- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); +- struct snd_pcm_hw_params *hw_params; +- +- hw_params = &rtd->dpcm[substream->stream].hw_params; +- + dai_runtime->suspended = false; + + /* +@@ -415,15 +412,11 @@ static int intel_prepare(struct snd_pcm_substream *substream, + /* the SHIM will be configured in the callback functions */ + + sdw_cdns_config_stream(cdns, ch, dir, dai_runtime->pdi); +- +- /* Inform DSP about PDI stream number */ +- ret = intel_params_stream(sdw, substream, dai, +- hw_params, +- sdw->instance, +- dai_runtime->pdi->intel_alh_id); + } + +- return ret; ++ /* Inform DSP about PDI stream number */ ++ return intel_params_stream(sdw, substream, dai, hw_params, sdw->instance, ++ dai_runtime->pdi->intel_alh_id); + } + + static int +-- +2.47.0 +