From: Greg Kroah-Hartman Date: Fri, 20 Jun 2025 05:53:35 +0000 (+0200) Subject: 6.15-stable patches X-Git-Tag: v5.4.295~175 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=49370284f9fb37ba6ad1d766ea21920d22a69aea;p=thirdparty%2Fkernel%2Fstable-queue.git 6.15-stable patches added patches: alloc_tag-handle-module-codetag-load-errors-as-module-load-failures.patch asoc-amd-amd_sdw-fix-unlikely-uninitialized-variable-use-in-create_sdw_dailinks.patch asoc-amd-sof_amd_sdw-fix-unlikely-uninitialized-variable-use-in-create_sdw_dailinks.patch asoc-meson-meson-card-utils-use-of_property_present-for-dt-parsing.patch asoc-qcom-sdm845-add-error-handling-in-sdm845_slim_snd_hw_params.patch configfs-do-not-override-creating-attribute-file-failure-in-populate_attrs.patch crypto-marvell-cesa-do-not-chain-submitted-requests.patch crypto-qat-add-shutdown-handler-to-qat_420xx.patch crypto-qat-add-shutdown-handler-to-qat_4xxx.patch crypto-qat-add-shutdown-handler-to-qat_c3xxx.patch crypto-qat-add-shutdown-handler-to-qat_c62x.patch crypto-qat-add-shutdown-handler-to-qat_dh895xcc.patch firmware-cs_dsp-fix-oob-memory-read-access-in-kunit-test.patch gfs2-move-msleep-to-sleepable-context.patch io_uring-account-drain-memory-to-cgroup.patch io_uring-kbuf-account-ring-io_buffer_list-memory.patch net-mlx5-add-error-handling-in-mlx5_query_nic_vport_node_guid.patch net-mlx5_core-add-error-handling-inmlx5_query_nic_vport_qkey_viol_cntr.patch powerpc-bpf-fix-jit-code-size-calculation-of-bpf-trampoline.patch powerpc-pseries-msi-avoid-reading-pci-device-registers-in-reduced-power-states.patch powerpc64-ftrace-fix-clobbered-r15-during-livepatching.patch regulator-max20086-change-enable-gpio-to-optional.patch regulator-max20086-fix-max200086-chip-id.patch s390-pci-allow-re-add-of-a-reserved-but-not-yet-removed-device.patch s390-pci-fix-__pcilg_mio_inuser-inline-assembly.patch s390-pci-prevent-self-deletion-in-disable_slot.patch s390-pci-remove-redundant-bus-removal-and-disable-from-zpci_release_device.patch s390-pci-serialize-device-addition-and-removal.patch sched-fair-adhere-to-place_entity-constraints.patch sched-rt-fix-race-in-push_rt_task.patch series wifi-mt76-mt7925-fix-host-interrupt-register-initialization.patch wifi-p54-prevent-buffer-overflow-in-p54_rx_eeprom_readback.patch --- diff --git a/queue-6.15/alloc_tag-handle-module-codetag-load-errors-as-module-load-failures.patch b/queue-6.15/alloc_tag-handle-module-codetag-load-errors-as-module-load-failures.patch new file mode 100644 index 0000000000..60eac33151 --- /dev/null +++ b/queue-6.15/alloc_tag-handle-module-codetag-load-errors-as-module-load-failures.patch @@ -0,0 +1,189 @@ +From 044d2aee6c575231ed4a24fb3d119bad0937488b Mon Sep 17 00:00:00 2001 +From: Suren Baghdasaryan +Date: Wed, 21 May 2025 09:06:02 -0700 +Subject: alloc_tag: handle module codetag load errors as module load failures + +From: Suren Baghdasaryan + +commit 044d2aee6c575231ed4a24fb3d119bad0937488b upstream. + +Failures inside codetag_load_module() are currently ignored. As a result +an error there would not cause a module load failure and freeing of the +associated resources. Correct this behavior by propagating the error code +to the caller and handling possible errors. With this change, error to +allocate percpu counters, which happens at this stage, will not be ignored +and will cause a module load failure and freeing of resources. With this +change we also do not need to disable memory allocation profiling when +this error happens, instead we fail to load the module. + +Link: https://lkml.kernel.org/r/20250521160602.1940771-1-surenb@google.com +Fixes: 10075262888b ("alloc_tag: allocate percpu counters for module tags dynamically") +Signed-off-by: Suren Baghdasaryan +Reported-by: Casey Chen +Closes: https://lore.kernel.org/all/20250520231620.15259-1-cachen@purestorage.com/ +Cc: Daniel Gomez +Cc: David Wang <00107082@163.com> +Cc: Kent Overstreet +Cc: Luis Chamberalin +Cc: Petr Pavlu +Cc: Sami Tolvanen +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/codetag.h | 8 ++++---- + kernel/module/main.c | 5 +++-- + lib/alloc_tag.c | 12 +++++++----- + lib/codetag.c | 34 +++++++++++++++++++++++++--------- + 4 files changed, 39 insertions(+), 20 deletions(-) + +--- a/include/linux/codetag.h ++++ b/include/linux/codetag.h +@@ -36,8 +36,8 @@ union codetag_ref { + struct codetag_type_desc { + const char *section; + size_t tag_size; +- void (*module_load)(struct module *mod, +- struct codetag *start, struct codetag *end); ++ int (*module_load)(struct module *mod, ++ struct codetag *start, struct codetag *end); + void (*module_unload)(struct module *mod, + struct codetag *start, struct codetag *end); + #ifdef CONFIG_MODULES +@@ -89,7 +89,7 @@ void *codetag_alloc_module_section(struc + unsigned long align); + void codetag_free_module_sections(struct module *mod); + void codetag_module_replaced(struct module *mod, struct module *new_mod); +-void codetag_load_module(struct module *mod); ++int codetag_load_module(struct module *mod); + void codetag_unload_module(struct module *mod); + + #else /* defined(CONFIG_CODE_TAGGING) && defined(CONFIG_MODULES) */ +@@ -103,7 +103,7 @@ codetag_alloc_module_section(struct modu + unsigned long align) { return NULL; } + static inline void codetag_free_module_sections(struct module *mod) {} + static inline void codetag_module_replaced(struct module *mod, struct module *new_mod) {} +-static inline void codetag_load_module(struct module *mod) {} ++static inline int codetag_load_module(struct module *mod) { return 0; } + static inline void codetag_unload_module(struct module *mod) {} + + #endif /* defined(CONFIG_CODE_TAGGING) && defined(CONFIG_MODULES) */ +--- a/kernel/module/main.c ++++ b/kernel/module/main.c +@@ -3399,11 +3399,12 @@ static int load_module(struct load_info + goto sysfs_cleanup; + } + ++ if (codetag_load_module(mod)) ++ goto sysfs_cleanup; ++ + /* Get rid of temporary copy. */ + free_copy(info, flags); + +- codetag_load_module(mod); +- + /* Done! */ + trace_module_load(mod); + +--- a/lib/alloc_tag.c ++++ b/lib/alloc_tag.c +@@ -618,15 +618,16 @@ out: + mas_unlock(&mas); + } + +-static void load_module(struct module *mod, struct codetag *start, struct codetag *stop) ++static int load_module(struct module *mod, struct codetag *start, struct codetag *stop) + { + /* Allocate module alloc_tag percpu counters */ + struct alloc_tag *start_tag; + struct alloc_tag *stop_tag; + struct alloc_tag *tag; + ++ /* percpu counters for core allocations are already statically allocated */ + if (!mod) +- return; ++ return 0; + + start_tag = ct_to_alloc_tag(start); + stop_tag = ct_to_alloc_tag(stop); +@@ -638,12 +639,13 @@ static void load_module(struct module *m + free_percpu(tag->counters); + tag->counters = NULL; + } +- shutdown_mem_profiling(true); +- pr_err("Failed to allocate memory for allocation tag percpu counters in the module %s. Memory allocation profiling is disabled!\n", ++ pr_err("Failed to allocate memory for allocation tag percpu counters in the module %s\n", + mod->name); +- break; ++ return -ENOMEM; + } + } ++ ++ return 0; + } + + static void replace_module(struct module *mod, struct module *new_mod) +--- a/lib/codetag.c ++++ b/lib/codetag.c +@@ -167,6 +167,7 @@ static int codetag_module_init(struct co + { + struct codetag_range range; + struct codetag_module *cmod; ++ int mod_id; + int err; + + range = get_section_range(mod, cttype->desc.section); +@@ -190,11 +191,20 @@ static int codetag_module_init(struct co + cmod->range = range; + + down_write(&cttype->mod_lock); +- err = idr_alloc(&cttype->mod_idr, cmod, 0, 0, GFP_KERNEL); +- if (err >= 0) { +- cttype->count += range_size(cttype, &range); +- if (cttype->desc.module_load) +- cttype->desc.module_load(mod, range.start, range.stop); ++ mod_id = idr_alloc(&cttype->mod_idr, cmod, 0, 0, GFP_KERNEL); ++ if (mod_id >= 0) { ++ if (cttype->desc.module_load) { ++ err = cttype->desc.module_load(mod, range.start, range.stop); ++ if (!err) ++ cttype->count += range_size(cttype, &range); ++ else ++ idr_remove(&cttype->mod_idr, mod_id); ++ } else { ++ cttype->count += range_size(cttype, &range); ++ err = 0; ++ } ++ } else { ++ err = mod_id; + } + up_write(&cttype->mod_lock); + +@@ -295,17 +305,23 @@ void codetag_module_replaced(struct modu + mutex_unlock(&codetag_lock); + } + +-void codetag_load_module(struct module *mod) ++int codetag_load_module(struct module *mod) + { + struct codetag_type *cttype; ++ int ret = 0; + + if (!mod) +- return; ++ return 0; + + mutex_lock(&codetag_lock); +- list_for_each_entry(cttype, &codetag_types, link) +- codetag_module_init(cttype, mod); ++ list_for_each_entry(cttype, &codetag_types, link) { ++ ret = codetag_module_init(cttype, mod); ++ if (ret) ++ break; ++ } + mutex_unlock(&codetag_lock); ++ ++ return ret; + } + + void codetag_unload_module(struct module *mod) diff --git a/queue-6.15/asoc-amd-amd_sdw-fix-unlikely-uninitialized-variable-use-in-create_sdw_dailinks.patch b/queue-6.15/asoc-amd-amd_sdw-fix-unlikely-uninitialized-variable-use-in-create_sdw_dailinks.patch new file mode 100644 index 0000000000..91f38b9eee --- /dev/null +++ b/queue-6.15/asoc-amd-amd_sdw-fix-unlikely-uninitialized-variable-use-in-create_sdw_dailinks.patch @@ -0,0 +1,39 @@ +From 4d87ae7508cb7ff58fd0bcecc6e9491f42f987f8 Mon Sep 17 00:00:00 2001 +From: Vijendar Mukunda +Date: Tue, 6 May 2025 17:37:22 +0530 +Subject: ASoC: amd: amd_sdw: Fix unlikely uninitialized variable use in create_sdw_dailinks() + +From: Vijendar Mukunda + +commit 4d87ae7508cb7ff58fd0bcecc6e9491f42f987f8 upstream. + +Initialize current_be_id to 0 in AMD legacy stack(NO DSP enabled) SoundWire +generic machine driver code to handle the unlikely case when there are no +devices connected to a DAI. + +In this case create_sdw_dailink() would return without touching the passed +pointer to current_be_id. + +Found by gcc -fanalyzer + +Cc: stable@vger.kernel.org +Fixes: 2981d9b0789c4 ("ASoC: amd: acp: add soundwire machine driver for legacy stack") +Signed-off-by: Vijendar Mukunda +Link: https://patch.msgid.link/20250506120823.3621604-1-Vijendar.Mukunda@amd.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + sound/soc/amd/acp/acp-sdw-legacy-mach.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/sound/soc/amd/acp/acp-sdw-legacy-mach.c ++++ b/sound/soc/amd/acp/acp-sdw-legacy-mach.c +@@ -272,7 +272,7 @@ static int create_sdw_dailinks(struct sn + + /* generate DAI links by each sdw link */ + while (soc_dais->initialised) { +- int current_be_id; ++ int current_be_id = 0; + + ret = create_sdw_dailink(card, soc_dais, dai_links, + ¤t_be_id, codec_conf, sdw_platform_component); diff --git a/queue-6.15/asoc-amd-sof_amd_sdw-fix-unlikely-uninitialized-variable-use-in-create_sdw_dailinks.patch b/queue-6.15/asoc-amd-sof_amd_sdw-fix-unlikely-uninitialized-variable-use-in-create_sdw_dailinks.patch new file mode 100644 index 0000000000..aa96047360 --- /dev/null +++ b/queue-6.15/asoc-amd-sof_amd_sdw-fix-unlikely-uninitialized-variable-use-in-create_sdw_dailinks.patch @@ -0,0 +1,38 @@ +From 6b83ba4bc3ecb915476d688c9f00f3be57b49a0c Mon Sep 17 00:00:00 2001 +From: Vijendar Mukunda +Date: Tue, 6 May 2025 17:37:23 +0530 +Subject: ASoC: amd: sof_amd_sdw: Fix unlikely uninitialized variable use in create_sdw_dailinks() + +From: Vijendar Mukunda + +commit 6b83ba4bc3ecb915476d688c9f00f3be57b49a0c upstream. + +Initialize current_be_id to 0 in SOF based AMD generic SoundWire machine +driver to handle the unlikely case when there are no devices connected to +a DAI. +In this case create_sdw_dailink() would return without touching the passed +pointer to current_be_id. + +Found by gcc -fanalyzer + +Cc: stable@vger.kernel.org +Fixes: 6d8348ddc56ed ("ASoC: amd: acp: refactor SoundWire machine driver code") +Signed-off-by: Vijendar Mukunda +Link: https://patch.msgid.link/20250506120823.3621604-2-Vijendar.Mukunda@amd.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + sound/soc/amd/acp/acp-sdw-sof-mach.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/sound/soc/amd/acp/acp-sdw-sof-mach.c ++++ b/sound/soc/amd/acp/acp-sdw-sof-mach.c +@@ -219,7 +219,7 @@ static int create_sdw_dailinks(struct sn + + /* generate DAI links by each sdw link */ + while (sof_dais->initialised) { +- int current_be_id; ++ int current_be_id = 0; + + ret = create_sdw_dailink(card, sof_dais, dai_links, + ¤t_be_id, codec_conf); diff --git a/queue-6.15/asoc-meson-meson-card-utils-use-of_property_present-for-dt-parsing.patch b/queue-6.15/asoc-meson-meson-card-utils-use-of_property_present-for-dt-parsing.patch new file mode 100644 index 0000000000..ffa087cc53 --- /dev/null +++ b/queue-6.15/asoc-meson-meson-card-utils-use-of_property_present-for-dt-parsing.patch @@ -0,0 +1,43 @@ +From 171eb6f71e9e3ba6a7410a1d93f3ac213f39dae2 Mon Sep 17 00:00:00 2001 +From: Martin Blumenstingl +Date: Sat, 19 Apr 2025 23:34:48 +0200 +Subject: ASoC: meson: meson-card-utils: use of_property_present() for DT parsing + +From: Martin Blumenstingl + +commit 171eb6f71e9e3ba6a7410a1d93f3ac213f39dae2 upstream. + +Commit c141ecc3cecd ("of: Warn when of_property_read_bool() is used on +non-boolean properties") added a warning when trying to parse a property +with a value (boolean properties are defined as: absent = false, present +without any value = true). This causes a warning from meson-card-utils. + +meson-card-utils needs to know about the existence of the +"audio-routing" and/or "audio-widgets" properties in order to properly +parse them. Switch to of_property_present() in order to silence the +following warning messages during boot: + OF: /sound: Read of boolean property 'audio-routing' with a value. + OF: /sound: Read of boolean property 'audio-widgets' with a value. + +Fixes: 7864a79f37b5 ("ASoC: meson: add axg sound card support") +Tested-by: Christian Hewitt +Cc: stable@vger.kernel.org +Signed-off-by: Martin Blumenstingl +Link: https://patch.msgid.link/20250419213448.59647-1-martin.blumenstingl@googlemail.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + sound/soc/meson/meson-card-utils.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/sound/soc/meson/meson-card-utils.c ++++ b/sound/soc/meson/meson-card-utils.c +@@ -231,7 +231,7 @@ static int meson_card_parse_of_optional( + const char *p)) + { + /* If property is not provided, don't fail ... */ +- if (!of_property_read_bool(card->dev->of_node, propname)) ++ if (!of_property_present(card->dev->of_node, propname)) + return 0; + + /* ... but do fail if it is provided and the parsing fails */ diff --git a/queue-6.15/asoc-qcom-sdm845-add-error-handling-in-sdm845_slim_snd_hw_params.patch b/queue-6.15/asoc-qcom-sdm845-add-error-handling-in-sdm845_slim_snd_hw_params.patch new file mode 100644 index 0000000000..26db8a98c8 --- /dev/null +++ b/queue-6.15/asoc-qcom-sdm845-add-error-handling-in-sdm845_slim_snd_hw_params.patch @@ -0,0 +1,41 @@ +From 688abe2860fd9c644705b9e11cb9649eb891b879 Mon Sep 17 00:00:00 2001 +From: Wentao Liang +Date: Mon, 19 May 2025 15:57:39 +0800 +Subject: ASoC: qcom: sdm845: Add error handling in sdm845_slim_snd_hw_params() + +From: Wentao Liang + +commit 688abe2860fd9c644705b9e11cb9649eb891b879 upstream. + +The function sdm845_slim_snd_hw_params() calls the functuion +snd_soc_dai_set_channel_map() but does not check its return +value. A proper implementation can be found in msm_snd_hw_params(). + +Add error handling for snd_soc_dai_set_channel_map(). If the +function fails and it is not a unsupported error, return the +error code immediately. + +Fixes: 5caf64c633a3 ("ASoC: qcom: sdm845: add support to DB845c and Lenovo Yoga") +Cc: stable@vger.kernel.org # v5.6 +Signed-off-by: Wentao Liang +Reviewed-by: Dmitry Baryshkov +Link: https://patch.msgid.link/20250519075739.1458-1-vulab@iscas.ac.cn +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + sound/soc/qcom/sdm845.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/sound/soc/qcom/sdm845.c ++++ b/sound/soc/qcom/sdm845.c +@@ -91,6 +91,10 @@ static int sdm845_slim_snd_hw_params(str + else + ret = snd_soc_dai_set_channel_map(cpu_dai, tx_ch_cnt, + tx_ch, 0, NULL); ++ if (ret != 0 && ret != -ENOTSUPP) { ++ dev_err(rtd->dev, "failed to set cpu chan map, err:%d\n", ret); ++ return ret; ++ } + } + + return 0; diff --git a/queue-6.15/configfs-do-not-override-creating-attribute-file-failure-in-populate_attrs.patch b/queue-6.15/configfs-do-not-override-creating-attribute-file-failure-in-populate_attrs.patch new file mode 100644 index 0000000000..e88e10550e --- /dev/null +++ b/queue-6.15/configfs-do-not-override-creating-attribute-file-failure-in-populate_attrs.patch @@ -0,0 +1,39 @@ +From f830edbae247b89228c3e09294151b21e0dc849c Mon Sep 17 00:00:00 2001 +From: Zijun Hu +Date: Wed, 7 May 2025 19:50:26 +0800 +Subject: configfs: Do not override creating attribute file failure in populate_attrs() + +From: Zijun Hu + +commit f830edbae247b89228c3e09294151b21e0dc849c upstream. + +populate_attrs() may override failure for creating attribute files +by success for creating subsequent bin attribute files, and have +wrong return value. + +Fix by creating bin attribute files under successfully creating +attribute files. + +Fixes: 03607ace807b ("configfs: implement binary attributes") +Cc: stable@vger.kernel.org +Reviewed-by: Joel Becker +Reviewed-by: Breno Leitao +Signed-off-by: Zijun Hu +Link: https://lore.kernel.org/r/20250507-fix_configfs-v3-2-fe2d96de8dc4@quicinc.com +Signed-off-by: Andreas Hindborg +Signed-off-by: Greg Kroah-Hartman +--- + fs/configfs/dir.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/configfs/dir.c ++++ b/fs/configfs/dir.c +@@ -619,7 +619,7 @@ static int populate_attrs(struct config_ + break; + } + } +- if (t->ct_bin_attrs) { ++ if (!error && t->ct_bin_attrs) { + for (i = 0; (bin_attr = t->ct_bin_attrs[i]) != NULL; i++) { + if (ops && ops->is_bin_visible && !ops->is_bin_visible(item, bin_attr, i)) + continue; diff --git a/queue-6.15/crypto-marvell-cesa-do-not-chain-submitted-requests.patch b/queue-6.15/crypto-marvell-cesa-do-not-chain-submitted-requests.patch new file mode 100644 index 0000000000..7c14bf42d0 --- /dev/null +++ b/queue-6.15/crypto-marvell-cesa-do-not-chain-submitted-requests.patch @@ -0,0 +1,156 @@ +From 0413bcf0fc460a68a2a7a8354aee833293d7d693 Mon Sep 17 00:00:00 2001 +From: Herbert Xu +Date: Thu, 8 May 2025 13:22:16 +0800 +Subject: crypto: marvell/cesa - Do not chain submitted requests + +From: Herbert Xu + +commit 0413bcf0fc460a68a2a7a8354aee833293d7d693 upstream. + +This driver tries to chain requests together before submitting them +to hardware in order to reduce completion interrupts. + +However, it even extends chains that have already been submitted +to hardware. This is dangerous because there is no way of knowing +whether the hardware has already read the DMA memory in question +or not. + +Fix this by splitting the chain list into two. One for submitted +requests and one for requests that have not yet been submitted. +Only extend the latter. + +Reported-by: Klaus Kudielka +Fixes: 85030c5168f1 ("crypto: marvell - Add support for chaining crypto requests in TDMA mode") +Cc: +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/crypto/marvell/cesa/cesa.c | 2 - + drivers/crypto/marvell/cesa/cesa.h | 9 ++++-- + drivers/crypto/marvell/cesa/tdma.c | 53 ++++++++++++++++++++++--------------- + 3 files changed, 39 insertions(+), 25 deletions(-) + +--- a/drivers/crypto/marvell/cesa/cesa.c ++++ b/drivers/crypto/marvell/cesa/cesa.c +@@ -94,7 +94,7 @@ static int mv_cesa_std_process(struct mv + + static int mv_cesa_int_process(struct mv_cesa_engine *engine, u32 status) + { +- if (engine->chain.first && engine->chain.last) ++ if (engine->chain_hw.first && engine->chain_hw.last) + return mv_cesa_tdma_process(engine, status); + + return mv_cesa_std_process(engine, status); +--- a/drivers/crypto/marvell/cesa/cesa.h ++++ b/drivers/crypto/marvell/cesa/cesa.h +@@ -440,8 +440,10 @@ struct mv_cesa_dev { + * SRAM + * @queue: fifo of the pending crypto requests + * @load: engine load counter, useful for load balancing +- * @chain: list of the current tdma descriptors being processed +- * by this engine. ++ * @chain_hw: list of the current tdma descriptors being processed ++ * by the hardware. ++ * @chain_sw: list of the current tdma descriptors that will be ++ * submitted to the hardware. + * @complete_queue: fifo of the processed requests by the engine + * + * Structure storing CESA engine information. +@@ -463,7 +465,8 @@ struct mv_cesa_engine { + struct gen_pool *pool; + struct crypto_queue queue; + atomic_t load; +- struct mv_cesa_tdma_chain chain; ++ struct mv_cesa_tdma_chain chain_hw; ++ struct mv_cesa_tdma_chain chain_sw; + struct list_head complete_queue; + int irq; + }; +--- a/drivers/crypto/marvell/cesa/tdma.c ++++ b/drivers/crypto/marvell/cesa/tdma.c +@@ -38,6 +38,15 @@ void mv_cesa_dma_step(struct mv_cesa_req + { + struct mv_cesa_engine *engine = dreq->engine; + ++ spin_lock_bh(&engine->lock); ++ if (engine->chain_sw.first == dreq->chain.first) { ++ engine->chain_sw.first = NULL; ++ engine->chain_sw.last = NULL; ++ } ++ engine->chain_hw.first = dreq->chain.first; ++ engine->chain_hw.last = dreq->chain.last; ++ spin_unlock_bh(&engine->lock); ++ + writel_relaxed(0, engine->regs + CESA_SA_CFG); + + mv_cesa_set_int_mask(engine, CESA_SA_INT_ACC0_IDMA_DONE); +@@ -96,25 +105,27 @@ void mv_cesa_dma_prepare(struct mv_cesa_ + void mv_cesa_tdma_chain(struct mv_cesa_engine *engine, + struct mv_cesa_req *dreq) + { +- if (engine->chain.first == NULL && engine->chain.last == NULL) { +- engine->chain.first = dreq->chain.first; +- engine->chain.last = dreq->chain.last; +- } else { +- struct mv_cesa_tdma_desc *last; ++ struct mv_cesa_tdma_desc *last = engine->chain_sw.last; + +- last = engine->chain.last; ++ /* ++ * Break the DMA chain if the request being queued needs the IV ++ * regs to be set before lauching the request. ++ */ ++ if (!last || dreq->chain.first->flags & CESA_TDMA_SET_STATE) ++ engine->chain_sw.first = dreq->chain.first; ++ else { + last->next = dreq->chain.first; +- engine->chain.last = dreq->chain.last; +- +- /* +- * Break the DMA chain if the CESA_TDMA_BREAK_CHAIN is set on +- * the last element of the current chain, or if the request +- * being queued needs the IV regs to be set before lauching +- * the request. +- */ +- if (!(last->flags & CESA_TDMA_BREAK_CHAIN) && +- !(dreq->chain.first->flags & CESA_TDMA_SET_STATE)) +- last->next_dma = cpu_to_le32(dreq->chain.first->cur_dma); ++ last->next_dma = cpu_to_le32(dreq->chain.first->cur_dma); ++ } ++ last = dreq->chain.last; ++ engine->chain_sw.last = last; ++ /* ++ * Break the DMA chain if the CESA_TDMA_BREAK_CHAIN is set on ++ * the last element of the current chain. ++ */ ++ if (last->flags & CESA_TDMA_BREAK_CHAIN) { ++ engine->chain_sw.first = NULL; ++ engine->chain_sw.last = NULL; + } + } + +@@ -127,7 +138,7 @@ int mv_cesa_tdma_process(struct mv_cesa_ + + tdma_cur = readl(engine->regs + CESA_TDMA_CUR); + +- for (tdma = engine->chain.first; tdma; tdma = next) { ++ for (tdma = engine->chain_hw.first; tdma; tdma = next) { + spin_lock_bh(&engine->lock); + next = tdma->next; + spin_unlock_bh(&engine->lock); +@@ -149,12 +160,12 @@ int mv_cesa_tdma_process(struct mv_cesa_ + &backlog); + + /* Re-chaining to the next request */ +- engine->chain.first = tdma->next; ++ engine->chain_hw.first = tdma->next; + tdma->next = NULL; + + /* If this is the last request, clear the chain */ +- if (engine->chain.first == NULL) +- engine->chain.last = NULL; ++ if (engine->chain_hw.first == NULL) ++ engine->chain_hw.last = NULL; + spin_unlock_bh(&engine->lock); + + ctx = crypto_tfm_ctx(req->tfm); diff --git a/queue-6.15/crypto-qat-add-shutdown-handler-to-qat_420xx.patch b/queue-6.15/crypto-qat-add-shutdown-handler-to-qat_420xx.patch new file mode 100644 index 0000000000..e33c5ca6f7 --- /dev/null +++ b/queue-6.15/crypto-qat-add-shutdown-handler-to-qat_420xx.patch @@ -0,0 +1,58 @@ +From 097143f23a1164bfd1b6f70279d229be44da2e30 Mon Sep 17 00:00:00 2001 +From: Giovanni Cabiddu +Date: Wed, 26 Mar 2025 15:59:47 +0000 +Subject: crypto: qat - add shutdown handler to qat_420xx + +From: Giovanni Cabiddu + +commit 097143f23a1164bfd1b6f70279d229be44da2e30 upstream. + +During a warm reset via kexec, the system bypasses the driver removal +sequence, meaning that the remove() callback is not invoked. +If a QAT device is not shutdown properly, the device driver will fail to +load in a newly rebooted kernel. + +This might result in output like the following after the kexec reboot: + + 420xx 0000:01:00.0: Failed to power up the device + 420xx 0000:01:00.0: Failed to initialize device + 420xx 0000:01:00.0: Resetting device qat_dev0 + 420xx 0000:01:00.0: probe with driver 420xx failed with error -14 + +Implement the shutdown() handler that hooks into the reboot notifier +list. This brings down the QAT device and ensures it is shut down +properly. + +Cc: +Fixes: fcf60f4bcf54 ("crypto: qat - add support for 420xx devices") +Reviewed-by: Ahsan Atta +Reviewed-by: Andy Shevchenko +Signed-off-by: Giovanni Cabiddu +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/crypto/intel/qat/qat_420xx/adf_drv.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/crypto/intel/qat/qat_420xx/adf_drv.c ++++ b/drivers/crypto/intel/qat/qat_420xx/adf_drv.c +@@ -186,11 +186,19 @@ static void adf_remove(struct pci_dev *p + adf_cleanup_accel(accel_dev); + } + ++static void adf_shutdown(struct pci_dev *pdev) ++{ ++ struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev); ++ ++ adf_dev_down(accel_dev); ++} ++ + static struct pci_driver adf_driver = { + .id_table = adf_pci_tbl, + .name = ADF_420XX_DEVICE_NAME, + .probe = adf_probe, + .remove = adf_remove, ++ .shutdown = adf_shutdown, + .sriov_configure = adf_sriov_configure, + .err_handler = &adf_err_handler, + }; diff --git a/queue-6.15/crypto-qat-add-shutdown-handler-to-qat_4xxx.patch b/queue-6.15/crypto-qat-add-shutdown-handler-to-qat_4xxx.patch new file mode 100644 index 0000000000..6c0f1ad581 --- /dev/null +++ b/queue-6.15/crypto-qat-add-shutdown-handler-to-qat_4xxx.patch @@ -0,0 +1,61 @@ +From 845bc952024dbf482c7434daeac66f764642d52d Mon Sep 17 00:00:00 2001 +From: Giovanni Cabiddu +Date: Wed, 26 Mar 2025 15:59:46 +0000 +Subject: crypto: qat - add shutdown handler to qat_4xxx + +From: Giovanni Cabiddu + +commit 845bc952024dbf482c7434daeac66f764642d52d upstream. + +During a warm reset via kexec, the system bypasses the driver removal +sequence, meaning that the remove() callback is not invoked. +If a QAT device is not shutdown properly, the device driver will fail to +load in a newly rebooted kernel. + +This might result in output like the following after the kexec reboot: + + 4xxx 0000:01:00.0: Failed to power up the device + 4xxx 0000:01:00.0: Failed to initialize device + 4xxx 0000:01:00.0: Resetting device qat_dev0 + 4xxx 0000:01:00.0: probe with driver 4xxx failed with error -14 + +Implement the shutdown() handler that hooks into the reboot notifier +list. This brings down the QAT device and ensures it is shut down +properly. + +Cc: +Fixes: 8c8268166e83 ("crypto: qat - add qat_4xxx driver") +Link: https://lore.kernel.org/all/Z-DGQrhRj9niR9iZ@gondor.apana.org.au/ +Reported-by: Randy Wright +Closes: https://issues.redhat.com/browse/RHEL-84366 +Reviewed-by: Ahsan Atta +Reviewed-by: Andy Shevchenko +Signed-off-by: Giovanni Cabiddu +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/crypto/intel/qat/qat_4xxx/adf_drv.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c ++++ b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c +@@ -188,11 +188,19 @@ static void adf_remove(struct pci_dev *p + adf_cleanup_accel(accel_dev); + } + ++static void adf_shutdown(struct pci_dev *pdev) ++{ ++ struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev); ++ ++ adf_dev_down(accel_dev); ++} ++ + static struct pci_driver adf_driver = { + .id_table = adf_pci_tbl, + .name = ADF_4XXX_DEVICE_NAME, + .probe = adf_probe, + .remove = adf_remove, ++ .shutdown = adf_shutdown, + .sriov_configure = adf_sriov_configure, + .err_handler = &adf_err_handler, + }; diff --git a/queue-6.15/crypto-qat-add-shutdown-handler-to-qat_c3xxx.patch b/queue-6.15/crypto-qat-add-shutdown-handler-to-qat_c3xxx.patch new file mode 100644 index 0000000000..45120a7091 --- /dev/null +++ b/queue-6.15/crypto-qat-add-shutdown-handler-to-qat_c3xxx.patch @@ -0,0 +1,63 @@ +From 71e0cc1eab584d6f95526a5e8c69ec666ca33e1b Mon Sep 17 00:00:00 2001 +From: Giovanni Cabiddu +Date: Wed, 26 Mar 2025 15:59:53 +0000 +Subject: crypto: qat - add shutdown handler to qat_c3xxx + +From: Giovanni Cabiddu + +commit 71e0cc1eab584d6f95526a5e8c69ec666ca33e1b upstream. + +During a warm reset via kexec, the system bypasses the driver removal +sequence, meaning that the remove() callback is not invoked. +If a QAT device is not shutdown properly, the device driver will fail to +load in a newly rebooted kernel. + +This might result in output like the following after the kexec reboot: + + QAT: AE0 is inactive!! + QAT: failed to get device out of reset + c3xxx 0000:3f:00.0: qat_hal_clr_reset error + c3xxx 0000:3f:00.0: Failed to init the AEs + c3xxx 0000:3f:00.0: Failed to initialise Acceleration Engine + c3xxx 0000:3f:00.0: Resetting device qat_dev0 + c3xxx 0000:3f:00.0: probe with driver c3xxx failed with error -14 + +Implement the shutdown() handler that hooks into the reboot notifier +list. This brings down the QAT device and ensures it is shut down +properly. + +Cc: +Fixes: 890c55f4dc0e ("crypto: qat - add support for c3xxx accel type") +Reviewed-by: Ahsan Atta +Reviewed-by: Andy Shevchenko +Signed-off-by: Giovanni Cabiddu +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c ++++ b/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c +@@ -19,6 +19,13 @@ + #include + #include "adf_c3xxx_hw_data.h" + ++static void adf_shutdown(struct pci_dev *pdev) ++{ ++ struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev); ++ ++ adf_dev_down(accel_dev); ++} ++ + static const struct pci_device_id adf_pci_tbl[] = { + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_QAT_C3XXX), }, + { } +@@ -33,6 +40,7 @@ static struct pci_driver adf_driver = { + .name = ADF_C3XXX_DEVICE_NAME, + .probe = adf_probe, + .remove = adf_remove, ++ .shutdown = adf_shutdown, + .sriov_configure = adf_sriov_configure, + .err_handler = &adf_err_handler, + }; diff --git a/queue-6.15/crypto-qat-add-shutdown-handler-to-qat_c62x.patch b/queue-6.15/crypto-qat-add-shutdown-handler-to-qat_c62x.patch new file mode 100644 index 0000000000..9a9607cc29 --- /dev/null +++ b/queue-6.15/crypto-qat-add-shutdown-handler-to-qat_c62x.patch @@ -0,0 +1,63 @@ +From a9a6e9279b2998e2610c70b0dfc80a234f97c76c Mon Sep 17 00:00:00 2001 +From: Giovanni Cabiddu +Date: Wed, 26 Mar 2025 15:59:51 +0000 +Subject: crypto: qat - add shutdown handler to qat_c62x + +From: Giovanni Cabiddu + +commit a9a6e9279b2998e2610c70b0dfc80a234f97c76c upstream. + +During a warm reset via kexec, the system bypasses the driver removal +sequence, meaning that the remove() callback is not invoked. +If a QAT device is not shutdown properly, the device driver will fail to +load in a newly rebooted kernel. + +This might result in output like the following after the kexec reboot: + + QAT: AE0 is inactive!! + QAT: failed to get device out of reset + c6xx 0000:3f:00.0: qat_hal_clr_reset error + c6xx 0000:3f:00.0: Failed to init the AEs + c6xx 0000:3f:00.0: Failed to initialise Acceleration Engine + c6xx 0000:3f:00.0: Resetting device qat_dev0 + c6xx 0000:3f:00.0: probe with driver c6xx failed with error -14 + +Implement the shutdown() handler that hooks into the reboot notifier +list. This brings down the QAT device and ensures it is shut down +properly. + +Cc: +Fixes: a6dabee6c8ba ("crypto: qat - add support for c62x accel type") +Reviewed-by: Ahsan Atta +Reviewed-by: Andy Shevchenko +Signed-off-by: Giovanni Cabiddu +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/crypto/intel/qat/qat_c62x/adf_drv.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/crypto/intel/qat/qat_c62x/adf_drv.c ++++ b/drivers/crypto/intel/qat/qat_c62x/adf_drv.c +@@ -19,6 +19,13 @@ + #include + #include "adf_c62x_hw_data.h" + ++static void adf_shutdown(struct pci_dev *pdev) ++{ ++ struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev); ++ ++ adf_dev_down(accel_dev); ++} ++ + static const struct pci_device_id adf_pci_tbl[] = { + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_QAT_C62X), }, + { } +@@ -33,6 +40,7 @@ static struct pci_driver adf_driver = { + .name = ADF_C62X_DEVICE_NAME, + .probe = adf_probe, + .remove = adf_remove, ++ .shutdown = adf_shutdown, + .sriov_configure = adf_sriov_configure, + .err_handler = &adf_err_handler, + }; diff --git a/queue-6.15/crypto-qat-add-shutdown-handler-to-qat_dh895xcc.patch b/queue-6.15/crypto-qat-add-shutdown-handler-to-qat_dh895xcc.patch new file mode 100644 index 0000000000..6333e6f01f --- /dev/null +++ b/queue-6.15/crypto-qat-add-shutdown-handler-to-qat_dh895xcc.patch @@ -0,0 +1,63 @@ +From 2c4e8b228733bfbcaf49408fdf94d220f6eb78fc Mon Sep 17 00:00:00 2001 +From: Giovanni Cabiddu +Date: Wed, 26 Mar 2025 15:59:49 +0000 +Subject: crypto: qat - add shutdown handler to qat_dh895xcc + +From: Giovanni Cabiddu + +commit 2c4e8b228733bfbcaf49408fdf94d220f6eb78fc upstream. + +During a warm reset via kexec, the system bypasses the driver removal +sequence, meaning that the remove() callback is not invoked. +If a QAT device is not shutdown properly, the device driver will fail to +load in a newly rebooted kernel. + +This might result in output like the following after the kexec reboot: + + QAT: AE0 is inactive!! + QAT: failed to get device out of reset + dh895xcc 0000:3f:00.0: qat_hal_clr_reset error + dh895xcc 0000:3f:00.0: Failed to init the AEs + dh895xcc 0000:3f:00.0: Failed to initialise Acceleration Engine + dh895xcc 0000:3f:00.0: Resetting device qat_dev0 + dh895xcc 0000:3f:00.0: probe with driver dh895xcc failed with error -14 + +Implement the shutdown() handler that hooks into the reboot notifier +list. This brings down the QAT device and ensures it is shut down +properly. + +Cc: +Fixes: 7afa232e76ce ("crypto: qat - Intel(R) QAT DH895xcc accelerator") +Reviewed-by: Ahsan Atta +Reviewed-by: Andy Shevchenko +Signed-off-by: Giovanni Cabiddu +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c ++++ b/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c +@@ -19,6 +19,13 @@ + #include + #include "adf_dh895xcc_hw_data.h" + ++static void adf_shutdown(struct pci_dev *pdev) ++{ ++ struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev); ++ ++ adf_dev_down(accel_dev); ++} ++ + static const struct pci_device_id adf_pci_tbl[] = { + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_QAT_DH895XCC), }, + { } +@@ -33,6 +40,7 @@ static struct pci_driver adf_driver = { + .name = ADF_DH895XCC_DEVICE_NAME, + .probe = adf_probe, + .remove = adf_remove, ++ .shutdown = adf_shutdown, + .sriov_configure = adf_sriov_configure, + .err_handler = &adf_err_handler, + }; diff --git a/queue-6.15/firmware-cs_dsp-fix-oob-memory-read-access-in-kunit-test.patch b/queue-6.15/firmware-cs_dsp-fix-oob-memory-read-access-in-kunit-test.patch new file mode 100644 index 0000000000..0641aac2cc --- /dev/null +++ b/queue-6.15/firmware-cs_dsp-fix-oob-memory-read-access-in-kunit-test.patch @@ -0,0 +1,41 @@ +From fe6446215bfad11cf3b446f38b28dc7708973c25 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 23 May 2025 12:21:02 +0200 +Subject: firmware: cs_dsp: Fix OOB memory read access in KUnit test + +From: Jaroslav Kysela + +commit fe6446215bfad11cf3b446f38b28dc7708973c25 upstream. + +KASAN reported out of bounds access - cs_dsp_mock_bin_add_name_or_info(), +because the source string length was rounded up to the allocation size. + +Cc: Simon Trimmer +Cc: Charles Keepax +Cc: Richard Fitzgerald +Cc: patches@opensource.cirrus.com +Cc: stable@vger.kernel.org +Signed-off-by: Jaroslav Kysela +Link: https://patch.msgid.link/20250523102102.1177151-1-perex@perex.cz +Reviewed-by: Richard Fitzgerald +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/firmware/cirrus/test/cs_dsp_mock_bin.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/firmware/cirrus/test/cs_dsp_mock_bin.c ++++ b/drivers/firmware/cirrus/test/cs_dsp_mock_bin.c +@@ -96,10 +96,11 @@ static void cs_dsp_mock_bin_add_name_or_ + + if (info_len % 4) { + /* Create a padded string with length a multiple of 4 */ ++ size_t copy_len = info_len; + info_len = round_up(info_len, 4); + tmp = kunit_kzalloc(builder->test_priv->test, info_len, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(builder->test_priv->test, tmp); +- memcpy(tmp, info, info_len); ++ memcpy(tmp, info, copy_len); + info = tmp; + } + diff --git a/queue-6.15/gfs2-move-msleep-to-sleepable-context.patch b/queue-6.15/gfs2-move-msleep-to-sleepable-context.patch new file mode 100644 index 0000000000..ed7b7457a2 --- /dev/null +++ b/queue-6.15/gfs2-move-msleep-to-sleepable-context.patch @@ -0,0 +1,42 @@ +From ac5ee087d31ed93b6e45d2968a66828c6f621d8c Mon Sep 17 00:00:00 2001 +From: Alexander Aring +Date: Mon, 31 Mar 2025 19:03:24 -0400 +Subject: gfs2: move msleep to sleepable context + +From: Alexander Aring + +commit ac5ee087d31ed93b6e45d2968a66828c6f621d8c upstream. + +This patch moves the msleep_interruptible() out of the non-sleepable +context by moving the ls->ls_recover_spin spinlock around so +msleep_interruptible() will be called in a sleepable context. + +Cc: stable@vger.kernel.org +Fixes: 4a7727725dc7 ("GFS2: Fix recovery issues for spectators") +Suggested-by: Andreas Gruenbacher +Signed-off-by: Alexander Aring +Signed-off-by: Andreas Gruenbacher +Signed-off-by: Greg Kroah-Hartman +--- + fs/gfs2/lock_dlm.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/gfs2/lock_dlm.c ++++ b/fs/gfs2/lock_dlm.c +@@ -996,14 +996,15 @@ locks_done: + if (sdp->sd_args.ar_spectator) { + fs_info(sdp, "Recovery is required. Waiting for a " + "non-spectator to mount.\n"); ++ spin_unlock(&ls->ls_recover_spin); + msleep_interruptible(1000); + } else { + fs_info(sdp, "control_mount wait1 block %u start %u " + "mount %u lvb %u flags %lx\n", block_gen, + start_gen, mount_gen, lvb_gen, + ls->ls_recover_flags); ++ spin_unlock(&ls->ls_recover_spin); + } +- spin_unlock(&ls->ls_recover_spin); + goto restart; + } + diff --git a/queue-6.15/io_uring-account-drain-memory-to-cgroup.patch b/queue-6.15/io_uring-account-drain-memory-to-cgroup.patch new file mode 100644 index 0000000000..fb5db26bc3 --- /dev/null +++ b/queue-6.15/io_uring-account-drain-memory-to-cgroup.patch @@ -0,0 +1,33 @@ +From f979c20547e72568e3c793bc92c7522bc3166246 Mon Sep 17 00:00:00 2001 +From: Pavel Begunkov +Date: Fri, 9 May 2025 12:12:47 +0100 +Subject: io_uring: account drain memory to cgroup + +From: Pavel Begunkov + +commit f979c20547e72568e3c793bc92c7522bc3166246 upstream. + +Account drain allocations against memcg. It's not a big problem as each +such allocation is paired with a request, which is accounted, but it's +nicer to follow the limits more closely. + +Cc: stable@vger.kernel.org # 6.1 +Signed-off-by: Pavel Begunkov +Link: https://lore.kernel.org/r/f8dfdbd755c41fd9c75d12b858af07dfba5bbb68.1746788718.git.asml.silence@gmail.com +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + io_uring/io_uring.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/io_uring/io_uring.c ++++ b/io_uring/io_uring.c +@@ -1689,7 +1689,7 @@ queue: + spin_unlock(&ctx->completion_lock); + + io_prep_async_link(req); +- de = kmalloc(sizeof(*de), GFP_KERNEL); ++ de = kmalloc(sizeof(*de), GFP_KERNEL_ACCOUNT); + if (!de) { + ret = -ENOMEM; + io_req_defer_failed(req, ret); diff --git a/queue-6.15/io_uring-kbuf-account-ring-io_buffer_list-memory.patch b/queue-6.15/io_uring-kbuf-account-ring-io_buffer_list-memory.patch new file mode 100644 index 0000000000..50da303d66 --- /dev/null +++ b/queue-6.15/io_uring-kbuf-account-ring-io_buffer_list-memory.patch @@ -0,0 +1,34 @@ +From 475a8d30371604a6363da8e304a608a5959afc40 Mon Sep 17 00:00:00 2001 +From: Pavel Begunkov +Date: Tue, 13 May 2025 18:26:46 +0100 +Subject: io_uring/kbuf: account ring io_buffer_list memory + +From: Pavel Begunkov + +commit 475a8d30371604a6363da8e304a608a5959afc40 upstream. + +Follow the non-ringed pbuf struct io_buffer_list allocations and account +it against the memcg. There is low chance of that being an actual +problem as ring provided buffer should either pin user memory or +allocate it, which is already accounted. + +Cc: stable@vger.kernel.org # 6.1 +Signed-off-by: Pavel Begunkov +Link: https://lore.kernel.org/r/3985218b50d341273cafff7234e1a7e6d0db9808.1747150490.git.asml.silence@gmail.com +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + io_uring/kbuf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/io_uring/kbuf.c ++++ b/io_uring/kbuf.c +@@ -624,7 +624,7 @@ int io_register_pbuf_ring(struct io_ring + io_destroy_bl(ctx, bl); + } + +- free_bl = bl = kzalloc(sizeof(*bl), GFP_KERNEL); ++ free_bl = bl = kzalloc(sizeof(*bl), GFP_KERNEL_ACCOUNT); + if (!bl) + return -ENOMEM; + diff --git a/queue-6.15/net-mlx5-add-error-handling-in-mlx5_query_nic_vport_node_guid.patch b/queue-6.15/net-mlx5-add-error-handling-in-mlx5_query_nic_vport_node_guid.patch new file mode 100644 index 0000000000..977451ebed --- /dev/null +++ b/queue-6.15/net-mlx5-add-error-handling-in-mlx5_query_nic_vport_node_guid.patch @@ -0,0 +1,55 @@ +From c6bb8a21cdad8c975a3a646b9e5c8df01ad29783 Mon Sep 17 00:00:00 2001 +From: Wentao Liang +Date: Sun, 25 May 2025 00:34:25 +0800 +Subject: net/mlx5: Add error handling in mlx5_query_nic_vport_node_guid() + +From: Wentao Liang + +commit c6bb8a21cdad8c975a3a646b9e5c8df01ad29783 upstream. + +The function mlx5_query_nic_vport_node_guid() calls the function +mlx5_query_nic_vport_context() but does not check its return value. +A proper implementation can be found in mlx5_nic_vport_query_local_lb(). + +Add error handling for mlx5_query_nic_vport_context(). If it fails, free +the out buffer via kvfree() and return error code. + +Fixes: 9efa75254593 ("net/mlx5_core: Introduce access functions to query vport RoCE fields") +Cc: stable@vger.kernel.org # v4.5 +Signed-off-by: Wentao Liang +Reviewed-by: Tariq Toukan +Link: https://patch.msgid.link/20250524163425.1695-1-vulab@iscas.ac.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/mellanox/mlx5/core/vport.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c +@@ -465,19 +465,22 @@ int mlx5_query_nic_vport_node_guid(struc + { + u32 *out; + int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); ++ int err; + + out = kvzalloc(outlen, GFP_KERNEL); + if (!out) + return -ENOMEM; + +- mlx5_query_nic_vport_context(mdev, 0, out); ++ err = mlx5_query_nic_vport_context(mdev, 0, out); ++ if (err) ++ goto out; + + *node_guid = MLX5_GET64(query_nic_vport_context_out, out, + nic_vport_context.node_guid); +- ++out: + kvfree(out); + +- return 0; ++ return err; + } + EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_node_guid); + diff --git a/queue-6.15/net-mlx5_core-add-error-handling-inmlx5_query_nic_vport_qkey_viol_cntr.patch b/queue-6.15/net-mlx5_core-add-error-handling-inmlx5_query_nic_vport_qkey_viol_cntr.patch new file mode 100644 index 0000000000..52e528b950 --- /dev/null +++ b/queue-6.15/net-mlx5_core-add-error-handling-inmlx5_query_nic_vport_qkey_viol_cntr.patch @@ -0,0 +1,56 @@ +From f0b50730bdd8f2734e548de541e845c0d40dceb6 Mon Sep 17 00:00:00 2001 +From: Wentao Liang +Date: Wed, 21 May 2025 21:36:20 +0800 +Subject: net/mlx5_core: Add error handling inmlx5_query_nic_vport_qkey_viol_cntr() + +From: Wentao Liang + +commit f0b50730bdd8f2734e548de541e845c0d40dceb6 upstream. + +The function mlx5_query_nic_vport_qkey_viol_cntr() calls the function +mlx5_query_nic_vport_context() but does not check its return value. This +could lead to undefined behavior if the query fails. A proper +implementation can be found in mlx5_nic_vport_query_local_lb(). + +Add error handling for mlx5_query_nic_vport_context(). If it fails, free +the out buffer via kvfree() and return error code. + +Fixes: 9efa75254593 ("net/mlx5_core: Introduce access functions to query vport RoCE fields") +Cc: stable@vger.kernel.org # v4.5 +Signed-off-by: Wentao Liang +Reviewed-by: Tariq Toukan +Link: https://patch.msgid.link/20250521133620.912-1-vulab@iscas.ac.cn +Signed-off-by: Paolo Abeni +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/mellanox/mlx5/core/vport.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c +@@ -519,19 +519,22 @@ int mlx5_query_nic_vport_qkey_viol_cntr( + { + u32 *out; + int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); ++ int err; + + out = kvzalloc(outlen, GFP_KERNEL); + if (!out) + return -ENOMEM; + +- mlx5_query_nic_vport_context(mdev, 0, out); ++ err = mlx5_query_nic_vport_context(mdev, 0, out); ++ if (err) ++ goto out; + + *qkey_viol_cntr = MLX5_GET(query_nic_vport_context_out, out, + nic_vport_context.qkey_violation_counter); +- ++out: + kvfree(out); + +- return 0; ++ return err; + } + EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_qkey_viol_cntr); + diff --git a/queue-6.15/powerpc-bpf-fix-jit-code-size-calculation-of-bpf-trampoline.patch b/queue-6.15/powerpc-bpf-fix-jit-code-size-calculation-of-bpf-trampoline.patch new file mode 100644 index 0000000000..9088476305 --- /dev/null +++ b/queue-6.15/powerpc-bpf-fix-jit-code-size-calculation-of-bpf-trampoline.patch @@ -0,0 +1,223 @@ +From 59ba025948be2a92e8bc9ae1cbdaf197660bd508 Mon Sep 17 00:00:00 2001 +From: Hari Bathini +Date: Tue, 22 Apr 2025 13:56:09 +0530 +Subject: powerpc/bpf: fix JIT code size calculation of bpf trampoline + +From: Hari Bathini + +commit 59ba025948be2a92e8bc9ae1cbdaf197660bd508 upstream. + +arch_bpf_trampoline_size() provides JIT size of the BPF trampoline +before the buffer for JIT'ing it is allocated. The total number of +instructions emitted for BPF trampoline JIT code depends on where +the final image is located. So, the size arrived at with the dummy +pass in arch_bpf_trampoline_size() can vary from the actual size +needed in arch_prepare_bpf_trampoline(). When the instructions +accounted in arch_bpf_trampoline_size() is less than the number of +instructions emitted during the actual JIT compile of the trampoline, +the below warning is produced: + + WARNING: CPU: 8 PID: 204190 at arch/powerpc/net/bpf_jit_comp.c:981 __arch_prepare_bpf_trampoline.isra.0+0xd2c/0xdcc + +which is: + + /* Make sure the trampoline generation logic doesn't overflow */ + if (image && WARN_ON_ONCE(&image[ctx->idx] > + (u32 *)rw_image_end - BPF_INSN_SAFETY)) { + +So, during the dummy pass, instead of providing some arbitrary image +location, account for maximum possible instructions if and when there +is a dependency with image location for JIT'ing. + +Fixes: d243b62b7bd3 ("powerpc64/bpf: Add support for bpf trampolines") +Reported-by: Venkat Rao Bagalkote +Closes: https://lore.kernel.org/all/6168bfc8-659f-4b5a-a6fb-90a916dde3b3@linux.ibm.com/ +Cc: stable@vger.kernel.org # v6.13+ +Acked-by: Naveen N Rao (AMD) +Tested-by: Venkat Rao Bagalkote +Signed-off-by: Hari Bathini +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250422082609.949301-1-hbathini@linux.ibm.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/net/bpf_jit.h | 20 +++++++++++++++++--- + arch/powerpc/net/bpf_jit_comp.c | 33 ++++++++++----------------------- + arch/powerpc/net/bpf_jit_comp32.c | 6 ------ + arch/powerpc/net/bpf_jit_comp64.c | 15 ++++++++------- + 4 files changed, 35 insertions(+), 39 deletions(-) + +--- a/arch/powerpc/net/bpf_jit.h ++++ b/arch/powerpc/net/bpf_jit.h +@@ -51,8 +51,16 @@ + EMIT(PPC_INST_BRANCH_COND | (((cond) & 0x3ff) << 16) | (offset & 0xfffc)); \ + } while (0) + +-/* Sign-extended 32-bit immediate load */ ++/* ++ * Sign-extended 32-bit immediate load ++ * ++ * If this is a dummy pass (!image), account for ++ * maximum possible instructions. ++ */ + #define PPC_LI32(d, i) do { \ ++ if (!image) \ ++ ctx->idx += 2; \ ++ else { \ + if ((int)(uintptr_t)(i) >= -32768 && \ + (int)(uintptr_t)(i) < 32768) \ + EMIT(PPC_RAW_LI(d, i)); \ +@@ -60,10 +68,15 @@ + EMIT(PPC_RAW_LIS(d, IMM_H(i))); \ + if (IMM_L(i)) \ + EMIT(PPC_RAW_ORI(d, d, IMM_L(i))); \ +- } } while(0) ++ } \ ++ } } while (0) + + #ifdef CONFIG_PPC64 ++/* If dummy pass (!image), account for maximum possible instructions */ + #define PPC_LI64(d, i) do { \ ++ if (!image) \ ++ ctx->idx += 5; \ ++ else { \ + if ((long)(i) >= -2147483648 && \ + (long)(i) < 2147483648) \ + PPC_LI32(d, i); \ +@@ -84,7 +97,8 @@ + if ((uintptr_t)(i) & 0x000000000000ffffULL) \ + EMIT(PPC_RAW_ORI(d, d, (uintptr_t)(i) & \ + 0xffff)); \ +- } } while (0) ++ } \ ++ } } while (0) + #define PPC_LI_ADDR PPC_LI64 + + #ifndef CONFIG_PPC_KERNEL_PCREL +--- a/arch/powerpc/net/bpf_jit_comp.c ++++ b/arch/powerpc/net/bpf_jit_comp.c +@@ -504,10 +504,11 @@ static int invoke_bpf_prog(u32 *image, u + EMIT(PPC_RAW_ADDI(_R3, _R1, regs_off)); + if (!p->jited) + PPC_LI_ADDR(_R4, (unsigned long)p->insnsi); +- if (!create_branch(&branch_insn, (u32 *)&ro_image[ctx->idx], (unsigned long)p->bpf_func, +- BRANCH_SET_LINK)) { +- if (image) +- image[ctx->idx] = ppc_inst_val(branch_insn); ++ /* Account for max possible instructions during dummy pass for size calculation */ ++ if (image && !create_branch(&branch_insn, (u32 *)&ro_image[ctx->idx], ++ (unsigned long)p->bpf_func, ++ BRANCH_SET_LINK)) { ++ image[ctx->idx] = ppc_inst_val(branch_insn); + ctx->idx++; + } else { + EMIT(PPC_RAW_LL(_R12, _R25, offsetof(struct bpf_prog, bpf_func))); +@@ -889,7 +890,8 @@ static int __arch_prepare_bpf_trampoline + bpf_trampoline_restore_tail_call_cnt(image, ctx, func_frame_offset, r4_off); + + /* Reserve space to patch branch instruction to skip fexit progs */ +- im->ip_after_call = &((u32 *)ro_image)[ctx->idx]; ++ if (ro_image) /* image is NULL for dummy pass */ ++ im->ip_after_call = &((u32 *)ro_image)[ctx->idx]; + EMIT(PPC_RAW_NOP()); + } + +@@ -912,7 +914,8 @@ static int __arch_prepare_bpf_trampoline + } + + if (flags & BPF_TRAMP_F_CALL_ORIG) { +- im->ip_epilogue = &((u32 *)ro_image)[ctx->idx]; ++ if (ro_image) /* image is NULL for dummy pass */ ++ im->ip_epilogue = &((u32 *)ro_image)[ctx->idx]; + PPC_LI_ADDR(_R3, im); + ret = bpf_jit_emit_func_call_rel(image, ro_image, ctx, + (unsigned long)__bpf_tramp_exit); +@@ -973,25 +976,9 @@ int arch_bpf_trampoline_size(const struc + struct bpf_tramp_links *tlinks, void *func_addr) + { + struct bpf_tramp_image im; +- void *image; + int ret; + +- /* +- * Allocate a temporary buffer for __arch_prepare_bpf_trampoline(). +- * This will NOT cause fragmentation in direct map, as we do not +- * call set_memory_*() on this buffer. +- * +- * We cannot use kvmalloc here, because we need image to be in +- * module memory range. +- */ +- image = bpf_jit_alloc_exec(PAGE_SIZE); +- if (!image) +- return -ENOMEM; +- +- ret = __arch_prepare_bpf_trampoline(&im, image, image + PAGE_SIZE, image, +- m, flags, tlinks, func_addr); +- bpf_jit_free_exec(image); +- ++ ret = __arch_prepare_bpf_trampoline(&im, NULL, NULL, NULL, m, flags, tlinks, func_addr); + return ret; + } + +--- a/arch/powerpc/net/bpf_jit_comp32.c ++++ b/arch/powerpc/net/bpf_jit_comp32.c +@@ -313,7 +313,6 @@ int bpf_jit_build_body(struct bpf_prog * + u64 func_addr; + u32 true_cond; + u32 tmp_idx; +- int j; + + if (i && (BPF_CLASS(code) == BPF_ALU64 || BPF_CLASS(code) == BPF_ALU) && + (BPF_CLASS(prevcode) == BPF_ALU64 || BPF_CLASS(prevcode) == BPF_ALU) && +@@ -1099,13 +1098,8 @@ int bpf_jit_build_body(struct bpf_prog * + * 16 byte instruction that uses two 'struct bpf_insn' + */ + case BPF_LD | BPF_IMM | BPF_DW: /* dst = (u64) imm */ +- tmp_idx = ctx->idx; + PPC_LI32(dst_reg_h, (u32)insn[i + 1].imm); + PPC_LI32(dst_reg, (u32)insn[i].imm); +- /* padding to allow full 4 instructions for later patching */ +- if (!image) +- for (j = ctx->idx - tmp_idx; j < 4; j++) +- EMIT(PPC_RAW_NOP()); + /* Adjust for two bpf instructions */ + addrs[++i] = ctx->idx * 4; + break; +--- a/arch/powerpc/net/bpf_jit_comp64.c ++++ b/arch/powerpc/net/bpf_jit_comp64.c +@@ -227,7 +227,14 @@ int bpf_jit_emit_func_call_rel(u32 *imag + #ifdef CONFIG_PPC_KERNEL_PCREL + reladdr = func_addr - local_paca->kernelbase; + +- if (reladdr < (long)SZ_8G && reladdr >= -(long)SZ_8G) { ++ /* ++ * If fimage is NULL (the initial pass to find image size), ++ * account for the maximum no. of instructions possible. ++ */ ++ if (!fimage) { ++ ctx->idx += 7; ++ return 0; ++ } else if (reladdr < (long)SZ_8G && reladdr >= -(long)SZ_8G) { + EMIT(PPC_RAW_LD(_R12, _R13, offsetof(struct paca_struct, kernelbase))); + /* Align for subsequent prefix instruction */ + if (!IS_ALIGNED((unsigned long)fimage + CTX_NIA(ctx), 8)) +@@ -412,7 +419,6 @@ int bpf_jit_build_body(struct bpf_prog * + u64 imm64; + u32 true_cond; + u32 tmp_idx; +- int j; + + /* + * addrs[] maps a BPF bytecode address into a real offset from +@@ -1046,12 +1052,7 @@ emit_clear: + case BPF_LD | BPF_IMM | BPF_DW: /* dst = (u64) imm */ + imm64 = ((u64)(u32) insn[i].imm) | + (((u64)(u32) insn[i+1].imm) << 32); +- tmp_idx = ctx->idx; + PPC_LI64(dst_reg, imm64); +- /* padding to allow full 5 instructions for later patching */ +- if (!image) +- for (j = ctx->idx - tmp_idx; j < 5; j++) +- EMIT(PPC_RAW_NOP()); + /* Adjust for two bpf instructions */ + addrs[++i] = ctx->idx * 4; + break; diff --git a/queue-6.15/powerpc-pseries-msi-avoid-reading-pci-device-registers-in-reduced-power-states.patch b/queue-6.15/powerpc-pseries-msi-avoid-reading-pci-device-registers-in-reduced-power-states.patch new file mode 100644 index 0000000000..3512eeee58 --- /dev/null +++ b/queue-6.15/powerpc-pseries-msi-avoid-reading-pci-device-registers-in-reduced-power-states.patch @@ -0,0 +1,57 @@ +From 9cc0eafd28c7faef300822992bb08d79cab2a36c Mon Sep 17 00:00:00 2001 +From: Gautam Menghani +Date: Wed, 5 Mar 2025 14:32:36 +0530 +Subject: powerpc/pseries/msi: Avoid reading PCI device registers in reduced power states + +From: Gautam Menghani + +commit 9cc0eafd28c7faef300822992bb08d79cab2a36c upstream. + +When a system is being suspended to RAM, the PCI devices are also +suspended and the PPC code ends up calling pseries_msi_compose_msg() and +this triggers the BUG_ON() in __pci_read_msi_msg() because the device at +this point is in reduced power state. In reduced power state, the memory +mapped registers of the PCI device are not accessible. + +To replicate the bug: +1. Make sure deep sleep is selected + # cat /sys/power/mem_sleep + s2idle [deep] + +2. Make sure console is not suspended (so that dmesg logs are visible) + echo N > /sys/module/printk/parameters/console_suspend + +3. Suspend the system + echo mem > /sys/power/state + +To fix this behaviour, read the cached msi message of the device when the +device is not in PCI_D0 power state instead of touching the hardware. + +Fixes: a5f3d2c17b07 ("powerpc/pseries/pci: Add MSI domains") +Cc: stable@vger.kernel.org # v5.15+ +Signed-off-by: Gautam Menghani +Tested-by: Venkat Rao Bagalkote +Reviewed-by: Vaibhav Jain +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250305090237.294633-1-gautam@linux.ibm.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/platforms/pseries/msi.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/arch/powerpc/platforms/pseries/msi.c ++++ b/arch/powerpc/platforms/pseries/msi.c +@@ -525,7 +525,12 @@ static struct msi_domain_info pseries_ms + + static void pseries_msi_compose_msg(struct irq_data *data, struct msi_msg *msg) + { +- __pci_read_msi_msg(irq_data_get_msi_desc(data), msg); ++ struct pci_dev *dev = msi_desc_to_pci_dev(irq_data_get_msi_desc(data)); ++ ++ if (dev->current_state == PCI_D0) ++ __pci_read_msi_msg(irq_data_get_msi_desc(data), msg); ++ else ++ get_cached_msi_msg(data->irq, msg); + } + + static struct irq_chip pseries_msi_irq_chip = { diff --git a/queue-6.15/powerpc64-ftrace-fix-clobbered-r15-during-livepatching.patch b/queue-6.15/powerpc64-ftrace-fix-clobbered-r15-during-livepatching.patch new file mode 100644 index 0000000000..6284d4645d --- /dev/null +++ b/queue-6.15/powerpc64-ftrace-fix-clobbered-r15-during-livepatching.patch @@ -0,0 +1,70 @@ +From cb5b691f8273432297611863ac142e17119279e0 Mon Sep 17 00:00:00 2001 +From: Hari Bathini +Date: Thu, 17 Apr 2025 00:42:27 +0530 +Subject: powerpc64/ftrace: fix clobbered r15 during livepatching + +From: Hari Bathini + +commit cb5b691f8273432297611863ac142e17119279e0 upstream. + +While r15 is clobbered always with PPC_FTRACE_OUT_OF_LINE, it is +not restored in livepatch sequence leading to not so obvious fails +like below: + + BUG: Unable to handle kernel data access on write at 0xc0000000000f9078 + Faulting instruction address: 0xc0000000018ff958 + Oops: Kernel access of bad area, sig: 11 [#1] + ... + NIP: c0000000018ff958 LR: c0000000018ff930 CTR: c0000000009c0790 + REGS: c00000005f2e7790 TRAP: 0300 Tainted: G K (6.14.0+) + MSR: 8000000000009033 CR: 2822880b XER: 20040000 + CFAR: c0000000008addc0 DAR: c0000000000f9078 DSISR: 0a000000 IRQMASK: 1 + GPR00: c0000000018f2584 c00000005f2e7a30 c00000000280a900 c000000017ffa488 + GPR04: 0000000000000008 0000000000000000 c0000000018f24fc 000000000000000d + GPR08: fffffffffffe0000 000000000000000d 0000000000000000 0000000000008000 + GPR12: c0000000009c0790 c000000017ffa480 c00000005f2e7c78 c0000000000f9070 + GPR16: c00000005f2e7c90 0000000000000000 0000000000000000 0000000000000000 + GPR20: 0000000000000000 c00000005f3efa80 c00000005f2e7c60 c00000005f2e7c88 + GPR24: c00000005f2e7c60 0000000000000001 c0000000000f9078 0000000000000000 + GPR28: 00007fff97960000 c000000017ffa480 0000000000000000 c0000000000f9078 + ... + Call Trace: + check_heap_object+0x34/0x390 (unreliable) + __mutex_unlock_slowpath.isra.0+0xe4/0x230 + seq_read_iter+0x430/0xa90 + proc_reg_read_iter+0xa4/0x200 + vfs_read+0x41c/0x510 + ksys_read+0xa4/0x190 + system_call_exception+0x1d0/0x440 + system_call_vectored_common+0x15c/0x2ec + +Fix it by restoring r15 always. + +Fixes: eec37961a56a ("powerpc64/ftrace: Move ftrace sequence out of line") +Reported-by: Viktor Malik +Closes: https://lore.kernel.org/lkml/1aec4a9a-a30b-43fd-b303-7a351caeccb7@redhat.com +Cc: stable@vger.kernel.org # v6.13+ +Signed-off-by: Hari Bathini +Tested-by: Viktor Malik +Acked-by: Naveen N Rao (AMD) +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/20250416191227.201146-1-hbathini@linux.ibm.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/kernel/trace/ftrace_entry.S | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/powerpc/kernel/trace/ftrace_entry.S ++++ b/arch/powerpc/kernel/trace/ftrace_entry.S +@@ -212,10 +212,10 @@ + bne- 1f + + mr r3, r15 ++1: mtlr r3 + .if \allregs == 0 + REST_GPR(15, r1) + .endif +-1: mtlr r3 + #endif + + /* Restore gprs */ diff --git a/queue-6.15/regulator-max20086-change-enable-gpio-to-optional.patch b/queue-6.15/regulator-max20086-change-enable-gpio-to-optional.patch new file mode 100644 index 0000000000..416f82e280 --- /dev/null +++ b/queue-6.15/regulator-max20086-change-enable-gpio-to-optional.patch @@ -0,0 +1,38 @@ +From e8ac7336dd62f0443a675ed80b17f0f0e6846e20 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jo=C3=A3o=20Paulo=20Gon=C3=A7alves?= + +Date: Sun, 20 Apr 2025 15:28:02 -0300 +Subject: regulator: max20086: Change enable gpio to optional +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: João Paulo Gonçalves + +commit e8ac7336dd62f0443a675ed80b17f0f0e6846e20 upstream. + +The enable pin can be configured as always enabled by the hardware. Make +the enable gpio request optional so the driver doesn't fail to probe +when `enable-gpios` property is not present in the device tree. + +Cc: stable@vger.kernel.org +Fixes: bfff546aae50 ("regulator: Add MAX20086-MAX20089 driver") +Signed-off-by: João Paulo Gonçalves +Link: https://patch.msgid.link/20250420-fix-max20086-v1-2-8cc9ee0d5a08@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/regulator/max20086-regulator.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/regulator/max20086-regulator.c ++++ b/drivers/regulator/max20086-regulator.c +@@ -264,7 +264,7 @@ static int max20086_i2c_probe(struct i2c + * shutdown. + */ + flags = boot_on ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW; +- chip->ena_gpiod = devm_gpiod_get(chip->dev, "enable", flags); ++ chip->ena_gpiod = devm_gpiod_get_optional(chip->dev, "enable", flags); + if (IS_ERR(chip->ena_gpiod)) { + ret = PTR_ERR(chip->ena_gpiod); + dev_err(chip->dev, "Failed to get enable GPIO: %d\n", ret); diff --git a/queue-6.15/regulator-max20086-fix-max200086-chip-id.patch b/queue-6.15/regulator-max20086-fix-max200086-chip-id.patch new file mode 100644 index 0000000000..de3cf1a15f --- /dev/null +++ b/queue-6.15/regulator-max20086-fix-max200086-chip-id.patch @@ -0,0 +1,38 @@ +From 71406b6d1155d883c80c1b4405939a52f723aa05 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jo=C3=A3o=20Paulo=20Gon=C3=A7alves?= + +Date: Sun, 20 Apr 2025 15:28:01 -0300 +Subject: regulator: max20086: Fix MAX200086 chip id +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: João Paulo Gonçalves + +commit 71406b6d1155d883c80c1b4405939a52f723aa05 upstream. + +>From MAX20086-MAX20089 datasheet, the id for a MAX20086 is 0x30 and not +0x40. With the current code, the driver will fail on probe when the +driver tries to identify the chip id from a MAX20086 device over I2C. + +Cc: stable@vger.kernel.org +Fixes: bfff546aae50 ("regulator: Add MAX20086-MAX20089 driver") +Signed-off-by: João Paulo Gonçalves +Link: https://patch.msgid.link/20250420-fix-max20086-v1-1-8cc9ee0d5a08@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + drivers/regulator/max20086-regulator.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/regulator/max20086-regulator.c ++++ b/drivers/regulator/max20086-regulator.c +@@ -29,7 +29,7 @@ + #define MAX20086_REG_ADC4 0x09 + + /* DEVICE IDs */ +-#define MAX20086_DEVICE_ID_MAX20086 0x40 ++#define MAX20086_DEVICE_ID_MAX20086 0x30 + #define MAX20086_DEVICE_ID_MAX20087 0x20 + #define MAX20086_DEVICE_ID_MAX20088 0x10 + #define MAX20086_DEVICE_ID_MAX20089 0x00 diff --git a/queue-6.15/s390-pci-allow-re-add-of-a-reserved-but-not-yet-removed-device.patch b/queue-6.15/s390-pci-allow-re-add-of-a-reserved-but-not-yet-removed-device.patch new file mode 100644 index 0000000000..9ad881b10d --- /dev/null +++ b/queue-6.15/s390-pci-allow-re-add-of-a-reserved-but-not-yet-removed-device.patch @@ -0,0 +1,178 @@ +From 4b1815a52d7eb03b3e0e6742c6728bc16a4b2d1d Mon Sep 17 00:00:00 2001 +From: Niklas Schnelle +Date: Thu, 22 May 2025 14:13:14 +0200 +Subject: s390/pci: Allow re-add of a reserved but not yet removed device + +From: Niklas Schnelle + +commit 4b1815a52d7eb03b3e0e6742c6728bc16a4b2d1d upstream. + +The architecture assumes that PCI functions can be removed synchronously +as PCI events are processed. This however clashes with the reference +counting of struct pci_dev which allows device drivers to hold on to a +struct pci_dev reference even as the underlying device is removed. To +bridge this gap commit 2a671f77ee49 ("s390/pci: fix use after free of +zpci_dev") keeps the struct zpci_dev in ZPCI_FN_STATE_RESERVED state +until common code releases the struct pci_dev. Only when all references +are dropped, the struct zpci_dev can be removed and freed. + +Later commit a46044a92add ("s390/pci: fix zpci_zdev_put() on reserve") +moved the deletion of the struct zpci_dev from the zpci_list in +zpci_release_device() to the point where the device is reserved. This +was done to prevent handling events for a device that is already being +removed, e.g. when the platform generates both PCI event codes 0x304 +and 0x308. In retrospect, deletion from the zpci_list in the release +function without holding the zpci_list_lock was also racy. + +A side effect of this handling is that if the underlying device +re-appears while the struct zpci_dev is in the ZPCI_FN_STATE_RESERVED +state, the new and old instances of the struct zpci_dev and/or struct +pci_dev may clash. For example when trying to create the IOMMU sysfs +files for the new instance. In this case, re-adding the new instance is +aborted. The old instance is removed, and the device will remain absent +until the platform issues another event. + +Fix this by allowing the struct zpci_dev to be brought back up right +until it is finally removed. To this end also keep the struct zpci_dev +in the zpci_list until it is finally released when all references have +been dropped. + +Deletion from the zpci_list from within the release function is made +safe by using kref_put_lock() with the zpci_list_lock. This ensures that +the releasing code holds the last reference. + +Cc: stable@vger.kernel.org +Fixes: a46044a92add ("s390/pci: fix zpci_zdev_put() on reserve") +Reviewed-by: Gerd Bayer +Tested-by: Gerd Bayer +Signed-off-by: Niklas Schnelle +Signed-off-by: Heiko Carstens +Signed-off-by: Greg Kroah-Hartman +--- + arch/s390/pci/pci.c | 32 ++++++++++++++++++++++---------- + arch/s390/pci/pci_bus.h | 7 ++----- + arch/s390/pci/pci_event.c | 22 +++++++++++++++++++++- + 3 files changed, 45 insertions(+), 16 deletions(-) + +--- a/arch/s390/pci/pci.c ++++ b/arch/s390/pci/pci.c +@@ -70,6 +70,13 @@ EXPORT_SYMBOL_GPL(zpci_aipb); + struct airq_iv *zpci_aif_sbv; + EXPORT_SYMBOL_GPL(zpci_aif_sbv); + ++void zpci_zdev_put(struct zpci_dev *zdev) ++{ ++ if (!zdev) ++ return; ++ kref_put_lock(&zdev->kref, zpci_release_device, &zpci_list_lock); ++} ++ + struct zpci_dev *get_zdev_by_fid(u32 fid) + { + struct zpci_dev *tmp, *zdev = NULL; +@@ -925,21 +932,20 @@ int zpci_deconfigure_device(struct zpci_ + * @zdev: the zpci_dev that was reserved + * + * Handle the case that a given zPCI function was reserved by another system. +- * After a call to this function the zpci_dev can not be found via +- * get_zdev_by_fid() anymore but may still be accessible via existing +- * references though it will not be functional anymore. + */ + void zpci_device_reserved(struct zpci_dev *zdev) + { +- /* +- * Remove device from zpci_list as it is going away. This also +- * makes sure we ignore subsequent zPCI events for this device. +- */ +- spin_lock(&zpci_list_lock); +- list_del(&zdev->entry); +- spin_unlock(&zpci_list_lock); ++ lockdep_assert_held(&zdev->state_lock); ++ /* We may declare the device reserved multiple times */ ++ if (zdev->state == ZPCI_FN_STATE_RESERVED) ++ return; + zdev->state = ZPCI_FN_STATE_RESERVED; + zpci_dbg(3, "rsv fid:%x\n", zdev->fid); ++ /* ++ * The underlying device is gone. Allow the zdev to be freed ++ * as soon as all other references are gone by accounting for ++ * the removal as a dropped reference. ++ */ + zpci_zdev_put(zdev); + } + +@@ -948,6 +954,12 @@ void zpci_release_device(struct kref *kr + struct zpci_dev *zdev = container_of(kref, struct zpci_dev, kref); + + WARN_ON(zdev->state != ZPCI_FN_STATE_RESERVED); ++ /* ++ * We already hold zpci_list_lock thanks to kref_put_lock(). ++ * This makes sure no new reference can be taken from the list. ++ */ ++ list_del(&zdev->entry); ++ spin_unlock(&zpci_list_lock); + + if (zdev->has_hp_slot) + zpci_exit_slot(zdev); +--- a/arch/s390/pci/pci_bus.h ++++ b/arch/s390/pci/pci_bus.h +@@ -21,11 +21,8 @@ int zpci_bus_scan_device(struct zpci_dev + void zpci_bus_remove_device(struct zpci_dev *zdev, bool set_error); + + void zpci_release_device(struct kref *kref); +-static inline void zpci_zdev_put(struct zpci_dev *zdev) +-{ +- if (zdev) +- kref_put(&zdev->kref, zpci_release_device); +-} ++ ++void zpci_zdev_put(struct zpci_dev *zdev); + + static inline void zpci_zdev_get(struct zpci_dev *zdev) + { +--- a/arch/s390/pci/pci_event.c ++++ b/arch/s390/pci/pci_event.c +@@ -335,6 +335,22 @@ static void zpci_event_hard_deconfigured + zdev->state = ZPCI_FN_STATE_STANDBY; + } + ++static void zpci_event_reappear(struct zpci_dev *zdev) ++{ ++ lockdep_assert_held(&zdev->state_lock); ++ /* ++ * The zdev is in the reserved state. This means that it was presumed to ++ * go away but there are still undropped references. Now, the platform ++ * announced its availability again. Bring back the lingering zdev ++ * to standby. This is safe because we hold a temporary reference ++ * now so that it won't go away. Account for the re-appearance of the ++ * underlying device by incrementing the reference count. ++ */ ++ zdev->state = ZPCI_FN_STATE_STANDBY; ++ zpci_zdev_get(zdev); ++ zpci_dbg(1, "rea fid:%x, fh:%x\n", zdev->fid, zdev->fh); ++} ++ + static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) + { + struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); +@@ -358,8 +374,10 @@ static void __zpci_event_availability(st + break; + } + } else { ++ if (zdev->state == ZPCI_FN_STATE_RESERVED) ++ zpci_event_reappear(zdev); + /* the configuration request may be stale */ +- if (zdev->state != ZPCI_FN_STATE_STANDBY) ++ else if (zdev->state != ZPCI_FN_STATE_STANDBY) + break; + zdev->state = ZPCI_FN_STATE_CONFIGURED; + } +@@ -375,6 +393,8 @@ static void __zpci_event_availability(st + break; + } + } else { ++ if (zdev->state == ZPCI_FN_STATE_RESERVED) ++ zpci_event_reappear(zdev); + zpci_update_fh(zdev, ccdf->fh); + } + break; diff --git a/queue-6.15/s390-pci-fix-__pcilg_mio_inuser-inline-assembly.patch b/queue-6.15/s390-pci-fix-__pcilg_mio_inuser-inline-assembly.patch new file mode 100644 index 0000000000..67ed8f6b9b --- /dev/null +++ b/queue-6.15/s390-pci-fix-__pcilg_mio_inuser-inline-assembly.patch @@ -0,0 +1,44 @@ +From c4abe6234246c75cdc43326415d9cff88b7cf06c Mon Sep 17 00:00:00 2001 +From: Heiko Carstens +Date: Mon, 19 May 2025 18:07:11 +0200 +Subject: s390/pci: Fix __pcilg_mio_inuser() inline assembly + +From: Heiko Carstens + +commit c4abe6234246c75cdc43326415d9cff88b7cf06c upstream. + +Use "a" constraint for the shift operand of the __pcilg_mio_inuser() inline +assembly. The used "d" constraint allows the compiler to use any general +purpose register for the shift operand, including register zero. + +If register zero is used this my result in incorrect code generation: + + 8f6: a7 0a ff f8 ahi %r0,-8 + 8fa: eb 32 00 00 00 0c srlg %r3,%r2,0 <---- + +If register zero is selected to contain the shift value, the srlg +instruction ignores the contents of the register and always shifts zero +bits. Therefore use the "a" constraint which does not permit to select +register zero. + +Fixes: f058599e22d5 ("s390/pci: Fix s390_mmio_read/write with MIO") +Cc: stable@vger.kernel.org +Reported-by: Niklas Schnelle +Reviewed-by: Niklas Schnelle +Signed-off-by: Heiko Carstens +Signed-off-by: Greg Kroah-Hartman +--- + arch/s390/pci/pci_mmio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/s390/pci/pci_mmio.c ++++ b/arch/s390/pci/pci_mmio.c +@@ -236,7 +236,7 @@ static inline int __pcilg_mio_inuser( + : [ioaddr_len] "+&d" (ioaddr_len.pair), [exc] "+d" (exception), + CC_OUT(cc, cc), [val] "=d" (val), + [dst] "+a" (dst), [cnt] "+d" (cnt), [tmp] "=d" (tmp), +- [shift] "+d" (shift) ++ [shift] "+a" (shift) + : + : CC_CLOBBER_LIST("memory")); + diff --git a/queue-6.15/s390-pci-prevent-self-deletion-in-disable_slot.patch b/queue-6.15/s390-pci-prevent-self-deletion-in-disable_slot.patch new file mode 100644 index 0000000000..be4d490d99 --- /dev/null +++ b/queue-6.15/s390-pci-prevent-self-deletion-in-disable_slot.patch @@ -0,0 +1,53 @@ +From 47c397844869ad0e6738afb5879c7492f4691122 Mon Sep 17 00:00:00 2001 +From: Niklas Schnelle +Date: Thu, 22 May 2025 14:13:13 +0200 +Subject: s390/pci: Prevent self deletion in disable_slot() + +From: Niklas Schnelle + +commit 47c397844869ad0e6738afb5879c7492f4691122 upstream. + +As disable_slot() takes a struct zpci_dev from the Configured to the +Standby state. In Standby there is still a hotplug slot so this is not +usually a case of sysfs self deletion. This is important because self +deletion gets very hairy in terms of locking (see for example +recover_store() in arch/s390/pci/pci_sysfs.c). + +Because the pci_dev_put() is not within the critical section of the +zdev->state_lock however, disable_slot() can turn into a case of self +deletion if zPCI device event handling slips between the mutex_unlock() +and the pci_dev_put(). If the latter is the last put and +zpci_release_device() is called this then tries to remove the hotplug +slot via zpci_exit_slot() which will try to remove the hotplug slot +directory the disable_slot() is part of i.e. self deletion. + +Prevent this by widening the zdev->state_lock critical section to +include the pci_dev_put() which is then guaranteed to happen with the +struct zpci_dev still in Standby state ensuring it will not lead to +a zpci_release_device() call as at least the zPCI event handling code +still holds a reference. + +Cc: stable@vger.kernel.org +Fixes: a46044a92add ("s390/pci: fix zpci_zdev_put() on reserve") +Reviewed-by: Gerd Bayer +Tested-by: Gerd Bayer +Signed-off-by: Niklas Schnelle +Signed-off-by: Heiko Carstens +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/hotplug/s390_pci_hpc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/pci/hotplug/s390_pci_hpc.c ++++ b/drivers/pci/hotplug/s390_pci_hpc.c +@@ -65,9 +65,9 @@ static int disable_slot(struct hotplug_s + + rc = zpci_deconfigure_device(zdev); + out: +- mutex_unlock(&zdev->state_lock); + if (pdev) + pci_dev_put(pdev); ++ mutex_unlock(&zdev->state_lock); + return rc; + } + diff --git a/queue-6.15/s390-pci-remove-redundant-bus-removal-and-disable-from-zpci_release_device.patch b/queue-6.15/s390-pci-remove-redundant-bus-removal-and-disable-from-zpci_release_device.patch new file mode 100644 index 0000000000..31a6460344 --- /dev/null +++ b/queue-6.15/s390-pci-remove-redundant-bus-removal-and-disable-from-zpci_release_device.patch @@ -0,0 +1,43 @@ +From d76f9633296785343d45f85199f4138cb724b6d2 Mon Sep 17 00:00:00 2001 +From: Niklas Schnelle +Date: Thu, 22 May 2025 14:13:12 +0200 +Subject: s390/pci: Remove redundant bus removal and disable from zpci_release_device() + +From: Niklas Schnelle + +commit d76f9633296785343d45f85199f4138cb724b6d2 upstream. + +Remove zpci_bus_remove_device() and zpci_disable_device() calls from +zpci_release_device(). These calls were done when the device +transitioned into the ZPCI_FN_STATE_STANDBY state which is guaranteed to +happen before it enters the ZPCI_FN_STATE_RESERVED state. When +zpci_release_device() is called the device is known to be in the +ZPCI_FN_STATE_RESERVED state which is also checked by a WARN_ON(). + +Cc: stable@vger.kernel.org +Fixes: a46044a92add ("s390/pci: fix zpci_zdev_put() on reserve") +Reviewed-by: Gerd Bayer +Reviewed-by: Julian Ruess +Tested-by: Gerd Bayer +Signed-off-by: Niklas Schnelle +Signed-off-by: Heiko Carstens +Signed-off-by: Greg Kroah-Hartman +--- + arch/s390/pci/pci.c | 6 ------ + 1 file changed, 6 deletions(-) + +--- a/arch/s390/pci/pci.c ++++ b/arch/s390/pci/pci.c +@@ -949,12 +949,6 @@ void zpci_release_device(struct kref *kr + + WARN_ON(zdev->state != ZPCI_FN_STATE_RESERVED); + +- if (zdev->zbus->bus) +- zpci_bus_remove_device(zdev, false); +- +- if (zdev_enabled(zdev)) +- zpci_disable_device(zdev); +- + if (zdev->has_hp_slot) + zpci_exit_slot(zdev); + diff --git a/queue-6.15/s390-pci-serialize-device-addition-and-removal.patch b/queue-6.15/s390-pci-serialize-device-addition-and-removal.patch new file mode 100644 index 0000000000..ce61998675 --- /dev/null +++ b/queue-6.15/s390-pci-serialize-device-addition-and-removal.patch @@ -0,0 +1,86 @@ +From 774a1fa880bc949d88b5ddec9494a13be733dfa8 Mon Sep 17 00:00:00 2001 +From: Niklas Schnelle +Date: Thu, 22 May 2025 14:13:15 +0200 +Subject: s390/pci: Serialize device addition and removal + +From: Niklas Schnelle + +commit 774a1fa880bc949d88b5ddec9494a13be733dfa8 upstream. + +Prior changes ensured that when zpci_release_device() is called and it +removed the zdev from the zpci_list this instance can not be found via +the zpci_list anymore even while allowing re-add of reserved devices. +This only accounts for the overall lifetime and zpci_list addition and +removal, it does not yet prevent concurrent add of a new instance for +the same underlying device. Such concurrent add would subsequently cause +issues such as attempted re-use of the same IOMMU sysfs directory and is +generally undesired. + +Introduce a new zpci_add_remove_lock mutex to serialize adding a new +device with removal. Together this ensures that if a struct zpci_dev is +not found in the zpci_list it was either already removed and torn down, +or its removal and tear down is in progress with the +zpci_add_remove_lock held. + +Cc: stable@vger.kernel.org +Fixes: a46044a92add ("s390/pci: fix zpci_zdev_put() on reserve") +Reviewed-by: Gerd Bayer +Tested-by: Gerd Bayer +Signed-off-by: Niklas Schnelle +Signed-off-by: Heiko Carstens +Signed-off-by: Greg Kroah-Hartman +--- + arch/s390/pci/pci.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/arch/s390/pci/pci.c ++++ b/arch/s390/pci/pci.c +@@ -45,6 +45,7 @@ + /* list of all detected zpci devices */ + static LIST_HEAD(zpci_list); + static DEFINE_SPINLOCK(zpci_list_lock); ++static DEFINE_MUTEX(zpci_add_remove_lock); + + static DECLARE_BITMAP(zpci_domain, ZPCI_DOMAIN_BITMAP_SIZE); + static DEFINE_SPINLOCK(zpci_domain_lock); +@@ -74,7 +75,9 @@ void zpci_zdev_put(struct zpci_dev *zdev + { + if (!zdev) + return; ++ mutex_lock(&zpci_add_remove_lock); + kref_put_lock(&zdev->kref, zpci_release_device, &zpci_list_lock); ++ mutex_unlock(&zpci_add_remove_lock); + } + + struct zpci_dev *get_zdev_by_fid(u32 fid) +@@ -844,6 +847,7 @@ int zpci_add_device(struct zpci_dev *zde + { + int rc; + ++ mutex_lock(&zpci_add_remove_lock); + zpci_dbg(1, "add fid:%x, fh:%x, c:%d\n", zdev->fid, zdev->fh, zdev->state); + rc = zpci_init_iommu(zdev); + if (rc) +@@ -857,12 +861,14 @@ int zpci_add_device(struct zpci_dev *zde + spin_lock(&zpci_list_lock); + list_add_tail(&zdev->entry, &zpci_list); + spin_unlock(&zpci_list_lock); ++ mutex_unlock(&zpci_add_remove_lock); + return 0; + + error_destroy_iommu: + zpci_destroy_iommu(zdev); + error: + zpci_dbg(0, "add fid:%x, rc:%d\n", zdev->fid, rc); ++ mutex_unlock(&zpci_add_remove_lock); + return rc; + } + +@@ -953,6 +959,7 @@ void zpci_release_device(struct kref *kr + { + struct zpci_dev *zdev = container_of(kref, struct zpci_dev, kref); + ++ lockdep_assert_held(&zpci_add_remove_lock); + WARN_ON(zdev->state != ZPCI_FN_STATE_RESERVED); + /* + * We already hold zpci_list_lock thanks to kref_put_lock(). diff --git a/queue-6.15/sched-fair-adhere-to-place_entity-constraints.patch b/queue-6.15/sched-fair-adhere-to-place_entity-constraints.patch new file mode 100644 index 0000000000..785320cd22 --- /dev/null +++ b/queue-6.15/sched-fair-adhere-to-place_entity-constraints.patch @@ -0,0 +1,67 @@ +From c70fc32f44431bb30f9025ce753ba8be25acbba3 Mon Sep 17 00:00:00 2001 +From: Peter Zijlstra +Date: Tue, 28 Jan 2025 15:39:49 +0100 +Subject: sched/fair: Adhere to place_entity() constraints + +From: Peter Zijlstra + +commit c70fc32f44431bb30f9025ce753ba8be25acbba3 upstream. + +Mike reports that commit 6d71a9c61604 ("sched/fair: Fix EEVDF entity +placement bug causing scheduling lag") relies on commit 4423af84b297 +("sched/fair: optimize the PLACE_LAG when se->vlag is zero") to not +trip a WARN in place_entity(). + +What happens is that the lag of the very last entity is 0 per +definition -- the average of one element matches the value of that +element. Therefore place_entity() will match the condition skipping +the lag adjustment: + + if (sched_feat(PLACE_LAG) && cfs_rq->nr_queued && se->vlag) { + +Without the 'se->vlag' condition -- it will attempt to adjust the zero +lag even though we're inserting into an empty tree. + +Notably, we should have failed the 'cfs_rq->nr_queued' condition, but +don't because they didn't get updated. + +Additionally, move update_load_add() after placement() as is +consistent with other place_entity() users -- this change is +non-functional, place_entity() does not use cfs_rq->load. + +Fixes: 6d71a9c61604 ("sched/fair: Fix EEVDF entity placement bug causing scheduling lag") +Signed-off-by: Peter Zijlstra (Intel) +Reported-by: Mike Galbraith +Signed-off-by: "Peter Zijlstra (Intel)" +Signed-off-by: Mike Galbraith +Signed-off-by: Peter Zijlstra (Intel) +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/c216eb4ef0e0e0029c600aefc69d56681cee5581.camel@gmx.de +Signed-off-by: Greg Kroah-Hartman +--- + kernel/sched/fair.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -3795,6 +3795,7 @@ static void reweight_entity(struct cfs_r + update_entity_lag(cfs_rq, se); + se->deadline -= se->vruntime; + se->rel_deadline = 1; ++ cfs_rq->nr_queued--; + if (!curr) + __dequeue_entity(cfs_rq, se); + update_load_sub(&cfs_rq->load, se->load.weight); +@@ -3821,10 +3822,11 @@ static void reweight_entity(struct cfs_r + + enqueue_load_avg(cfs_rq, se); + if (se->on_rq) { +- update_load_add(&cfs_rq->load, se->load.weight); + place_entity(cfs_rq, se, 0); ++ update_load_add(&cfs_rq->load, se->load.weight); + if (!curr) + __enqueue_entity(cfs_rq, se); ++ cfs_rq->nr_queued++; + + /* + * The entity's vruntime has been adjusted, so let's check diff --git a/queue-6.15/sched-rt-fix-race-in-push_rt_task.patch b/queue-6.15/sched-rt-fix-race-in-push_rt_task.patch new file mode 100644 index 0000000000..c85cb6e738 --- /dev/null +++ b/queue-6.15/sched-rt-fix-race-in-push_rt_task.patch @@ -0,0 +1,293 @@ +From 690e47d1403e90b7f2366f03b52ed3304194c793 Mon Sep 17 00:00:00 2001 +From: Harshit Agarwal +Date: Tue, 25 Feb 2025 18:05:53 +0000 +Subject: sched/rt: Fix race in push_rt_task +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Harshit Agarwal + +commit 690e47d1403e90b7f2366f03b52ed3304194c793 upstream. + +Overview +======== +When a CPU chooses to call push_rt_task and picks a task to push to +another CPU's runqueue then it will call find_lock_lowest_rq method +which would take a double lock on both CPUs' runqueues. If one of the +locks aren't readily available, it may lead to dropping the current +runqueue lock and reacquiring both the locks at once. During this window +it is possible that the task is already migrated and is running on some +other CPU. These cases are already handled. However, if the task is +migrated and has already been executed and another CPU is now trying to +wake it up (ttwu) such that it is queued again on the runqeue +(on_rq is 1) and also if the task was run by the same CPU, then the +current checks will pass even though the task was migrated out and is no +longer in the pushable tasks list. + +Crashes +======= +This bug resulted in quite a few flavors of crashes triggering kernel +panics with various crash signatures such as assert failures, page +faults, null pointer dereferences, and queue corruption errors all +coming from scheduler itself. + +Some of the crashes: +-> kernel BUG at kernel/sched/rt.c:1616! BUG_ON(idx >= MAX_RT_PRIO) + Call Trace: + ? __die_body+0x1a/0x60 + ? die+0x2a/0x50 + ? do_trap+0x85/0x100 + ? pick_next_task_rt+0x6e/0x1d0 + ? do_error_trap+0x64/0xa0 + ? pick_next_task_rt+0x6e/0x1d0 + ? exc_invalid_op+0x4c/0x60 + ? pick_next_task_rt+0x6e/0x1d0 + ? asm_exc_invalid_op+0x12/0x20 + ? pick_next_task_rt+0x6e/0x1d0 + __schedule+0x5cb/0x790 + ? update_ts_time_stats+0x55/0x70 + schedule_idle+0x1e/0x40 + do_idle+0x15e/0x200 + cpu_startup_entry+0x19/0x20 + start_secondary+0x117/0x160 + secondary_startup_64_no_verify+0xb0/0xbb + +-> BUG: kernel NULL pointer dereference, address: 00000000000000c0 + Call Trace: + ? __die_body+0x1a/0x60 + ? no_context+0x183/0x350 + ? __warn+0x8a/0xe0 + ? exc_page_fault+0x3d6/0x520 + ? asm_exc_page_fault+0x1e/0x30 + ? pick_next_task_rt+0xb5/0x1d0 + ? pick_next_task_rt+0x8c/0x1d0 + __schedule+0x583/0x7e0 + ? update_ts_time_stats+0x55/0x70 + schedule_idle+0x1e/0x40 + do_idle+0x15e/0x200 + cpu_startup_entry+0x19/0x20 + start_secondary+0x117/0x160 + secondary_startup_64_no_verify+0xb0/0xbb + +-> BUG: unable to handle page fault for address: ffff9464daea5900 + kernel BUG at kernel/sched/rt.c:1861! BUG_ON(rq->cpu != task_cpu(p)) + +-> kernel BUG at kernel/sched/rt.c:1055! BUG_ON(!rq->nr_running) + Call Trace: + ? __die_body+0x1a/0x60 + ? die+0x2a/0x50 + ? do_trap+0x85/0x100 + ? dequeue_top_rt_rq+0xa2/0xb0 + ? do_error_trap+0x64/0xa0 + ? dequeue_top_rt_rq+0xa2/0xb0 + ? exc_invalid_op+0x4c/0x60 + ? dequeue_top_rt_rq+0xa2/0xb0 + ? asm_exc_invalid_op+0x12/0x20 + ? dequeue_top_rt_rq+0xa2/0xb0 + dequeue_rt_entity+0x1f/0x70 + dequeue_task_rt+0x2d/0x70 + __schedule+0x1a8/0x7e0 + ? blk_finish_plug+0x25/0x40 + schedule+0x3c/0xb0 + futex_wait_queue_me+0xb6/0x120 + futex_wait+0xd9/0x240 + do_futex+0x344/0xa90 + ? get_mm_exe_file+0x30/0x60 + ? audit_exe_compare+0x58/0x70 + ? audit_filter_rules.constprop.26+0x65e/0x1220 + __x64_sys_futex+0x148/0x1f0 + do_syscall_64+0x30/0x80 + entry_SYSCALL_64_after_hwframe+0x62/0xc7 + +-> BUG: unable to handle page fault for address: ffff8cf3608bc2c0 + Call Trace: + ? __die_body+0x1a/0x60 + ? no_context+0x183/0x350 + ? spurious_kernel_fault+0x171/0x1c0 + ? exc_page_fault+0x3b6/0x520 + ? plist_check_list+0x15/0x40 + ? plist_check_list+0x2e/0x40 + ? asm_exc_page_fault+0x1e/0x30 + ? _cond_resched+0x15/0x30 + ? futex_wait_queue_me+0xc8/0x120 + ? futex_wait+0xd9/0x240 + ? try_to_wake_up+0x1b8/0x490 + ? futex_wake+0x78/0x160 + ? do_futex+0xcd/0xa90 + ? plist_check_list+0x15/0x40 + ? plist_check_list+0x2e/0x40 + ? plist_del+0x6a/0xd0 + ? plist_check_list+0x15/0x40 + ? plist_check_list+0x2e/0x40 + ? dequeue_pushable_task+0x20/0x70 + ? __schedule+0x382/0x7e0 + ? asm_sysvec_reschedule_ipi+0xa/0x20 + ? schedule+0x3c/0xb0 + ? exit_to_user_mode_prepare+0x9e/0x150 + ? irqentry_exit_to_user_mode+0x5/0x30 + ? asm_sysvec_reschedule_ipi+0x12/0x20 + +Above are some of the common examples of the crashes that were observed +due to this issue. + +Details +======= +Let's look at the following scenario to understand this race. + +1) CPU A enters push_rt_task + a) CPU A has chosen next_task = task p. + b) CPU A calls find_lock_lowest_rq(Task p, CPU Z’s rq). + c) CPU A identifies CPU X as a destination CPU (X < Z). + d) CPU A enters double_lock_balance(CPU Z’s rq, CPU X’s rq). + e) Since X is lower than Z, CPU A unlocks CPU Z’s rq. Someone else has + locked CPU X’s rq, and thus, CPU A must wait. + +2) At CPU Z + a) Previous task has completed execution and thus, CPU Z enters + schedule, locks its own rq after CPU A releases it. + b) CPU Z dequeues previous task and begins executing task p. + c) CPU Z unlocks its rq. + d) Task p yields the CPU (ex. by doing IO or waiting to acquire a + lock) which triggers the schedule function on CPU Z. + e) CPU Z enters schedule again, locks its own rq, and dequeues task p. + f) As part of dequeue, it sets p.on_rq = 0 and unlocks its rq. + +3) At CPU B + a) CPU B enters try_to_wake_up with input task p. + b) Since CPU Z dequeued task p, p.on_rq = 0, and CPU B updates + B.state = WAKING. + c) CPU B via select_task_rq determines CPU Y as the target CPU. + +4) The race + a) CPU A acquires CPU X’s lock and relocks CPU Z. + b) CPU A reads task p.cpu = Z and incorrectly concludes task p is + still on CPU Z. + c) CPU A failed to notice task p had been dequeued from CPU Z while + CPU A was waiting for locks in double_lock_balance. If CPU A knew + that task p had been dequeued, it would return NULL forcing + push_rt_task to give up the task p's migration. + d) CPU B updates task p.cpu = Y and calls ttwu_queue. + e) CPU B locks Ys rq. CPU B enqueues task p onto Y and sets task + p.on_rq = 1. + f) CPU B unlocks CPU Y, triggering memory synchronization. + g) CPU A reads task p.on_rq = 1, cementing its assumption that task p + has not migrated. + h) CPU A decides to migrate p to CPU X. + +This leads to A dequeuing p from Y's queue and various crashes down the +line. + +Solution +======== +The solution here is fairly simple. After obtaining the lock (at 4a), +the check is enhanced to make sure that the task is still at the head of +the pushable tasks list. If not, then it is anyway not suitable for +being pushed out. + +Testing +======= +The fix is tested on a cluster of 3 nodes, where the panics due to this +are hit every couple of days. A fix similar to this was deployed on such +cluster and was stable for more than 30 days. + +Co-developed-by: Jon Kohler +Signed-off-by: Jon Kohler +Co-developed-by: Gauri Patwardhan +Signed-off-by: Gauri Patwardhan +Co-developed-by: Rahul Chunduru +Signed-off-by: Rahul Chunduru +Signed-off-by: Harshit Agarwal +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: "Steven Rostedt (Google)" +Reviewed-by: Phil Auld +Tested-by: Will Ton +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20250225180553.167995-1-harshit@nutanix.com +Signed-off-by: Greg Kroah-Hartman +--- + kernel/sched/rt.c | 54 ++++++++++++++++++++++++++---------------------------- + 1 file changed, 26 insertions(+), 28 deletions(-) + +--- a/kernel/sched/rt.c ++++ b/kernel/sched/rt.c +@@ -1883,6 +1883,27 @@ static int find_lowest_rq(struct task_st + return -1; + } + ++static struct task_struct *pick_next_pushable_task(struct rq *rq) ++{ ++ struct task_struct *p; ++ ++ if (!has_pushable_tasks(rq)) ++ return NULL; ++ ++ p = plist_first_entry(&rq->rt.pushable_tasks, ++ struct task_struct, pushable_tasks); ++ ++ BUG_ON(rq->cpu != task_cpu(p)); ++ BUG_ON(task_current(rq, p)); ++ BUG_ON(task_current_donor(rq, p)); ++ BUG_ON(p->nr_cpus_allowed <= 1); ++ ++ BUG_ON(!task_on_rq_queued(p)); ++ BUG_ON(!rt_task(p)); ++ ++ return p; ++} ++ + /* Will lock the rq it finds */ + static struct rq *find_lock_lowest_rq(struct task_struct *task, struct rq *rq) + { +@@ -1913,18 +1934,16 @@ static struct rq *find_lock_lowest_rq(st + /* + * We had to unlock the run queue. In + * the mean time, task could have +- * migrated already or had its affinity changed. +- * Also make sure that it wasn't scheduled on its rq. ++ * migrated already or had its affinity changed, ++ * therefore check if the task is still at the ++ * head of the pushable tasks list. + * It is possible the task was scheduled, set + * "migrate_disabled" and then got preempted, so we must + * check the task migration disable flag here too. + */ +- if (unlikely(task_rq(task) != rq || ++ if (unlikely(is_migration_disabled(task) || + !cpumask_test_cpu(lowest_rq->cpu, &task->cpus_mask) || +- task_on_cpu(rq, task) || +- !rt_task(task) || +- is_migration_disabled(task) || +- !task_on_rq_queued(task))) { ++ task != pick_next_pushable_task(rq))) { + + double_unlock_balance(rq, lowest_rq); + lowest_rq = NULL; +@@ -1944,27 +1963,6 @@ static struct rq *find_lock_lowest_rq(st + return lowest_rq; + } + +-static struct task_struct *pick_next_pushable_task(struct rq *rq) +-{ +- struct task_struct *p; +- +- if (!has_pushable_tasks(rq)) +- return NULL; +- +- p = plist_first_entry(&rq->rt.pushable_tasks, +- struct task_struct, pushable_tasks); +- +- BUG_ON(rq->cpu != task_cpu(p)); +- BUG_ON(task_current(rq, p)); +- BUG_ON(task_current_donor(rq, p)); +- BUG_ON(p->nr_cpus_allowed <= 1); +- +- BUG_ON(!task_on_rq_queued(p)); +- BUG_ON(!rt_task(p)); +- +- return p; +-} +- + /* + * If the current CPU has more than one RT task, see if the non + * running task can migrate over to a CPU that is running a task diff --git a/queue-6.15/series b/queue-6.15/series new file mode 100644 index 0000000000..20f375b671 --- /dev/null +++ b/queue-6.15/series @@ -0,0 +1,32 @@ +alloc_tag-handle-module-codetag-load-errors-as-module-load-failures.patch +configfs-do-not-override-creating-attribute-file-failure-in-populate_attrs.patch +crypto-marvell-cesa-do-not-chain-submitted-requests.patch +gfs2-move-msleep-to-sleepable-context.patch +sched-rt-fix-race-in-push_rt_task.patch +sched-fair-adhere-to-place_entity-constraints.patch +crypto-qat-add-shutdown-handler-to-qat_c3xxx.patch +crypto-qat-add-shutdown-handler-to-qat_420xx.patch +crypto-qat-add-shutdown-handler-to-qat_4xxx.patch +crypto-qat-add-shutdown-handler-to-qat_c62x.patch +crypto-qat-add-shutdown-handler-to-qat_dh895xcc.patch +asoc-qcom-sdm845-add-error-handling-in-sdm845_slim_snd_hw_params.patch +firmware-cs_dsp-fix-oob-memory-read-access-in-kunit-test.patch +asoc-meson-meson-card-utils-use-of_property_present-for-dt-parsing.patch +asoc-amd-amd_sdw-fix-unlikely-uninitialized-variable-use-in-create_sdw_dailinks.patch +asoc-amd-sof_amd_sdw-fix-unlikely-uninitialized-variable-use-in-create_sdw_dailinks.patch +io_uring-account-drain-memory-to-cgroup.patch +io_uring-kbuf-account-ring-io_buffer_list-memory.patch +powerpc-pseries-msi-avoid-reading-pci-device-registers-in-reduced-power-states.patch +powerpc64-ftrace-fix-clobbered-r15-during-livepatching.patch +powerpc-bpf-fix-jit-code-size-calculation-of-bpf-trampoline.patch +s390-pci-fix-__pcilg_mio_inuser-inline-assembly.patch +s390-pci-remove-redundant-bus-removal-and-disable-from-zpci_release_device.patch +s390-pci-prevent-self-deletion-in-disable_slot.patch +s390-pci-allow-re-add-of-a-reserved-but-not-yet-removed-device.patch +s390-pci-serialize-device-addition-and-removal.patch +regulator-max20086-fix-max200086-chip-id.patch +regulator-max20086-change-enable-gpio-to-optional.patch +net-mlx5_core-add-error-handling-inmlx5_query_nic_vport_qkey_viol_cntr.patch +net-mlx5-add-error-handling-in-mlx5_query_nic_vport_node_guid.patch +wifi-p54-prevent-buffer-overflow-in-p54_rx_eeprom_readback.patch +wifi-mt76-mt7925-fix-host-interrupt-register-initialization.patch diff --git a/queue-6.15/wifi-mt76-mt7925-fix-host-interrupt-register-initialization.patch b/queue-6.15/wifi-mt76-mt7925-fix-host-interrupt-register-initialization.patch new file mode 100644 index 0000000000..c33cc9f1dd --- /dev/null +++ b/queue-6.15/wifi-mt76-mt7925-fix-host-interrupt-register-initialization.patch @@ -0,0 +1,47 @@ +From ca872e0ad97159375da8f3d05cac1f48239e01d7 Mon Sep 17 00:00:00 2001 +From: Michael Lo +Date: Fri, 9 May 2025 16:35:12 +0800 +Subject: wifi: mt76: mt7925: fix host interrupt register initialization + +From: Michael Lo + +commit ca872e0ad97159375da8f3d05cac1f48239e01d7 upstream. + +ensure proper interrupt handling and aligns with the hardware spec by +updating the register offset for MT_WFDMA0_HOST_INT_ENA. + +Cc: stable@vger.kernel.org +Fixes: c948b5da6bbe ("wifi: mt76: mt7925: add Mediatek Wi-Fi7 driver for mt7925 chips") +Signed-off-by: Michael Lo +Signed-off-by: Ming Yen Hsieh +Link: https://patch.msgid.link/20250509083512.455095-1-mingyen.hsieh@mediatek.com +Signed-off-by: Felix Fietkau +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/mediatek/mt76/mt7925/pci.c | 3 --- + drivers/net/wireless/mediatek/mt76/mt7925/regs.h | 2 +- + 2 files changed, 1 insertion(+), 4 deletions(-) + +--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c +@@ -490,9 +490,6 @@ static int mt7925_pci_suspend(struct dev + + /* disable interrupt */ + mt76_wr(dev, dev->irq_map->host_irq_enable, 0); +- mt76_wr(dev, MT_WFDMA0_HOST_INT_DIS, +- dev->irq_map->tx.all_complete_mask | +- MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD); + + mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); + +--- a/drivers/net/wireless/mediatek/mt76/mt7925/regs.h ++++ b/drivers/net/wireless/mediatek/mt76/mt7925/regs.h +@@ -28,7 +28,7 @@ + #define MT_MDP_TO_HIF 0 + #define MT_MDP_TO_WM 1 + +-#define MT_WFDMA0_HOST_INT_ENA MT_WFDMA0(0x228) ++#define MT_WFDMA0_HOST_INT_ENA MT_WFDMA0(0x204) + #define MT_WFDMA0_HOST_INT_DIS MT_WFDMA0(0x22c) + #define HOST_RX_DONE_INT_ENA4 BIT(12) + #define HOST_RX_DONE_INT_ENA5 BIT(13) diff --git a/queue-6.15/wifi-p54-prevent-buffer-overflow-in-p54_rx_eeprom_readback.patch b/queue-6.15/wifi-p54-prevent-buffer-overflow-in-p54_rx_eeprom_readback.patch new file mode 100644 index 0000000000..19f5100ecc --- /dev/null +++ b/queue-6.15/wifi-p54-prevent-buffer-overflow-in-p54_rx_eeprom_readback.patch @@ -0,0 +1,114 @@ +From da1b9a55ff116cb040528ef664c70a4eec03ae99 Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Fri, 16 May 2025 20:41:06 +0200 +Subject: wifi: p54: prevent buffer-overflow in p54_rx_eeprom_readback() + +From: Christian Lamparter + +commit da1b9a55ff116cb040528ef664c70a4eec03ae99 upstream. + +Robert Morris reported: + +|If a malicious USB device pretends to be an Intersil p54 wifi +|interface and generates an eeprom_readback message with a large +|eeprom->v1.len, p54_rx_eeprom_readback() will copy data from the +|message beyond the end of priv->eeprom. +| +|static void p54_rx_eeprom_readback(struct p54_common *priv, +| struct sk_buff *skb) +|{ +| struct p54_hdr *hdr = (struct p54_hdr *) skb->data; +| struct p54_eeprom_lm86 *eeprom = (struct p54_eeprom_lm86 *) hdr->data; +| +| if (priv->fw_var >= 0x509) { +| memcpy(priv->eeprom, eeprom->v2.data, +| le16_to_cpu(eeprom->v2.len)); +| } else { +| memcpy(priv->eeprom, eeprom->v1.data, +| le16_to_cpu(eeprom->v1.len)); +| } +| [...] + +The eeprom->v{1,2}.len is set by the driver in p54_download_eeprom(). +The device is supposed to provide the same length back to the driver. +But yes, it's possible (like shown in the report) to alter the value +to something that causes a crash/panic due to overrun. + +This patch addresses the issue by adding the size to the common device +context, so p54_rx_eeprom_readback no longer relies on possibly tampered +values... That said, it also checks if the "firmware" altered the value +and no longer copies them. + +The one, small saving grace is: Before the driver tries to read the eeprom, +it needs to upload >a< firmware. the vendor firmware has a proprietary +license and as a reason, it is not present on most distributions by +default. + +Cc: +Reported-by: Robert Morris +Closes: https://lore.kernel.org/linux-wireless/28782.1747258414@localhost/ +Fixes: 7cb770729ba8 ("p54: move eeprom code into common library") +Signed-off-by: Christian Lamparter +Link: https://patch.msgid.link/20250516184107.47794-1-chunkeey@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/intersil/p54/fwio.c | 2 ++ + drivers/net/wireless/intersil/p54/p54.h | 1 + + drivers/net/wireless/intersil/p54/txrx.c | 13 +++++++++---- + 3 files changed, 12 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/intersil/p54/fwio.c ++++ b/drivers/net/wireless/intersil/p54/fwio.c +@@ -231,6 +231,7 @@ int p54_download_eeprom(struct p54_commo + + mutex_lock(&priv->eeprom_mutex); + priv->eeprom = buf; ++ priv->eeprom_slice_size = len; + eeprom_hdr = skb_put(skb, eeprom_hdr_size + len); + + if (priv->fw_var < 0x509) { +@@ -253,6 +254,7 @@ int p54_download_eeprom(struct p54_commo + ret = -EBUSY; + } + priv->eeprom = NULL; ++ priv->eeprom_slice_size = 0; + mutex_unlock(&priv->eeprom_mutex); + return ret; + } +--- a/drivers/net/wireless/intersil/p54/p54.h ++++ b/drivers/net/wireless/intersil/p54/p54.h +@@ -258,6 +258,7 @@ struct p54_common { + + /* eeprom handling */ + void *eeprom; ++ size_t eeprom_slice_size; + struct completion eeprom_comp; + struct mutex eeprom_mutex; + }; +--- a/drivers/net/wireless/intersil/p54/txrx.c ++++ b/drivers/net/wireless/intersil/p54/txrx.c +@@ -496,14 +496,19 @@ static void p54_rx_eeprom_readback(struc + return ; + + if (priv->fw_var >= 0x509) { +- memcpy(priv->eeprom, eeprom->v2.data, +- le16_to_cpu(eeprom->v2.len)); ++ if (le16_to_cpu(eeprom->v2.len) != priv->eeprom_slice_size) ++ return; ++ ++ memcpy(priv->eeprom, eeprom->v2.data, priv->eeprom_slice_size); + } else { +- memcpy(priv->eeprom, eeprom->v1.data, +- le16_to_cpu(eeprom->v1.len)); ++ if (le16_to_cpu(eeprom->v1.len) != priv->eeprom_slice_size) ++ return; ++ ++ memcpy(priv->eeprom, eeprom->v1.data, priv->eeprom_slice_size); + } + + priv->eeprom = NULL; ++ priv->eeprom_slice_size = 0; + tmp = p54_find_and_unlink_skb(priv, hdr->req_id); + dev_kfree_skb_any(tmp); + complete(&priv->eeprom_comp);