From 58c1e8c569bd39d3c74a7db4a24e5c1561f057d2 Mon Sep 17 00:00:00 2001 From: Edward Liaw Date: Fri, 4 Apr 2025 22:12:20 +0000 Subject: [PATCH 001/606] selftests/futex: futex_waitv wouldblock test should fail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 7d50e00fef2832e98d7e06bbfc85c1d66ee110ca ] Testcase should fail if -EWOULDBLOCK is not returned when expected value differs from actual value from the waiter. Link: https://lore.kernel.org/r/20250404221225.1596324-1-edliaw@google.com Fixes: 9d57f7c79748920636f8293d2f01192d702fe390 ("selftests: futex: Test sys_futex_waitv() wouldblock") Signed-off-by: Edward Liaw Reviewed-by: Thomas Gleixner Reviewed-by: André Almeida Signed-off-by: Shuah Khan Signed-off-by: Sasha Levin --- .../testing/selftests/futex/functional/futex_wait_wouldblock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c b/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c index 7d7a6a06cdb7..2d8230da9064 100644 --- a/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c +++ b/tools/testing/selftests/futex/functional/futex_wait_wouldblock.c @@ -98,7 +98,7 @@ int main(int argc, char *argv[]) info("Calling futex_waitv on f1: %u @ %p with val=%u\n", f1, &f1, f1+1); res = futex_waitv(&waitv, 1, 0, &to, CLOCK_MONOTONIC); if (!res || errno != EWOULDBLOCK) { - ksft_test_result_pass("futex_waitv returned: %d %s\n", + ksft_test_result_fail("futex_waitv returned: %d %s\n", res ? errno : res, res ? strerror(errno) : ""); ret = RET_FAIL; From 18520ecc3cfabc32401c0ecfbe34dd7a807aa78a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 2 Oct 2023 11:47:02 +0300 Subject: [PATCH 002/606] drm/i915/mocs: use to_gt() instead of direct &i915->gt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 5ed8c7bcf9a58372d3be3d9cd167e45497efaae2 ] Have to give up the const on i915 pointer, but it's not big of a deal considering non-const i915 gets passed all over the place. Signed-off-by: Jani Nikula Reviewed-by: Gustavo Sousa Reviewed-by: Andi Shyti Acked-by: Michał Winiarski Link: https://patchwork.freedesktop.org/patch/msgid/63e644f056c7745eb0e8e165c990c392a38ec85c.1696236329.git.jani.nikula@intel.com Stable-dep-of: 9d3d9776bd3b ("drm/i915: Disable RPG during live selftest") Signed-off-by: Sasha Levin --- drivers/gpu/drm/i915/gt/intel_mocs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_mocs.c b/drivers/gpu/drm/i915/gt/intel_mocs.c index 07269ff3be13..353f93baaca0 100644 --- a/drivers/gpu/drm/i915/gt/intel_mocs.c +++ b/drivers/gpu/drm/i915/gt/intel_mocs.c @@ -487,7 +487,7 @@ static bool has_mocs(const struct drm_i915_private *i915) return !IS_DGFX(i915); } -static unsigned int get_mocs_settings(const struct drm_i915_private *i915, +static unsigned int get_mocs_settings(struct drm_i915_private *i915, struct drm_i915_mocs_table *table) { unsigned int flags; @@ -495,7 +495,7 @@ static unsigned int get_mocs_settings(const struct drm_i915_private *i915, memset(table, 0, sizeof(struct drm_i915_mocs_table)); table->unused_entries_index = I915_MOCS_PTE; - if (IS_GFX_GT_IP_RANGE(&i915->gt0, IP_VER(12, 70), IP_VER(12, 71))) { + if (IS_GFX_GT_IP_RANGE(to_gt(i915), IP_VER(12, 70), IP_VER(12, 71))) { table->size = ARRAY_SIZE(mtl_mocs_table); table->table = mtl_mocs_table; table->n_entries = MTL_NUM_MOCS_ENTRIES; From 8b2148daa73b02adddf6ed36f233c8f09d78573f Mon Sep 17 00:00:00 2001 From: Harish Chegondi Date: Mon, 8 Jan 2024 17:57:37 +0530 Subject: [PATCH 003/606] drm/i915/xelpg: Extend driver code of Xe_LPG to Xe_LPG+ [ Upstream commit 84bf82f4f8661930a134a1d86bde16f7d8bcd699 ] Xe_LPG+ (IP version 12.74) should take the same general code paths as Xe_LPG (versions 12.70 and 12.71). Xe_LPG+'s workaround list will be handled by the next patch. Signed-off-by: Harish Chegondi Signed-off-by: Haridhar Kalvala Reviewed-by: Matt Roper Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20240108122738.14399-3-haridhar.kalvala@intel.com Stable-dep-of: 9d3d9776bd3b ("drm/i915: Disable RPG during live selftest") Signed-off-by: Sasha Levin --- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 3 ++- drivers/gpu/drm/i915/gt/intel_mocs.c | 2 +- drivers/gpu/drm/i915/gt/intel_rc6.c | 2 +- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index d9bb352b8baa..0729ab595517 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -1218,7 +1218,8 @@ static int intel_engine_init_tlb_invalidation(struct intel_engine_cs *engine) num = ARRAY_SIZE(xelpmp_regs); } } else { - if (GRAPHICS_VER_FULL(i915) == IP_VER(12, 71) || + if (GRAPHICS_VER_FULL(i915) == IP_VER(12, 74) || + GRAPHICS_VER_FULL(i915) == IP_VER(12, 71) || GRAPHICS_VER_FULL(i915) == IP_VER(12, 70) || GRAPHICS_VER_FULL(i915) == IP_VER(12, 50) || GRAPHICS_VER_FULL(i915) == IP_VER(12, 55)) { diff --git a/drivers/gpu/drm/i915/gt/intel_mocs.c b/drivers/gpu/drm/i915/gt/intel_mocs.c index 353f93baaca0..25c1023eb5f9 100644 --- a/drivers/gpu/drm/i915/gt/intel_mocs.c +++ b/drivers/gpu/drm/i915/gt/intel_mocs.c @@ -495,7 +495,7 @@ static unsigned int get_mocs_settings(struct drm_i915_private *i915, memset(table, 0, sizeof(struct drm_i915_mocs_table)); table->unused_entries_index = I915_MOCS_PTE; - if (IS_GFX_GT_IP_RANGE(to_gt(i915), IP_VER(12, 70), IP_VER(12, 71))) { + if (IS_GFX_GT_IP_RANGE(to_gt(i915), IP_VER(12, 70), IP_VER(12, 74))) { table->size = ARRAY_SIZE(mtl_mocs_table); table->table = mtl_mocs_table; table->n_entries = MTL_NUM_MOCS_ENTRIES; diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c index 6e8c182b2559..483d55785881 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.c +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c @@ -123,7 +123,7 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6) * temporary wa and should be removed after fixing real cause * of forcewake timeouts. */ - if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) + if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 74))) pg_enable = GEN9_MEDIA_PG_ENABLE | GEN11_MEDIA_SAMPLER_PG_ENABLE; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 7a90a2e32c9f..1fde21d8bb59 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -144,7 +144,7 @@ static const char *i915_cache_level_str(struct drm_i915_gem_object *obj) { struct drm_i915_private *i915 = obj_to_i915(obj); - if (IS_GFX_GT_IP_RANGE(to_gt(i915), IP_VER(12, 70), IP_VER(12, 71))) { + if (IS_GFX_GT_IP_RANGE(to_gt(i915), IP_VER(12, 70), IP_VER(12, 74))) { switch (obj->pat_index) { case 0: return " WB"; case 1: return " WT"; From 303d7604751435b511e68b06a62b787999152968 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 10 Apr 2024 13:15:05 -0700 Subject: [PATCH 004/606] drm/i915/dg2: wait for HuC load completion before running selftests [ Upstream commit c3015eb6e25a735ab77591573236169eab8e2e3a ] On DG2, submissions to VCS engines tied to a gem context are blocked until the HuC is loaded. Since some selftests do use a gem context, wait for the HuC load to complete before running the tests to avoid contamination. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/10564 Signed-off-by: Daniele Ceraolo Spurio Cc: John Harrison Reviewed-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20240410201505.894594-1-daniele.ceraolospurio@intel.com Stable-dep-of: 9d3d9776bd3b ("drm/i915: Disable RPG during live selftest") Signed-off-by: Sasha Levin --- .../gpu/drm/i915/selftests/i915_selftest.c | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/selftests/i915_selftest.c b/drivers/gpu/drm/i915/selftests/i915_selftest.c index ee79e0809a6d..fee76c1d2f45 100644 --- a/drivers/gpu/drm/i915/selftests/i915_selftest.c +++ b/drivers/gpu/drm/i915/selftests/i915_selftest.c @@ -154,6 +154,30 @@ __wait_gsc_proxy_completed(struct drm_i915_private *i915) pr_warn(DRIVER_NAME "Timed out waiting for gsc_proxy_completion!\n"); } +static void +__wait_gsc_huc_load_completed(struct drm_i915_private *i915) +{ + /* this only applies to DG2, so we only care about GT0 */ + struct intel_huc *huc = &to_gt(i915)->uc.huc; + bool need_to_wait = (IS_ENABLED(CONFIG_INTEL_MEI_PXP) && + intel_huc_wait_required(huc)); + /* + * The GSC and PXP mei bringup depends on the kernel boot ordering, so + * to account for the worst case scenario the HuC code waits for up to + * 10s for the GSC driver to load and then another 5s for the PXP + * component to bind before giving up, even though those steps normally + * complete in less than a second from the i915 load. We match that + * timeout here, but we expect to bail early due to the fence being + * signalled even in a failure case, as it is extremely unlikely that + * both components will use their full timeout. + */ + unsigned long timeout_ms = 15000; + + if (need_to_wait && + wait_for(i915_sw_fence_done(&huc->delayed_load.fence), timeout_ms)) + pr_warn(DRIVER_NAME "Timed out waiting for huc load via GSC!\n"); +} + static int __run_selftests(const char *name, struct selftest *st, unsigned int count, @@ -228,14 +252,16 @@ int i915_mock_selftests(void) int i915_live_selftests(struct pci_dev *pdev) { + struct drm_i915_private *i915 = pdev_to_i915(pdev); int err; if (!i915_selftest.live) return 0; - __wait_gsc_proxy_completed(pdev_to_i915(pdev)); + __wait_gsc_proxy_completed(i915); + __wait_gsc_huc_load_completed(i915); - err = run_selftests(live, pdev_to_i915(pdev)); + err = run_selftests(live, i915); if (err) { i915_selftest.live = err; return err; @@ -251,14 +277,16 @@ int i915_live_selftests(struct pci_dev *pdev) int i915_perf_selftests(struct pci_dev *pdev) { + struct drm_i915_private *i915 = pdev_to_i915(pdev); int err; if (!i915_selftest.perf) return 0; - __wait_gsc_proxy_completed(pdev_to_i915(pdev)); + __wait_gsc_proxy_completed(i915); + __wait_gsc_huc_load_completed(i915); - err = run_selftests(perf, pdev_to_i915(pdev)); + err = run_selftests(perf, i915); if (err) { i915_selftest.perf = err; return err; From 4d4bf6d6b14758784617e31a6a3a89d520172768 Mon Sep 17 00:00:00 2001 From: Badal Nilawar Date: Mon, 10 Mar 2025 20:58:21 +0530 Subject: [PATCH 005/606] drm/i915: Disable RPG during live selftest [ Upstream commit 9d3d9776bd3bd9c32d460dfe6c3363134de578bc ] The Forcewake timeout issue has been observed on Gen 12.0 and above. To address this, disable Render Power-Gating (RPG) during live self-tests for these generations. The temporary workaround 'drm/i915/mtl: do not enable render power-gating on MTL' disables RPG globally, which is unnecessary since the issues were only seen during self-tests. v2: take runtime pm wakeref Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9413 Fixes: 25e7976db86b ("drm/i915/mtl: do not enable render power-gating on MTL") Cc: Rodrigo Vivi Cc: Andi Shyti Cc: Andrzej Hajda Signed-off-by: Badal Nilawar Signed-off-by: Sk Anirban Reviewed-by: Karthik Poosa Signed-off-by: Anshuman Gupta Link: https://patchwork.freedesktop.org/patch/msgid/20250310152821.2931678-1-sk.anirban@intel.com (cherry picked from commit 0a4ae87706c6d15d14648e428c3a76351f823e48) Signed-off-by: Jani Nikula Signed-off-by: Sasha Levin --- drivers/gpu/drm/i915/gt/intel_rc6.c | 19 ++++--------------- .../gpu/drm/i915/selftests/i915_selftest.c | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c index 483d55785881..3c7f4ed51bb0 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.c +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c @@ -117,21 +117,10 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6) GEN6_RC_CTL_RC6_ENABLE | GEN6_RC_CTL_EI_MODE(1); - /* - * BSpec 52698 - Render powergating must be off. - * FIXME BSpec is outdated, disabling powergating for MTL is just - * temporary wa and should be removed after fixing real cause - * of forcewake timeouts. - */ - if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 74))) - pg_enable = - GEN9_MEDIA_PG_ENABLE | - GEN11_MEDIA_SAMPLER_PG_ENABLE; - else - pg_enable = - GEN9_RENDER_PG_ENABLE | - GEN9_MEDIA_PG_ENABLE | - GEN11_MEDIA_SAMPLER_PG_ENABLE; + pg_enable = + GEN9_RENDER_PG_ENABLE | + GEN9_MEDIA_PG_ENABLE | + GEN11_MEDIA_SAMPLER_PG_ENABLE; if (GRAPHICS_VER(gt->i915) >= 12 && !IS_DG1(gt->i915)) { for (i = 0; i < I915_MAX_VCS; i++) diff --git a/drivers/gpu/drm/i915/selftests/i915_selftest.c b/drivers/gpu/drm/i915/selftests/i915_selftest.c index fee76c1d2f45..889281819c5b 100644 --- a/drivers/gpu/drm/i915/selftests/i915_selftest.c +++ b/drivers/gpu/drm/i915/selftests/i915_selftest.c @@ -23,7 +23,9 @@ #include +#include "gt/intel_gt.h" #include "gt/intel_gt_pm.h" +#include "gt/intel_gt_regs.h" #include "gt/uc/intel_gsc_fw.h" #include "i915_driver.h" @@ -253,11 +255,27 @@ int i915_mock_selftests(void) int i915_live_selftests(struct pci_dev *pdev) { struct drm_i915_private *i915 = pdev_to_i915(pdev); + struct intel_uncore *uncore = &i915->uncore; int err; + u32 pg_enable; + intel_wakeref_t wakeref; if (!i915_selftest.live) return 0; + /* + * FIXME Disable render powergating, this is temporary wa and should be removed + * after fixing real cause of forcewake timeouts. + */ + with_intel_runtime_pm(uncore->rpm, wakeref) { + if (IS_GFX_GT_IP_RANGE(to_gt(i915), IP_VER(12, 00), IP_VER(12, 74))) { + pg_enable = intel_uncore_read(uncore, GEN9_PG_ENABLE); + if (pg_enable & GEN9_RENDER_PG_ENABLE) + intel_uncore_write_fw(uncore, GEN9_PG_ENABLE, + pg_enable & ~GEN9_RENDER_PG_ENABLE); + } + } + __wait_gsc_proxy_completed(i915); __wait_gsc_huc_load_completed(i915); From 5b09bf6243b0bc0ae58bd9efdf6f0de5546f8d06 Mon Sep 17 00:00:00 2001 From: Henry Martin Date: Fri, 4 Apr 2025 14:14:38 +0800 Subject: [PATCH 006/606] ata: pata_pxa: Fix potential NULL pointer dereference in pxa_ata_probe() [ Upstream commit ad320e408a8c95a282ab9c05cdf0c9b95e317985 ] devm_ioremap() returns NULL on error. Currently, pxa_ata_probe() does not check for this case, which can result in a NULL pointer dereference. Add NULL check after devm_ioremap() to prevent this issue. Fixes: 2dc6c6f15da9 ("[ARM] pata_pxa: DMA-capable PATA driver") Signed-off-by: Henry Martin Signed-off-by: Damien Le Moal Signed-off-by: Sasha Levin --- drivers/ata/pata_pxa.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/ata/pata_pxa.c b/drivers/ata/pata_pxa.c index 5275c6464f57..821bcf20741e 100644 --- a/drivers/ata/pata_pxa.c +++ b/drivers/ata/pata_pxa.c @@ -223,10 +223,16 @@ static int pxa_ata_probe(struct platform_device *pdev) ap->ioaddr.cmd_addr = devm_ioremap(&pdev->dev, cmd_res->start, resource_size(cmd_res)); + if (!ap->ioaddr.cmd_addr) + return -ENOMEM; ap->ioaddr.ctl_addr = devm_ioremap(&pdev->dev, ctl_res->start, resource_size(ctl_res)); + if (!ap->ioaddr.ctl_addr) + return -ENOMEM; ap->ioaddr.bmdma_addr = devm_ioremap(&pdev->dev, dma_res->start, resource_size(dma_res)); + if (!ap->ioaddr.bmdma_addr) + return -ENOMEM; /* * Adjust register offsets From ae7e9d29a3c3286e8a5d0d7e88822a3ff437d9c3 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Tue, 8 Apr 2025 00:02:13 -0700 Subject: [PATCH 007/606] objtool: Fix INSN_CONTEXT_SWITCH handling in validate_unret() [ Upstream commit a8df7d0ef92eca28c610206c6748daf537ac0586 ] The !CONFIG_IA32_EMULATION version of xen_entry_SYSCALL_compat() ends with a SYSCALL instruction which is classified by objtool as INSN_CONTEXT_SWITCH. Unlike validate_branch(), validate_unret() doesn't consider INSN_CONTEXT_SWITCH in a non-function to be a dead end, so it keeps going past the end of xen_entry_SYSCALL_compat(), resulting in the following warning: vmlinux.o: warning: objtool: xen_reschedule_interrupt+0x2a: RET before UNTRAIN Fix that by adding INSN_CONTEXT_SWITCH handling to validate_unret() to match what validate_branch() is already doing. Fixes: a09a6e2399ba ("objtool: Add entry UNRET validation") Reported-by: Andrew Cooper Signed-off-by: Josh Poimboeuf Signed-off-by: Ingo Molnar Cc: Linus Torvalds Link: https://lore.kernel.org/r/f5eda46fd09f15b1f5cde3d9ae3b92b958342add.1744095216.git.jpoimboe@kernel.org Signed-off-by: Sasha Levin --- tools/objtool/check.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/objtool/check.c b/tools/objtool/check.c index 9102ad5985cc..8ba5bcfd5cd5 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -3926,6 +3926,11 @@ static int validate_unret(struct objtool_file *file, struct instruction *insn) WARN_INSN(insn, "RET before UNTRAIN"); return 1; + case INSN_CONTEXT_SWITCH: + if (insn_func(insn)) + break; + return 0; + case INSN_NOP: if (insn->retpoline_safe) return 0; From 09c2dcda2c551bba30710c33f6ac678ae7395389 Mon Sep 17 00:00:00 2001 From: Tung Nguyen Date: Thu, 3 Apr 2025 09:24:31 +0000 Subject: [PATCH 008/606] tipc: fix memory leak in tipc_link_xmit [ Upstream commit 69ae94725f4fc9e75219d2d69022029c5b24bc9a ] In case the backlog transmit queue for system-importance messages is overloaded, tipc_link_xmit() returns -ENOBUFS but the skb list is not purged. This leads to memory leak and failure when a skb is allocated. This commit fixes this issue by purging the skb list before tipc_link_xmit() returns. Fixes: 365ad353c256 ("tipc: reduce risk of user starvation during link congestion") Signed-off-by: Tung Nguyen Link: https://patch.msgid.link/20250403092431.514063-1-tung.quang.nguyen@est.tech Signed-off-by: Paolo Abeni Signed-off-by: Sasha Levin --- net/tipc/link.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/tipc/link.c b/net/tipc/link.c index d0143823658d..6c6d8546c578 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1068,6 +1068,7 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list, if (unlikely(l->backlog[imp].len >= l->backlog[imp].limit)) { if (imp == TIPC_SYSTEM_IMPORTANCE) { pr_warn("%s<%s>, link overflow", link_rst_msg, l->name); + __skb_queue_purge(list); return -ENOBUFS; } rc = link_schedule_user(l, hdr); From 2f9761a94bae33d26e6a81b31b36e7d776d93dc1 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Thu, 3 Apr 2025 14:16:31 -0700 Subject: [PATCH 009/606] codel: remove sch->q.qlen check before qdisc_tree_reduce_backlog() [ Upstream commit 342debc12183b51773b3345ba267e9263bdfaaef ] After making all ->qlen_notify() callbacks idempotent, now it is safe to remove the check of qlen!=0 from both fq_codel_dequeue() and codel_qdisc_dequeue(). Reported-by: Gerrard Tai Fixes: 4b549a2ef4be ("fq_codel: Fair Queue Codel AQM") Fixes: 76e3cc126bb2 ("codel: Controlled Delay AQM") Signed-off-by: Cong Wang Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250403211636.166257-1-xiyou.wangcong@gmail.com Acked-by: Jamal Hadi Salim Signed-off-by: Paolo Abeni Signed-off-by: Sasha Levin --- net/sched/sch_codel.c | 5 +---- net/sched/sch_fq_codel.c | 6 ++---- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/net/sched/sch_codel.c b/net/sched/sch_codel.c index d7a4874543de..5f2e06815745 100644 --- a/net/sched/sch_codel.c +++ b/net/sched/sch_codel.c @@ -95,10 +95,7 @@ static struct sk_buff *codel_qdisc_dequeue(struct Qdisc *sch) &q->stats, qdisc_pkt_len, codel_get_enqueue_time, drop_func, dequeue_func); - /* We cant call qdisc_tree_reduce_backlog() if our qlen is 0, - * or HTB crashes. Defer it for next round. - */ - if (q->stats.drop_count && sch->q.qlen) { + if (q->stats.drop_count) { qdisc_tree_reduce_backlog(sch, q->stats.drop_count, q->stats.drop_len); q->stats.drop_count = 0; q->stats.drop_len = 0; diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index 8c4fee063436..9330923a624c 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c @@ -314,10 +314,8 @@ begin: } qdisc_bstats_update(sch, skb); flow->deficit -= qdisc_pkt_len(skb); - /* We cant call qdisc_tree_reduce_backlog() if our qlen is 0, - * or HTB crashes. Defer it for next round. - */ - if (q->cstats.drop_count && sch->q.qlen) { + + if (q->cstats.drop_count) { qdisc_tree_reduce_backlog(sch, q->cstats.drop_count, q->cstats.drop_len); q->cstats.drop_count = 0; From 2bcad8fefcecdd5f005d8c550b25d703c063c34a Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Fri, 4 Apr 2025 11:03:33 -0700 Subject: [PATCH 010/606] net: tls: explicitly disallow disconnect [ Upstream commit 5071a1e606b30c0c11278d3c6620cd6a24724cf6 ] syzbot discovered that it can disconnect a TLS socket and then run into all sort of unexpected corner cases. I have a vague recollection of Eric pointing this out to us a long time ago. Supporting disconnect is really hard, for one thing if offload is enabled we'd need to wait for all packets to be _acked_. Disconnect is not commonly used, disallow it. The immediate problem syzbot run into is the warning in the strp, but that's just the easiest bug to trigger: WARNING: CPU: 0 PID: 5834 at net/tls/tls_strp.c:486 tls_strp_msg_load+0x72e/0xa80 net/tls/tls_strp.c:486 RIP: 0010:tls_strp_msg_load+0x72e/0xa80 net/tls/tls_strp.c:486 Call Trace: tls_rx_rec_wait+0x280/0xa60 net/tls/tls_sw.c:1363 tls_sw_recvmsg+0x85c/0x1c30 net/tls/tls_sw.c:2043 inet6_recvmsg+0x2c9/0x730 net/ipv6/af_inet6.c:678 sock_recvmsg_nosec net/socket.c:1023 [inline] sock_recvmsg+0x109/0x280 net/socket.c:1045 __sys_recvfrom+0x202/0x380 net/socket.c:2237 Fixes: 3c4d7559159b ("tls: kernel TLS support") Reported-by: syzbot+b4cd76826045a1eb93c1@syzkaller.appspotmail.com Signed-off-by: Jakub Kicinski Reviewed-by: Eric Dumazet Reviewed-by: Sabrina Dubroca Link: https://patch.msgid.link/20250404180334.3224206-1-kuba@kernel.org Signed-off-by: Paolo Abeni Signed-off-by: Sasha Levin --- net/tls/tls_main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c index 0a67b93a52ec..d7dea82bcf56 100644 --- a/net/tls/tls_main.c +++ b/net/tls/tls_main.c @@ -804,6 +804,11 @@ static int tls_setsockopt(struct sock *sk, int level, int optname, return do_tls_setsockopt(sk, optname, optval, optlen); } +static int tls_disconnect(struct sock *sk, int flags) +{ + return -EOPNOTSUPP; +} + struct tls_context *tls_ctx_create(struct sock *sk) { struct inet_connection_sock *icsk = inet_csk(sk); @@ -899,6 +904,7 @@ static void build_protos(struct proto prot[TLS_NUM_CONFIG][TLS_NUM_CONFIG], prot[TLS_BASE][TLS_BASE] = *base; prot[TLS_BASE][TLS_BASE].setsockopt = tls_setsockopt; prot[TLS_BASE][TLS_BASE].getsockopt = tls_getsockopt; + prot[TLS_BASE][TLS_BASE].disconnect = tls_disconnect; prot[TLS_BASE][TLS_BASE].close = tls_sk_proto_close; prot[TLS_SW][TLS_BASE] = prot[TLS_BASE][TLS_BASE]; From af4e364fb1c3b592d015e7a7c034540570ca831c Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Mon, 7 Apr 2025 12:33:41 +0530 Subject: [PATCH 011/606] octeontx2-pf: qos: fix VF root node parent queue index [ Upstream commit b7db94734e785e380b0db0f9295e07024f4d42a0 ] The current code configures the Physical Function (PF) root node at TL1 and the Virtual Function (VF) root node at TL2. This ensure at any given point of time PF traffic gets more priority. PF root node TL1 / \ TL2 TL2 VF root node / \ TL3 TL3 / \ TL4 TL4 / \ SMQ SMQ Due to a bug in the current code, the TL2 parent queue index on the VF interface is not being configured, leading to 'SMQ Flush' errors Fixes: 5e6808b4c68d ("octeontx2-pf: Add support for HTB offload") Signed-off-by: Hariprasad Kelam Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250407070341.2765426-1-hkelam@marvell.com Signed-off-by: Paolo Abeni Signed-off-by: Sasha Levin --- drivers/net/ethernet/marvell/octeontx2/nic/qos.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c index 4995a2d54d7d..37db19584c14 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c @@ -165,6 +165,11 @@ static void __otx2_qos_txschq_cfg(struct otx2_nic *pfvf, otx2_config_sched_shaping(pfvf, node, cfg, &num_regs); } else if (level == NIX_TXSCH_LVL_TL2) { + /* configure parent txschq */ + cfg->reg[num_regs] = NIX_AF_TL2X_PARENT(node->schq); + cfg->regval[num_regs] = (u64)hw->tx_link << 16; + num_regs++; + /* configure link cfg */ if (level == pfvf->qos.link_cfg_lvl) { cfg->reg[num_regs] = NIX_AF_TL3_TL2X_LINKX_CFG(node->schq, hw->tx_link); From abd07987f7fee97da3593558d29a4de989b27246 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Fri, 8 Dec 2023 16:28:41 -0300 Subject: [PATCH 012/606] rtnl: add helper to check if rtnl group has listeners [ Upstream commit c5e2a973448d958feb7881e4d875eac59fdeff3d ] As of today, rtnl code creates a new skb and unconditionally fills and broadcasts it to the relevant group. For most operations this is okay and doesn't waste resources in general. When operations are done without the rtnl_lock, as in tc-flower, such skb allocation, message fill and no-op broadcasting can happen in all cores of the system, which contributes to system pressure and wastes precious cpu cycles when no one will receive the built message. Introduce this helper so rtnetlink operations can simply check if someone is listening and then proceed if necessary. Reviewed-by: Jiri Pirko Reviewed-by: Simon Horman Signed-off-by: Jamal Hadi Salim Signed-off-by: Victor Nogueira Signed-off-by: Pedro Tammela Link: https://lore.kernel.org/r/20231208192847.714940-2-pctammela@mojatatu.com Signed-off-by: Jakub Kicinski Stable-dep-of: 369609fc6272 ("tc: Ensure we have enough buffer space when sending filter netlink notifications") Signed-off-by: Sasha Levin --- include/linux/rtnetlink.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 3d6cf306cd55..a7d757e96c55 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -130,4 +130,11 @@ extern int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, extern void rtnl_offload_xstats_notify(struct net_device *dev); +static inline int rtnl_has_listeners(const struct net *net, u32 group) +{ + struct sock *rtnl = net->rtnl; + + return netlink_has_listeners(rtnl, group); +} + #endif /* __LINUX_RTNETLINK_H */ From aa258dbf4598faad9d3248ec9363dcedd30c413e Mon Sep 17 00:00:00 2001 From: Victor Nogueira Date: Fri, 8 Dec 2023 16:28:42 -0300 Subject: [PATCH 013/606] rtnl: add helper to check if a notification is needed [ Upstream commit 8439109b76a3c405808383bf9dd532fc4b9c2dbd ] Building on the rtnl_has_listeners helper, add the rtnl_notify_needed helper to check if we can bail out early in the notification routines. Reviewed-by: Jiri Pirko Reviewed-by: Simon Horman Signed-off-by: Victor Nogueira Signed-off-by: Pedro Tammela Link: https://lore.kernel.org/r/20231208192847.714940-3-pctammela@mojatatu.com Signed-off-by: Jakub Kicinski Stable-dep-of: 369609fc6272 ("tc: Ensure we have enough buffer space when sending filter netlink notifications") Signed-off-by: Sasha Levin --- include/linux/rtnetlink.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index a7d757e96c55..0cbbbded0331 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -137,4 +137,19 @@ static inline int rtnl_has_listeners(const struct net *net, u32 group) return netlink_has_listeners(rtnl, group); } +/** + * rtnl_notify_needed - check if notification is needed + * @net: Pointer to the net namespace + * @nlflags: netlink ingress message flags + * @group: rtnl group + * + * Based on the ingress message flags and rtnl group, returns true + * if a notification is needed, false otherwise. + */ +static inline bool +rtnl_notify_needed(const struct net *net, u16 nlflags, u32 group) +{ + return (nlflags & NLM_F_ECHO) || rtnl_has_listeners(net, group); +} + #endif /* __LINUX_RTNETLINK_H */ From 28f2cd143b5b2b35b83669d892b15871f2a57efe Mon Sep 17 00:00:00 2001 From: Pedro Tammela Date: Fri, 8 Dec 2023 16:28:47 -0300 Subject: [PATCH 014/606] net/sched: cls_api: conditional notification of events [ Upstream commit 93775590b1ee98bf2976b1f4a1ed24e9ff76170f ] As of today tc-filter/chain events are unconditionally built and sent to RTNLGRP_TC. As with the introduction of rtnl_notify_needed we can check before-hand if they are really needed. This will help to alleviate system pressure when filters are concurrently added without the rtnl lock as in tc-flower. Reviewed-by: Jiri Pirko Reviewed-by: Simon Horman Signed-off-by: Pedro Tammela Link: https://lore.kernel.org/r/20231208192847.714940-8-pctammela@mojatatu.com Signed-off-by: Jakub Kicinski Stable-dep-of: 369609fc6272 ("tc: Ensure we have enough buffer space when sending filter netlink notifications") Signed-off-by: Sasha Levin --- net/sched/cls_api.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 96c39e9a873c..a0eb389b4fb4 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -2038,6 +2038,9 @@ static int tfilter_notify(struct net *net, struct sk_buff *oskb, u32 portid = oskb ? NETLINK_CB(oskb).portid : 0; int err = 0; + if (!unicast && !rtnl_notify_needed(net, n->nlmsg_flags, RTNLGRP_TC)) + return 0; + skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); if (!skb) return -ENOBUFS; @@ -2067,6 +2070,9 @@ static int tfilter_del_notify(struct net *net, struct sk_buff *oskb, u32 portid = oskb ? NETLINK_CB(oskb).portid : 0; int err; + if (!rtnl_notify_needed(net, n->nlmsg_flags, RTNLGRP_TC)) + return tp->ops->delete(tp, fh, last, rtnl_held, extack); + skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); if (!skb) return -ENOBUFS; @@ -2891,6 +2897,9 @@ static int tc_chain_notify(struct tcf_chain *chain, struct sk_buff *oskb, struct sk_buff *skb; int err = 0; + if (!unicast && !rtnl_notify_needed(net, flags, RTNLGRP_TC)) + return 0; + skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); if (!skb) return -ENOBUFS; @@ -2920,6 +2929,9 @@ static int tc_chain_notify_delete(const struct tcf_proto_ops *tmplt_ops, struct net *net = block->net; struct sk_buff *skb; + if (!rtnl_notify_needed(net, flags, RTNLGRP_TC)) + return 0; + skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); if (!skb) return -ENOBUFS; From 8b158a0d19eda97eafef24b1f689f0eb43af16a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= Date: Mon, 7 Apr 2025 12:55:34 +0200 Subject: [PATCH 015/606] tc: Ensure we have enough buffer space when sending filter netlink notifications MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 369609fc6272c2f6ad666ba4fd913f3baf32908f ] The tfilter_notify() and tfilter_del_notify() functions assume that NLMSG_GOODSIZE is always enough to dump the filter chain. This is not always the case, which can lead to silent notify failures (because the return code of tfilter_notify() is not always checked). In particular, this can lead to NLM_F_ECHO not being honoured even though an action succeeds, which forces userspace to create workarounds[0]. Fix this by increasing the message size if dumping the filter chain into the allocated skb fails. Use the size of the incoming skb as a size hint if set, so we can start at a larger value when appropriate. To trigger this, run the following commands: # ip link add type veth # tc qdisc replace dev veth0 root handle 1: fq_codel # tc -echo filter add dev veth0 parent 1: u32 match u32 0 0 $(for i in $(seq 32); do echo action pedit munge ip dport set 22; done) Before this fix, tc just returns: Not a filter(cmd 2) After the fix, we get the correct echo: added filter dev veth0 parent 1: protocol all pref 49152 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 terminal flowid not_in_hw match 00000000/00000000 at 0 action order 1: pedit action pass keys 1 index 1 ref 1 bind 1 key #0 at 20: val 00000016 mask ffff0000 [repeated 32 times] [0] https://github.com/openvswitch/ovs/commit/106ef21860c935e5e0017a88bf42b94025c4e511 Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reported-by: Frode Nordahl Closes: https://bugs.launchpad.net/ubuntu/+source/openvswitch/+bug/2018500 Signed-off-by: Toke Høiland-Jørgensen Reviewed-by: Jiri Pirko Link: https://patch.msgid.link/20250407105542.16601-1-toke@redhat.com Signed-off-by: Paolo Abeni Signed-off-by: Sasha Levin --- net/sched/cls_api.c | 66 ++++++++++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index a0eb389b4fb4..7245f39d1e65 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -1977,6 +1977,7 @@ static int tcf_fill_node(struct net *net, struct sk_buff *skb, struct tcmsg *tcm; struct nlmsghdr *nlh; unsigned char *b = skb_tail_pointer(skb); + int ret = -EMSGSIZE; nlh = nlmsg_put(skb, portid, seq, event, sizeof(*tcm), flags); if (!nlh) @@ -2021,11 +2022,45 @@ static int tcf_fill_node(struct net *net, struct sk_buff *skb, return skb->len; +cls_op_not_supp: + ret = -EOPNOTSUPP; out_nlmsg_trim: nla_put_failure: -cls_op_not_supp: nlmsg_trim(skb, b); - return -1; + return ret; +} + +static struct sk_buff *tfilter_notify_prep(struct net *net, + struct sk_buff *oskb, + struct nlmsghdr *n, + struct tcf_proto *tp, + struct tcf_block *block, + struct Qdisc *q, u32 parent, + void *fh, int event, + u32 portid, bool rtnl_held, + struct netlink_ext_ack *extack) +{ + unsigned int size = oskb ? max(NLMSG_GOODSIZE, oskb->len) : NLMSG_GOODSIZE; + struct sk_buff *skb; + int ret; + +retry: + skb = alloc_skb(size, GFP_KERNEL); + if (!skb) + return ERR_PTR(-ENOBUFS); + + ret = tcf_fill_node(net, skb, tp, block, q, parent, fh, portid, + n->nlmsg_seq, n->nlmsg_flags, event, false, + rtnl_held, extack); + if (ret <= 0) { + kfree_skb(skb); + if (ret == -EMSGSIZE) { + size += NLMSG_GOODSIZE; + goto retry; + } + return ERR_PTR(-EINVAL); + } + return skb; } static int tfilter_notify(struct net *net, struct sk_buff *oskb, @@ -2041,16 +2076,10 @@ static int tfilter_notify(struct net *net, struct sk_buff *oskb, if (!unicast && !rtnl_notify_needed(net, n->nlmsg_flags, RTNLGRP_TC)) return 0; - skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); - if (!skb) - return -ENOBUFS; - - if (tcf_fill_node(net, skb, tp, block, q, parent, fh, portid, - n->nlmsg_seq, n->nlmsg_flags, event, - false, rtnl_held, extack) <= 0) { - kfree_skb(skb); - return -EINVAL; - } + skb = tfilter_notify_prep(net, oskb, n, tp, block, q, parent, fh, event, + portid, rtnl_held, extack); + if (IS_ERR(skb)) + return PTR_ERR(skb); if (unicast) err = rtnl_unicast(skb, net, portid); @@ -2073,16 +2102,11 @@ static int tfilter_del_notify(struct net *net, struct sk_buff *oskb, if (!rtnl_notify_needed(net, n->nlmsg_flags, RTNLGRP_TC)) return tp->ops->delete(tp, fh, last, rtnl_held, extack); - skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); - if (!skb) - return -ENOBUFS; - - if (tcf_fill_node(net, skb, tp, block, q, parent, fh, portid, - n->nlmsg_seq, n->nlmsg_flags, RTM_DELTFILTER, - false, rtnl_held, extack) <= 0) { + skb = tfilter_notify_prep(net, oskb, n, tp, block, q, parent, fh, + RTM_DELTFILTER, portid, rtnl_held, extack); + if (IS_ERR(skb)) { NL_SET_ERR_MSG(extack, "Failed to build del event notification"); - kfree_skb(skb); - return -EINVAL; + return PTR_ERR(skb); } err = tp->ops->delete(tp, fh, last, rtnl_held, extack); From c5ed0eaddcbda56079091fc3876b140a6e70a548 Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Mon, 7 Apr 2025 15:05:10 +0200 Subject: [PATCH 016/606] net: ethtool: Don't call .cleanup_data when prepare_data fails [ Upstream commit 4f038a6a02d20859a3479293cbf172b0f14cbdd6 ] There's a consistent pattern where the .cleanup_data() callback is called when .prepare_data() fails, when it should really be called to clean after a successful .prepare_data() as per the documentation. Rewrite the error-handling paths to make sure we don't cleanup un-prepared data. Fixes: c781ff12a2f3 ("ethtool: Allow network drivers to dump arbitrary EEPROM data") Reviewed-by: Kory Maincent Reviewed-by: Simon Horman Reviewed-by: Michal Kubecek Signed-off-by: Maxime Chevallier Link: https://patch.msgid.link/20250407130511.75621-1-maxime.chevallier@bootlin.com Signed-off-by: Paolo Abeni Signed-off-by: Sasha Levin --- net/ethtool/netlink.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index c1ad63bee8ea..7a9d8fe78ae9 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -402,7 +402,7 @@ static int ethnl_default_doit(struct sk_buff *skb, struct genl_info *info) ret = ops->prepare_data(req_info, reply_data, info); rtnl_unlock(); if (ret < 0) - goto err_cleanup; + goto err_dev; ret = ops->reply_size(req_info, reply_data); if (ret < 0) goto err_cleanup; @@ -460,7 +460,7 @@ static int ethnl_default_dump_one(struct sk_buff *skb, struct net_device *dev, ret = ctx->ops->prepare_data(ctx->req_info, ctx->reply_data, info); rtnl_unlock(); if (ret < 0) - goto out; + goto out_cancel; ret = ethnl_fill_reply_header(skb, dev, ctx->ops->hdr_attr); if (ret < 0) goto out; @@ -469,6 +469,7 @@ static int ethnl_default_dump_one(struct sk_buff *skb, struct net_device *dev, out: if (ctx->ops->cleanup_data) ctx->ops->cleanup_data(ctx->reply_data); +out_cancel: ctx->reply_data->dev = NULL; if (ret < 0) genlmsg_cancel(skb, ehdr); @@ -676,7 +677,7 @@ static void ethnl_default_notify(struct net_device *dev, unsigned int cmd, ethnl_init_reply_data(reply_data, ops, dev); ret = ops->prepare_data(req_info, reply_data, &info); if (ret < 0) - goto err_cleanup; + goto err_rep; ret = ops->reply_size(req_info, reply_data); if (ret < 0) goto err_cleanup; @@ -711,6 +712,7 @@ err_skb: err_cleanup: if (ops->cleanup_data) ops->cleanup_data(reply_data); +err_rep: kfree(reply_data); kfree(req_info); return; From eceb15bbf6ed3091ba5f037912e215d0b33a654e Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 8 Apr 2025 09:34:08 +0200 Subject: [PATCH 017/606] drm/tests: modeset: Fix drm_display_mode memory leak [ Upstream commit dacafdcc7789cfeb0f0552716db56f210238225d ] drm_mode_find_dmt() returns a drm_display_mode that needs to be destroyed later one. The drm_test_pick_cmdline_res_1920_1080_60() test never does however, which leads to a memory leak. Let's make sure it's freed. Reported-by: Philipp Stanner Closes: https://lore.kernel.org/dri-devel/a7655158a6367ac46194d57f4b7433ef0772a73e.camel@mailbox.org/ Fixes: 8fc0380f6ba7 ("drm/client: Add some tests for drm_connector_pick_cmdline_mode()") Reviewed-by: Thomas Zimmermann Link: https://lore.kernel.org/r/20250408-drm-kunit-drm-display-mode-memleak-v1-2-996305a2e75a@kernel.org Signed-off-by: Maxime Ripard Signed-off-by: Sasha Levin --- drivers/gpu/drm/tests/drm_client_modeset_test.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/tests/drm_client_modeset_test.c b/drivers/gpu/drm/tests/drm_client_modeset_test.c index 7516f6cb36e4..3e9518d7b8b7 100644 --- a/drivers/gpu/drm/tests/drm_client_modeset_test.c +++ b/drivers/gpu/drm/tests/drm_client_modeset_test.c @@ -95,6 +95,9 @@ static void drm_test_pick_cmdline_res_1920_1080_60(struct kunit *test) expected_mode = drm_mode_find_dmt(priv->drm, 1920, 1080, 60, false); KUNIT_ASSERT_NOT_NULL(test, expected_mode); + ret = drm_kunit_add_mode_destroy_action(test, expected_mode); + KUNIT_ASSERT_EQ(test, ret, 0); + KUNIT_ASSERT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline, connector, From a31fd0eaf75e0e136bf9f16bbb379e10640fc4c8 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 22 Feb 2024 19:13:48 +0100 Subject: [PATCH 018/606] drm/tests: helpers: Add atomic helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 66671944e17644804cb0886489e1b8fde924e9b9 ] The mock device we were creating was missing any of the driver-wide helpers. That was fine before since we weren't testing the atomic state path, but we're going to start, so let's use the default implementations. Reviewed-by: Maíra Canal Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20240222-kms-hdmi-connector-state-v7-2-8f4af575fce2@kernel.org Stable-dep-of: 70f29ca3117a ("drm/tests: cmdline: Fix drm_display_mode memory leak") Signed-off-by: Sasha Levin --- drivers/gpu/drm/tests/drm_kunit_helpers.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c index bccb33b900f3..272a3ba46d60 100644 --- a/drivers/gpu/drm/tests/drm_kunit_helpers.c +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include #include #include @@ -13,6 +14,8 @@ #define KUNIT_DEVICE_NAME "drm-kunit-mock-device" static const struct drm_mode_config_funcs drm_mode_config_funcs = { + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, }; static int fake_probe(struct platform_device *pdev) From af1dccab386f46ec8da07cf80a794bf19ae3cc96 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 22 Feb 2024 19:13:49 +0100 Subject: [PATCH 019/606] drm/tests: Add helper to create mock plane MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 7a48da0febd5113d9de6f51592a09825ebd8415c ] We're going to need a full-blown, functional, KMS device to test more components of the atomic modesetting infrastructure. Let's add a new helper to create a dumb, mocked, primary plane. By default, it will create a linear XRGB8888 plane, using the default helpers. Reviewed-by: Maíra Canal Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20240222-kms-hdmi-connector-state-v7-3-8f4af575fce2@kernel.org Stable-dep-of: 70f29ca3117a ("drm/tests: cmdline: Fix drm_display_mode memory leak") Signed-off-by: Sasha Levin --- drivers/gpu/drm/tests/drm_kunit_helpers.c | 85 +++++++++++++++++++++++ include/drm/drm_kunit_helpers.h | 11 +++ 2 files changed, 96 insertions(+) diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c index 272a3ba46d60..e0778a7ec260 100644 --- a/drivers/gpu/drm/tests/drm_kunit_helpers.c +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -236,5 +237,89 @@ drm_kunit_helper_atomic_state_alloc(struct kunit *test, } EXPORT_SYMBOL_GPL(drm_kunit_helper_atomic_state_alloc); +static const uint32_t default_plane_formats[] = { + DRM_FORMAT_XRGB8888, +}; + +static const uint64_t default_plane_modifiers[] = { + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID +}; + +static const struct drm_plane_helper_funcs default_plane_helper_funcs = { +}; + +static const struct drm_plane_funcs default_plane_funcs = { + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .reset = drm_atomic_helper_plane_reset, +}; + +/** + * drm_kunit_helper_create_primary_plane - Creates a mock primary plane for a KUnit test + * @test: The test context object + * @drm: The device to alloc the plane for + * @funcs: Callbacks for the new plane. Optional. + * @helper_funcs: Helpers callbacks for the new plane. Optional. + * @formats: array of supported formats (DRM_FORMAT\_\*). Optional. + * @num_formats: number of elements in @formats + * @modifiers: array of struct drm_format modifiers terminated by + * DRM_FORMAT_MOD_INVALID. Optional. + * + * This allocates and initializes a mock struct &drm_plane meant to be + * part of a mock device for a KUnit test. + * + * Resources will be cleaned up automatically. + * + * @funcs will default to the default helpers implementations. + * @helper_funcs will default to an empty implementation. @formats will + * default to XRGB8888 only. @modifiers will default to a linear + * modifier only. + * + * Returns: + * A pointer to the new plane, or an ERR_PTR() otherwise. + */ +struct drm_plane * +drm_kunit_helper_create_primary_plane(struct kunit *test, + struct drm_device *drm, + const struct drm_plane_funcs *funcs, + const struct drm_plane_helper_funcs *helper_funcs, + const uint32_t *formats, + unsigned int num_formats, + const uint64_t *modifiers) +{ + struct drm_plane *plane; + + if (!funcs) + funcs = &default_plane_funcs; + + if (!helper_funcs) + helper_funcs = &default_plane_helper_funcs; + + if (!formats || !num_formats) { + formats = default_plane_formats; + num_formats = ARRAY_SIZE(default_plane_formats); + } + + if (!modifiers) + modifiers = default_plane_modifiers; + + plane = __drmm_universal_plane_alloc(drm, + sizeof(struct drm_plane), 0, + 0, + funcs, + formats, + num_formats, + default_plane_modifiers, + DRM_PLANE_TYPE_PRIMARY, + NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane); + + drm_plane_helper_add(plane, helper_funcs); + + return plane; +} +EXPORT_SYMBOL_GPL(drm_kunit_helper_create_primary_plane); + MODULE_AUTHOR("Maxime Ripard "); MODULE_LICENSE("GPL"); diff --git a/include/drm/drm_kunit_helpers.h b/include/drm/drm_kunit_helpers.h index 3ae19892229d..38667d624aa8 100644 --- a/include/drm/drm_kunit_helpers.h +++ b/include/drm/drm_kunit_helpers.h @@ -10,6 +10,8 @@ #include struct drm_device; +struct drm_plane_funcs; +struct drm_plane_helper_funcs; struct kunit; struct device *drm_kunit_helper_alloc_device(struct kunit *test); @@ -99,4 +101,13 @@ drm_kunit_helper_atomic_state_alloc(struct kunit *test, struct drm_device *drm, struct drm_modeset_acquire_ctx *ctx); +struct drm_plane * +drm_kunit_helper_create_primary_plane(struct kunit *test, + struct drm_device *drm, + const struct drm_plane_funcs *funcs, + const struct drm_plane_helper_funcs *helper_funcs, + const uint32_t *formats, + unsigned int num_formats, + const uint64_t *modifiers); + #endif // DRM_KUNIT_HELPERS_H_ From 60f481fdf1e75187975ba86945f0be68eb22c511 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 22 Feb 2024 19:13:50 +0100 Subject: [PATCH 020/606] drm/tests: Add helper to create mock crtc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 51f90720381dea79208513d059e0eb426dee511e ] We're going to need a full-blown, functional, KMS device to test more components of the atomic modesetting infrastructure. Let's add a new helper to create a dumb, mocked, CRTC. By default it will create a CRTC relying only on the default helpers, but drivers are free to deviate from that. Reviewed-by: Maíra Canal Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20240222-kms-hdmi-connector-state-v7-4-8f4af575fce2@kernel.org Stable-dep-of: 70f29ca3117a ("drm/tests: cmdline: Fix drm_display_mode memory leak") Signed-off-by: Sasha Levin --- drivers/gpu/drm/tests/drm_kunit_helpers.c | 62 +++++++++++++++++++++++ include/drm/drm_kunit_helpers.h | 10 ++++ 2 files changed, 72 insertions(+) diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c index e0778a7ec260..ca513235b5e2 100644 --- a/drivers/gpu/drm/tests/drm_kunit_helpers.c +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c @@ -321,5 +321,67 @@ drm_kunit_helper_create_primary_plane(struct kunit *test, } EXPORT_SYMBOL_GPL(drm_kunit_helper_create_primary_plane); +static const struct drm_crtc_helper_funcs default_crtc_helper_funcs = { +}; + +static const struct drm_crtc_funcs default_crtc_funcs = { + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .reset = drm_atomic_helper_crtc_reset, +}; + +/** + * drm_kunit_helper_create_crtc - Creates a mock CRTC for a KUnit test + * @test: The test context object + * @drm: The device to alloc the plane for + * @primary: Primary plane for CRTC + * @cursor: Cursor plane for CRTC. Optional. + * @funcs: Callbacks for the new plane. Optional. + * @helper_funcs: Helpers callbacks for the new plane. Optional. + * + * This allocates and initializes a mock struct &drm_crtc meant to be + * part of a mock device for a KUnit test. + * + * Resources will be cleaned up automatically. + * + * @funcs will default to the default helpers implementations. + * @helper_funcs will default to an empty implementation. + * + * Returns: + * A pointer to the new CRTC, or an ERR_PTR() otherwise. + */ +struct drm_crtc * +drm_kunit_helper_create_crtc(struct kunit *test, + struct drm_device *drm, + struct drm_plane *primary, + struct drm_plane *cursor, + const struct drm_crtc_funcs *funcs, + const struct drm_crtc_helper_funcs *helper_funcs) +{ + struct drm_crtc *crtc; + int ret; + + if (!funcs) + funcs = &default_crtc_funcs; + + if (!helper_funcs) + helper_funcs = &default_crtc_helper_funcs; + + crtc = drmm_kzalloc(drm, sizeof(*crtc), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, crtc); + + ret = drmm_crtc_init_with_planes(drm, crtc, + primary, + cursor, + funcs, + NULL); + KUNIT_ASSERT_EQ(test, ret, 0); + + drm_crtc_helper_add(crtc, helper_funcs); + + return crtc; +} +EXPORT_SYMBOL_GPL(drm_kunit_helper_create_crtc); + MODULE_AUTHOR("Maxime Ripard "); MODULE_LICENSE("GPL"); diff --git a/include/drm/drm_kunit_helpers.h b/include/drm/drm_kunit_helpers.h index 38667d624aa8..6e99627edf45 100644 --- a/include/drm/drm_kunit_helpers.h +++ b/include/drm/drm_kunit_helpers.h @@ -9,6 +9,8 @@ #include +struct drm_crtc_funcs; +struct drm_crtc_helper_funcs; struct drm_device; struct drm_plane_funcs; struct drm_plane_helper_funcs; @@ -110,4 +112,12 @@ drm_kunit_helper_create_primary_plane(struct kunit *test, unsigned int num_formats, const uint64_t *modifiers); +struct drm_crtc * +drm_kunit_helper_create_crtc(struct kunit *test, + struct drm_device *drm, + struct drm_plane *primary, + struct drm_plane *cursor, + const struct drm_crtc_funcs *funcs, + const struct drm_crtc_helper_funcs *helper_funcs); + #endif // DRM_KUNIT_HELPERS_H_ From 85926abafad54ce1da8683cc32a401b0714246a8 Mon Sep 17 00:00:00 2001 From: Jinjie Ruan Date: Wed, 30 Oct 2024 10:35:02 +0800 Subject: [PATCH 021/606] drm/tests: helpers: Add helper for drm_display_mode_from_cea_vic() [ Upstream commit caa714f86699bcfb01aa2d698db12d91af7d0d81 ] As Maxime suggested, add a new helper drm_kunit_display_mode_from_cea_vic(), it can replace the direct call of drm_display_mode_from_cea_vic(), and it will help solving the `mode` memory leaks. Acked-by: Maxime Ripard Suggested-by: Maxime Ripard Signed-off-by: Jinjie Ruan Link: https://patchwork.freedesktop.org/patch/msgid/20241030023504.530425-2-ruanjinjie@huawei.com Signed-off-by: Maxime Ripard Stable-dep-of: 70f29ca3117a ("drm/tests: cmdline: Fix drm_display_mode memory leak") Signed-off-by: Sasha Levin --- drivers/gpu/drm/tests/drm_kunit_helpers.c | 42 +++++++++++++++++++++++ include/drm/drm_kunit_helpers.h | 4 +++ 2 files changed, 46 insertions(+) diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c index ca513235b5e2..9a35b2cf6a03 100644 --- a/drivers/gpu/drm/tests/drm_kunit_helpers.c +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -383,5 +384,46 @@ drm_kunit_helper_create_crtc(struct kunit *test, } EXPORT_SYMBOL_GPL(drm_kunit_helper_create_crtc); +static void kunit_action_drm_mode_destroy(void *ptr) +{ + struct drm_display_mode *mode = ptr; + + drm_mode_destroy(NULL, mode); +} + +/** + * drm_kunit_display_mode_from_cea_vic() - return a mode for CEA VIC + for a KUnit test + * @test: The test context object + * @dev: DRM device + * @video_code: CEA VIC of the mode + * + * Creates a new mode matching the specified CEA VIC for a KUnit test. + * + * Resources will be cleaned up automatically. + * + * Returns: A new drm_display_mode on success or NULL on failure + */ +struct drm_display_mode * +drm_kunit_display_mode_from_cea_vic(struct kunit *test, struct drm_device *dev, + u8 video_code) +{ + struct drm_display_mode *mode; + int ret; + + mode = drm_display_mode_from_cea_vic(dev, video_code); + if (!mode) + return NULL; + + ret = kunit_add_action_or_reset(test, + kunit_action_drm_mode_destroy, + mode); + if (ret) + return NULL; + + return mode; +} +EXPORT_SYMBOL_GPL(drm_kunit_display_mode_from_cea_vic); + MODULE_AUTHOR("Maxime Ripard "); MODULE_LICENSE("GPL"); diff --git a/include/drm/drm_kunit_helpers.h b/include/drm/drm_kunit_helpers.h index 6e99627edf45..3e5f4a23685e 100644 --- a/include/drm/drm_kunit_helpers.h +++ b/include/drm/drm_kunit_helpers.h @@ -120,4 +120,8 @@ drm_kunit_helper_create_crtc(struct kunit *test, const struct drm_crtc_funcs *funcs, const struct drm_crtc_helper_funcs *helper_funcs); +struct drm_display_mode * +drm_kunit_display_mode_from_cea_vic(struct kunit *test, struct drm_device *dev, + u8 video_code); + #endif // DRM_KUNIT_HELPERS_H_ From 0c6550ab45c3c11f37d1fc1bc2d187f50467f0aa Mon Sep 17 00:00:00 2001 From: Yu-Chun Lin Date: Sun, 5 Jan 2025 00:51:33 +0800 Subject: [PATCH 022/606] drm/tests: helpers: Fix compiler warning [ Upstream commit b9097e4c8bf3934e4e07e6f9b88741957fef351e ] Delete one line break to make the format correct, resolving the following warning during a W=1 build: >> drivers/gpu/drm/tests/drm_kunit_helpers.c:324: warning: bad line: for a KUnit test Fixes: caa714f86699 ("drm/tests: helpers: Add helper for drm_display_mode_from_cea_vic()") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202501032001.O6WY1VCW-lkp@intel.com/ Reviewed-by: Kuan-Wei Chiu Tested-by: Kuan-Wei Chiu Reviewed-by: Dmitry Baryshkov Signed-off-by: Yu-Chun Lin Link: https://patchwork.freedesktop.org/patch/msgid/20250104165134.1695864-1-eleanor15x@gmail.com Signed-off-by: Maxime Ripard Stable-dep-of: 70f29ca3117a ("drm/tests: cmdline: Fix drm_display_mode memory leak") Signed-off-by: Sasha Levin --- drivers/gpu/drm/tests/drm_kunit_helpers.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c index 9a35b2cf6a03..12d58353a54e 100644 --- a/drivers/gpu/drm/tests/drm_kunit_helpers.c +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c @@ -392,8 +392,7 @@ static void kunit_action_drm_mode_destroy(void *ptr) } /** - * drm_kunit_display_mode_from_cea_vic() - return a mode for CEA VIC - for a KUnit test + * drm_kunit_display_mode_from_cea_vic() - return a mode for CEA VIC for a KUnit test * @test: The test context object * @dev: DRM device * @video_code: CEA VIC of the mode From 742a084c6a9ea6f02c59438762bb1715d24f3833 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 8 Apr 2025 09:34:07 +0200 Subject: [PATCH 023/606] drm/tests: helpers: Create kunit helper to destroy a drm_display_mode [ Upstream commit 13c1d5f3a7fa7b55a26e73bb9e95342374a489b2 ] A number of test suites call functions that expect the returned drm_display_mode to be destroyed eventually. However, none of the tests called drm_mode_destroy, which results in a memory leak. Since drm_mode_destroy takes two pointers as argument, we can't use a kunit wrapper. Let's just create a helper every test suite can use. Reviewed-by: Thomas Zimmermann Link: https://lore.kernel.org/r/20250408-drm-kunit-drm-display-mode-memleak-v1-1-996305a2e75a@kernel.org Signed-off-by: Maxime Ripard Stable-dep-of: 70f29ca3117a ("drm/tests: cmdline: Fix drm_display_mode memory leak") Signed-off-by: Sasha Levin --- drivers/gpu/drm/tests/drm_kunit_helpers.c | 22 ++++++++++++++++++++++ include/drm/drm_kunit_helpers.h | 3 +++ 2 files changed, 25 insertions(+) diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c index 12d58353a54e..04d98f81c522 100644 --- a/drivers/gpu/drm/tests/drm_kunit_helpers.c +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c @@ -391,6 +391,28 @@ static void kunit_action_drm_mode_destroy(void *ptr) drm_mode_destroy(NULL, mode); } +/** + * drm_kunit_add_mode_destroy_action() - Add a drm_destroy_mode kunit action + * @test: The test context object + * @mode: The drm_display_mode to destroy eventually + * + * Registers a kunit action that will destroy the drm_display_mode at + * the end of the test. + * + * If an error occurs, the drm_display_mode will be destroyed. + * + * Returns: + * 0 on success, an error code otherwise. + */ +int drm_kunit_add_mode_destroy_action(struct kunit *test, + struct drm_display_mode *mode) +{ + return kunit_add_action_or_reset(test, + kunit_action_drm_mode_destroy, + mode); +} +EXPORT_SYMBOL_GPL(drm_kunit_add_mode_destroy_action); + /** * drm_kunit_display_mode_from_cea_vic() - return a mode for CEA VIC for a KUnit test * @test: The test context object diff --git a/include/drm/drm_kunit_helpers.h b/include/drm/drm_kunit_helpers.h index 3e5f4a23685e..07e9a451262b 100644 --- a/include/drm/drm_kunit_helpers.h +++ b/include/drm/drm_kunit_helpers.h @@ -120,6 +120,9 @@ drm_kunit_helper_create_crtc(struct kunit *test, const struct drm_crtc_funcs *funcs, const struct drm_crtc_helper_funcs *helper_funcs); +int drm_kunit_add_mode_destroy_action(struct kunit *test, + struct drm_display_mode *mode); + struct drm_display_mode * drm_kunit_display_mode_from_cea_vic(struct kunit *test, struct drm_device *dev, u8 video_code); From cea2c8ace75c3ab2a33d71f523bc69e87a2301f7 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 8 Apr 2025 09:34:10 +0200 Subject: [PATCH 024/606] drm/tests: cmdline: Fix drm_display_mode memory leak [ Upstream commit 70f29ca3117a8796cd6bde7612a3ded96d0f2dde ] drm_analog_tv_mode() and its variants return a drm_display_mode that needs to be destroyed later one. The drm_test_cmdline_tv_options() test never does however, which leads to a memory leak. Let's make sure it's freed. Reported-by: Philipp Stanner Closes: https://lore.kernel.org/dri-devel/a7655158a6367ac46194d57f4b7433ef0772a73e.camel@mailbox.org/ Fixes: e691c9992ae1 ("drm/modes: Introduce the tv_mode property as a command-line option") Reviewed-by: Thomas Zimmermann Link: https://lore.kernel.org/r/20250408-drm-kunit-drm-display-mode-memleak-v1-4-996305a2e75a@kernel.org Signed-off-by: Maxime Ripard Signed-off-by: Sasha Levin --- drivers/gpu/drm/tests/drm_cmdline_parser_test.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/tests/drm_cmdline_parser_test.c b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c index 88f7f518ffb3..05dd5cc3b604 100644 --- a/drivers/gpu/drm/tests/drm_cmdline_parser_test.c +++ b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c @@ -7,6 +7,7 @@ #include #include +#include #include static const struct drm_connector no_connector = {}; @@ -955,8 +956,15 @@ struct drm_cmdline_tv_option_test { static void drm_test_cmdline_tv_options(struct kunit *test) { const struct drm_cmdline_tv_option_test *params = test->param_value; - const struct drm_display_mode *expected_mode = params->mode_fn(NULL); + struct drm_display_mode *expected_mode; struct drm_cmdline_mode mode = { }; + int ret; + + expected_mode = params->mode_fn(NULL); + KUNIT_ASSERT_NOT_NULL(test, expected_mode); + + ret = drm_kunit_add_mode_destroy_action(test, expected_mode); + KUNIT_ASSERT_EQ(test, ret, 0); KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(params->cmdline, &no_connector, &mode)); From 718a892e2def7d601f1c27873677e065b08e738e Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 8 Apr 2025 09:34:11 +0200 Subject: [PATCH 025/606] drm/tests: modes: Fix drm_display_mode memory leak [ Upstream commit d34146340f95cd9bf06d4ce71cca72127dc0b7cd ] drm_analog_tv_mode() and its variants return a drm_display_mode that needs to be destroyed later one. The drm_modes_analog_tv tests never do however, which leads to a memory leak. Let's make sure it's freed. Reported-by: Philipp Stanner Closes: https://lore.kernel.org/dri-devel/a7655158a6367ac46194d57f4b7433ef0772a73e.camel@mailbox.org/ Fixes: 4fcd238560ee ("drm/modes: Add a function to generate analog display modes") Reviewed-by: Thomas Zimmermann Link: https://lore.kernel.org/r/20250408-drm-kunit-drm-display-mode-memleak-v1-5-996305a2e75a@kernel.org Signed-off-by: Maxime Ripard Signed-off-by: Sasha Levin --- drivers/gpu/drm/tests/drm_modes_test.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/gpu/drm/tests/drm_modes_test.c b/drivers/gpu/drm/tests/drm_modes_test.c index 1e9f63fbfead..e23067252d18 100644 --- a/drivers/gpu/drm/tests/drm_modes_test.c +++ b/drivers/gpu/drm/tests/drm_modes_test.c @@ -40,6 +40,7 @@ static void drm_test_modes_analog_tv_ntsc_480i(struct kunit *test) { struct drm_test_modes_priv *priv = test->priv; struct drm_display_mode *mode; + int ret; mode = drm_analog_tv_mode(priv->drm, DRM_MODE_TV_MODE_NTSC, @@ -47,6 +48,9 @@ static void drm_test_modes_analog_tv_ntsc_480i(struct kunit *test) true); KUNIT_ASSERT_NOT_NULL(test, mode); + ret = drm_kunit_add_mode_destroy_action(test, mode); + KUNIT_ASSERT_EQ(test, ret, 0); + KUNIT_EXPECT_EQ(test, drm_mode_vrefresh(mode), 60); KUNIT_EXPECT_EQ(test, mode->hdisplay, 720); @@ -70,6 +74,7 @@ static void drm_test_modes_analog_tv_ntsc_480i_inlined(struct kunit *test) { struct drm_test_modes_priv *priv = test->priv; struct drm_display_mode *expected, *mode; + int ret; expected = drm_analog_tv_mode(priv->drm, DRM_MODE_TV_MODE_NTSC, @@ -77,9 +82,15 @@ static void drm_test_modes_analog_tv_ntsc_480i_inlined(struct kunit *test) true); KUNIT_ASSERT_NOT_NULL(test, expected); + ret = drm_kunit_add_mode_destroy_action(test, expected); + KUNIT_ASSERT_EQ(test, ret, 0); + mode = drm_mode_analog_ntsc_480i(priv->drm); KUNIT_ASSERT_NOT_NULL(test, mode); + ret = drm_kunit_add_mode_destroy_action(test, mode); + KUNIT_ASSERT_EQ(test, ret, 0); + KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected, mode)); } @@ -87,6 +98,7 @@ static void drm_test_modes_analog_tv_pal_576i(struct kunit *test) { struct drm_test_modes_priv *priv = test->priv; struct drm_display_mode *mode; + int ret; mode = drm_analog_tv_mode(priv->drm, DRM_MODE_TV_MODE_PAL, @@ -94,6 +106,9 @@ static void drm_test_modes_analog_tv_pal_576i(struct kunit *test) true); KUNIT_ASSERT_NOT_NULL(test, mode); + ret = drm_kunit_add_mode_destroy_action(test, mode); + KUNIT_ASSERT_EQ(test, ret, 0); + KUNIT_EXPECT_EQ(test, drm_mode_vrefresh(mode), 50); KUNIT_EXPECT_EQ(test, mode->hdisplay, 720); @@ -117,6 +132,7 @@ static void drm_test_modes_analog_tv_pal_576i_inlined(struct kunit *test) { struct drm_test_modes_priv *priv = test->priv; struct drm_display_mode *expected, *mode; + int ret; expected = drm_analog_tv_mode(priv->drm, DRM_MODE_TV_MODE_PAL, @@ -124,9 +140,15 @@ static void drm_test_modes_analog_tv_pal_576i_inlined(struct kunit *test) true); KUNIT_ASSERT_NOT_NULL(test, expected); + ret = drm_kunit_add_mode_destroy_action(test, expected); + KUNIT_ASSERT_EQ(test, ret, 0); + mode = drm_mode_analog_pal_576i(priv->drm); KUNIT_ASSERT_NOT_NULL(test, mode); + ret = drm_kunit_add_mode_destroy_action(test, mode); + KUNIT_ASSERT_EQ(test, ret, 0); + KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected, mode)); } From 9649d08010ff94d95630bdea1288562cc1fc9683 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 8 Apr 2025 09:34:13 +0200 Subject: [PATCH 026/606] drm/tests: probe-helper: Fix drm_display_mode memory leak [ Upstream commit 8b6f2e28431b2f9f84073bff50353aeaf25559d0 ] drm_analog_tv_mode() and its variants return a drm_display_mode that needs to be destroyed later one. The drm_test_connector_helper_tv_get_modes_check() test never does however, which leads to a memory leak. Let's make sure it's freed. Reported-by: Philipp Stanner Closes: https://lore.kernel.org/dri-devel/a7655158a6367ac46194d57f4b7433ef0772a73e.camel@mailbox.org/ Fixes: 1e4a91db109f ("drm/probe-helper: Provide a TV get_modes helper") Reviewed-by: Thomas Zimmermann Link: https://lore.kernel.org/r/20250408-drm-kunit-drm-display-mode-memleak-v1-7-996305a2e75a@kernel.org Signed-off-by: Maxime Ripard Signed-off-by: Sasha Levin --- drivers/gpu/drm/tests/drm_probe_helper_test.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/tests/drm_probe_helper_test.c b/drivers/gpu/drm/tests/drm_probe_helper_test.c index 1a2044070a6c..2a7984431d47 100644 --- a/drivers/gpu/drm/tests/drm_probe_helper_test.c +++ b/drivers/gpu/drm/tests/drm_probe_helper_test.c @@ -98,7 +98,7 @@ drm_test_connector_helper_tv_get_modes_check(struct kunit *test) struct drm_connector *connector = &priv->connector; struct drm_cmdline_mode *cmdline = &connector->cmdline_mode; struct drm_display_mode *mode; - const struct drm_display_mode *expected; + struct drm_display_mode *expected; size_t len; int ret; @@ -134,6 +134,9 @@ drm_test_connector_helper_tv_get_modes_check(struct kunit *test) KUNIT_EXPECT_TRUE(test, drm_mode_equal(mode, expected)); KUNIT_EXPECT_TRUE(test, mode->type & DRM_MODE_TYPE_PREFERRED); + + ret = drm_kunit_add_mode_destroy_action(test, expected); + KUNIT_ASSERT_EQ(test, ret, 0); } if (params->num_expected_modes >= 2) { @@ -145,6 +148,9 @@ drm_test_connector_helper_tv_get_modes_check(struct kunit *test) KUNIT_EXPECT_TRUE(test, drm_mode_equal(mode, expected)); KUNIT_EXPECT_FALSE(test, mode->type & DRM_MODE_TYPE_PREFERRED); + + ret = drm_kunit_add_mode_destroy_action(test, expected); + KUNIT_ASSERT_EQ(test, ret, 0); } mutex_unlock(&priv->drm->mode_config.mutex); From c17ef974bfcf1a50818168b47c4606b425a957c4 Mon Sep 17 00:00:00 2001 From: Chenyuan Yang Date: Mon, 7 Apr 2025 13:49:52 -0500 Subject: [PATCH 027/606] net: libwx: handle page_pool_dev_alloc_pages error [ Upstream commit 7f1ff1b38a7c8b872382b796023419d87d78c47e ] page_pool_dev_alloc_pages could return NULL. There was a WARN_ON(!page) but it would still proceed to use the NULL pointer and then crash. This is similar to commit 001ba0902046 ("net: fec: handle page_pool_dev_alloc_pages error"). This is found by our static analysis tool KNighter. Signed-off-by: Chenyuan Yang Fixes: 3c47e8ae113a ("net: libwx: Support to receive packets in NAPI") Reviewed-by: Joe Damato Link: https://patch.msgid.link/20250407184952.2111299-1-chenyuan0y@gmail.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/wangxun/libwx/wx_lib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c index c37500aa0637..c019fe964ece 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c @@ -311,7 +311,8 @@ static bool wx_alloc_mapped_page(struct wx_ring *rx_ring, return true; page = page_pool_dev_alloc_pages(rx_ring->page_pool); - WARN_ON(!page); + if (unlikely(!page)) + return false; dma = page_pool_get_dma_addr(page); bi->page_dma = dma; From 44984339d38ea000f0d07ca9b9bf1cf47ca6cae9 Mon Sep 17 00:00:00 2001 From: Wentao Liang Date: Tue, 8 Apr 2025 15:30:01 +0800 Subject: [PATCH 028/606] ata: sata_sx4: Add error handling in pdc20621_i2c_read() [ Upstream commit 8d46a27085039158eb5e253ab8a35a0e33b5e864 ] The function pdc20621_prog_dimm0() calls the function pdc20621_i2c_read() but does not handle the error if the read fails. This could lead to process with invalid data. A proper implementation can be found in /source/drivers/ata/sata_sx4.c, pdc20621_prog_dimm_global(). As mentioned in its commit: bb44e154e25125bef31fa956785e90fccd24610b, the variable spd0 might be used uninitialized when pdc20621_i2c_read() fails. Add error handling to pdc20621_i2c_read(). If a read operation fails, an error message is logged via dev_err(), and return a negative error code. Add error handling to pdc20621_prog_dimm0() in pdc20621_dimm_init(), and return a negative error code if pdc20621_prog_dimm0() fails. Fixes: 4447d3515616 ("libata: convert the remaining SATA drivers to new init model") Signed-off-by: Wentao Liang Reviewed-by: Niklas Cassel Signed-off-by: Damien Le Moal Signed-off-by: Sasha Levin --- drivers/ata/sata_sx4.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c index a482741eb181..c3042eca6332 100644 --- a/drivers/ata/sata_sx4.c +++ b/drivers/ata/sata_sx4.c @@ -1117,9 +1117,14 @@ static int pdc20621_prog_dimm0(struct ata_host *host) mmio += PDC_CHIP0_OFS; for (i = 0; i < ARRAY_SIZE(pdc_i2c_read_data); i++) - pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS, - pdc_i2c_read_data[i].reg, - &spd0[pdc_i2c_read_data[i].ofs]); + if (!pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS, + pdc_i2c_read_data[i].reg, + &spd0[pdc_i2c_read_data[i].ofs])) { + dev_err(host->dev, + "Failed in i2c read at index %d: device=%#x, reg=%#x\n", + i, PDC_DIMM0_SPD_DEV_ADDRESS, pdc_i2c_read_data[i].reg); + return -EIO; + } data |= (spd0[4] - 8) | ((spd0[21] != 0) << 3) | ((spd0[3]-11) << 4); data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) | @@ -1284,6 +1289,8 @@ static unsigned int pdc20621_dimm_init(struct ata_host *host) /* Programming DIMM0 Module Control Register (index_CID0:80h) */ size = pdc20621_prog_dimm0(host); + if (size < 0) + return size; dev_dbg(host->dev, "Local DIMM Size = %dMB\n", size); /* Programming DIMM Module Global Control Register (index_CID0:88h) */ From 9f5ef4a5eaa61a7a4ed31231da45deb85065397a Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Wed, 2 Apr 2025 19:20:57 +0200 Subject: [PATCH 029/606] drm/i915/huc: Fix fence not released on early probe errors [ Upstream commit e3ea2eae70692a455e256787e4f54153fb739b90 ] HuC delayed loading fence, introduced with commit 27536e03271da ("drm/i915/huc: track delayed HuC load with a fence"), is registered with object tracker early on driver probe but unregistered only from driver remove, which is not called on early probe errors. Since its memory is allocated under devres, then released anyway, it may happen to be allocated again to the fence and reused on future driver probes, resulting in kernel warnings that taint the kernel: <4> [309.731371] ------------[ cut here ]------------ <3> [309.731373] ODEBUG: init destroyed (active state 0) object: ffff88813d7dd2e0 object type: i915_sw_fence hint: sw_fence_dummy_notify+0x0/0x20 [i915] <4> [309.731575] WARNING: CPU: 2 PID: 3161 at lib/debugobjects.c:612 debug_print_object+0x93/0xf0 ... <4> [309.731693] CPU: 2 UID: 0 PID: 3161 Comm: i915_module_loa Tainted: G U 6.14.0-CI_DRM_16362-gf0fd77956987+ #1 ... <4> [309.731700] RIP: 0010:debug_print_object+0x93/0xf0 ... <4> [309.731728] Call Trace: <4> [309.731730] ... <4> [309.731949] __debug_object_init+0x17b/0x1c0 <4> [309.731957] debug_object_init+0x34/0x50 <4> [309.732126] __i915_sw_fence_init+0x34/0x60 [i915] <4> [309.732256] intel_huc_init_early+0x4b/0x1d0 [i915] <4> [309.732468] intel_uc_init_early+0x61/0x680 [i915] <4> [309.732667] intel_gt_common_init_early+0x105/0x130 [i915] <4> [309.732804] intel_root_gt_init_early+0x63/0x80 [i915] <4> [309.732938] i915_driver_probe+0x1fa/0xeb0 [i915] <4> [309.733075] i915_pci_probe+0xe6/0x220 [i915] <4> [309.733198] local_pci_probe+0x44/0xb0 <4> [309.733203] pci_device_probe+0xf4/0x270 <4> [309.733209] really_probe+0xee/0x3c0 <4> [309.733215] __driver_probe_device+0x8c/0x180 <4> [309.733219] driver_probe_device+0x24/0xd0 <4> [309.733223] __driver_attach+0x10f/0x220 <4> [309.733230] bus_for_each_dev+0x7d/0xe0 <4> [309.733236] driver_attach+0x1e/0x30 <4> [309.733239] bus_add_driver+0x151/0x290 <4> [309.733244] driver_register+0x5e/0x130 <4> [309.733247] __pci_register_driver+0x7d/0x90 <4> [309.733251] i915_pci_register_driver+0x23/0x30 [i915] <4> [309.733413] i915_init+0x34/0x120 [i915] <4> [309.733655] do_one_initcall+0x62/0x3f0 <4> [309.733667] do_init_module+0x97/0x2a0 <4> [309.733671] load_module+0x25ff/0x2890 <4> [309.733688] init_module_from_file+0x97/0xe0 <4> [309.733701] idempotent_init_module+0x118/0x330 <4> [309.733711] __x64_sys_finit_module+0x77/0x100 <4> [309.733715] x64_sys_call+0x1f37/0x2650 <4> [309.733719] do_syscall_64+0x91/0x180 <4> [309.733763] entry_SYSCALL_64_after_hwframe+0x76/0x7e <4> [309.733792] ... <4> [309.733806] ---[ end trace 0000000000000000 ]--- That scenario is most easily reproducible with igt@i915_module_load@reload-with-fault-injection. Fix the issue by moving the cleanup step to driver release path. Fixes: 27536e03271da ("drm/i915/huc: track delayed HuC load with a fence") Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13592 Cc: Daniele Ceraolo Spurio Cc: Alan Previn Signed-off-by: Janusz Krzysztofik Reviewed-by: Daniele Ceraolo Spurio Reviewed-by: Krzysztof Karas Signed-off-by: Daniele Ceraolo Spurio Link: https://lore.kernel.org/r/20250402172057.209924-2-janusz.krzysztofik@linux.intel.com (cherry picked from commit 795dbde92fe5c6996a02a5b579481de73035e7bf) Signed-off-by: Jani Nikula Signed-off-by: Sasha Levin --- drivers/gpu/drm/i915/gt/uc/intel_huc.c | 11 +++++------ drivers/gpu/drm/i915/gt/uc/intel_huc.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_uc.c | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.c b/drivers/gpu/drm/i915/gt/uc/intel_huc.c index ba9e07fc2b57..552662953e7a 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_huc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.c @@ -316,6 +316,11 @@ void intel_huc_init_early(struct intel_huc *huc) } } +void intel_huc_fini_late(struct intel_huc *huc) +{ + delayed_huc_load_fini(huc); +} + #define HUC_LOAD_MODE_STRING(x) (x ? "GSC" : "legacy") static int check_huc_loading_mode(struct intel_huc *huc) { @@ -413,12 +418,6 @@ out: void intel_huc_fini(struct intel_huc *huc) { - /* - * the fence is initialized in init_early, so we need to clean it up - * even if HuC loading is off. - */ - delayed_huc_load_fini(huc); - if (huc->heci_pkt) i915_vma_unpin_and_release(&huc->heci_pkt, 0); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.h b/drivers/gpu/drm/i915/gt/uc/intel_huc.h index ba5cb08e9e7b..09aff3148f7d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_huc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.h @@ -55,6 +55,7 @@ struct intel_huc { int intel_huc_sanitize(struct intel_huc *huc); void intel_huc_init_early(struct intel_huc *huc); +void intel_huc_fini_late(struct intel_huc *huc); int intel_huc_init(struct intel_huc *huc); void intel_huc_fini(struct intel_huc *huc); void intel_huc_suspend(struct intel_huc *huc); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c index 98b103375b7a..c29d187ddad1 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c @@ -145,6 +145,7 @@ void intel_uc_init_late(struct intel_uc *uc) void intel_uc_driver_late_release(struct intel_uc *uc) { + intel_huc_fini_late(&uc->huc); } /** From a8008b9758904aa7bfcbe187f5907e6f28a3d216 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 8 Apr 2025 17:29:03 +0200 Subject: [PATCH 030/606] nvmet-fcloop: swap list_add_tail arguments [ Upstream commit 2b5f0c5bc819af2b0759a8fcddc1b39102735c0f ] The newly element to be added to the list is the first argument of list_add_tail. This fix is missing dcfad4ab4d67 ("nvmet-fcloop: swap the list_add_tail arguments"). Fixes: 437c0b824dbd ("nvme-fcloop: add target to host LS request support") Signed-off-by: Daniel Wagner Reviewed-by: Hannes Reinecke Signed-off-by: Christoph Hellwig Signed-off-by: Sasha Levin --- drivers/nvme/target/fcloop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nvme/target/fcloop.c b/drivers/nvme/target/fcloop.c index e6d4226827b5..4b35bdcac185 100644 --- a/drivers/nvme/target/fcloop.c +++ b/drivers/nvme/target/fcloop.c @@ -478,7 +478,7 @@ fcloop_t2h_xmt_ls_rsp(struct nvme_fc_local_port *localport, if (targetport) { tport = targetport->private; spin_lock(&tport->lock); - list_add_tail(&tport->ls_list, &tls_req->ls_list); + list_add_tail(&tls_req->ls_list, &tport->ls_list); spin_unlock(&tport->lock); queue_work(nvmet_wq, &tport->ls_work); } From 00d44fe29e75dae7bec2ade7f5839e38cdaf70e0 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Mon, 7 Apr 2025 13:24:07 -0700 Subject: [PATCH 031/606] net_sched: sch_sfq: use a temporary work area for validating configuration [ Upstream commit 8c0cea59d40cf6dd13c2950437631dd614fbade6 ] Many configuration parameters have influence on others (e.g. divisor -> flows -> limit, depth -> limit) and so it is difficult to correctly do all of the validation before applying the configuration. And if a validation error is detected late it is difficult to roll back a partially applied configuration. To avoid these issues use a temporary work area to update and validate the configuration and only then apply the configuration to the internal state. Signed-off-by: Octavian Purdila Acked-by: Cong Wang Signed-off-by: David S. Miller Stable-dep-of: b3bf8f63e617 ("net_sched: sch_sfq: move the limit validation") Signed-off-by: Sasha Levin --- net/sched/sch_sfq.c | 56 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 60754f366ab7..68e909e8fabd 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -631,6 +631,15 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt, struct red_parms *p = NULL; struct sk_buff *to_free = NULL; struct sk_buff *tail = NULL; + unsigned int maxflows; + unsigned int quantum; + unsigned int divisor; + int perturb_period; + u8 headdrop; + u8 maxdepth; + int limit; + u8 flags; + if (opt->nla_len < nla_attr_size(sizeof(*ctl))) return -EINVAL; @@ -656,36 +665,59 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt, NL_SET_ERR_MSG_MOD(extack, "invalid limit"); return -EINVAL; } + sch_tree_lock(sch); + + limit = q->limit; + divisor = q->divisor; + headdrop = q->headdrop; + maxdepth = q->maxdepth; + maxflows = q->maxflows; + perturb_period = q->perturb_period; + quantum = q->quantum; + flags = q->flags; + + /* update and validate configuration */ if (ctl->quantum) - q->quantum = ctl->quantum; - WRITE_ONCE(q->perturb_period, ctl->perturb_period * HZ); + quantum = ctl->quantum; + perturb_period = ctl->perturb_period * HZ; if (ctl->flows) - q->maxflows = min_t(u32, ctl->flows, SFQ_MAX_FLOWS); + maxflows = min_t(u32, ctl->flows, SFQ_MAX_FLOWS); if (ctl->divisor) { - q->divisor = ctl->divisor; - q->maxflows = min_t(u32, q->maxflows, q->divisor); + divisor = ctl->divisor; + maxflows = min_t(u32, maxflows, divisor); } if (ctl_v1) { if (ctl_v1->depth) - q->maxdepth = min_t(u32, ctl_v1->depth, SFQ_MAX_DEPTH); + maxdepth = min_t(u32, ctl_v1->depth, SFQ_MAX_DEPTH); if (p) { - swap(q->red_parms, p); - red_set_parms(q->red_parms, + red_set_parms(p, ctl_v1->qth_min, ctl_v1->qth_max, ctl_v1->Wlog, ctl_v1->Plog, ctl_v1->Scell_log, NULL, ctl_v1->max_P); } - q->flags = ctl_v1->flags; - q->headdrop = ctl_v1->headdrop; + flags = ctl_v1->flags; + headdrop = ctl_v1->headdrop; } if (ctl->limit) { - q->limit = min_t(u32, ctl->limit, q->maxdepth * q->maxflows); - q->maxflows = min_t(u32, q->maxflows, q->limit); + limit = min_t(u32, ctl->limit, maxdepth * maxflows); + maxflows = min_t(u32, maxflows, limit); } + /* commit configuration */ + q->limit = limit; + q->divisor = divisor; + q->headdrop = headdrop; + q->maxdepth = maxdepth; + q->maxflows = maxflows; + WRITE_ONCE(q->perturb_period, perturb_period); + q->quantum = quantum; + q->flags = flags; + if (p) + swap(q->red_parms, p); + qlen = sch->q.qlen; while (sch->q.qlen > q->limit) { dropped += sfq_drop(sch, &to_free); From d2718324f9e329b10ddc091fba5a0ba2b9d4d96a Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Mon, 7 Apr 2025 13:24:08 -0700 Subject: [PATCH 032/606] net_sched: sch_sfq: move the limit validation [ Upstream commit b3bf8f63e6179076b57c9de660c9f80b5abefe70 ] It is not sufficient to directly validate the limit on the data that the user passes as it can be updated based on how the other parameters are changed. Move the check at the end of the configuration update process to also catch scenarios where the limit is indirectly updated, for example with the following configurations: tc qdisc add dev dummy0 handle 1: root sfq limit 2 flows 1 depth 1 tc qdisc add dev dummy0 handle 1: root sfq limit 2 flows 1 divisor 1 This fixes the following syzkaller reported crash: ------------[ cut here ]------------ UBSAN: array-index-out-of-bounds in net/sched/sch_sfq.c:203:6 index 65535 is out of range for type 'struct sfq_head[128]' CPU: 1 UID: 0 PID: 3037 Comm: syz.2.16 Not tainted 6.14.0-rc2-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 12/27/2024 Call Trace: __dump_stack lib/dump_stack.c:94 [inline] dump_stack_lvl+0x201/0x300 lib/dump_stack.c:120 ubsan_epilogue lib/ubsan.c:231 [inline] __ubsan_handle_out_of_bounds+0xf5/0x120 lib/ubsan.c:429 sfq_link net/sched/sch_sfq.c:203 [inline] sfq_dec+0x53c/0x610 net/sched/sch_sfq.c:231 sfq_dequeue+0x34e/0x8c0 net/sched/sch_sfq.c:493 sfq_reset+0x17/0x60 net/sched/sch_sfq.c:518 qdisc_reset+0x12e/0x600 net/sched/sch_generic.c:1035 tbf_reset+0x41/0x110 net/sched/sch_tbf.c:339 qdisc_reset+0x12e/0x600 net/sched/sch_generic.c:1035 dev_reset_queue+0x100/0x1b0 net/sched/sch_generic.c:1311 netdev_for_each_tx_queue include/linux/netdevice.h:2590 [inline] dev_deactivate_many+0x7e5/0xe70 net/sched/sch_generic.c:1375 Reported-by: syzbot Fixes: 10685681bafc ("net_sched: sch_sfq: don't allow 1 packet limit") Signed-off-by: Octavian Purdila Acked-by: Cong Wang Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- net/sched/sch_sfq.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 68e909e8fabd..002941d35b64 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -661,10 +661,6 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt, if (!p) return -ENOMEM; } - if (ctl->limit == 1) { - NL_SET_ERR_MSG_MOD(extack, "invalid limit"); - return -EINVAL; - } sch_tree_lock(sch); @@ -705,6 +701,12 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt, limit = min_t(u32, ctl->limit, maxdepth * maxflows); maxflows = min_t(u32, maxflows, limit); } + if (limit == 1) { + sch_tree_unlock(sch); + kfree(p); + NL_SET_ERR_MSG_MOD(extack, "invalid limit"); + return -EINVAL; + } /* commit configuration */ q->limit = limit; From 6509e2e17d325b2b1c0364ab6798f2b01137677b Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 8 Apr 2025 11:43:16 +0300 Subject: [PATCH 033/606] ipv6: Align behavior across nexthops during path selection [ Upstream commit 6933cd4714861eea6848f18396a119d741f25fc3 ] A nexthop is only chosen when the calculated multipath hash falls in the nexthop's hash region (i.e., the hash is smaller than the nexthop's hash threshold) and when the nexthop is assigned a non-negative score by rt6_score_route(). Commit 4d0ab3a6885e ("ipv6: Start path selection from the first nexthop") introduced an unintentional difference between the first nexthop and the rest when the score is negative. When the first nexthop matches, but has a negative score, the code will currently evaluate subsequent nexthops until one is found with a non-negative score. On the other hand, when a different nexthop matches, but has a negative score, the code will fallback to the nexthop with which the selection started ('match'). Align the behavior across all nexthops and fallback to 'match' when the first nexthop matches, but has a negative score. Fixes: 3d709f69a3e7 ("ipv6: Use hash-threshold instead of modulo-N") Fixes: 4d0ab3a6885e ("ipv6: Start path selection from the first nexthop") Reported-by: Willem de Bruijn Closes: https://lore.kernel.org/netdev/67efef607bc41_1ddca82948c@willemb.c.googlers.com.notmuch/ Signed-off-by: Ido Schimmel Reviewed-by: Willem de Bruijn Reviewed-by: David Ahern Link: https://patch.msgid.link/20250408084316.243559-1-idosch@nvidia.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- net/ipv6/route.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 2e98531fa51a..53197087353a 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -472,10 +472,10 @@ void fib6_select_path(const struct net *net, struct fib6_result *res, goto out; hash = fl6->mp_hash; - if (hash <= atomic_read(&first->fib6_nh->fib_nh_upper_bound) && - rt6_score_route(first->fib6_nh, first->fib6_flags, oif, - strict) >= 0) { - match = first; + if (hash <= atomic_read(&first->fib6_nh->fib_nh_upper_bound)) { + if (rt6_score_route(first->fib6_nh, first->fib6_flags, oif, + strict) >= 0) + match = first; goto out; } From fbaffe8bccf148ece8ad67eb5d7aa852cabf59c8 Mon Sep 17 00:00:00 2001 From: Arnaud Lecomte Date: Tue, 8 Apr 2025 17:55:08 +0200 Subject: [PATCH 034/606] net: ppp: Add bound checking for skb data on ppp_sync_txmung MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit aabc6596ffb377c4c9c8f335124b92ea282c9821 ] Ensure we have enough data in linear buffer from skb before accessing initial bytes. This prevents potential out-of-bounds accesses when processing short packets. When ppp_sync_txmung receives an incoming package with an empty payload: (remote) gef➤ p *(struct pppoe_hdr *) (skb->head + skb->network_header) $18 = { type = 0x1, ver = 0x1, code = 0x0, sid = 0x2, length = 0x0, tag = 0xffff8880371cdb96 } from the skb struct (trimmed) tail = 0x16, end = 0x140, head = 0xffff88803346f400 "4", data = 0xffff88803346f416 ":\377", truesize = 0x380, len = 0x0, data_len = 0x0, mac_len = 0xe, hdr_len = 0x0, it is not safe to access data[2]. Reported-by: syzbot+29fc8991b0ecb186cf40@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=29fc8991b0ecb186cf40 Tested-by: syzbot+29fc8991b0ecb186cf40@syzkaller.appspotmail.com Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Arnaud Lecomte Link: https://patch.msgid.link/20250408-bound-checking-ppp_txmung-v2-1-94bb6e1b92d0@arnaud-lcm.com [pabeni@redhat.com: fixed subj typo] Signed-off-by: Paolo Abeni Signed-off-by: Sasha Levin --- drivers/net/ppp/ppp_synctty.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ppp/ppp_synctty.c b/drivers/net/ppp/ppp_synctty.c index 52d05ce4a281..02e1c5bd1892 100644 --- a/drivers/net/ppp/ppp_synctty.c +++ b/drivers/net/ppp/ppp_synctty.c @@ -506,6 +506,11 @@ ppp_sync_txmunge(struct syncppp *ap, struct sk_buff *skb) unsigned char *data; int islcp; + /* Ensure we can safely access protocol field and LCP code */ + if (!pskb_may_pull(skb, 3)) { + kfree_skb(skb); + return NULL; + } data = skb->data; proto = get_unaligned_be16(data); From 90cdd7e5a4848e5a838742d69dc44f22db0e0888 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 7 Apr 2025 19:40:18 +0200 Subject: [PATCH 035/606] nft_set_pipapo: fix incorrect avx2 match of 5th field octet [ Upstream commit e042ed950d4e176379ba4c0722146cd96fb38aa2 ] Given a set element like: icmpv6 . dead:beef:00ff::1 The value of 'ff' is irrelevant, any address will be matched as long as the other octets are the same. This is because of too-early register clobbering: ymm7 is reloaded with new packet data (pkt[9]) but it still holds data of an earlier load that wasn't processed yet. The existing tests in nft_concat_range.sh selftests do exercise this code path, but do not trigger incorrect matching due to the network prefix limitation. Fixes: 7400b063969b ("nft_set_pipapo: Introduce AVX2-based lookup implementation") Reported-by: sontu mazumdar Closes: https://lore.kernel.org/netfilter/CANgxkqwnMH7fXra+VUfODT-8+qFLgskq3set1cAzqqJaV4iEZg@mail.gmail.com/T/#t Reviewed-by: Stefano Brivio Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso Signed-off-by: Sasha Levin --- net/netfilter/nft_set_pipapo_avx2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nft_set_pipapo_avx2.c b/net/netfilter/nft_set_pipapo_avx2.c index b8d3c3213efe..c15db28c5ebc 100644 --- a/net/netfilter/nft_set_pipapo_avx2.c +++ b/net/netfilter/nft_set_pipapo_avx2.c @@ -994,8 +994,9 @@ static int nft_pipapo_avx2_lookup_8b_16(unsigned long *map, unsigned long *fill, NFT_PIPAPO_AVX2_BUCKET_LOAD8(5, lt, 8, pkt[8], bsize); NFT_PIPAPO_AVX2_AND(6, 2, 3); + NFT_PIPAPO_AVX2_AND(3, 4, 7); NFT_PIPAPO_AVX2_BUCKET_LOAD8(7, lt, 9, pkt[9], bsize); - NFT_PIPAPO_AVX2_AND(0, 4, 5); + NFT_PIPAPO_AVX2_AND(0, 3, 5); NFT_PIPAPO_AVX2_BUCKET_LOAD8(1, lt, 10, pkt[10], bsize); NFT_PIPAPO_AVX2_AND(2, 6, 7); NFT_PIPAPO_AVX2_BUCKET_LOAD8(3, lt, 11, pkt[11], bsize); From 6abd09bed43b8d83d461e0fb5b9a200a06aa8a27 Mon Sep 17 00:00:00 2001 From: Louis-Alexis Eyraud Date: Thu, 3 Apr 2025 12:22:12 +0200 Subject: [PATCH 036/606] iommu/mediatek: Fix NULL pointer deference in mtk_iommu_device_group [ Upstream commit 38e8844005e6068f336a3ad45451a562a0040ca1 ] Currently, mtk_iommu calls during probe iommu_device_register before the hw_list from driver data is initialized. Since iommu probing issue fix, it leads to NULL pointer dereference in mtk_iommu_device_group when hw_list is accessed with list_first_entry (not null safe). So, change the call order to ensure iommu_device_register is called after the driver data are initialized. Fixes: 9e3a2a643653 ("iommu/mediatek: Adapt sharing and non-sharing pgtable case") Fixes: bcb81ac6ae3c ("iommu: Get DT/ACPI parsing into the proper probe path") Reviewed-by: Yong Wu Tested-by: Chen-Yu Tsai # MT8183 Juniper, MT8186 Tentacruel Reviewed-by: AngeloGioacchino Del Regno Tested-by: AngeloGioacchino Del Regno Signed-off-by: Louis-Alexis Eyraud Link: https://lore.kernel.org/r/20250403-fix-mtk-iommu-error-v2-1-fe8b18f8b0a8@collabora.com Signed-off-by: Joerg Roedel Signed-off-by: Sasha Levin --- drivers/iommu/mtk_iommu.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index de698463e94a..06c0770ff894 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -1354,15 +1354,6 @@ static int mtk_iommu_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); mutex_init(&data->mutex); - ret = iommu_device_sysfs_add(&data->iommu, dev, NULL, - "mtk-iommu.%pa", &ioaddr); - if (ret) - goto out_link_remove; - - ret = iommu_device_register(&data->iommu, &mtk_iommu_ops, dev); - if (ret) - goto out_sysfs_remove; - if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE)) { list_add_tail(&data->list, data->plat_data->hw_list); data->hw_list = data->plat_data->hw_list; @@ -1372,19 +1363,28 @@ static int mtk_iommu_probe(struct platform_device *pdev) data->hw_list = &data->hw_list_head; } + ret = iommu_device_sysfs_add(&data->iommu, dev, NULL, + "mtk-iommu.%pa", &ioaddr); + if (ret) + goto out_list_del; + + ret = iommu_device_register(&data->iommu, &mtk_iommu_ops, dev); + if (ret) + goto out_sysfs_remove; + if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) { ret = component_master_add_with_match(dev, &mtk_iommu_com_ops, match); if (ret) - goto out_list_del; + goto out_device_unregister; } return ret; -out_list_del: - list_del(&data->list); +out_device_unregister: iommu_device_unregister(&data->iommu); out_sysfs_remove: iommu_device_sysfs_remove(&data->iommu); -out_link_remove: +out_list_del: + list_del(&data->list); if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) device_link_remove(data->smicomm_dev, dev); out_runtime_disable: From 323960a187a9622d9006484ff6635680d3a0118f Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Thu, 13 Mar 2025 14:57:25 +0100 Subject: [PATCH 037/606] fs: consistently deref the files table with rcu_dereference_raw() [ Upstream commit f381640e1bd4f2de7ccafbfe8703d33c3718aad9 ] ... except when the table is known to be only used by one thread. A file pointer can get installed at any moment despite the ->file_lock being held since the following: 8a81252b774b53e6 ("fs/file.c: don't acquire files->file_lock in fd_install()") Accesses subject to such a race can in principle suffer load tearing. While here redo the comment in dup_fd -- it only covered a race against files showing up, still assuming fd_install() takes the lock. Signed-off-by: Mateusz Guzik Link: https://lore.kernel.org/r/20250313135725.1320914-1-mjguzik@gmail.com Signed-off-by: Christian Brauner Signed-off-by: Sasha Levin --- fs/file.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/fs/file.c b/fs/file.c index a178efc8cf4b..f8cf6728c6a0 100644 --- a/fs/file.c +++ b/fs/file.c @@ -362,17 +362,25 @@ struct files_struct *dup_fd(struct files_struct *oldf, struct fd_range *punch_ho old_fds = old_fdt->fd; new_fds = new_fdt->fd; + /* + * We may be racing against fd allocation from other threads using this + * files_struct, despite holding ->file_lock. + * + * alloc_fd() might have already claimed a slot, while fd_install() + * did not populate it yet. Note the latter operates locklessly, so + * the file can show up as we are walking the array below. + * + * At the same time we know no files will disappear as all other + * operations take the lock. + * + * Instead of trying to placate userspace racing with itself, we + * ref the file if we see it and mark the fd slot as unused otherwise. + */ for (i = open_files; i != 0; i--) { - struct file *f = *old_fds++; + struct file *f = rcu_dereference_raw(*old_fds++); if (f) { get_file(f); } else { - /* - * The fd may be claimed in the fd bitmap but not yet - * instantiated in the files array if a sibling thread - * is partway through open(). So make sure that this - * fd is available to the new process. - */ __clear_open_fd(open_files - i, new_fdt); } rcu_assign_pointer(*new_fds++, f); @@ -625,7 +633,7 @@ static struct file *pick_file(struct files_struct *files, unsigned fd) return NULL; fd = array_index_nospec(fd, fdt->max_fds); - file = fdt->fd[fd]; + file = rcu_dereference_raw(fdt->fd[fd]); if (file) { rcu_assign_pointer(fdt->fd[fd], NULL); __put_unused_fd(files, fd); @@ -1095,7 +1103,7 @@ __releases(&files->file_lock) */ fdt = files_fdtable(files); fd = array_index_nospec(fd, fdt->max_fds); - tofree = fdt->fd[fd]; + tofree = rcu_dereference_raw(fdt->fd[fd]); if (!tofree && fd_is_open(fd, fdt)) goto Ebusy; get_file(file); From 4ec80a68733f7dc6ad367d2c23f5d590f9fa5ec4 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 18 Mar 2025 12:29:21 -0400 Subject: [PATCH 038/606] umount: Allow superblock owners to force umount [ Upstream commit e1ff7aa34dec7e650159fd7ca8ec6af7cc428d9f ] Loosen the permission check on forced umount to allow users holding CAP_SYS_ADMIN privileges in namespaces that are privileged with respect to the userns that originally mounted the filesystem. Signed-off-by: Trond Myklebust Link: https://lore.kernel.org/r/12f212d4ef983714d065a6bb372fbb378753bf4c.1742315194.git.trond.myklebust@hammerspace.com Acked-by: "Eric W. Biederman" Signed-off-by: Christian Brauner Signed-off-by: Sasha Levin --- fs/namespace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/namespace.c b/fs/namespace.c index b4385e2413d5..671e266b8fc5 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1869,6 +1869,7 @@ static void warn_mandlock(void) static int can_umount(const struct path *path, int flags) { struct mount *mnt = real_mount(path->mnt); + struct super_block *sb = path->dentry->d_sb; if (!may_mount()) return -EPERM; @@ -1878,7 +1879,7 @@ static int can_umount(const struct path *path, int flags) return -EINVAL; if (mnt->mnt.mnt_flags & MNT_LOCKED) /* Check optimistically */ return -EINVAL; - if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN)) + if (flags & MNT_FORCE && !ns_capable(sb->s_user_ns, CAP_SYS_ADMIN)) return -EPERM; return 0; } From 942a4b97fc77516678b1d8af1521ff9a94c13b3e Mon Sep 17 00:00:00 2001 From: Zhongqiu Han Date: Wed, 19 Feb 2025 20:27:15 +0800 Subject: [PATCH 039/606] pm: cpupower: bench: Prevent NULL dereference on malloc failure [ Upstream commit 208baa3ec9043a664d9acfb8174b332e6b17fb69 ] If malloc returns NULL due to low memory, 'config' pointer can be NULL. Add a check to prevent NULL dereference. Link: https://lore.kernel.org/r/20250219122715.3892223-1-quic_zhonhan@quicinc.com Signed-off-by: Zhongqiu Han Signed-off-by: Shuah Khan Signed-off-by: Sasha Levin --- tools/power/cpupower/bench/parse.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/power/cpupower/bench/parse.c b/tools/power/cpupower/bench/parse.c index e63dc11fa3a5..48e25be6e163 100644 --- a/tools/power/cpupower/bench/parse.c +++ b/tools/power/cpupower/bench/parse.c @@ -120,6 +120,10 @@ out_dir: struct config *prepare_default_config() { struct config *config = malloc(sizeof(struct config)); + if (!config) { + perror("malloc"); + return NULL; + } dprintf("loading defaults\n"); From d0f4b75a8f96aa27ca017a6f2e7eb81041803528 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Tue, 25 Feb 2025 19:37:32 +0000 Subject: [PATCH 040/606] x86/mm: Clear _PAGE_DIRTY for kernel mappings when we clear _PAGE_RW [ Upstream commit c1fcf41cf37f7a3fd3bbf6f0c04aba3ea4258888 ] The bit pattern of _PAGE_DIRTY set and _PAGE_RW clear is used to mark shadow stacks. This is currently checked for in mk_pte() but not pfn_pte(). If we add the check to pfn_pte(), it catches vfree() calling set_direct_map_invalid_noflush() which calls __change_page_attr() which loads the old protection bits from the PTE, clears the specified bits and uses pfn_pte() to construct the new PTE. We should, therefore, for kernel mappings, clear the _PAGE_DIRTY bit consistently whenever we clear _PAGE_RW. I opted to do it in the callers in case we want to use __change_page_attr() to create shadow stacks inside the kernel at some point in the future. Arguably, we might also want to clear _PAGE_ACCESSED here. Note that the 3 functions involved: __set_pages_np() kernel_map_pages_in_pgd() kernel_unmap_pages_in_pgd() Only ever manipulate non-swappable kernel mappings, so maintaining the DIRTY:1|RW:0 special pattern for shadow stacks and DIRTY:0 pattern for non-shadow-stack entries can be maintained consistently and doesn't result in the unintended clearing of a live dirty bit that could corrupt (destroy) dirty bit information for user mappings. Reported-by: kernel test robot Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: Ingo Molnar Acked-by: Linus Torvalds Link: https://lore.kernel.org/r/174051422675.10177.13226545170101706336.tip-bot2@tip-bot2 Closes: https://lore.kernel.org/oe-lkp/202502241646.719f4651-lkp@intel.com Signed-off-by: Sasha Levin --- arch/x86/mm/pat/set_memory.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c index 2d850f6bae70..525794f1eefb 100644 --- a/arch/x86/mm/pat/set_memory.c +++ b/arch/x86/mm/pat/set_memory.c @@ -2374,7 +2374,7 @@ static int __set_pages_np(struct page *page, int numpages) .pgd = NULL, .numpages = numpages, .mask_set = __pgprot(0), - .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW), + .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY), .flags = CPA_NO_CHECK_ALIAS }; /* @@ -2453,7 +2453,7 @@ int __init kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn, unsigned long address, .pgd = pgd, .numpages = numpages, .mask_set = __pgprot(0), - .mask_clr = __pgprot(~page_flags & (_PAGE_NX|_PAGE_RW)), + .mask_clr = __pgprot(~page_flags & (_PAGE_NX|_PAGE_RW|_PAGE_DIRTY)), .flags = CPA_NO_CHECK_ALIAS, }; @@ -2496,7 +2496,7 @@ int __init kernel_unmap_pages_in_pgd(pgd_t *pgd, unsigned long address, .pgd = pgd, .numpages = numpages, .mask_set = __pgprot(0), - .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW), + .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY), .flags = CPA_NO_CHECK_ALIAS, }; From 8449fd2a1433b7e61c842d4942ed888850cef017 Mon Sep 17 00:00:00 2001 From: "Xin Li (Intel)" Date: Tue, 26 Nov 2024 10:45:28 -0800 Subject: [PATCH 041/606] x86/ia32: Leave NULL selector values 0~3 unchanged [ Upstream commit ad546940b5991d3e141238cd80a6d1894b767184 ] The first GDT descriptor is reserved as 'NULL descriptor'. As bits 0 and 1 of a segment selector, i.e., the RPL bits, are NOT used to index GDT, selector values 0~3 all point to the NULL descriptor, thus values 0, 1, 2 and 3 are all valid NULL selector values. When a NULL selector value is to be loaded into a segment register, reload_segments() sets its RPL bits. Later IRET zeros ES, FS, GS, and DS segment registers if any of them is found to have any nonzero NULL selector value. The two operations offset each other to actually effect a nop. Besides, zeroing of RPL in NULL selector values is an information leak in pre-FRED systems as userspace can spot any interrupt/exception by loading a nonzero NULL selector, and waiting for it to become zero. But there is nothing software can do to prevent it before FRED. ERETU, the only legit instruction to return to userspace from kernel under FRED, by design does NOT zero any segment register to avoid this problem behavior. As such, leave NULL selector values 0~3 unchanged and close the leak. Do the same on 32-bit kernel as well. Signed-off-by: Xin Li (Intel) Signed-off-by: Ingo Molnar Reviewed-by: Andrew Cooper Cc: Linus Torvalds Cc: Andy Lutomirski Cc: Brian Gerst Cc: Peter Zijlstra Link: https://lore.kernel.org/r/20241126184529.1607334-1-xin@zytor.com Signed-off-by: Sasha Levin --- arch/x86/kernel/signal_32.c | 62 +++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index c12624bc82a3..983f8f5893a4 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -33,25 +33,55 @@ #include #include +/* + * The first GDT descriptor is reserved as 'NULL descriptor'. As bits 0 + * and 1 of a segment selector, i.e., the RPL bits, are NOT used to index + * GDT, selector values 0~3 all point to the NULL descriptor, thus values + * 0, 1, 2 and 3 are all valid NULL selector values. + * + * However IRET zeros ES, FS, GS, and DS segment registers if any of them + * is found to have any nonzero NULL selector value, which can be used by + * userspace in pre-FRED systems to spot any interrupt/exception by loading + * a nonzero NULL selector and waiting for it to become zero. Before FRED + * there was nothing software could do to prevent such an information leak. + * + * ERETU, the only legit instruction to return to userspace from kernel + * under FRED, by design does NOT zero any segment register to avoid this + * problem behavior. + * + * As such, leave NULL selector values 0~3 unchanged. + */ +static inline u16 fixup_rpl(u16 sel) +{ + return sel <= 3 ? sel : sel | 3; +} + #ifdef CONFIG_IA32_EMULATION #include static inline void reload_segments(struct sigcontext_32 *sc) { - unsigned int cur; + u16 cur; + /* + * Reload fs and gs if they have changed in the signal + * handler. This does not handle long fs/gs base changes in + * the handler, but does not clobber them at least in the + * normal case. + */ savesegment(gs, cur); - if ((sc->gs | 0x03) != cur) - load_gs_index(sc->gs | 0x03); + if (fixup_rpl(sc->gs) != cur) + load_gs_index(fixup_rpl(sc->gs)); savesegment(fs, cur); - if ((sc->fs | 0x03) != cur) - loadsegment(fs, sc->fs | 0x03); + if (fixup_rpl(sc->fs) != cur) + loadsegment(fs, fixup_rpl(sc->fs)); + savesegment(ds, cur); - if ((sc->ds | 0x03) != cur) - loadsegment(ds, sc->ds | 0x03); + if (fixup_rpl(sc->ds) != cur) + loadsegment(ds, fixup_rpl(sc->ds)); savesegment(es, cur); - if ((sc->es | 0x03) != cur) - loadsegment(es, sc->es | 0x03); + if (fixup_rpl(sc->es) != cur) + loadsegment(es, fixup_rpl(sc->es)); } #define sigset32_t compat_sigset_t @@ -105,18 +135,12 @@ static bool ia32_restore_sigcontext(struct pt_regs *regs, regs->orig_ax = -1; #ifdef CONFIG_IA32_EMULATION - /* - * Reload fs and gs if they have changed in the signal - * handler. This does not handle long fs/gs base changes in - * the handler, but does not clobber them at least in the - * normal case. - */ reload_segments(&sc); #else - loadsegment(gs, sc.gs); - regs->fs = sc.fs; - regs->es = sc.es; - regs->ds = sc.ds; + loadsegment(gs, fixup_rpl(sc.gs)); + regs->fs = fixup_rpl(sc.fs); + regs->es = fixup_rpl(sc.es); + regs->ds = fixup_rpl(sc.ds); #endif return fpu__restore_sig(compat_ptr(sc.fpstate), 1); From c7dec3461275dd6ff1dfd02c168456e93196bf4a Mon Sep 17 00:00:00 2001 From: Max Grobecker Date: Thu, 27 Feb 2025 21:45:05 +0100 Subject: [PATCH 042/606] x86/cpu: Don't clear X86_FEATURE_LAHF_LM flag in init_amd_k8() on AMD when running in a virtual machine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit a4248ee16f411ac1ea7dfab228a6659b111e3d65 ] When running in a virtual machine, we might see the original hardware CPU vendor string (i.e. "AuthenticAMD"), but a model and family ID set by the hypervisor. In case we run on AMD hardware and the hypervisor sets a model ID < 0x14, the LAHF cpu feature is eliminated from the the list of CPU capabilities present to circumvent a bug with some BIOSes in conjunction with AMD K8 processors. Parsing the flags list from /proc/cpuinfo seems to be happening mostly in bash scripts and prebuilt Docker containers, as it does not need to have additionals tools present – even though more reliable ways like using "kcpuid", which calls the CPUID instruction instead of parsing a list, should be preferred. Scripts, that use /proc/cpuinfo to determine if the current CPU is "compliant" with defined microarchitecture levels like x86-64-v2 will falsely claim the CPU is incapable of modern CPU instructions when "lahf_lm" is missing in that flags list. This can prevent some docker containers from starting or build scripts to create unoptimized binaries. Admittably, this is more a small inconvenience than a severe bug in the kernel and the shoddy scripts that rely on parsing /proc/cpuinfo should be fixed instead. This patch adds an additional check to see if we're running inside a virtual machine (X86_FEATURE_HYPERVISOR is present), which, to my understanding, can't be present on a real K8 processor as it was introduced only with the later/other Athlon64 models. Example output with the "lahf_lm" flag missing in the flags list (should be shown between "hypervisor" and "abm"): $ cat /proc/cpuinfo processor : 0 vendor_id : AuthenticAMD cpu family : 15 model : 6 model name : Common KVM processor stepping : 1 microcode : 0x1000065 cpu MHz : 2599.998 cache size : 512 KB physical id : 0 siblings : 1 core id : 0 cpu cores : 1 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 syscall nx rdtscp lm rep_good nopl cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c hypervisor abm 3dnowprefetch vmmcall bmi1 avx2 bmi2 xsaveopt ... while kcpuid shows the feature to be present in the CPU: # kcpuid -d | grep lahf lahf_lm - LAHF/SAHF available in 64-bit mode [ mingo: Updated the comment a bit, incorporated Boris's review feedback. ] Signed-off-by: Max Grobecker Signed-off-by: Ingo Molnar Cc: linux-kernel@vger.kernel.org Cc: Borislav Petkov Signed-off-by: Sasha Levin --- arch/x86/kernel/cpu/amd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 9413fb767c6a..be378b44ca35 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -825,7 +825,7 @@ static void init_amd_k8(struct cpuinfo_x86 *c) * (model = 0x14) and later actually support it. * (AMD Erratum #110, docId: 25759). */ - if (c->x86_model < 0x14 && cpu_has(c, X86_FEATURE_LAHF_LM)) { + if (c->x86_model < 0x14 && cpu_has(c, X86_FEATURE_LAHF_LM) && !cpu_has(c, X86_FEATURE_HYPERVISOR)) { clear_cpu_cap(c, X86_FEATURE_LAHF_LM); if (!rdmsrl_amd_safe(0xc001100d, &value)) { value &= ~BIT_64(32); From f14d29b891865e0b59acbb6ee0995f09da2d89f2 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Tue, 18 Feb 2025 14:39:57 -0600 Subject: [PATCH 043/606] perf: arm_pmu: Don't disable counter in armpmu_add() [ Upstream commit dcca27bc1eccb9abc2552aab950b18a9742fb8e7 ] Currently armpmu_add() tries to handle a newly-allocated counter having a stale associated event, but this should not be possible, and if this were to happen the current mitigation is insufficient and potentially expensive. It would be better to warn if we encounter the impossible case. Calls to pmu::add() and pmu::del() are serialized by the core perf code, and armpmu_del() clears the relevant slot in pmu_hw_events::events[] before clearing the bit in pmu_hw_events::used_mask such that the counter can be reallocated. Thus when armpmu_add() allocates a counter index from pmu_hw_events::used_mask, it should not be possible to observe a stale even in pmu_hw_events::events[] unless either pmu_hw_events::used_mask or pmu_hw_events::events[] have been corrupted. If this were to happen, we'd end up with two events with the same event->hw.idx, which would clash with each other during reprogramming, deletion, etc, and produce bogus results. Add a WARN_ON_ONCE() for this case so that we can detect if this ever occurs in practice. That possiblity aside, there's no need to call arm_pmu::disable(event) for the new event. The PMU reset code initialises the counter in a disabled state, and armpmu_del() will disable the counter before it can be reused. Remove the redundant disable. Signed-off-by: Mark Rutland Signed-off-by: Rob Herring (Arm) Reviewed-by: Anshuman Khandual Tested-by: James Clark Link: https://lore.kernel.org/r/20250218-arm-brbe-v19-v20-2-4e9922fc2e8e@kernel.org Signed-off-by: Will Deacon Signed-off-by: Sasha Levin --- drivers/perf/arm_pmu.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c index d712a19e47ac..b3bb4d62f13d 100644 --- a/drivers/perf/arm_pmu.c +++ b/drivers/perf/arm_pmu.c @@ -342,12 +342,10 @@ armpmu_add(struct perf_event *event, int flags) if (idx < 0) return idx; - /* - * If there is an event in the counter we are going to use then make - * sure it is disabled. - */ + /* The newly-allocated counter should be empty */ + WARN_ON_ONCE(hw_events->events[idx]); + event->hw.idx = idx; - armpmu->disable(event); hw_events->events[idx] = event; hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; From 150d1cbdf78126b7d0348701e1b15e86d59d27b1 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Thu, 19 Dec 2024 13:11:09 -0800 Subject: [PATCH 044/606] arm64: cputype: Add QCOM_CPU_PART_KRYO_3XX_GOLD [ Upstream commit 401c3333bb2396aa52e4121887a6f6a6e2f040bc ] Add a definition for the Qualcomm Kryo 300-series Gold cores. Reviewed-by: Dmitry Baryshkov Signed-off-by: Douglas Anderson Acked-by: Trilok Soni Link: https://lore.kernel.org/r/20241219131107.v3.1.I18e0288742871393228249a768e5d56ea65d93dc@changeid Signed-off-by: Catalin Marinas Signed-off-by: Sasha Levin --- arch/arm64/include/asm/cputype.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index 488f8e751349..c8058f91a5bd 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h @@ -119,6 +119,7 @@ #define QCOM_CPU_PART_KRYO 0x200 #define QCOM_CPU_PART_KRYO_2XX_GOLD 0x800 #define QCOM_CPU_PART_KRYO_2XX_SILVER 0x801 +#define QCOM_CPU_PART_KRYO_3XX_GOLD 0x802 #define QCOM_CPU_PART_KRYO_3XX_SILVER 0x803 #define QCOM_CPU_PART_KRYO_4XX_GOLD 0x804 #define QCOM_CPU_PART_KRYO_4XX_SILVER 0x805 @@ -195,6 +196,7 @@ #define MIDR_QCOM_KRYO MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO) #define MIDR_QCOM_KRYO_2XX_GOLD MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_2XX_GOLD) #define MIDR_QCOM_KRYO_2XX_SILVER MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_2XX_SILVER) +#define MIDR_QCOM_KRYO_3XX_GOLD MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_3XX_GOLD) #define MIDR_QCOM_KRYO_3XX_SILVER MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_3XX_SILVER) #define MIDR_QCOM_KRYO_4XX_GOLD MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_4XX_GOLD) #define MIDR_QCOM_KRYO_4XX_SILVER MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_4XX_SILVER) From af71db7de0679e91f2e9e82868df8e7a2fe695b2 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 10 Mar 2025 15:22:38 -0700 Subject: [PATCH 045/606] xen/mcelog: Add __nonstring annotations for unterminated strings [ Upstream commit 1c3dfc7c6b0f551fdca3f7c1f1e4c73be8adb17d ] When a character array without a terminating NUL character has a static initializer, GCC 15's -Wunterminated-string-initialization will only warn if the array lacks the "nonstring" attribute[1]. Mark the arrays with __nonstring to and correctly identify the char array as "not a C string" and thereby eliminate the warning. Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117178 [1] Cc: Juergen Gross Cc: Stefano Stabellini Cc: Oleksandr Tyshchenko Cc: xen-devel@lists.xenproject.org Signed-off-by: Kees Cook Acked-by: Juergen Gross Message-ID: <20250310222234.work.473-kees@kernel.org> Signed-off-by: Juergen Gross Signed-off-by: Sasha Levin --- include/xen/interface/xen-mca.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/xen/interface/xen-mca.h b/include/xen/interface/xen-mca.h index 464aa6b3a5f9..1c9afbe8cc26 100644 --- a/include/xen/interface/xen-mca.h +++ b/include/xen/interface/xen-mca.h @@ -372,7 +372,7 @@ struct xen_mce { #define XEN_MCE_LOG_LEN 32 struct xen_mce_log { - char signature[12]; /* "MACHINECHECK" */ + char signature[12] __nonstring; /* "MACHINECHECK" */ unsigned len; /* = XEN_MCE_LOG_LEN */ unsigned next; unsigned flags; From 1e5b04f08e52d1c39deca67953e39e4569bb96bb Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 21 Mar 2025 08:38:43 +0100 Subject: [PATCH 046/606] zstd: Increase DYNAMIC_BMI2 GCC version cutoff from 4.8 to 11.0 to work around compiler segfault [ Upstream commit 1400c87e6cac47eb243f260352c854474d9a9073 ] Due to pending percpu improvements in -next, GCC9 and GCC10 are crashing during the build with: lib/zstd/compress/huf_compress.c:1033:1: internal compiler error: Segmentation fault 1033 | { | ^ Please submit a full bug report, with preprocessed source if appropriate. See for instructions. The DYNAMIC_BMI2 feature is a known-challenging feature of the ZSTD library, with an existing GCC quirk turning it off for GCC versions below 4.8. Increase the DYNAMIC_BMI2 version cutoff to GCC 11.0 - GCC 10.5 is the last version known to crash. Reported-by: Michael Kelley Debugged-by: Ard Biesheuvel Signed-off-by: Ingo Molnar Cc: https://lore.kernel.org/r/SN6PR02MB415723FBCD79365E8D72CA5FD4D82@SN6PR02MB4157.namprd02.prod.outlook.com Cc: Linus Torvalds Signed-off-by: Sasha Levin --- lib/zstd/common/portability_macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/zstd/common/portability_macros.h b/lib/zstd/common/portability_macros.h index 0e3b2c0a527d..0dde8bf56595 100644 --- a/lib/zstd/common/portability_macros.h +++ b/lib/zstd/common/portability_macros.h @@ -55,7 +55,7 @@ #ifndef DYNAMIC_BMI2 #if ((defined(__clang__) && __has_attribute(__target__)) \ || (defined(__GNUC__) \ - && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))) \ + && (__GNUC__ >= 11))) \ && (defined(__x86_64__) || defined(_M_X64)) \ && !defined(__BMI2__) # define DYNAMIC_BMI2 1 From 4a29465fbe6019d9b5a07e58177c97f14063439d Mon Sep 17 00:00:00 2001 From: Zhang Heng Date: Fri, 17 Jan 2025 09:43:43 +0800 Subject: [PATCH 047/606] ASoC: SOF: topology: Use krealloc_array() to replace krealloc() [ Upstream commit a05143a8f713d9ae6abc41141dac52c66fca8b06 ] Use krealloc_array() to replace krealloc() with multiplication. krealloc_array() has multiply overflow check, which will be safer. Signed-off-by: Zhang Heng Link: https://patch.msgid.link/20250117014343.451503-1-zhangheng@kylinos.cn Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/sof/topology.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index cf1e63daad86..7afded323150 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1267,8 +1267,8 @@ static int sof_widget_parse_tokens(struct snd_soc_component *scomp, struct snd_s struct snd_sof_tuple *new_tuples; num_tuples += token_list[object_token_list[i]].count * (num_sets - 1); - new_tuples = krealloc(swidget->tuples, - sizeof(*new_tuples) * num_tuples, GFP_KERNEL); + new_tuples = krealloc_array(swidget->tuples, + num_tuples, sizeof(*new_tuples), GFP_KERNEL); if (!new_tuples) { ret = -ENOMEM; goto err; From 520e0371d1dc272bafffecd4190516d92367dea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Sat, 1 Feb 2025 12:38:45 +0100 Subject: [PATCH 048/606] HID: pidff: Convert infinite length from Linux API to PID standard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 37e0591fe44dce39d1ebc7a82d5b6e4dba1582eb ] Software uses 0 as de-facto infinite lenght on Linux FF apis (SDL), Linux doesn't actually define anythi as of now, while USB PID defines NULL (0xffff). Most PID devices do not expect a 0-length effect and can't interpret it as infinite. This change fixes Force Feedback for most PID compliant devices. As most games depend on updating the values of already playing infinite effects, this is crucial to ensure they will actually work. Previously, users had to rely on third-party software to do this conversion and make their PID devices usable. Co-developed-by: Makarenko Oleg Signed-off-by: Makarenko Oleg Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Tested-by: Paul Dino Jones Tested-by: Cristóferson Bueno Tested-by: Pablo Cisneros Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index 3b4ee21cd811..5fe4422bb5ba 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -21,6 +21,7 @@ #include "usbhid.h" #define PID_EFFECTS_MAX 64 +#define PID_INFINITE 0xffff /* Report usage table used to put reports into an array */ @@ -301,7 +302,12 @@ static void pidff_set_effect_report(struct pidff_device *pidff, pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; pidff->set_effect_type->value[0] = pidff->create_new_effect_type->value[0]; - pidff->set_effect[PID_DURATION].value[0] = effect->replay.length; + + /* Convert infinite length from Linux API (0) + to PID standard (NULL) if needed */ + pidff->set_effect[PID_DURATION].value[0] = + effect->replay.length == 0 ? PID_INFINITE : effect->replay.length; + pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = effect->trigger.button; pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = effect->trigger.interval; From a08ee3c7eecae24eb44a4afac6857e1c8ce044c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Sat, 1 Feb 2025 12:38:46 +0100 Subject: [PATCH 049/606] HID: pidff: Do not send effect envelope if it's empty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 8876fc1884f5b39550c8387ff3176396c988541d ] Envelope struct is always initialized, but the envelope itself is optional as described in USB PID Device class definition 1.0. 5.1.1.1 Type Specific Block Offsets ... 4) Effects that do not use Condition Blocks use 1 Parameter Block and an *optional* Envelope Block. Sending out "empty" envelope breaks force feedback on some devices with games that use SINE effect + offset to emulate constant force effect, as well as generally breaking Constant/Periodic effects. One of the affected brands is Moza Racing. This change prevents the envelope from being sent if it contains all 0 values while keeping the old behavior of only sending it, if it differs from the old one. Changes in v6: - Simplify the checks to make them clearer - Fix possible null pointer dereference while calling pidff_needs_set_envelope Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Tested-by: Paul Dino Jones Tested-by: Cristóferson Bueno Tested-by: Pablo Cisneros Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 42 +++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index 5fe4422bb5ba..a01c1b2ab2f4 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -262,10 +262,22 @@ static void pidff_set_envelope_report(struct pidff_device *pidff, static int pidff_needs_set_envelope(struct ff_envelope *envelope, struct ff_envelope *old) { - return envelope->attack_level != old->attack_level || - envelope->fade_level != old->fade_level || + bool needs_new_envelope; + needs_new_envelope = envelope->attack_level != 0 || + envelope->fade_level != 0 || + envelope->attack_length != 0 || + envelope->fade_length != 0; + + if (!needs_new_envelope) + return false; + + if (!old) + return needs_new_envelope; + + return envelope->attack_level != old->attack_level || + envelope->fade_level != old->fade_level || envelope->attack_length != old->attack_length || - envelope->fade_length != old->fade_length; + envelope->fade_length != old->fade_length; } /* @@ -580,11 +592,9 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect, pidff_set_effect_report(pidff, effect); if (!old || pidff_needs_set_constant(effect, old)) pidff_set_constant_force_report(pidff, effect); - if (!old || - pidff_needs_set_envelope(&effect->u.constant.envelope, - &old->u.constant.envelope)) - pidff_set_envelope_report(pidff, - &effect->u.constant.envelope); + if (pidff_needs_set_envelope(&effect->u.constant.envelope, + old ? &old->u.constant.envelope : NULL)) + pidff_set_envelope_report(pidff, &effect->u.constant.envelope); break; case FF_PERIODIC: @@ -619,11 +629,9 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect, pidff_set_effect_report(pidff, effect); if (!old || pidff_needs_set_periodic(effect, old)) pidff_set_periodic_report(pidff, effect); - if (!old || - pidff_needs_set_envelope(&effect->u.periodic.envelope, - &old->u.periodic.envelope)) - pidff_set_envelope_report(pidff, - &effect->u.periodic.envelope); + if (pidff_needs_set_envelope(&effect->u.periodic.envelope, + old ? &old->u.periodic.envelope : NULL)) + pidff_set_envelope_report(pidff, &effect->u.periodic.envelope); break; case FF_RAMP: @@ -637,11 +645,9 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect, pidff_set_effect_report(pidff, effect); if (!old || pidff_needs_set_ramp(effect, old)) pidff_set_ramp_force_report(pidff, effect); - if (!old || - pidff_needs_set_envelope(&effect->u.ramp.envelope, - &old->u.ramp.envelope)) - pidff_set_envelope_report(pidff, - &effect->u.ramp.envelope); + if (pidff_needs_set_envelope(&effect->u.ramp.envelope, + old ? &old->u.ramp.envelope : NULL)) + pidff_set_envelope_report(pidff, &effect->u.ramp.envelope); break; case FF_SPRING: From bf284760372bd3f044c3f986a97726f4cb079492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Sat, 1 Feb 2025 12:38:48 +0100 Subject: [PATCH 050/606] HID: pidff: Add MISSING_DELAY quirk and its detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 2d5c7ce5bf4cc27db41632f357f682d0ee4518e7 ] A lot of devices do not include this field, and it's seldom used in force feedback implementations. I tested about three dozen applications and none of them make use of the delay. This fixes initialization of a lot of PID wheels like Cammus, VRS, FFBeast This change has no effect on fully compliant devices Co-developed-by: Makarenko Oleg Signed-off-by: Makarenko Oleg Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Tested-by: Paul Dino Jones Tested-by: Cristóferson Bueno Tested-by: Pablo Cisneros Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 33 ++++++++++++++++++++++++++++----- include/linux/hid.h | 3 +++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index a01c1b2ab2f4..929f5967e7cb 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -185,6 +185,8 @@ struct pidff_device { int operation_id[sizeof(pidff_effect_operation_status)]; int pid_id[PID_EFFECTS_MAX]; + + u32 quirks; }; /* @@ -329,7 +331,10 @@ static void pidff_set_effect_report(struct pidff_device *pidff, pidff->effect_direction->value[0] = pidff_rescale(effect->direction, 0xffff, pidff->effect_direction); - pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay; + + /* Omit setting delay field if it's missing */ + if (!(pidff->quirks & HID_PIDFF_QUIRK_MISSING_DELAY)) + pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay; hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT], HID_REQ_SET_REPORT); @@ -748,7 +753,10 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude) pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0; pidff_set(&pidff->set_effect[PID_GAIN], magnitude); pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1; - pidff->set_effect[PID_START_DELAY].value[0] = 0; + + /* Omit setting delay field if it's missing */ + if (!(pidff->quirks & HID_PIDFF_QUIRK_MISSING_DELAY)) + pidff->set_effect[PID_START_DELAY].value[0] = 0; hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT], HID_REQ_SET_REPORT); @@ -771,6 +779,7 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table, struct hid_report *report, int count, int strict) { int i, j, k, found; + int return_value = 0; for (k = 0; k < count; k++) { found = 0; @@ -795,12 +804,17 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table, if (found) break; } - if (!found && strict) { + if (!found && table[k] == pidff_set_effect[PID_START_DELAY]) { + pr_debug("Delay field not found, but that's OK\n"); + pr_debug("Setting MISSING_DELAY quirk\n"); + return_value |= HID_PIDFF_QUIRK_MISSING_DELAY; + } + else if (!found && strict) { pr_debug("failed to locate %d\n", k); return -1; } } - return 0; + return return_value; } /* @@ -1075,11 +1089,19 @@ static int pidff_find_effects(struct pidff_device *pidff, static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) { int envelope_ok = 0; + int status = 0; - if (PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1)) { + /* Save info about the device not having the DELAY ffb field. */ + status = PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1); + if (status == -1) { hid_err(pidff->hid, "unknown set_effect report layout\n"); return -ENODEV; } + pidff->quirks |= status; + + if (status & HID_PIDFF_QUIRK_MISSING_DELAY) + hid_dbg(pidff->hid, "Adding MISSING_DELAY quirk\n"); + PIDFF_FIND_FIELDS(block_load, PID_BLOCK_LOAD, 0); if (!pidff->block_load[PID_EFFECT_BLOCK_INDEX].value) { @@ -1323,6 +1345,7 @@ int hid_pidff_init(struct hid_device *hid) ff->playback = pidff_playback; hid_info(dev, "Force feedback for USB HID PID devices by Anssi Hannula \n"); + hid_dbg(dev, "Active quirks mask: 0x%x\n", pidff->quirks); hid_device_io_stop(hid); diff --git a/include/linux/hid.h b/include/linux/hid.h index 774cb25dec34..744a498462ce 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -1218,6 +1218,9 @@ int hid_pidff_init(struct hid_device *hid); #define hid_pidff_init NULL #endif +/* HID PIDFF quirks */ +#define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0) + #define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__) #define hid_err(hid, fmt, ...) \ From 1830b4166f0178452e1b28c5a58ba1551bd3626d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Sat, 1 Feb 2025 12:38:49 +0100 Subject: [PATCH 051/606] HID: pidff: Add MISSING_PBO quirk and its detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit fc7c154e9bb3c2b98875cfc565406f4787e3b7a4 ] Some devices with only one axis are missing PARAMETER_BLOCK_OFFSET field for conditional effects. They can only have one axis, so we're limiting the max_axis when setting the report for those effects. Automatic detection ensures compatibility even if such device won't be explicitly defined in the kernel. Fixes initialization of VRS DirectForce PRO and possibly other devices. Changes in v6: - Fixed NULL pointer dereference. When PBO is missing, make sure not to set it anyway Co-developed-by: Makarenko Oleg Signed-off-by: Makarenko Oleg Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Tested-by: Paul Dino Jones Tested-by: Cristóferson Bueno Tested-by: Pablo Cisneros Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 47 +++++++++++++++++++++------------- include/linux/hid.h | 1 + 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index 929f5967e7cb..503b22feacdb 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -391,13 +391,19 @@ static int pidff_needs_set_periodic(struct ff_effect *effect, static void pidff_set_condition_report(struct pidff_device *pidff, struct ff_effect *effect) { - int i; + int i, max_axis; + + /* Devices missing Parameter Block Offset can only have one axis */ + max_axis = pidff->quirks & HID_PIDFF_QUIRK_MISSING_PBO ? 1 : 2; pidff->set_condition[PID_EFFECT_BLOCK_INDEX].value[0] = pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; - for (i = 0; i < 2; i++) { - pidff->set_condition[PID_PARAM_BLOCK_OFFSET].value[0] = i; + for (i = 0; i < max_axis; i++) { + /* Omit Parameter Block Offset if missing */ + if (!(pidff->quirks & HID_PIDFF_QUIRK_MISSING_PBO)) + pidff->set_condition[PID_PARAM_BLOCK_OFFSET].value[0] = i; + pidff_set_signed(&pidff->set_condition[PID_CP_OFFSET], effect->u.condition[i].center); pidff_set_signed(&pidff->set_condition[PID_POS_COEFFICIENT], @@ -809,6 +815,11 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table, pr_debug("Setting MISSING_DELAY quirk\n"); return_value |= HID_PIDFF_QUIRK_MISSING_DELAY; } + else if (!found && table[k] == pidff_set_condition[PID_PARAM_BLOCK_OFFSET]) { + pr_debug("PBO field not found, but that's OK\n"); + pr_debug("Setting MISSING_PBO quirk\n"); + return_value |= HID_PIDFF_QUIRK_MISSING_PBO; + } else if (!found && strict) { pr_debug("failed to locate %d\n", k); return -1; @@ -1088,7 +1099,6 @@ static int pidff_find_effects(struct pidff_device *pidff, */ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) { - int envelope_ok = 0; int status = 0; /* Save info about the device not having the DELAY ffb field. */ @@ -1119,13 +1129,10 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) return -ENODEV; } - if (!PIDFF_FIND_FIELDS(set_envelope, PID_SET_ENVELOPE, 1)) - envelope_ok = 1; - if (pidff_find_special_fields(pidff) || pidff_find_effects(pidff, dev)) return -ENODEV; - if (!envelope_ok) { + if (PIDFF_FIND_FIELDS(set_envelope, PID_SET_ENVELOPE, 1)) { if (test_and_clear_bit(FF_CONSTANT, dev->ffbit)) hid_warn(pidff->hid, "has constant effect but no envelope\n"); @@ -1150,16 +1157,20 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) clear_bit(FF_RAMP, dev->ffbit); } - if ((test_bit(FF_SPRING, dev->ffbit) || - test_bit(FF_DAMPER, dev->ffbit) || - test_bit(FF_FRICTION, dev->ffbit) || - test_bit(FF_INERTIA, dev->ffbit)) && - PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) { - hid_warn(pidff->hid, "unknown condition effect layout\n"); - clear_bit(FF_SPRING, dev->ffbit); - clear_bit(FF_DAMPER, dev->ffbit); - clear_bit(FF_FRICTION, dev->ffbit); - clear_bit(FF_INERTIA, dev->ffbit); + if (test_bit(FF_SPRING, dev->ffbit) || + test_bit(FF_DAMPER, dev->ffbit) || + test_bit(FF_FRICTION, dev->ffbit) || + test_bit(FF_INERTIA, dev->ffbit)) { + status = PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1); + + if (status < 0) { + hid_warn(pidff->hid, "unknown condition effect layout\n"); + clear_bit(FF_SPRING, dev->ffbit); + clear_bit(FF_DAMPER, dev->ffbit); + clear_bit(FF_FRICTION, dev->ffbit); + clear_bit(FF_INERTIA, dev->ffbit); + } + pidff->quirks |= status; } if (test_bit(FF_PERIODIC, dev->ffbit) && diff --git a/include/linux/hid.h b/include/linux/hid.h index 744a498462ce..8876d5f0cd87 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -1220,6 +1220,7 @@ int hid_pidff_init(struct hid_device *hid); /* HID PIDFF quirks */ #define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0) +#define HID_PIDFF_QUIRK_MISSING_PBO BIT(1) #define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__) From b2f378891cb28dba58c5b2d5c70be80f6d36ae0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Sat, 1 Feb 2025 12:38:50 +0100 Subject: [PATCH 052/606] HID: pidff: Add PERMISSIVE_CONTROL quirk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit a4119108d2530747e61c7cbf52e2affd089cb1f6 ] With this quirk, a PID device isn't required to have a strict logical_minimum of 1 for the the PID_DEVICE_CONTROL usage page. Some devices come with weird values in their device descriptors and this quirk enables their initialization even if the logical minimum of the DEVICE_CONTROL page is not 1. Fixes initialization of VRS Direct Force Pro Changes in v6: - Change quirk name to better reflect it's intention Co-developed-by: Makarenko Oleg Signed-off-by: Makarenko Oleg Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Tested-by: Paul Dino Jones Tested-by: Cristóferson Bueno Tested-by: Pablo Cisneros Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 3 ++- include/linux/hid.h | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index 503b22feacdb..5a57ba0d7026 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -969,7 +969,8 @@ static int pidff_find_special_fields(struct pidff_device *pidff) 0x57, 0); pidff->device_control = pidff_find_special_field(pidff->reports[PID_DEVICE_CONTROL], - 0x96, 1); + 0x96, !(pidff->quirks & HID_PIDFF_QUIRK_PERMISSIVE_CONTROL)); + pidff->block_load_status = pidff_find_special_field(pidff->reports[PID_BLOCK_LOAD], 0x8b, 1); diff --git a/include/linux/hid.h b/include/linux/hid.h index 8876d5f0cd87..a06f38c1441a 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -1219,8 +1219,9 @@ int hid_pidff_init(struct hid_device *hid); #endif /* HID PIDFF quirks */ -#define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0) -#define HID_PIDFF_QUIRK_MISSING_PBO BIT(1) +#define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0) +#define HID_PIDFF_QUIRK_MISSING_PBO BIT(1) +#define HID_PIDFF_QUIRK_PERMISSIVE_CONTROL BIT(2) #define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__) From 123e94f66d2a434e87186c1a4289e848f8cec055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Sat, 1 Feb 2025 12:38:51 +0100 Subject: [PATCH 053/606] HID: pidff: Add hid_pidff_init_with_quirks and export as GPL symbol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 36de0164bbaff1484288e84ac5df5cff00580263 ] This lays out a way to provide an initial set of quirks to enable before device initialization takes place. GPL symbol export needed for the possibility of building HID drivers which use this function as modules. Adding a wrapper function to ensure compatibility with the old behavior of hid_pidff_init. Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Tested-by: Paul Dino Jones Tested-by: Cristóferson Bueno Tested-by: Pablo Cisneros Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 15 ++++++++++++++- include/linux/hid.h | 2 ++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index 5a57ba0d7026..b8c2ba0a930c 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -1268,8 +1268,9 @@ static int pidff_check_autocenter(struct pidff_device *pidff, /* * Check if the device is PID and initialize it + * Set initial quirks */ -int hid_pidff_init(struct hid_device *hid) +int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks) { struct pidff_device *pidff; struct hid_input *hidinput = list_entry(hid->inputs.next, @@ -1291,6 +1292,7 @@ int hid_pidff_init(struct hid_device *hid) return -ENOMEM; pidff->hid = hid; + pidff->quirks = initial_quirks; hid_device_io_start(hid); @@ -1369,3 +1371,14 @@ int hid_pidff_init(struct hid_device *hid) kfree(pidff); return error; } +EXPORT_SYMBOL_GPL(hid_pidff_init_with_quirks); + +/* + * Check if the device is PID and initialize it + * Wrapper made to keep the compatibility with old + * init function + */ +int hid_pidff_init(struct hid_device *hid) +{ + return hid_pidff_init_with_quirks(hid, 0); +} diff --git a/include/linux/hid.h b/include/linux/hid.h index a06f38c1441a..3f776ab47e27 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -1214,8 +1214,10 @@ void hid_quirks_exit(__u16 bus); #ifdef CONFIG_HID_PID int hid_pidff_init(struct hid_device *hid); +int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks); #else #define hid_pidff_init NULL +#define hid_pidff_init_with_quirks NULL #endif /* HID PIDFF quirks */ From fd6055c1a10311cb609726e27e8a259a0132ee3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Sat, 1 Feb 2025 12:38:52 +0100 Subject: [PATCH 054/606] HID: pidff: Add FIX_WHEEL_DIRECTION quirk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 3051bf5ec773b803c474ea556b57d678a8885be3 ] Most steering wheels simply ignore DIRECTION field, but some try to be compliant with the PID standard and use it in force calculations. Games often ignore setting this field properly and/or there can be issues with dinput8 -> wine -> SDL -> Linux API translation, and this value can be incorrect. This can lead to partial/complete loss of Force Feedback or even unexpected force reversal. Sadly, this quirk can't be detected automatically without sending out effects that would move an axis. This fixes FFB on Moza Racing devices and others where effect direction is not simply ignored. Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 12 +++++++++--- include/linux/hid.h | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index b8c2ba0a930c..a37cf852a283 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -137,6 +137,9 @@ static const u8 pidff_block_load_status[] = { 0x8c, 0x8d }; #define PID_EFFECT_STOP 1 static const u8 pidff_effect_operation_status[] = { 0x79, 0x7b }; +/* Polar direction 90 degrees (North) */ +#define PIDFF_FIXED_WHEEL_DIRECTION 0x4000 + struct pidff_usage { struct hid_field *field; s32 *value; @@ -328,9 +331,12 @@ static void pidff_set_effect_report(struct pidff_device *pidff, pidff->set_effect[PID_GAIN].value[0] = pidff->set_effect[PID_GAIN].field->logical_maximum; pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1; - pidff->effect_direction->value[0] = - pidff_rescale(effect->direction, 0xffff, - pidff->effect_direction); + + /* Use fixed direction if needed */ + pidff->effect_direction->value[0] = pidff_rescale( + pidff->quirks & HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION ? + PIDFF_FIXED_WHEEL_DIRECTION : effect->direction, + 0xffff, pidff->effect_direction); /* Omit setting delay field if it's missing */ if (!(pidff->quirks & HID_PIDFF_QUIRK_MISSING_DELAY)) diff --git a/include/linux/hid.h b/include/linux/hid.h index 3f776ab47e27..e3a55fd4e9fc 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -1224,6 +1224,7 @@ int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks); #define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0) #define HID_PIDFF_QUIRK_MISSING_PBO BIT(1) #define HID_PIDFF_QUIRK_PERMISSIVE_CONTROL BIT(2) +#define HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION BIT(3) #define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__) From c1fde337b317f0a226de92803288741c30799eb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Sat, 1 Feb 2025 12:38:54 +0100 Subject: [PATCH 055/606] HID: Add hid-universal-pidff driver and supported device ids MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit f06bf8d94fffbb544b1cb5402c92e0a075f0d420 ] Extend pidff compatibility, usable button range, manage pidff quirks and set improved fuzz/flat default for high precision devices. Possibility of fixing device descriptors in the future if such needs arises. As many of PID devices are quite similar and not dependent on custom drivers, this one can handle all of PID devices which need special care. Numerous sim racing/sim flight bases report a lot of buttons in excess of 100. Moza Racing exposes 128 of them and thus the need to extend the available range. All the included devices were tested and confirmed working with the help of the sim racing community. Changes in v6: - Support "split" devices with a separate "input device" for buttons - Fixed comment styling Co-developed-by: Makarenko Oleg Signed-off-by: Makarenko Oleg Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Tested-by: Cristóferson Bueno Tested-by: Pablo Cisneros Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/Kconfig | 14 +++ drivers/hid/Makefile | 1 + drivers/hid/hid-ids.h | 31 +++++ drivers/hid/hid-universal-pidff.c | 192 ++++++++++++++++++++++++++++++ 4 files changed, 238 insertions(+) create mode 100644 drivers/hid/hid-universal-pidff.c diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 979ebe69c8e3..ffbeb39341e1 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -1202,6 +1202,20 @@ config HID_U2FZERO allow setting the brightness to anything but 1, which will trigger a single blink and immediately reset back to 0. +config HID_UNIVERSAL_PIDFF + tristate "universal-pidff: extended USB PID driver compatibility and usage" + depends on USB_HID + depends on HID_PID + help + Extended PID support for selected devices. + + Contains report fixups, extended usable button range and + pidff quirk management to extend compatibility with slightly + non-compliant USB PID devices and better fuzz/flat values for + high precision direct drive devices. + + Supports Moza Racing, Cammus, VRS, FFBeast and more. + config HID_WACOM tristate "Wacom Intuos/Graphire tablet support (USB)" depends on USB_HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index f5a06b62b385..dcb81891c725 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -138,6 +138,7 @@ hid-uclogic-objs := hid-uclogic-core.o \ hid-uclogic-params.o obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o obj-$(CONFIG_HID_UDRAW_PS3) += hid-udraw-ps3.o +obj-$(CONFIG_HID_UNIVERSAL_PIDFF) += hid-universal-pidff.o obj-$(CONFIG_HID_LED) += hid-led.o obj-$(CONFIG_HID_XIAOMI) += hid-xiaomi.o obj-$(CONFIG_HID_XINMO) += hid-xinmo.o diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 09090803f1dd..8e721ec3faaf 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -262,6 +262,10 @@ #define USB_DEVICE_ID_BTC_EMPREX_REMOTE 0x5578 #define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2 0x5577 +#define USB_VENDOR_ID_CAMMUS 0x3416 +#define USB_DEVICE_ID_CAMMUS_C5 0x0301 +#define USB_DEVICE_ID_CAMMUS_C12 0x0302 + #define USB_VENDOR_ID_CANDO 0x2087 #define USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH 0x0703 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 @@ -453,6 +457,11 @@ #define USB_VENDOR_ID_EVISION 0x320f #define USB_DEVICE_ID_EVISION_ICL01 0x5041 +#define USB_VENDOR_ID_FFBEAST 0x045b +#define USB_DEVICE_ID_FFBEAST_JOYSTICK 0x58f9 +#define USB_DEVICE_ID_FFBEAST_RUDDER 0x5968 +#define USB_DEVICE_ID_FFBEAST_WHEEL 0x59d7 + #define USB_VENDOR_ID_FLATFROG 0x25b5 #define USB_DEVICE_ID_MULTITOUCH_3200 0x0002 @@ -812,6 +821,13 @@ #define I2C_DEVICE_ID_LG_8001 0x8001 #define I2C_DEVICE_ID_LG_7010 0x7010 +#define USB_VENDOR_ID_LITE_STAR 0x11ff +#define USB_DEVICE_ID_PXN_V10 0x3245 +#define USB_DEVICE_ID_PXN_V12 0x1212 +#define USB_DEVICE_ID_PXN_V12_LITE 0x1112 +#define USB_DEVICE_ID_PXN_V12_LITE_2 0x1211 +#define USB_DEVICE_LITE_STAR_GT987_FF 0x2141 + #define USB_VENDOR_ID_LOGITECH 0x046d #define USB_DEVICE_ID_LOGITECH_Z_10_SPK 0x0a07 #define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e @@ -959,6 +975,18 @@ #define USB_VENDOR_ID_MONTEREY 0x0566 #define USB_DEVICE_ID_GENIUS_KB29E 0x3004 +#define USB_VENDOR_ID_MOZA 0x346e +#define USB_DEVICE_ID_MOZA_R3 0x0005 +#define USB_DEVICE_ID_MOZA_R3_2 0x0015 +#define USB_DEVICE_ID_MOZA_R5 0x0004 +#define USB_DEVICE_ID_MOZA_R5_2 0x0014 +#define USB_DEVICE_ID_MOZA_R9 0x0002 +#define USB_DEVICE_ID_MOZA_R9_2 0x0012 +#define USB_DEVICE_ID_MOZA_R12 0x0006 +#define USB_DEVICE_ID_MOZA_R12_2 0x0016 +#define USB_DEVICE_ID_MOZA_R16_R21 0x0000 +#define USB_DEVICE_ID_MOZA_R16_R21_2 0x0010 + #define USB_VENDOR_ID_MSI 0x1770 #define USB_DEVICE_ID_MSI_GT683R_LED_PANEL 0xff00 @@ -1360,6 +1388,9 @@ #define USB_DEVICE_ID_VELLEMAN_K8061_FIRST 0x8061 #define USB_DEVICE_ID_VELLEMAN_K8061_LAST 0x8068 +#define USB_VENDOR_ID_VRS 0x0483 +#define USB_DEVICE_ID_VRS_DFP 0xa355 + #define USB_VENDOR_ID_VTL 0x0306 #define USB_DEVICE_ID_VTL_MULTITOUCH_FF3F 0xff3f diff --git a/drivers/hid/hid-universal-pidff.c b/drivers/hid/hid-universal-pidff.c new file mode 100644 index 000000000000..55aad2e4ac1b --- /dev/null +++ b/drivers/hid/hid-universal-pidff.c @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * HID UNIVERSAL PIDFF + * hid-pidff wrapper for PID-enabled devices + * Handles device reports, quirks and extends usable button range + * + * Copyright (c) 2024, 2025 Makarenko Oleg + * Copyright (c) 2024, 2025 Tomasz Pakuła + */ + +#include +#include +#include +#include +#include "hid-ids.h" + +#define JOY_RANGE (BTN_DEAD - BTN_JOYSTICK + 1) + +/* + * Map buttons manually to extend the default joystick button limit + */ +static int universal_pidff_input_mapping(struct hid_device *hdev, + struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, + unsigned long **bit, int *max) +{ + if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) + return 0; + + if (field->application != HID_GD_JOYSTICK) + return 0; + + int button = ((usage->hid - 1) & HID_USAGE); + int code = button + BTN_JOYSTICK; + + /* Detect the end of JOYSTICK buttons range */ + if (code > BTN_DEAD) + code = button + KEY_NEXT_FAVORITE - JOY_RANGE; + + /* + * Map overflowing buttons to KEY_RESERVED to not ignore + * them and let them still trigger MSC_SCAN + */ + if (code > KEY_MAX) + code = KEY_RESERVED; + + hid_map_usage(hi, usage, bit, max, EV_KEY, code); + hid_dbg(hdev, "Button %d: usage %d", button, code); + return 1; +} + +/* + * Check if the device is PID and initialize it + * Add quirks after initialisation + */ +static int universal_pidff_probe(struct hid_device *hdev, + const struct hid_device_id *id) +{ + int i, error; + error = hid_parse(hdev); + if (error) { + hid_err(hdev, "HID parse failed\n"); + goto err; + } + + error = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); + if (error) { + hid_err(hdev, "HID hw start failed\n"); + goto err; + } + + /* Check if device contains PID usage page */ + error = 1; + for (i = 0; i < hdev->collection_size; i++) + if ((hdev->collection[i].usage & HID_USAGE_PAGE) == HID_UP_PID) { + error = 0; + hid_dbg(hdev, "PID usage page found\n"); + break; + } + + /* + * Do not fail as this might be the second "device" + * just for additional buttons/axes. Exit cleanly if force + * feedback usage page wasn't found (included devices were + * tested and confirmed to be USB PID after all). + */ + if (error) { + hid_dbg(hdev, "PID usage page not found in the descriptor\n"); + return 0; + } + + /* Check if HID_PID support is enabled */ + int (*init_function)(struct hid_device *, __u32); + init_function = hid_pidff_init_with_quirks; + + if (!init_function) { + hid_warn(hdev, "HID_PID support not enabled!\n"); + return 0; + } + + error = init_function(hdev, id->driver_data); + if (error) { + hid_warn(hdev, "Error initialising force feedback\n"); + goto err; + } + + hid_info(hdev, "Universal pidff driver loaded sucesfully!"); + + return 0; +err: + return error; +} + +static int universal_pidff_input_configured(struct hid_device *hdev, + struct hid_input *hidinput) +{ + int axis; + struct input_dev *input = hidinput->input; + + if (!input->absinfo) + return 0; + + /* Decrease fuzz and deadzone on available axes */ + for (axis = ABS_X; axis <= ABS_BRAKE; axis++) { + if (!test_bit(axis, input->absbit)) + continue; + + input_set_abs_params(input, axis, + input->absinfo[axis].minimum, + input->absinfo[axis].maximum, + axis == ABS_X ? 0 : 8, 0); + } + + /* Remove fuzz and deadzone from the second joystick axis */ + if (hdev->vendor == USB_VENDOR_ID_FFBEAST && + hdev->product == USB_DEVICE_ID_FFBEAST_JOYSTICK) + input_set_abs_params(input, ABS_Y, + input->absinfo[ABS_Y].minimum, + input->absinfo[ABS_Y].maximum, 0, 0); + + return 0; +} + +static const struct hid_device_id universal_pidff_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R3), + .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION }, + { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R3_2), + .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION }, + { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R5), + .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION }, + { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R5_2), + .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION }, + { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R9), + .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION }, + { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R9_2), + .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION }, + { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R12), + .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION }, + { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R12_2), + .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION }, + { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R16_R21), + .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION }, + { HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R16_R21_2), + .driver_data = HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION }, + { HID_USB_DEVICE(USB_VENDOR_ID_CAMMUS, USB_DEVICE_ID_CAMMUS_C5) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CAMMUS, USB_DEVICE_ID_CAMMUS_C12) }, + { HID_USB_DEVICE(USB_VENDOR_ID_VRS, USB_DEVICE_ID_VRS_DFP), + .driver_data = HID_PIDFF_QUIRK_PERMISSIVE_CONTROL }, + { HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_JOYSTICK), }, + { HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_RUDDER), }, + { HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_WHEEL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V10) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12_LITE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12_LITE_2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_LITE_STAR_GT987_FF) }, + { } +}; +MODULE_DEVICE_TABLE(hid, universal_pidff_devices); + +static struct hid_driver universal_pidff = { + .name = "hid-universal-pidff", + .id_table = universal_pidff_devices, + .input_mapping = universal_pidff_input_mapping, + .probe = universal_pidff_probe, + .input_configured = universal_pidff_input_configured +}; +module_hid_driver(universal_pidff); + +MODULE_DESCRIPTION("Universal driver for USB PID Force Feedback devices"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Makarenko Oleg "); +MODULE_AUTHOR("Tomasz Pakuła "); From 4d5bcca217aededfa6fde145f91ba9a39f289ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Sat, 1 Feb 2025 12:38:56 +0100 Subject: [PATCH 056/606] HID: pidff: Add PERIODIC_SINE_ONLY quirk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit abdbf8764f4962af2a910abb3a213ecf304a73d3 ] Some devices only support SINE periodic effect although they advertise support for all PERIODIC effect in their HID descriptor. Some just do nothing when trying to play such an effect (upload goes fine), some express undefined behavior like turning to one side. This quirk forces all the periodic effects to be uploaded as SINE. This is acceptable as all these effects are similar in nature and are mostly used as rumble. SINE is the most popular with others seldom used (especially SAW_UP and SAW_DOWN). Fixes periodic effects for PXN and LITE STAR wheels Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Tested-by: Cristóferson Bueno Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/hid-universal-pidff.c | 15 ++++++++++----- drivers/hid/usbhid/hid-pidff.c | 3 +++ include/linux/hid.h | 1 + 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/hid/hid-universal-pidff.c b/drivers/hid/hid-universal-pidff.c index 55aad2e4ac1b..7ef5ab9146b1 100644 --- a/drivers/hid/hid-universal-pidff.c +++ b/drivers/hid/hid-universal-pidff.c @@ -168,11 +168,16 @@ static const struct hid_device_id universal_pidff_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_JOYSTICK), }, { HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_RUDDER), }, { HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_WHEEL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V10) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12_LITE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12_LITE_2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_LITE_STAR_GT987_FF) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V10), + .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY }, + { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12), + .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY }, + { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12_LITE), + .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY }, + { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12_LITE_2), + .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY }, + { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_LITE_STAR_GT987_FF), + .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY }, { } }; MODULE_DEVICE_TABLE(hid, universal_pidff_devices); diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index a37cf852a283..4c94d8cbac43 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -637,6 +637,9 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect, return -EINVAL; } + if (pidff->quirks & HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY) + type_id = PID_SINE; + error = pidff_request_effect_upload(pidff, pidff->type_id[type_id]); if (error) diff --git a/include/linux/hid.h b/include/linux/hid.h index e3a55fd4e9fc..38e161a827bd 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -1225,6 +1225,7 @@ int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks); #define HID_PIDFF_QUIRK_MISSING_PBO BIT(1) #define HID_PIDFF_QUIRK_PERMISSIVE_CONTROL BIT(2) #define HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION BIT(3) +#define HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY BIT(4) #define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__) From be706a48bb7896d4130edc82811233d1d62158e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Sat, 1 Feb 2025 12:39:02 +0100 Subject: [PATCH 057/606] HID: pidff: Fix null pointer dereference in pidff_find_fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 22a05462c3d0eee15154faf8d13c49e6295270a5 ] This function triggered a null pointer dereference if used to search for a report that isn't implemented on the device. This happened both for optional and required reports alike. The same logic was applied to pidff_find_special_field and although pidff_init_fields should return an error earlier if one of the required reports is missing, future modifications could change this logic and resurface this possible null pointer dereference again. LKML bug report: https://lore.kernel.org/all/CAL-gK7f5=R0nrrQdPtaZZr1fd-cdAMbDMuZ_NLA8vM0SX+nGSw@mail.gmail.com Reported-by: Nolan Nicholson Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Tested-by: Paul Dino Jones Tested-by: Cristóferson Bueno Tested-by: Pablo Cisneros Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index 4c94d8cbac43..25dbed076f53 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -793,6 +793,11 @@ static void pidff_set_autocenter(struct input_dev *dev, u16 magnitude) static int pidff_find_fields(struct pidff_usage *usage, const u8 *table, struct hid_report *report, int count, int strict) { + if (!report) { + pr_debug("pidff_find_fields, null report\n"); + return -1; + } + int i, j, k, found; int return_value = 0; @@ -917,6 +922,11 @@ static int pidff_reports_ok(struct pidff_device *pidff) static struct hid_field *pidff_find_special_field(struct hid_report *report, int usage, int enforce_min) { + if (!report) { + pr_debug("pidff_find_special_field, null report\n"); + return NULL; + } + int i; for (i = 0; i < report->maxfield; i++) { From fb44392bd5a4dde1c5dc61bda6c1631a8c184e38 Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Sat, 8 Feb 2025 23:46:01 +0200 Subject: [PATCH 058/606] ALSA: hda: intel: Fix Optimus when GPU has no sound [ Upstream commit 2b360ba9a4936486380bc30d1eabceb40a714d98 ] quirk_nvidia_hda() forcefully enables HDA controller on all NVIDIA GPUs, because some buggy BIOSes leave it disabled. However, some dual-GPU laptops do not have a functional HDA controller in DGPU, and BIOS disables it on purpose. After quirk_nvidia_hda() reenables this dummy HDA controller, attempting to probe it fails at azx_first_init(), which is too late to cancel the probe, as it happens in azx_probe_continue(). The sna_hda_intel driver calls azx_free() and stops the chip, however, it stays probed, and from the runtime PM point of view, the device remains active (it was set as active by the PCI subsystem on probe). It prevents vga_switcheroo from turning off the DGPU, because pci_create_device_link() syncs power management for video and audio devices. Affected devices should be added to driver_denylist to prevent them from probing early. This patch helps identify such devices by printing a warning, and also forces the device to the suspended state to allow vga_switcheroo turn off DGPU. Signed-off-by: Maxim Mikityanskiy Link: https://patch.msgid.link/20250208214602.39607-2-maxtram95@gmail.com Signed-off-by: Takashi Iwai Signed-off-by: Sasha Levin --- sound/pci/hda/hda_intel.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index d90151910bee..da9b9dc0c96d 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1363,8 +1363,21 @@ static void azx_free(struct azx *chip) if (use_vga_switcheroo(hda)) { if (chip->disabled && hda->probe_continued) snd_hda_unlock_devices(&chip->bus); - if (hda->vga_switcheroo_registered) + if (hda->vga_switcheroo_registered) { vga_switcheroo_unregister_client(chip->pci); + + /* Some GPUs don't have sound, and azx_first_init fails, + * leaving the device probed but non-functional. As long + * as it's probed, the PCI subsystem keeps its runtime + * PM status as active. Force it to suspended (as we + * actually stop the chip) to allow GPU to suspend via + * vga_switcheroo, and print a warning. + */ + dev_warn(&pci->dev, "GPU sound probed, but not operational: please add a quirk to driver_denylist\n"); + pm_runtime_disable(&pci->dev); + pm_runtime_set_suspended(&pci->dev); + pm_runtime_enable(&pci->dev); + } } if (bus->chip_init) { From 1d91458b126e224b69d1813f424da9079929f3fe Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Sat, 8 Feb 2025 23:46:02 +0200 Subject: [PATCH 059/606] ALSA: hda: intel: Add Lenovo IdeaPad Z570 to probe denylist [ Upstream commit becc794c5e46f4dfca59f2385f78d83fc9e84700 ] Lenovo IdeaPad Z570 with NVIDIA GeForce Ge 540M doesn't have sound on the discrete GPU. The HDA controller in DGPU is disabled by BIOS, but then reenabled by quirk_nvidia_hda(). The probe fails and ends up with the "GPU sound probed, but not operational" error. Add this laptop to DMI-based denylist to prevent probe early. DMI is used, because the audio device has zero subsystem IDs, and this entry would be too much, blocking all 540M chips: PCI_DEVICE_SUB(0x10de, 0x0bea, 0x0000, 0x0000) Also, this laptop comes in a variety of modifications with different NVIDIA GPUs, so the DMI check will cover them all. Signed-off-by: Maxim Mikityanskiy Link: https://patch.msgid.link/20250208214602.39607-3-maxtram95@gmail.com Signed-off-by: Takashi Iwai Signed-off-by: Sasha Levin --- sound/pci/hda/hda_intel.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index da9b9dc0c96d..3a0df631d25d 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -37,6 +37,7 @@ #include #include #include +#include #ifdef CONFIG_X86 /* for snoop control */ @@ -2092,6 +2093,27 @@ static const struct pci_device_id driver_denylist[] = { {} }; +static struct pci_device_id driver_denylist_ideapad_z570[] = { + { PCI_DEVICE_SUB(0x10de, 0x0bea, 0x0000, 0x0000) }, /* NVIDIA GF108 HDA */ + {} +}; + +/* DMI-based denylist, to be used when: + * - PCI subsystem IDs are zero, impossible to distinguish from valid sound cards. + * - Different modifications of the same laptop use different GPU models. + */ +static const struct dmi_system_id driver_denylist_dmi[] = { + { + /* No HDA in NVIDIA DGPU. BIOS disables it, but quirk_nvidia_hda() reenables. */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Ideapad Z570"), + }, + .driver_data = &driver_denylist_ideapad_z570, + }, + {} +}; + static const struct hda_controller_ops pci_hda_ops = { .disable_msi_reset_irq = disable_msi_reset_irq, .position_check = azx_position_check, @@ -2102,6 +2124,7 @@ static DECLARE_BITMAP(probed_devs, SNDRV_CARDS); static int azx_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { + const struct dmi_system_id *dmi; struct snd_card *card; struct hda_intel *hda; struct azx *chip; @@ -2114,6 +2137,12 @@ static int azx_probe(struct pci_dev *pci, return -ENODEV; } + dmi = dmi_first_match(driver_denylist_dmi); + if (dmi && pci_match_id(dmi->driver_data, pci)) { + dev_info(&pci->dev, "Skipping the device on the DMI denylist\n"); + return -ENODEV; + } + dev = find_first_zero_bit(probed_devs, SNDRV_CARDS); if (dev >= SNDRV_CARDS) return -ENODEV; From bd095d3a9dff5a2ad0853c7b1a5ab3f9da87483a Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 26 Feb 2025 18:05:08 +0800 Subject: [PATCH 060/606] ASoC: fsl_audmix: register card device depends on 'dais' property [ Upstream commit 294a60e5e9830045c161181286d44ce669f88833 ] In order to make the audmix device linked by audio graph card, make 'dais' property to be optional. If 'dais' property exists, then register the imx-audmix card driver. otherwise, it should be linked by audio graph card. Signed-off-by: Shengjiu Wang Link: https://patch.msgid.link/20250226100508.2352568-5-shengjiu.wang@nxp.com Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/fsl/fsl_audmix.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c index 0ab2c1962117..d8e44470f501 100644 --- a/sound/soc/fsl/fsl_audmix.c +++ b/sound/soc/fsl/fsl_audmix.c @@ -492,11 +492,17 @@ static int fsl_audmix_probe(struct platform_device *pdev) goto err_disable_pm; } - priv->pdev = platform_device_register_data(dev, "imx-audmix", 0, NULL, 0); - if (IS_ERR(priv->pdev)) { - ret = PTR_ERR(priv->pdev); - dev_err(dev, "failed to register platform: %d\n", ret); - goto err_disable_pm; + /* + * If dais property exist, then register the imx-audmix card driver. + * otherwise, it should be linked by audio graph card. + */ + if (of_find_property(pdev->dev.of_node, "dais", NULL)) { + priv->pdev = platform_device_register_data(dev, "imx-audmix", 0, NULL, 0); + if (IS_ERR(priv->pdev)) { + ret = PTR_ERR(priv->pdev); + dev_err(dev, "failed to register platform: %d\n", ret); + goto err_disable_pm; + } } return 0; From 035c6e60074f7b5dccc90bfb64816bc82cde7239 Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Date: Tue, 10 Dec 2024 10:48:14 +0000 Subject: [PATCH 061/606] media: uvcvideo: Add quirk for Actions UVC05 [ Upstream commit 8c54e58f94ed3ff28643aefd2c0c2c98313ee770 ] Actions UVC05 is a HDMI to USB dongle that implements the UVC protocol. When the device suspends, its firmware seems to enter a weird mode when it does not produce more frames. Add the device to the quirk list to disable autosuspend. Bus 001 Device 007: ID 1de1:f105 Actions Microelectronics Co. Display capture-UVC05 Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 239 Miscellaneous Device bDeviceSubClass 2 [unknown] bDeviceProtocol 1 Interface Association bMaxPacketSize0 64 idVendor 0x1de1 Actions Microelectronics Co. idProduct 0xf105 Display capture-UVC05 bcdDevice 4.09 iManufacturer 1 Actions Micro iProduct 2 Display capture-UVC05 iSerial 3 -1005308387 bNumConfigurations 1 Signed-off-by: Ricardo Ribalda Reviewed-by: Laurent Pinchart Link: https://lore.kernel.org/r/20241210-uvc-hdmi-suspend-v1-1-01f5dec023ea@chromium.org Signed-off-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Sasha Levin --- drivers/media/usb/uvc/uvc_driver.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index ae2e8bd2b3f7..02cfa12b9cb9 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -3116,6 +3116,15 @@ static const struct usb_device_id uvc_ids[] = { .bInterfaceProtocol = 0, .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX | UVC_QUIRK_IGNORE_SELECTOR_UNIT) }, + /* Actions Microelectronics Co. Display capture-UVC05 */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x1de1, + .idProduct = 0xf105, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_DISABLE_AUTOSUSPEND) }, /* NXP Semiconductors IR VIDEO */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, From 0932950d3a3f7a2fabd2af5352774b43bae522c2 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Wed, 19 Feb 2025 00:17:48 +0530 Subject: [PATCH 062/606] mmc: dw_mmc: add a quirk for accessing 64-bit FIFOs in two halves [ Upstream commit 57c0902f8bec51add5a1eb908d8b876592725d81 ] In certain DW MMC implementations (such as in some Exynos7870 controllers), 64-bit read/write is not allowed from a 64-bit FIFO. Add a quirk which facilitates accessing the 64-bit FIFO registers in two 32-bit halves. Signed-off-by: Kaustabh Chakraborty Link: https://lore.kernel.org/r/20250219-exynos7870-mmc-v2-2-b4255a3e39ed@disroot.org Signed-off-by: Ulf Hansson Signed-off-by: Sasha Levin --- drivers/mmc/host/dw_mmc.c | 94 ++++++++++++++++++++++++++++++++++++++- drivers/mmc/host/dw_mmc.h | 27 +++++++++++ 2 files changed, 119 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 02bee7afab37..f97caaa829f7 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2574,6 +2574,91 @@ static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt) } } +static void dw_mci_push_data64_32(struct dw_mci *host, void *buf, int cnt) +{ + struct mmc_data *data = host->data; + int init_cnt = cnt; + + /* try and push anything in the part_buf */ + if (unlikely(host->part_buf_count)) { + int len = dw_mci_push_part_bytes(host, buf, cnt); + + buf += len; + cnt -= len; + + if (host->part_buf_count == 8) { + mci_fifo_l_writeq(host->fifo_reg, host->part_buf); + host->part_buf_count = 0; + } + } +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + if (unlikely((unsigned long)buf & 0x7)) { + while (cnt >= 8) { + u64 aligned_buf[16]; + int len = min(cnt & -8, (int)sizeof(aligned_buf)); + int items = len >> 3; + int i; + /* memcpy from input buffer into aligned buffer */ + memcpy(aligned_buf, buf, len); + buf += len; + cnt -= len; + /* push data from aligned buffer into fifo */ + for (i = 0; i < items; ++i) + mci_fifo_l_writeq(host->fifo_reg, aligned_buf[i]); + } + } else +#endif + { + u64 *pdata = buf; + + for (; cnt >= 8; cnt -= 8) + mci_fifo_l_writeq(host->fifo_reg, *pdata++); + buf = pdata; + } + /* put anything remaining in the part_buf */ + if (cnt) { + dw_mci_set_part_bytes(host, buf, cnt); + /* Push data if we have reached the expected data length */ + if ((data->bytes_xfered + init_cnt) == + (data->blksz * data->blocks)) + mci_fifo_l_writeq(host->fifo_reg, host->part_buf); + } +} + +static void dw_mci_pull_data64_32(struct dw_mci *host, void *buf, int cnt) +{ +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + if (unlikely((unsigned long)buf & 0x7)) { + while (cnt >= 8) { + /* pull data from fifo into aligned buffer */ + u64 aligned_buf[16]; + int len = min(cnt & -8, (int)sizeof(aligned_buf)); + int items = len >> 3; + int i; + + for (i = 0; i < items; ++i) + aligned_buf[i] = mci_fifo_l_readq(host->fifo_reg); + + /* memcpy from aligned buffer into output buffer */ + memcpy(buf, aligned_buf, len); + buf += len; + cnt -= len; + } + } else +#endif + { + u64 *pdata = buf; + + for (; cnt >= 8; cnt -= 8) + *pdata++ = mci_fifo_l_readq(host->fifo_reg); + buf = pdata; + } + if (cnt) { + host->part_buf = mci_fifo_l_readq(host->fifo_reg); + dw_mci_pull_final_bytes(host, buf, cnt); + } +} + static void dw_mci_pull_data(struct dw_mci *host, void *buf, int cnt) { int len; @@ -3374,8 +3459,13 @@ int dw_mci_probe(struct dw_mci *host) width = 16; host->data_shift = 1; } else if (i == 2) { - host->push_data = dw_mci_push_data64; - host->pull_data = dw_mci_pull_data64; + if ((host->quirks & DW_MMC_QUIRK_FIFO64_32)) { + host->push_data = dw_mci_push_data64_32; + host->pull_data = dw_mci_pull_data64_32; + } else { + host->push_data = dw_mci_push_data64; + host->pull_data = dw_mci_pull_data64; + } width = 64; host->data_shift = 3; } else { diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 4ed81f94f7ca..af16dbb37f26 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -280,6 +280,8 @@ struct dw_mci_board { /* Support for longer data read timeout */ #define DW_MMC_QUIRK_EXTENDED_TMOUT BIT(0) +/* Force 32-bit access to the FIFO */ +#define DW_MMC_QUIRK_FIFO64_32 BIT(1) #define DW_MMC_240A 0x240a #define DW_MMC_280A 0x280a @@ -471,6 +473,31 @@ struct dw_mci_board { #define mci_fifo_writel(__value, __reg) __raw_writel(__reg, __value) #define mci_fifo_writeq(__value, __reg) __raw_writeq(__reg, __value) +/* + * Some dw_mmc devices have 64-bit FIFOs, but expect them to be + * accessed using two 32-bit accesses. If such controller is used + * with a 64-bit kernel, this has to be done explicitly. + */ +static inline u64 mci_fifo_l_readq(void __iomem *addr) +{ + u64 ans; + u32 proxy[2]; + + proxy[0] = mci_fifo_readl(addr); + proxy[1] = mci_fifo_readl(addr + 4); + memcpy(&ans, proxy, 8); + return ans; +} + +static inline void mci_fifo_l_writeq(void __iomem *addr, u64 value) +{ + u32 proxy[2]; + + memcpy(proxy, &value, 8); + mci_fifo_writel(addr, proxy[0]); + mci_fifo_writel(addr + 4, proxy[1]); +} + /* Register access macros */ #define mci_readl(dev, reg) \ readl_relaxed((dev)->regs + SDMMC_##reg) From 63f516088870d1f3bf3419753bab6e5005fff435 Mon Sep 17 00:00:00 2001 From: Ricard Wanderlof Date: Thu, 13 Mar 2025 23:16:17 +0100 Subject: [PATCH 063/606] ALSA: usb-audio: Fix CME quirk for UF series keyboards [ Upstream commit c2820405ba55a38932aa2177f026b70064296663 ] Fix quirk for CME master keyboards so it not only handles sysex but also song position pointer, MIDI timing clock, start and stop messages, and active sensing. All of these can be output by the CME UF series master keyboards. Tested with a CME UF6 in a desktop Linux environment as well as on the Zynthian Raspberry Pi based platform. Signed-off-by: Ricard Wanderlof Link: https://patch.msgid.link/20250313-cme-fix-v1-1-d404889e4de8@butoba.net Signed-off-by: Takashi Iwai Signed-off-by: Sasha Levin --- sound/usb/midi.c | 80 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 74 insertions(+), 6 deletions(-) diff --git a/sound/usb/midi.c b/sound/usb/midi.c index 6d861046b582..3059f814eb5c 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -489,16 +489,84 @@ static void ch345_broken_sysex_input(struct snd_usb_midi_in_endpoint *ep, /* * CME protocol: like the standard protocol, but SysEx commands are sent as a - * single USB packet preceded by a 0x0F byte. + * single USB packet preceded by a 0x0F byte, as are system realtime + * messages and MIDI Active Sensing. + * Also, multiple messages can be sent in the same packet. */ static void snd_usbmidi_cme_input(struct snd_usb_midi_in_endpoint *ep, uint8_t *buffer, int buffer_length) { - if (buffer_length < 2 || (buffer[0] & 0x0f) != 0x0f) - snd_usbmidi_standard_input(ep, buffer, buffer_length); - else - snd_usbmidi_input_data(ep, buffer[0] >> 4, - &buffer[1], buffer_length - 1); + int remaining = buffer_length; + + /* + * CME send sysex, song position pointer, system realtime + * and active sensing using CIN 0x0f, which in the standard + * is only intended for single byte unparsed data. + * So we need to interpret these here before sending them on. + * By default, we assume single byte data, which is true + * for system realtime (midi clock, start, stop and continue) + * and active sensing, and handle the other (known) cases + * separately. + * In contrast to the standard, CME does not split sysex + * into multiple 4-byte packets, but lumps everything together + * into one. In addition, CME can string multiple messages + * together in the same packet; pressing the Record button + * on an UF6 sends a sysex message directly followed + * by a song position pointer in the same packet. + * For it to have any reasonable meaning, a sysex message + * needs to be at least 3 bytes in length (0xf0, id, 0xf7), + * corresponding to a packet size of 4 bytes, and the ones sent + * by CME devices are 6 or 7 bytes, making the packet fragments + * 7 or 8 bytes long (six or seven bytes plus preceding CN+CIN byte). + * For the other types, the packet size is always 4 bytes, + * as per the standard, with the data size being 3 for SPP + * and 1 for the others. + * Thus all packet fragments are at least 4 bytes long, so we can + * skip anything that is shorter; this also conveniantly skips + * packets with size 0, which CME devices continuously send when + * they have nothing better to do. + * Another quirk is that sometimes multiple messages are sent + * in the same packet. This has been observed for midi clock + * and active sensing i.e. 0x0f 0xf8 0x00 0x00 0x0f 0xfe 0x00 0x00, + * but also multiple note ons/offs, and control change together + * with MIDI clock. Similarly, some sysex messages are followed by + * the song position pointer in the same packet, and occasionally + * additionally by a midi clock or active sensing. + * We handle this by looping over all data and parsing it along the way. + */ + while (remaining >= 4) { + int source_length = 4; /* default */ + + if ((buffer[0] & 0x0f) == 0x0f) { + int data_length = 1; /* default */ + + if (buffer[1] == 0xf0) { + /* Sysex: Find EOX and send on whole message. */ + /* To kick off the search, skip the first + * two bytes (CN+CIN and SYSEX (0xf0). + */ + uint8_t *tmp_buf = buffer + 2; + int tmp_length = remaining - 2; + + while (tmp_length > 1 && *tmp_buf != 0xf7) { + tmp_buf++; + tmp_length--; + } + data_length = tmp_buf - buffer; + source_length = data_length + 1; + } else if (buffer[1] == 0xf2) { + /* Three byte song position pointer */ + data_length = 3; + } + snd_usbmidi_input_data(ep, buffer[0] >> 4, + &buffer[1], data_length); + } else { + /* normal channel events */ + snd_usbmidi_standard_input(ep, buffer, source_length); + } + buffer += source_length; + remaining -= source_length; + } } /* From 01529e60ae141ba089884df1d7f8908b2aebf680 Mon Sep 17 00:00:00 2001 From: keenplify Date: Sat, 15 Mar 2025 19:16:17 +0800 Subject: [PATCH 064/606] ASoC: amd: Add DMI quirk for ACP6X mic support [ Upstream commit 309b367eafc8e162603cd29189da6db770411fea ] Some AMD laptops with ACP6X do not expose the DMIC properly on Linux. Adding a DMI quirk enables mic functionality. Similar to Bugzilla #218402, this issue affects multiple users. Link: https://bugzilla.kernel.org/show_bug.cgi?id=219853 Signed-off-by: keenplify Link: https://patch.msgid.link/20250315111617.12194-1-keenplify@gmail.com Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/amd/yc/acp6x-mach.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c index 2981bd1c3530..2536bd3d5946 100644 --- a/sound/soc/amd/yc/acp6x-mach.c +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -584,6 +584,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_VERSION, "pang13"), } }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."), + DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 15 C7UCX"), + } + }, {} }; From b3e04472a87bbff4196505258f117255b5adf5e1 Mon Sep 17 00:00:00 2001 From: Syed Saba kareem Date: Fri, 21 Mar 2025 17:55:03 +0530 Subject: [PATCH 065/606] ASoC: amd: yc: update quirk data for new Lenovo model [ Upstream commit 5a4dd520ef8a94ecf81ac77b90d6a03e91c100a9 ] Update Quirk data for new Lenovo model 83J2 for YC platform. Signed-off-by: Syed Saba kareem Link: https://patch.msgid.link/20250321122507.190193-1-syed.sabakareem@amd.com Reported-by: Reiner Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219887 Tested-by: Reiner Reviewed-by: Mario Limonciello Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/amd/yc/acp6x-mach.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c index 2536bd3d5946..622df58a9694 100644 --- a/sound/soc/amd/yc/acp6x-mach.c +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -339,6 +339,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "83Q3"), } }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83J2"), + } + }, { .driver_data = &acp6x_card, .matches = { From 2c512f2eadabb1e80816116894ffaf7d802a944e Mon Sep 17 00:00:00 2001 From: P Praneesh Date: Mon, 23 Dec 2024 11:31:24 +0530 Subject: [PATCH 066/606] wifi: ath12k: Fix invalid entry fetch in ath12k_dp_mon_srng_process [ Upstream commit 63fdc4509bcf483e79548de6bc08bf3c8e504bb3 ] Currently, ath12k_dp_mon_srng_process uses ath12k_hal_srng_src_get_next_entry to fetch the next entry from the destination ring. This is incorrect because ath12k_hal_srng_src_get_next_entry is intended for source rings, not destination rings. This leads to invalid entry fetches, causing potential data corruption or crashes due to accessing incorrect memory locations. This happens because the source ring and destination ring have different handling mechanisms and using the wrong function results in incorrect pointer arithmetic and ring management. To fix this issue, replace the call to ath12k_hal_srng_src_get_next_entry with ath12k_hal_srng_dst_get_next_entry in ath12k_dp_mon_srng_process. This ensures that the correct function is used for fetching entries from the destination ring, preventing invalid memory accesses. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: P Praneesh Link: https://patch.msgid.link/20241223060132.3506372-7-quic_ppranees@quicinc.com Signed-off-by: Jeff Johnson Signed-off-by: Sasha Levin --- drivers/net/wireless/ath/ath12k/dp_mon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c index f1e57e98bdc6..35f22a4a16cf 100644 --- a/drivers/net/wireless/ath/ath12k/dp_mon.c +++ b/drivers/net/wireless/ath/ath12k/dp_mon.c @@ -2571,7 +2571,7 @@ int ath12k_dp_mon_rx_process_stats(struct ath12k *ar, int mac_id, dest_idx = 0; move_next: ath12k_dp_mon_buf_replenish(ab, buf_ring, 1); - ath12k_hal_srng_src_get_next_entry(ab, srng); + ath12k_hal_srng_dst_get_next_entry(ab, srng); num_buffs_reaped++; } From 4fc5c17538cbf7ab69e55771095e839607e46b8a Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Mon, 10 Feb 2025 15:36:32 +0800 Subject: [PATCH 067/606] f2fs: don't retry IO for corrupted data scenario [ Upstream commit 1534747d3170646ddeb9ea5f7caaac90359707cf ] F2FS-fs (dm-105): inconsistent node block, nid:430, node_footer[nid:2198964142,ino:598252782,ofs:118300154,cpver:5409237455940746069,blkaddr:2125070942] F2FS-fs (dm-105): inconsistent node block, nid:430, node_footer[nid:2198964142,ino:598252782,ofs:118300154,cpver:5409237455940746069,blkaddr:2125070942] F2FS-fs (dm-105): inconsistent node block, nid:430, node_footer[nid:2198964142,ino:598252782,ofs:118300154,cpver:5409237455940746069,blkaddr:2125070942] F2FS-fs (dm-105): inconsistent node block, nid:430, node_footer[nid:2198964142,ino:598252782,ofs:118300154,cpver:5409237455940746069,blkaddr:2125070942] F2FS-fs (dm-105): inconsistent node block, nid:430, node_footer[nid:2198964142,ino:598252782,ofs:118300154,cpver:5409237455940746069,blkaddr:2125070942] F2FS-fs (dm-105): inconsistent node block, nid:430, node_footer[nid:2198964142,ino:598252782,ofs:118300154,cpver:5409237455940746069,blkaddr:2125070942] F2FS-fs (dm-105): inconsistent node block, nid:430, node_footer[nid:2198964142,ino:598252782,ofs:118300154,cpver:5409237455940746069,blkaddr:2125070942] F2FS-fs (dm-105): inconsistent node block, nid:430, node_footer[nid:2198964142,ino:598252782,ofs:118300154,cpver:5409237455940746069,blkaddr:2125070942] F2FS-fs (dm-105): inconsistent node block, nid:430, node_footer[nid:2198964142,ino:598252782,ofs:118300154,cpver:5409237455940746069,blkaddr:2125070942] F2FS-fs (dm-105): inconsistent node block, nid:430, node_footer[nid:2198964142,ino:598252782,ofs:118300154,cpver:5409237455940746069,blkaddr:2125070942] If node block is loaded successfully, but its content is inconsistent, it doesn't need to retry IO. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim Signed-off-by: Sasha Levin --- fs/f2fs/inode.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 7ad4a9241759..173832fd0168 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -764,8 +764,12 @@ retry: if (err == -ENOENT) return; + if (err == -EFSCORRUPTED) + goto stop_checkpoint; + if (err == -ENOMEM || ++count <= DEFAULT_RETRY_IO_COUNT) goto retry; +stop_checkpoint: f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_UPDATE_INODE); return; } From 4ae2e891552ec331f62db61875ce38f817fd7855 Mon Sep 17 00:00:00 2001 From: Chaohai Chen Date: Wed, 15 Jan 2025 15:07:39 +0800 Subject: [PATCH 068/606] scsi: target: spc: Fix RSOC parameter data header size [ Upstream commit b50532318793d28a7628c1ffc129a2226e83e495 ] The SPC document states that "The COMMAND DATA LENGTH field indicates the length in bytes of the command descriptor list". The length should be subtracted by 4 to represent the length of the description list, not 3. Signed-off-by: Chaohai Chen Link: https://lore.kernel.org/r/20250115070739.216154-1-wdhh66@163.com Reviewed-by: Dmitry Bogdanov Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin --- drivers/target/target_core_spc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 50290abc07bc..f110f932ba05 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -2243,7 +2243,7 @@ spc_emulate_report_supp_op_codes(struct se_cmd *cmd) response_length += spc_rsoc_encode_command_descriptor( &buf[response_length], rctd, descr); } - put_unaligned_be32(response_length - 3, buf); + put_unaligned_be32(response_length - 4, buf); } else { response_length = spc_rsoc_encode_one_command_descriptor( &buf[response_length], rctd, descr, From 809bf3a7d05d2a4c7086a89954d65d4e5297cc21 Mon Sep 17 00:00:00 2001 From: Max Schulze Date: Wed, 12 Feb 2025 16:09:51 +0100 Subject: [PATCH 069/606] net: usb: asix_devices: add FiberGecko DeviceID [ Upstream commit 4079918ae720e842ed7dff65fedeb9980b374995 ] The FiberGecko is a small USB module that connects a 100 Mbit/s SFP Signed-off-by: Max Schulze Tested-by: Max Schulze Suggested-by: David Hollis Reported-by: Sven Kreiensen Link: https://patch.msgid.link/20250212150957.43900-2-max.schulze@online.de Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/usb/asix_devices.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index f7cff58fe044..ec4dcf89cbed 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c @@ -1421,6 +1421,19 @@ static const struct driver_info hg20f9_info = { .data = FLAG_EEPROM_MAC, }; +static const struct driver_info lyconsys_fibergecko100_info = { + .description = "LyconSys FiberGecko 100 USB 2.0 to SFP Adapter", + .bind = ax88178_bind, + .status = asix_status, + .link_reset = ax88178_link_reset, + .reset = ax88178_link_reset, + .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | + FLAG_MULTI_PACKET, + .rx_fixup = asix_rx_fixup_common, + .tx_fixup = asix_tx_fixup, + .data = 0x20061201, +}; + static const struct usb_device_id products [] = { { // Linksys USB200M @@ -1578,6 +1591,10 @@ static const struct usb_device_id products [] = { // Linux Automation GmbH USB 10Base-T1L USB_DEVICE(0x33f7, 0x0004), .driver_info = (unsigned long) &lxausb_t1l_info, +}, { + /* LyconSys FiberGecko 100 */ + USB_DEVICE(0x1d2a, 0x0801), + .driver_info = (unsigned long) &lyconsys_fibergecko100_info, }, { }, // END }; From 95f17738b86fd198924d874a5639bcdc49c7e5b8 Mon Sep 17 00:00:00 2001 From: Jason Xing Date: Fri, 14 Feb 2025 14:42:50 +0800 Subject: [PATCH 070/606] page_pool: avoid infinite loop to schedule delayed worker [ Upstream commit 43130d02baa137033c25297aaae95fd0edc41654 ] We noticed the kworker in page_pool_release_retry() was waken up repeatedly and infinitely in production because of the buggy driver causing the inflight less than 0 and warning us in page_pool_inflight()[1]. Since the inflight value goes negative, it means we should not expect the whole page_pool to get back to work normally. This patch mitigates the adverse effect by not rescheduling the kworker when detecting the inflight negative in page_pool_release_retry(). [1] [Mon Feb 10 20:36:11 2025] ------------[ cut here ]------------ [Mon Feb 10 20:36:11 2025] Negative(-51446) inflight packet-pages ... [Mon Feb 10 20:36:11 2025] Call Trace: [Mon Feb 10 20:36:11 2025] page_pool_release_retry+0x23/0x70 [Mon Feb 10 20:36:11 2025] process_one_work+0x1b1/0x370 [Mon Feb 10 20:36:11 2025] worker_thread+0x37/0x3a0 [Mon Feb 10 20:36:11 2025] kthread+0x11a/0x140 [Mon Feb 10 20:36:11 2025] ? process_one_work+0x370/0x370 [Mon Feb 10 20:36:11 2025] ? __kthread_cancel_work+0x40/0x40 [Mon Feb 10 20:36:11 2025] ret_from_fork+0x35/0x40 [Mon Feb 10 20:36:11 2025] ---[ end trace ebffe800f33e7e34 ]--- Note: before this patch, the above calltrace would flood the dmesg due to repeated reschedule of release_dw kworker. Signed-off-by: Jason Xing Reviewed-by: Mina Almasry Link: https://patch.msgid.link/20250214064250.85987-1-kerneljasonxing@gmail.com Signed-off-by: Paolo Abeni Signed-off-by: Sasha Levin --- net/core/page_pool.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/net/core/page_pool.c b/net/core/page_pool.c index 31f923e7b5c4..2f2f63c8cf4b 100644 --- a/net/core/page_pool.c +++ b/net/core/page_pool.c @@ -865,7 +865,13 @@ static void page_pool_release_retry(struct work_struct *wq) int inflight; inflight = page_pool_release(pool); - if (!inflight) + /* In rare cases, a driver bug may cause inflight to go negative. + * Don't reschedule release if inflight is 0 or negative. + * - If 0, the page_pool has been destroyed + * - if negative, we will never recover + * in both cases no reschedule is necessary. + */ + if (inflight <= 0) return; /* Periodic warning */ From 067347e00a3a7d04afed93f080c6c131e5dd15ee Mon Sep 17 00:00:00 2001 From: Zhongqiu Han Date: Wed, 19 Feb 2025 22:02:11 +0800 Subject: [PATCH 071/606] jfs: Fix uninit-value access of imap allocated in the diMount() function [ Upstream commit 9629d7d66c621671d9a47afe27ca9336bfc8a9ea ] syzbot reports that hex_dump_to_buffer is using uninit-value: ===================================================== BUG: KMSAN: uninit-value in hex_dump_to_buffer+0x888/0x1100 lib/hexdump.c:171 hex_dump_to_buffer+0x888/0x1100 lib/hexdump.c:171 print_hex_dump+0x13d/0x3e0 lib/hexdump.c:276 diFree+0x5ba/0x4350 fs/jfs/jfs_imap.c:876 jfs_evict_inode+0x510/0x550 fs/jfs/inode.c:156 evict+0x723/0xd10 fs/inode.c:796 iput_final fs/inode.c:1946 [inline] iput+0x97b/0xdb0 fs/inode.c:1972 txUpdateMap+0xf3e/0x1150 fs/jfs/jfs_txnmgr.c:2367 txLazyCommit fs/jfs/jfs_txnmgr.c:2664 [inline] jfs_lazycommit+0x627/0x11d0 fs/jfs/jfs_txnmgr.c:2733 kthread+0x6b9/0xef0 kernel/kthread.c:464 ret_from_fork+0x6d/0x90 arch/x86/kernel/process.c:148 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244 Uninit was created at: slab_post_alloc_hook mm/slub.c:4121 [inline] slab_alloc_node mm/slub.c:4164 [inline] __kmalloc_cache_noprof+0x8e3/0xdf0 mm/slub.c:4320 kmalloc_noprof include/linux/slab.h:901 [inline] diMount+0x61/0x7f0 fs/jfs/jfs_imap.c:105 jfs_mount+0xa8e/0x11d0 fs/jfs/jfs_mount.c:176 jfs_fill_super+0xa47/0x17c0 fs/jfs/super.c:523 get_tree_bdev_flags+0x6ec/0x910 fs/super.c:1636 get_tree_bdev+0x37/0x50 fs/super.c:1659 jfs_get_tree+0x34/0x40 fs/jfs/super.c:635 vfs_get_tree+0xb1/0x5a0 fs/super.c:1814 do_new_mount+0x71f/0x15e0 fs/namespace.c:3560 path_mount+0x742/0x1f10 fs/namespace.c:3887 do_mount fs/namespace.c:3900 [inline] __do_sys_mount fs/namespace.c:4111 [inline] __se_sys_mount+0x71f/0x800 fs/namespace.c:4088 __x64_sys_mount+0xe4/0x150 fs/namespace.c:4088 x64_sys_call+0x39bf/0x3c30 arch/x86/include/generated/asm/syscalls_64.h:166 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xcd/0x1e0 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f ===================================================== The reason is that imap is not properly initialized after memory allocation. It will cause the snprintf() function to write uninitialized data into linebuf within hex_dump_to_buffer(). Fix this by using kzalloc instead of kmalloc to clear its content at the beginning in diMount(). Signed-off-by: Zhongqiu Han Reported-by: syzbot+df6cdcb35904203d2b6d@syzkaller.appspotmail.com Closes: https://lore.kernel.org/lkml/67b5d07e.050a0220.14d86d.00e6.GAE@google.com/ Signed-off-by: Dave Kleikamp Signed-off-by: Sasha Levin --- fs/jfs/jfs_imap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index b30e4cf2f579..8b876e2db8c6 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -102,7 +102,7 @@ int diMount(struct inode *ipimap) * allocate/initialize the in-memory inode map control structure */ /* allocate the in-memory inode map control structure. */ - imap = kmalloc(sizeof(struct inomap), GFP_KERNEL); + imap = kzalloc(sizeof(struct inomap), GFP_KERNEL); if (imap == NULL) return -ENOMEM; From a14b2592a7a73601594290a2cbf27b8ee8791202 Mon Sep 17 00:00:00 2001 From: Rand Deeb Date: Thu, 20 Feb 2025 12:43:49 +0300 Subject: [PATCH 072/606] fs/jfs: cast inactags to s64 to prevent potential overflow [ Upstream commit 70ca3246ad201b53a9f09380b3f29d8bac320383 ] The expression "inactags << bmp->db_agl2size" in the function dbFinalizeBmap() is computed using int operands. Although the values (inactags and db_agl2size) are derived from filesystem parameters and are usually small, there is a theoretical risk that the shift could overflow a 32-bit int if extreme values occur. According to the C standard, shifting a signed 32-bit int can lead to undefined behavior if the result exceeds its range. In our case, an overflow could miscalculate free blocks, potentially leading to erroneous filesystem accounting. To ensure the arithmetic is performed in 64-bit space, we cast "inactags" to s64 before shifting. This defensive fix prevents any risk of overflow and complies with kernel coding best practices. Found by Linux Verification Center (linuxtesting.org) with SVACE. Signed-off-by: Rand Deeb Signed-off-by: Dave Kleikamp Signed-off-by: Sasha Levin --- fs/jfs/jfs_dmap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index f9009e4f9ffd..f89f07c9580e 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c @@ -3666,8 +3666,8 @@ void dbFinalizeBmap(struct inode *ipbmap) * system size is not a multiple of the group size). */ inactfree = (inactags && ag_rem) ? - ((inactags - 1) << bmp->db_agl2size) + ag_rem - : inactags << bmp->db_agl2size; + (((s64)inactags - 1) << bmp->db_agl2size) + ag_rem + : ((s64)inactags << bmp->db_agl2size); /* determine how many free blocks are in the active * allocation groups plus the average number of free blocks From 7ccf3b35274512b60ecb614e0637e76bd6f2d829 Mon Sep 17 00:00:00 2001 From: Rand Deeb Date: Thu, 20 Feb 2025 12:52:31 +0300 Subject: [PATCH 073/606] fs/jfs: Prevent integer overflow in AG size calculation [ Upstream commit 7fcbf789629cdb9fbf4e2172ce31136cfed11e5e ] The JFS filesystem calculates allocation group (AG) size using 1 << l2agsize in dbExtendFS(). When l2agsize exceeds 31 (possible with >2TB aggregates on 32-bit systems), this 32-bit shift operation causes undefined behavior and improper AG sizing. On 32-bit architectures: - Left-shifting 1 by 32+ bits results in 0 due to integer overflow - This creates invalid AG sizes (0 or garbage values) in sbi->bmap->db_agsize - Subsequent block allocations would reference invalid AG structures - Could lead to: - Filesystem corruption during extend operations - Kernel crashes due to invalid memory accesses - Security vulnerabilities via malformed on-disk structures Fix by casting to s64 before shifting: bmp->db_agsize = (s64)1 << l2agsize; This ensures 64-bit arithmetic even on 32-bit architectures. The cast matches the data type of db_agsize (s64) and follows similar patterns in JFS block calculation code. Found by Linux Verification Center (linuxtesting.org) with SVACE. Signed-off-by: Rand Deeb Signed-off-by: Dave Kleikamp Signed-off-by: Sasha Levin --- fs/jfs/jfs_dmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index f89f07c9580e..9ac1fc2ed05b 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c @@ -3403,7 +3403,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks) oldl2agsize = bmp->db_agl2size; bmp->db_agl2size = l2agsize; - bmp->db_agsize = 1 << l2agsize; + bmp->db_agsize = (s64)1 << l2agsize; /* compute new number of AG */ agno = bmp->db_numag; From b3c4884b987e5d8d0ec061a4d52653c4f4b9c37e Mon Sep 17 00:00:00 2001 From: Edward Adam Davis Date: Thu, 20 Feb 2025 19:13:21 +0800 Subject: [PATCH 074/606] jfs: Prevent copying of nlink with value 0 from disk inode [ Upstream commit b61e69bb1c049cf507e3c654fa3dc1568231bd07 ] syzbot report a deadlock in diFree. [1] When calling "ioctl$LOOP_SET_STATUS64", the offset value passed in is 4, which does not match the mounted loop device, causing the mapping of the mounted loop device to be invalidated. When creating the directory and creating the inode of iag in diReadSpecial(), read the page of fixed disk inode (AIT) in raw mode in read_metapage(), the metapage data it returns is corrupted, which causes the nlink value of 0 to be assigned to the iag inode when executing copy_from_dinode(), which ultimately causes a deadlock when entering diFree(). To avoid this, first check the nlink value of dinode before setting iag inode. [1] WARNING: possible recursive locking detected 6.12.0-rc7-syzkaller-00212-g4a5df3796467 #0 Not tainted -------------------------------------------- syz-executor301/5309 is trying to acquire lock: ffff888044548920 (&(imap->im_aglock[index])){+.+.}-{3:3}, at: diFree+0x37c/0x2fb0 fs/jfs/jfs_imap.c:889 but task is already holding lock: ffff888044548920 (&(imap->im_aglock[index])){+.+.}-{3:3}, at: diAlloc+0x1b6/0x1630 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&(imap->im_aglock[index])); lock(&(imap->im_aglock[index])); *** DEADLOCK *** May be due to missing lock nesting notation 5 locks held by syz-executor301/5309: #0: ffff8880422a4420 (sb_writers#9){.+.+}-{0:0}, at: mnt_want_write+0x3f/0x90 fs/namespace.c:515 #1: ffff88804755b390 (&type->i_mutex_dir_key#6/1){+.+.}-{3:3}, at: inode_lock_nested include/linux/fs.h:850 [inline] #1: ffff88804755b390 (&type->i_mutex_dir_key#6/1){+.+.}-{3:3}, at: filename_create+0x260/0x540 fs/namei.c:4026 #2: ffff888044548920 (&(imap->im_aglock[index])){+.+.}-{3:3}, at: diAlloc+0x1b6/0x1630 #3: ffff888044548890 (&imap->im_freelock){+.+.}-{3:3}, at: diNewIAG fs/jfs/jfs_imap.c:2460 [inline] #3: ffff888044548890 (&imap->im_freelock){+.+.}-{3:3}, at: diAllocExt fs/jfs/jfs_imap.c:1905 [inline] #3: ffff888044548890 (&imap->im_freelock){+.+.}-{3:3}, at: diAllocAG+0x4b7/0x1e50 fs/jfs/jfs_imap.c:1669 #4: ffff88804755a618 (&jfs_ip->rdwrlock/1){++++}-{3:3}, at: diNewIAG fs/jfs/jfs_imap.c:2477 [inline] #4: ffff88804755a618 (&jfs_ip->rdwrlock/1){++++}-{3:3}, at: diAllocExt fs/jfs/jfs_imap.c:1905 [inline] #4: ffff88804755a618 (&jfs_ip->rdwrlock/1){++++}-{3:3}, at: diAllocAG+0x869/0x1e50 fs/jfs/jfs_imap.c:1669 stack backtrace: CPU: 0 UID: 0 PID: 5309 Comm: syz-executor301 Not tainted 6.12.0-rc7-syzkaller-00212-g4a5df3796467 #0 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:94 [inline] dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120 print_deadlock_bug+0x483/0x620 kernel/locking/lockdep.c:3037 check_deadlock kernel/locking/lockdep.c:3089 [inline] validate_chain+0x15e2/0x5920 kernel/locking/lockdep.c:3891 __lock_acquire+0x1384/0x2050 kernel/locking/lockdep.c:5202 lock_acquire+0x1ed/0x550 kernel/locking/lockdep.c:5825 __mutex_lock_common kernel/locking/mutex.c:608 [inline] __mutex_lock+0x136/0xd70 kernel/locking/mutex.c:752 diFree+0x37c/0x2fb0 fs/jfs/jfs_imap.c:889 jfs_evict_inode+0x32d/0x440 fs/jfs/inode.c:156 evict+0x4e8/0x9b0 fs/inode.c:725 diFreeSpecial fs/jfs/jfs_imap.c:552 [inline] duplicateIXtree+0x3c6/0x550 fs/jfs/jfs_imap.c:3022 diNewIAG fs/jfs/jfs_imap.c:2597 [inline] diAllocExt fs/jfs/jfs_imap.c:1905 [inline] diAllocAG+0x17dc/0x1e50 fs/jfs/jfs_imap.c:1669 diAlloc+0x1d2/0x1630 fs/jfs/jfs_imap.c:1590 ialloc+0x8f/0x900 fs/jfs/jfs_inode.c:56 jfs_mkdir+0x1c5/0xba0 fs/jfs/namei.c:225 vfs_mkdir+0x2f9/0x4f0 fs/namei.c:4257 do_mkdirat+0x264/0x3a0 fs/namei.c:4280 __do_sys_mkdirat fs/namei.c:4295 [inline] __se_sys_mkdirat fs/namei.c:4293 [inline] __x64_sys_mkdirat+0x87/0xa0 fs/namei.c:4293 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f Reported-by: syzbot+355da3b3a74881008e8f@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=355da3b3a74881008e8f Signed-off-by: Edward Adam Davis Signed-off-by: Dave Kleikamp Signed-off-by: Sasha Levin --- fs/jfs/jfs_imap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index 8b876e2db8c6..9a6d504228e7 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -456,7 +456,7 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary) dp += inum % 8; /* 8 inodes per 4K page */ /* copy on-disk inode to in-memory inode */ - if ((copy_from_dinode(dp, ip)) != 0) { + if ((copy_from_dinode(dp, ip) != 0) || (ip->i_nlink == 0)) { /* handle bad return by returning NULL for ip */ set_nlink(ip, 1); /* Don't want iput() deleting it */ iput(ip); From cc0bc4cb62ce5fa0c383e3bf0765d01f46bd49ac Mon Sep 17 00:00:00 2001 From: Edward Adam Davis Date: Thu, 20 Feb 2025 19:24:19 +0800 Subject: [PATCH 075/606] jfs: add sanity check for agwidth in dbMount [ Upstream commit ddf2846f22e8575d6b4b6a66f2100f168b8cd73d ] The width in dmapctl of the AG is zero, it trigger a divide error when calculating the control page level in dbAllocAG. To avoid this issue, add a check for agwidth in dbAllocAG. Reported-and-tested-by: syzbot+7c808908291a569281a9@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=7c808908291a569281a9 Signed-off-by: Edward Adam Davis Signed-off-by: Dave Kleikamp Signed-off-by: Sasha Levin --- fs/jfs/jfs_dmap.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index 9ac1fc2ed05b..0e1019382cf5 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c @@ -204,6 +204,10 @@ int dbMount(struct inode *ipbmap) bmp->db_aglevel = le32_to_cpu(dbmp_le->dn_aglevel); bmp->db_agheight = le32_to_cpu(dbmp_le->dn_agheight); bmp->db_agwidth = le32_to_cpu(dbmp_le->dn_agwidth); + if (!bmp->db_agwidth) { + err = -EINVAL; + goto err_release_metapage; + } bmp->db_agstart = le32_to_cpu(dbmp_le->dn_agstart); bmp->db_agl2size = le32_to_cpu(dbmp_le->dn_agl2size); if (bmp->db_agl2size > L2MAXL2SIZE - L2MAXAG || From 7568e5e4486d3ca6299a9da85c19e2adcd6c9785 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Fri, 21 Feb 2025 02:54:23 +0100 Subject: [PATCH 076/606] ata: libata-eh: Do not use ATAPI DMA for a device limited to PIO mode [ Upstream commit 91ec84f8eaddbc93d7c62e363d68aeb7b89879c7 ] atapi_eh_request_sense() currently uses ATAPI DMA if the SATA controller has ATA_FLAG_PIO_DMA (PIO cmds via DMA) set. However, ATA_FLAG_PIO_DMA is a flag that can be set by a low-level driver on a port at initialization time, before any devices are scanned. If a controller detects a connected device that only supports PIO, we set the flag ATA_DFLAG_PIO. Modify atapi_eh_request_sense() to not use ATAPI DMA if the connected device only supports PIO. Reported-by: Philip Pemberton Closes: https://lore.kernel.org/linux-ide/c6722ee8-5e21-4169-af59-cbbae9edc02f@philpem.me.uk/ Tested-by: Philip Pemberton Reviewed-by: Damien Le Moal Link: https://lore.kernel.org/r/20250221015422.20687-2-cassel@kernel.org Signed-off-by: Niklas Cassel Signed-off-by: Sasha Levin --- drivers/ata/libata-eh.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 9cc022522184..3263fc13491e 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1496,8 +1496,15 @@ unsigned int atapi_eh_request_sense(struct ata_device *dev, tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; tf.command = ATA_CMD_PACKET; - /* is it pointless to prefer PIO for "safety reasons"? */ - if (ap->flags & ATA_FLAG_PIO_DMA) { + /* + * Do not use DMA if the connected device only supports PIO, even if the + * port prefers PIO commands via DMA. + * + * Ideally, we should call atapi_check_dma() to check if it is safe for + * the LLD to use DMA for REQUEST_SENSE, but we don't have a qc. + * Since we can't check the command, perhaps we should only use pio? + */ + if ((ap->flags & ATA_FLAG_PIO_DMA) && !(dev->flags & ATA_DFLAG_PIO)) { tf.protocol = ATAPI_PROT_DMA; tf.feature |= ATAPI_PKT_DMA; } else { From da3ba4a44e96ce8c517a709bd80a002f19d49dfb Mon Sep 17 00:00:00 2001 From: Birger Koblitz Date: Tue, 18 Feb 2025 18:59:40 +0100 Subject: [PATCH 077/606] net: sfp: add quirk for 2.5G OEM BX SFP [ Upstream commit a85035561025063125f81090e4f2bd65da368c83 ] The OEM SFP-2.5G-BX10-D/U SFP module pair is meant to operate with 2500Base-X. However, in their EEPROM they incorrectly specify: Transceiver codes : 0x00 0x12 0x00 0x00 0x12 0x00 0x01 0x05 0x00 BR, Nominal : 2500MBd Use sfp_quirk_2500basex for this module to allow 2500Base-X mode anyway. Tested on BananaPi R3. Signed-off-by: Birger Koblitz Reviewed-by: Daniel Golle Link: https://patch.msgid.link/20250218-b4-lkmsub-v1-1-1e51dcabed90@birger-koblitz.de Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/phy/sfp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c index e0e4a68cda3e..dc62f141f403 100644 --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c @@ -488,6 +488,8 @@ static const struct sfp_quirk sfp_quirks[] = { SFP_QUIRK_F("OEM", "SFP-10G-T", sfp_fixup_rollball_cc), SFP_QUIRK_M("OEM", "SFP-2.5G-T", sfp_quirk_oem_2_5g), + SFP_QUIRK_M("OEM", "SFP-2.5G-BX10-D", sfp_quirk_2500basex), + SFP_QUIRK_M("OEM", "SFP-2.5G-BX10-U", sfp_quirk_2500basex), SFP_QUIRK_F("OEM", "RTSFP-10", sfp_fixup_rollball_cc), SFP_QUIRK_F("OEM", "RTSFP-10G", sfp_fixup_rollball_cc), SFP_QUIRK_F("Turris", "RTSFP-10", sfp_fixup_rollball), From 7f1d986da5c6abb75ffe4d0d325fc9b341c41a1c Mon Sep 17 00:00:00 2001 From: Manish Dharanenthiran Date: Tue, 11 Feb 2025 14:33:02 +0530 Subject: [PATCH 078/606] wifi: ath12k: Fix invalid data access in ath12k_dp_rx_h_undecap_nwifi [ Upstream commit 9a0dddfb30f120db3851627935851d262e4e7acb ] In certain cases, hardware might provide packets with a length greater than the maximum native Wi-Fi header length. This can lead to accessing and modifying fields in the header within the ath12k_dp_rx_h_undecap_nwifi function for DP_RX_DECAP_TYPE_NATIVE_WIFI decap type and potentially resulting in invalid data access and memory corruption. Add a sanity check before processing the SKB to prevent invalid data access in the undecap native Wi-Fi function for the DP_RX_DECAP_TYPE_NATIVE_WIFI decap type. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 Signed-off-by: Manish Dharanenthiran Signed-off-by: Tamizh Chelvam Raja Link: https://patch.msgid.link/20250211090302.4105141-1-tamizh.raja@oss.qualcomm.com Signed-off-by: Jeff Johnson Signed-off-by: Sasha Levin --- drivers/net/wireless/ath/ath12k/dp_rx.c | 42 +++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c index 70ad035acac7..8d9315038a75 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c @@ -2484,6 +2484,29 @@ static void ath12k_dp_rx_deliver_msdu(struct ath12k *ar, struct napi_struct *nap ieee80211_rx_napi(ar->hw, pubsta, msdu, napi); } +static bool ath12k_dp_rx_check_nwifi_hdr_len_valid(struct ath12k_base *ab, + struct hal_rx_desc *rx_desc, + struct sk_buff *msdu) +{ + struct ieee80211_hdr *hdr; + u8 decap_type; + u32 hdr_len; + + decap_type = ath12k_dp_rx_h_decap_type(ab, rx_desc); + if (decap_type != DP_RX_DECAP_TYPE_NATIVE_WIFI) + return true; + + hdr = (struct ieee80211_hdr *)msdu->data; + hdr_len = ieee80211_hdrlen(hdr->frame_control); + + if ((likely(hdr_len <= DP_MAX_NWIFI_HDR_LEN))) + return true; + + ab->soc_stats.invalid_rbm++; + WARN_ON_ONCE(1); + return false; +} + static int ath12k_dp_rx_process_msdu(struct ath12k *ar, struct sk_buff *msdu, struct sk_buff_head *msdu_list, @@ -2542,6 +2565,11 @@ static int ath12k_dp_rx_process_msdu(struct ath12k *ar, } } + if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(ab, rx_desc, msdu))) { + ret = -EINVAL; + goto free_out; + } + ath12k_dp_rx_h_ppdu(ar, rx_desc, rx_status); ath12k_dp_rx_h_mpdu(ar, msdu, rx_desc, rx_status); @@ -2867,6 +2895,9 @@ mic_fail: RX_FLAG_IV_STRIPPED | RX_FLAG_DECRYPTED; skb_pull(msdu, hal_rx_desc_sz); + if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(ab, rx_desc, msdu))) + return -EINVAL; + ath12k_dp_rx_h_ppdu(ar, rx_desc, rxs); ath12k_dp_rx_h_undecap(ar, msdu, rx_desc, HAL_ENCRYPT_TYPE_TKIP_MIC, rxs, true); @@ -3590,6 +3621,9 @@ static int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu, skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len); skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes); } + if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(ab, desc, msdu))) + return -EINVAL; + ath12k_dp_rx_h_ppdu(ar, desc, status); ath12k_dp_rx_h_mpdu(ar, msdu, desc, status); @@ -3634,7 +3668,7 @@ static bool ath12k_dp_rx_h_reo_err(struct ath12k *ar, struct sk_buff *msdu, return drop; } -static void ath12k_dp_rx_h_tkip_mic_err(struct ath12k *ar, struct sk_buff *msdu, +static bool ath12k_dp_rx_h_tkip_mic_err(struct ath12k *ar, struct sk_buff *msdu, struct ieee80211_rx_status *status) { struct ath12k_base *ab = ar->ab; @@ -3652,6 +3686,9 @@ static void ath12k_dp_rx_h_tkip_mic_err(struct ath12k *ar, struct sk_buff *msdu, skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len); skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes); + if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(ab, desc, msdu))) + return true; + ath12k_dp_rx_h_ppdu(ar, desc, status); status->flag |= (RX_FLAG_MMIC_STRIPPED | RX_FLAG_MMIC_ERROR | @@ -3659,6 +3696,7 @@ static void ath12k_dp_rx_h_tkip_mic_err(struct ath12k *ar, struct sk_buff *msdu, ath12k_dp_rx_h_undecap(ar, msdu, desc, HAL_ENCRYPT_TYPE_TKIP_MIC, status, false); + return false; } static bool ath12k_dp_rx_h_rxdma_err(struct ath12k *ar, struct sk_buff *msdu, @@ -3677,7 +3715,7 @@ static bool ath12k_dp_rx_h_rxdma_err(struct ath12k *ar, struct sk_buff *msdu, case HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR: err_bitmap = ath12k_dp_rx_h_mpdu_err(ab, rx_desc); if (err_bitmap & HAL_RX_MPDU_ERR_TKIP_MIC) { - ath12k_dp_rx_h_tkip_mic_err(ar, msdu, status); + drop = ath12k_dp_rx_h_tkip_mic_err(ar, msdu, status); break; } fallthrough; From 8b5e5aac44fee122947a269f9034c048e4c295de Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Mon, 3 Mar 2025 11:47:38 +0800 Subject: [PATCH 079/606] f2fs: fix to avoid out-of-bounds access in f2fs_truncate_inode_blocks() [ Upstream commit e6494977bd4a83862118a05f57a8df40256951c0 ] syzbot reports an UBSAN issue as below: ------------[ cut here ]------------ UBSAN: array-index-out-of-bounds in fs/f2fs/node.h:381:10 index 18446744073709550692 is out of range for type '__le32[5]' (aka 'unsigned int[5]') CPU: 0 UID: 0 PID: 5318 Comm: syz.0.0 Not tainted 6.14.0-rc3-syzkaller-00060-g6537cfb395f3 #0 Call Trace: __dump_stack lib/dump_stack.c:94 [inline] dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120 ubsan_epilogue lib/ubsan.c:231 [inline] __ubsan_handle_out_of_bounds+0x121/0x150 lib/ubsan.c:429 get_nid fs/f2fs/node.h:381 [inline] f2fs_truncate_inode_blocks+0xa5e/0xf60 fs/f2fs/node.c:1181 f2fs_do_truncate_blocks+0x782/0x1030 fs/f2fs/file.c:808 f2fs_truncate_blocks+0x10d/0x300 fs/f2fs/file.c:836 f2fs_truncate+0x417/0x720 fs/f2fs/file.c:886 f2fs_file_write_iter+0x1bdb/0x2550 fs/f2fs/file.c:5093 aio_write+0x56b/0x7c0 fs/aio.c:1633 io_submit_one+0x8a7/0x18a0 fs/aio.c:2052 __do_sys_io_submit fs/aio.c:2111 [inline] __se_sys_io_submit+0x171/0x2e0 fs/aio.c:2081 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f238798cde9 index 18446744073709550692 (decimal, unsigned long long) = 0xfffffffffffffc64 (hexadecimal, unsigned long long) = -924 (decimal, long long) In f2fs_truncate_inode_blocks(), UBSAN detects that get_nid() tries to access .i_nid[-924], it means both offset[0] and level should zero. The possible case should be in f2fs_do_truncate_blocks(), we try to truncate inode size to zero, however, dn.ofs_in_node is zero and dn.node_page is not an inode page, so it fails to truncate inode page, and then pass zeroed free_from to f2fs_truncate_inode_blocks(), result in this issue. if (dn.ofs_in_node || IS_INODE(dn.node_page)) { f2fs_truncate_data_blocks_range(&dn, count); free_from += count; } I guess the reason why dn.node_page is not an inode page could be: there are multiple nat entries share the same node block address, once the node block address was reused, f2fs_get_node_page() may load a non-inode block. Let's add a sanity check for such condition to avoid out-of-bounds access issue. Reported-by: syzbot+6653f10281a1badc749e@syzkaller.appspotmail.com Closes: https://lore.kernel.org/all/66fdcdf3.050a0220.40bef.0025.GAE@google.com Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim Signed-off-by: Sasha Levin --- fs/f2fs/node.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index dedba481b66d..d93282c1ed38 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1134,7 +1134,14 @@ int f2fs_truncate_inode_blocks(struct inode *inode, pgoff_t from) trace_f2fs_truncate_inode_blocks_enter(inode, from); level = get_node_path(inode, from, offset, noffset); - if (level < 0) { + if (level <= 0) { + if (!level) { + level = -EFSCORRUPTED; + f2fs_err(sbi, "%s: inode ino=%lx has corrupted node block, from:%lu addrs:%u", + __func__, inode->i_ino, + from, ADDRS_PER_INODE(inode)); + set_sbi_flag(sbi, SBI_NEED_FSCK); + } trace_f2fs_truncate_inode_blocks_exit(inode, level); return level; } From 1263713795d0a1adca044b0f3835cb7bbb93eb88 Mon Sep 17 00:00:00 2001 From: Daniel Kral Date: Tue, 4 Mar 2025 10:20:30 +0100 Subject: [PATCH 080/606] ahci: add PCI ID for Marvell 88SE9215 SATA Controller [ Upstream commit 885251dc35767b1c992f6909532ca366c830814a ] Add support for Marvell Technology Group Ltd. 88SE9215 SATA 6 Gb/s controller, which is e.g. used in the DAWICONTROL DC-614e RAID bus controller and was not automatically recognized before. Tested with a DAWICONTROL DC-614e RAID bus controller. Signed-off-by: Daniel Kral Link: https://lore.kernel.org/r/20250304092030.37108-1-d.kral@proxmox.com Signed-off-by: Niklas Cassel Signed-off-by: Sasha Levin --- drivers/ata/ahci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 6e76780fb430..98104d0b842b 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -591,6 +591,8 @@ static const struct pci_device_id ahci_pci_tbl[] = { .driver_data = board_ahci_yes_fbs }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3), .driver_data = board_ahci_yes_fbs }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9215), + .driver_data = board_ahci_yes_fbs }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9230), .driver_data = board_ahci_yes_fbs }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9235), From 1dbece9c2fbc5a11a9b68ae7193792090b0f9cd8 Mon Sep 17 00:00:00 2001 From: Ojaswin Mujoo Date: Thu, 21 Nov 2024 18:08:55 +0530 Subject: [PATCH 081/606] ext4: protect ext4_release_dquot against freezing [ Upstream commit 530fea29ef82e169cd7fe048c2b7baaeb85a0028 ] Protect ext4_release_dquot against freezing so that we don't try to start a transaction when FS is frozen, leading to warnings. Further, avoid taking the freeze protection if a transaction is already running so that we don't need end up in a deadlock as described in 46e294efc355 ext4: fix deadlock with fs freezing and EA inodes Suggested-by: Jan Kara Signed-off-by: Ojaswin Mujoo Reviewed-by: Baokun Li Reviewed-by: Jan Kara Link: https://patch.msgid.link/20241121123855.645335-3-ojaswin@linux.ibm.com Signed-off-by: Theodore Ts'o Signed-off-by: Sasha Levin --- fs/ext4/super.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index a4d7af7495b7..751c879271e0 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -6933,12 +6933,25 @@ static int ext4_release_dquot(struct dquot *dquot) { int ret, err; handle_t *handle; + bool freeze_protected = false; + + /* + * Trying to sb_start_intwrite() in a running transaction + * can result in a deadlock. Further, running transactions + * are already protected from freezing. + */ + if (!ext4_journal_current_handle()) { + sb_start_intwrite(dquot->dq_sb); + freeze_protected = true; + } handle = ext4_journal_start(dquot_to_inode(dquot), EXT4_HT_QUOTA, EXT4_QUOTA_DEL_BLOCKS(dquot->dq_sb)); if (IS_ERR(handle)) { /* Release dquot anyway to avoid endless cycle in dqput() */ dquot_release(dquot); + if (freeze_protected) + sb_end_intwrite(dquot->dq_sb); return PTR_ERR(handle); } ret = dquot_release(dquot); @@ -6949,6 +6962,10 @@ static int ext4_release_dquot(struct dquot *dquot) err = ext4_journal_stop(handle); if (!ret) ret = err; + + if (freeze_protected) + sb_end_intwrite(dquot->dq_sb); + return ret; } From b7cc9e3adfee33d6e01c8d539442c0924e30d81e Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Wed, 5 Mar 2025 19:07:12 +0800 Subject: [PATCH 082/606] Revert "f2fs: rebuild nat_bits during umount" [ Upstream commit 19426c4988aa85298c1b4caf2889d37ec5c80fea ] This reverts commit 94c821fb286b545d37549ff30a0c341e066f0d6c. It reports that there is potential corruption in node footer, the most suspious feature is nat_bits, let's revert recovery related code. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim Signed-off-by: Sasha Levin --- fs/f2fs/checkpoint.c | 21 +++------ fs/f2fs/f2fs.h | 32 +++++++++++++- fs/f2fs/node.c | 101 ++++++++++--------------------------------- 3 files changed, 59 insertions(+), 95 deletions(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index c6317596e695..3ec815e615e7 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -1327,21 +1327,13 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc) struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); unsigned long flags; - if (cpc->reason & CP_UMOUNT) { - if (le32_to_cpu(ckpt->cp_pack_total_block_count) + - NM_I(sbi)->nat_bits_blocks > BLKS_PER_SEG(sbi)) { - clear_ckpt_flags(sbi, CP_NAT_BITS_FLAG); - f2fs_notice(sbi, "Disable nat_bits due to no space"); - } else if (!is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG) && - f2fs_nat_bitmap_enabled(sbi)) { - f2fs_enable_nat_bits(sbi); - set_ckpt_flags(sbi, CP_NAT_BITS_FLAG); - f2fs_notice(sbi, "Rebuild and enable nat_bits"); - } - } - spin_lock_irqsave(&sbi->cp_lock, flags); + if ((cpc->reason & CP_UMOUNT) && + le32_to_cpu(ckpt->cp_pack_total_block_count) > + sbi->blocks_per_seg - NM_I(sbi)->nat_bits_blocks) + disable_nat_bits(sbi, false); + if (cpc->reason & CP_TRIMMED) __set_ckpt_flags(ckpt, CP_TRIMMED_FLAG); else @@ -1524,8 +1516,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) start_blk = __start_cp_next_addr(sbi); /* write nat bits */ - if ((cpc->reason & CP_UMOUNT) && - is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG)) { + if (enabled_nat_bits(sbi, cpc)) { __u64 cp_ver = cur_cp_version(ckpt); block_t blk; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index d28e3df61cc4..5f6f159be456 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -2197,6 +2197,36 @@ static inline void f2fs_up_write(struct f2fs_rwsem *sem) #endif } +static inline void disable_nat_bits(struct f2fs_sb_info *sbi, bool lock) +{ + unsigned long flags; + unsigned char *nat_bits; + + /* + * In order to re-enable nat_bits we need to call fsck.f2fs by + * set_sbi_flag(sbi, SBI_NEED_FSCK). But it may give huge cost, + * so let's rely on regular fsck or unclean shutdown. + */ + + if (lock) + spin_lock_irqsave(&sbi->cp_lock, flags); + __clear_ckpt_flags(F2FS_CKPT(sbi), CP_NAT_BITS_FLAG); + nat_bits = NM_I(sbi)->nat_bits; + NM_I(sbi)->nat_bits = NULL; + if (lock) + spin_unlock_irqrestore(&sbi->cp_lock, flags); + + kvfree(nat_bits); +} + +static inline bool enabled_nat_bits(struct f2fs_sb_info *sbi, + struct cp_control *cpc) +{ + bool set = is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG); + + return (cpc) ? (cpc->reason & CP_UMOUNT) && set : set; +} + static inline void f2fs_lock_op(struct f2fs_sb_info *sbi) { f2fs_down_read(&sbi->cp_rwsem); @@ -3623,7 +3653,6 @@ int f2fs_truncate_inode_blocks(struct inode *inode, pgoff_t from); int f2fs_truncate_xattr_node(struct inode *inode); int f2fs_wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, unsigned int seq_id); -bool f2fs_nat_bitmap_enabled(struct f2fs_sb_info *sbi); int f2fs_remove_inode_page(struct inode *inode); struct page *f2fs_new_inode_page(struct inode *inode); struct page *f2fs_new_node_page(struct dnode_of_data *dn, unsigned int ofs); @@ -3648,7 +3677,6 @@ int f2fs_recover_xattr_data(struct inode *inode, struct page *page); int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct page *page); int f2fs_restore_node_summary(struct f2fs_sb_info *sbi, unsigned int segno, struct f2fs_summary_block *sum); -void f2fs_enable_nat_bits(struct f2fs_sb_info *sbi); int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc); int f2fs_build_node_manager(struct f2fs_sb_info *sbi); void f2fs_destroy_node_manager(struct f2fs_sb_info *sbi); diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index d93282c1ed38..b00d66b95321 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -2265,24 +2265,6 @@ static void __move_free_nid(struct f2fs_sb_info *sbi, struct free_nid *i, } } -bool f2fs_nat_bitmap_enabled(struct f2fs_sb_info *sbi) -{ - struct f2fs_nm_info *nm_i = NM_I(sbi); - unsigned int i; - bool ret = true; - - f2fs_down_read(&nm_i->nat_tree_lock); - for (i = 0; i < nm_i->nat_blocks; i++) { - if (!test_bit_le(i, nm_i->nat_block_bitmap)) { - ret = false; - break; - } - } - f2fs_up_read(&nm_i->nat_tree_lock); - - return ret; -} - static void update_free_nid_bitmap(struct f2fs_sb_info *sbi, nid_t nid, bool set, bool build) { @@ -2961,23 +2943,7 @@ add_out: list_add_tail(&nes->set_list, head); } -static void __update_nat_bits(struct f2fs_nm_info *nm_i, unsigned int nat_ofs, - unsigned int valid) -{ - if (valid == 0) { - __set_bit_le(nat_ofs, nm_i->empty_nat_bits); - __clear_bit_le(nat_ofs, nm_i->full_nat_bits); - return; - } - - __clear_bit_le(nat_ofs, nm_i->empty_nat_bits); - if (valid == NAT_ENTRY_PER_BLOCK) - __set_bit_le(nat_ofs, nm_i->full_nat_bits); - else - __clear_bit_le(nat_ofs, nm_i->full_nat_bits); -} - -static void update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid, +static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid, struct page *page) { struct f2fs_nm_info *nm_i = NM_I(sbi); @@ -2986,7 +2952,7 @@ static void update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid, int valid = 0; int i = 0; - if (!is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG)) + if (!enabled_nat_bits(sbi, NULL)) return; if (nat_index == 0) { @@ -2997,36 +2963,17 @@ static void update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid, if (le32_to_cpu(nat_blk->entries[i].block_addr) != NULL_ADDR) valid++; } - - __update_nat_bits(nm_i, nat_index, valid); -} - -void f2fs_enable_nat_bits(struct f2fs_sb_info *sbi) -{ - struct f2fs_nm_info *nm_i = NM_I(sbi); - unsigned int nat_ofs; - - f2fs_down_read(&nm_i->nat_tree_lock); - - for (nat_ofs = 0; nat_ofs < nm_i->nat_blocks; nat_ofs++) { - unsigned int valid = 0, nid_ofs = 0; - - /* handle nid zero due to it should never be used */ - if (unlikely(nat_ofs == 0)) { - valid = 1; - nid_ofs = 1; - } - - for (; nid_ofs < NAT_ENTRY_PER_BLOCK; nid_ofs++) { - if (!test_bit_le(nid_ofs, - nm_i->free_nid_bitmap[nat_ofs])) - valid++; - } - - __update_nat_bits(nm_i, nat_ofs, valid); + if (valid == 0) { + __set_bit_le(nat_index, nm_i->empty_nat_bits); + __clear_bit_le(nat_index, nm_i->full_nat_bits); + return; } - f2fs_up_read(&nm_i->nat_tree_lock); + __clear_bit_le(nat_index, nm_i->empty_nat_bits); + if (valid == NAT_ENTRY_PER_BLOCK) + __set_bit_le(nat_index, nm_i->full_nat_bits); + else + __clear_bit_le(nat_index, nm_i->full_nat_bits); } static int __flush_nat_entry_set(struct f2fs_sb_info *sbi, @@ -3045,7 +2992,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi, * #1, flush nat entries to journal in current hot data summary block. * #2, flush nat entries to nat page. */ - if ((cpc->reason & CP_UMOUNT) || + if (enabled_nat_bits(sbi, cpc) || !__has_cursum_space(journal, set->entry_cnt, NAT_JOURNAL)) to_journal = false; @@ -3092,7 +3039,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi, if (to_journal) { up_write(&curseg->journal_rwsem); } else { - update_nat_bits(sbi, start_nid, page); + __update_nat_bits(sbi, start_nid, page); f2fs_put_page(page, 1); } @@ -3123,7 +3070,7 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) * during unmount, let's flush nat_bits before checking * nat_cnt[DIRTY_NAT]. */ - if (cpc->reason & CP_UMOUNT) { + if (enabled_nat_bits(sbi, cpc)) { f2fs_down_write(&nm_i->nat_tree_lock); remove_nats_in_journal(sbi); f2fs_up_write(&nm_i->nat_tree_lock); @@ -3139,7 +3086,7 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) * entries, remove all entries from journal and merge them * into nat entry set. */ - if (cpc->reason & CP_UMOUNT || + if (enabled_nat_bits(sbi, cpc) || !__has_cursum_space(journal, nm_i->nat_cnt[DIRTY_NAT], NAT_JOURNAL)) remove_nats_in_journal(sbi); @@ -3176,18 +3123,15 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi) __u64 cp_ver = cur_cp_version(ckpt); block_t nat_bits_addr; + if (!enabled_nat_bits(sbi, NULL)) + return 0; + nm_i->nat_bits_blocks = F2FS_BLK_ALIGN((nat_bits_bytes << 1) + 8); nm_i->nat_bits = f2fs_kvzalloc(sbi, nm_i->nat_bits_blocks << F2FS_BLKSIZE_BITS, GFP_KERNEL); if (!nm_i->nat_bits) return -ENOMEM; - nm_i->full_nat_bits = nm_i->nat_bits + 8; - nm_i->empty_nat_bits = nm_i->full_nat_bits + nat_bits_bytes; - - if (!is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG)) - return 0; - nat_bits_addr = __start_cp_addr(sbi) + BLKS_PER_SEG(sbi) - nm_i->nat_bits_blocks; for (i = 0; i < nm_i->nat_bits_blocks; i++) { @@ -3204,12 +3148,13 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi) cp_ver |= (cur_cp_crc(ckpt) << 32); if (cpu_to_le64(cp_ver) != *(__le64 *)nm_i->nat_bits) { - clear_ckpt_flags(sbi, CP_NAT_BITS_FLAG); - f2fs_notice(sbi, "Disable nat_bits due to incorrect cp_ver (%llu, %llu)", - cp_ver, le64_to_cpu(*(__le64 *)nm_i->nat_bits)); + disable_nat_bits(sbi, true); return 0; } + nm_i->full_nat_bits = nm_i->nat_bits + 8; + nm_i->empty_nat_bits = nm_i->full_nat_bits + nat_bits_bytes; + f2fs_notice(sbi, "Found nat_bits in checkpoint"); return 0; } @@ -3220,7 +3165,7 @@ static inline void load_free_nid_bitmap(struct f2fs_sb_info *sbi) unsigned int i = 0; nid_t nid, last_nid; - if (!is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG)) + if (!enabled_nat_bits(sbi, NULL)) return; for (i = 0; i < nm_i->nat_blocks; i++) { From 362a90cecd36e8a5c415966d0b75b04a0270e4dd Mon Sep 17 00:00:00 2001 From: Bhupesh Date: Tue, 28 Jan 2025 13:57:50 +0530 Subject: [PATCH 083/606] ext4: ignore xattrs past end [ Upstream commit c8e008b60492cf6fd31ef127aea6d02fd3d314cd ] Once inside 'ext4_xattr_inode_dec_ref_all' we should ignore xattrs entries past the 'end' entry. This fixes the following KASAN reported issue: ================================================================== BUG: KASAN: slab-use-after-free in ext4_xattr_inode_dec_ref_all+0xb8c/0xe90 Read of size 4 at addr ffff888012c120c4 by task repro/2065 CPU: 1 UID: 0 PID: 2065 Comm: repro Not tainted 6.13.0-rc2+ #11 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014 Call Trace: dump_stack_lvl+0x1fd/0x300 ? tcp_gro_dev_warn+0x260/0x260 ? _printk+0xc0/0x100 ? read_lock_is_recursive+0x10/0x10 ? irq_work_queue+0x72/0xf0 ? __virt_addr_valid+0x17b/0x4b0 print_address_description+0x78/0x390 print_report+0x107/0x1f0 ? __virt_addr_valid+0x17b/0x4b0 ? __virt_addr_valid+0x3ff/0x4b0 ? __phys_addr+0xb5/0x160 ? ext4_xattr_inode_dec_ref_all+0xb8c/0xe90 kasan_report+0xcc/0x100 ? ext4_xattr_inode_dec_ref_all+0xb8c/0xe90 ext4_xattr_inode_dec_ref_all+0xb8c/0xe90 ? ext4_xattr_delete_inode+0xd30/0xd30 ? __ext4_journal_ensure_credits+0x5f0/0x5f0 ? __ext4_journal_ensure_credits+0x2b/0x5f0 ? inode_update_timestamps+0x410/0x410 ext4_xattr_delete_inode+0xb64/0xd30 ? ext4_truncate+0xb70/0xdc0 ? ext4_expand_extra_isize_ea+0x1d20/0x1d20 ? __ext4_mark_inode_dirty+0x670/0x670 ? ext4_journal_check_start+0x16f/0x240 ? ext4_inode_is_fast_symlink+0x2f2/0x3a0 ext4_evict_inode+0xc8c/0xff0 ? ext4_inode_is_fast_symlink+0x3a0/0x3a0 ? do_raw_spin_unlock+0x53/0x8a0 ? ext4_inode_is_fast_symlink+0x3a0/0x3a0 evict+0x4ac/0x950 ? proc_nr_inodes+0x310/0x310 ? trace_ext4_drop_inode+0xa2/0x220 ? _raw_spin_unlock+0x1a/0x30 ? iput+0x4cb/0x7e0 do_unlinkat+0x495/0x7c0 ? try_break_deleg+0x120/0x120 ? 0xffffffff81000000 ? __check_object_size+0x15a/0x210 ? strncpy_from_user+0x13e/0x250 ? getname_flags+0x1dc/0x530 __x64_sys_unlinkat+0xc8/0xf0 do_syscall_64+0x65/0x110 entry_SYSCALL_64_after_hwframe+0x67/0x6f RIP: 0033:0x434ffd Code: 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 8 RSP: 002b:00007ffc50fa7b28 EFLAGS: 00000246 ORIG_RAX: 0000000000000107 RAX: ffffffffffffffda RBX: 00007ffc50fa7e18 RCX: 0000000000434ffd RDX: 0000000000000000 RSI: 0000000020000240 RDI: 0000000000000005 RBP: 00007ffc50fa7be0 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000001 R13: 00007ffc50fa7e08 R14: 00000000004bbf30 R15: 0000000000000001 The buggy address belongs to the object at ffff888012c12000 which belongs to the cache filp of size 360 The buggy address is located 196 bytes inside of freed 360-byte region [ffff888012c12000, ffff888012c12168) The buggy address belongs to the physical page: page: refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x12c12 head: order:1 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0 flags: 0x40(head|node=0|zone=0) page_type: f5(slab) raw: 0000000000000040 ffff888000ad7640 ffffea0000497a00 dead000000000004 raw: 0000000000000000 0000000000100010 00000001f5000000 0000000000000000 head: 0000000000000040 ffff888000ad7640 ffffea0000497a00 dead000000000004 head: 0000000000000000 0000000000100010 00000001f5000000 0000000000000000 head: 0000000000000001 ffffea00004b0481 ffffffffffffffff 0000000000000000 head: 0000000000000002 0000000000000000 00000000ffffffff 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff888012c11f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ffff888012c12000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb > ffff888012c12080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ^ ffff888012c12100: fb fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc ffff888012c12180: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc ================================================================== Reported-by: syzbot+b244bda78289b00204ed@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=b244bda78289b00204ed Suggested-by: Thadeu Lima de Souza Cascardo Signed-off-by: Bhupesh Link: https://patch.msgid.link/20250128082751.124948-2-bhupesh@igalia.com Signed-off-by: Theodore Ts'o Signed-off-by: Sasha Levin --- fs/ext4/xattr.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index df5ab1a75fc4..ca22aa9e04b4 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -1176,15 +1176,24 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent, { struct inode *ea_inode; struct ext4_xattr_entry *entry; + struct ext4_iloc iloc; bool dirty = false; unsigned int ea_ino; int err; int credits; + void *end; + + if (block_csum) + end = (void *)bh->b_data + bh->b_size; + else { + ext4_get_inode_loc(parent, &iloc); + end = (void *)ext4_raw_inode(&iloc) + EXT4_SB(parent->i_sb)->s_inode_size; + } /* One credit for dec ref on ea_inode, one for orphan list addition, */ credits = 2 + extra_credits; - for (entry = first; !IS_LAST_ENTRY(entry); + for (entry = first; (void *)entry < end && !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) { if (!entry->e_value_inum) continue; From 06f20cd706d79518c783d1dd9a8105f7ca6b9d03 Mon Sep 17 00:00:00 2001 From: Philipp Hahn Date: Mon, 10 Mar 2025 11:17:35 +0100 Subject: [PATCH 084/606] cdc_ether|r8152: ThinkPad Hybrid USB-C/A Dock quirk [ Upstream commit a07f23ad9baf716cbf7746e452c92960536ceae6 ] Lenovo ThinkPad Hybrid USB-C with USB-A Dock (17ef:a359) is affected by the same problem as the Lenovo Powered USB-C Travel Hub (17ef:721e): Both are based on the Realtek RTL8153B chip used to use the cdc_ether driver. However, using this driver, with the system suspended the device constantly sends pause-frames as soon as the receive buffer fills up. This causes issues with other devices, where some Ethernet switches stop forwarding packets altogether. Using the Realtek driver (r8152) fixes this issue. Pause frames are no longer sent while the host system is suspended. Cc: Leon Schuermann Cc: Jakub Kicinski Cc: Oliver Neukum (maintainer:USB CDC ETHERNET DRIVER) Cc: netdev@vger.kernel.org (open list:NETWORKING DRIVERS) Link: https://git.kernel.org/netdev/net/c/cb82a54904a9 Link: https://git.kernel.org/netdev/net/c/2284bbd0cf39 Link: https://www.lenovo.com/de/de/p/accessories-and-software/docking/docking-usb-docks/40af0135eu Signed-off-by: Philipp Hahn Reviewed-by: Kory Maincent Link: https://patch.msgid.link/484336aad52d14ccf061b535bc19ef6396ef5120.1741601523.git.p.hahn@avm.de Signed-off-by: Paolo Abeni Signed-off-by: Sasha Levin --- drivers/net/usb/cdc_ether.c | 7 +++++++ drivers/net/usb/r8152.c | 6 ++++++ drivers/net/usb/r8153_ecm.c | 6 ++++++ 3 files changed, 19 insertions(+) diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 6d61052353f0..a04f758b3ba0 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -782,6 +782,13 @@ static const struct usb_device_id products[] = { .driver_info = 0, }, +/* Lenovo ThinkPad Hybrid USB-C with USB-A Dock (40af0135eu, based on Realtek RTL8153) */ +{ + USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0xa359, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, + /* Aquantia AQtion USB to 5GbE Controller (based on AQC111U) */ { USB_DEVICE_AND_INTERFACE_INFO(AQUANTIA_VENDOR_ID, 0xc101, diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 3e5998555f98..bbcefcc7ef8f 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -784,6 +784,7 @@ enum rtl8152_flags { #define DEVICE_ID_THINKPAD_USB_C_DONGLE 0x720c #define DEVICE_ID_THINKPAD_USB_C_DOCK_GEN2 0xa387 #define DEVICE_ID_THINKPAD_USB_C_DOCK_GEN3 0x3062 +#define DEVICE_ID_THINKPAD_HYBRID_USB_C_DOCK 0xa359 struct tally_counter { __le64 tx_packets; @@ -9734,6 +9735,7 @@ static bool rtl8152_supports_lenovo_macpassthru(struct usb_device *udev) case DEVICE_ID_THINKPAD_USB_C_DOCK_GEN2: case DEVICE_ID_THINKPAD_USB_C_DOCK_GEN3: case DEVICE_ID_THINKPAD_USB_C_DONGLE: + case DEVICE_ID_THINKPAD_HYBRID_USB_C_DOCK: return 1; } } else if (vendor_id == VENDOR_ID_REALTEK && parent_vendor_id == VENDOR_ID_LENOVO) { @@ -10011,6 +10013,8 @@ static const struct usb_device_id rtl8152_table[] = { { USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0927) }, { USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0c5e) }, { USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101) }, + + /* Lenovo */ { USB_DEVICE(VENDOR_ID_LENOVO, 0x304f) }, { USB_DEVICE(VENDOR_ID_LENOVO, 0x3054) }, { USB_DEVICE(VENDOR_ID_LENOVO, 0x3062) }, @@ -10021,7 +10025,9 @@ static const struct usb_device_id rtl8152_table[] = { { USB_DEVICE(VENDOR_ID_LENOVO, 0x720c) }, { USB_DEVICE(VENDOR_ID_LENOVO, 0x7214) }, { USB_DEVICE(VENDOR_ID_LENOVO, 0x721e) }, + { USB_DEVICE(VENDOR_ID_LENOVO, 0xa359) }, { USB_DEVICE(VENDOR_ID_LENOVO, 0xa387) }, + { USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041) }, { USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff) }, { USB_DEVICE(VENDOR_ID_TPLINK, 0x0601) }, diff --git a/drivers/net/usb/r8153_ecm.c b/drivers/net/usb/r8153_ecm.c index 20b2df8d74ae..8d860dacdf49 100644 --- a/drivers/net/usb/r8153_ecm.c +++ b/drivers/net/usb/r8153_ecm.c @@ -135,6 +135,12 @@ static const struct usb_device_id products[] = { USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), .driver_info = (unsigned long)&r8153_info, }, +/* Lenovo ThinkPad Hybrid USB-C with USB-A Dock (40af0135eu, based on Realtek RTL8153) */ +{ + USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID_LENOVO, 0xa359, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&r8153_info, +}, { }, /* END */ }; From e4d1ca0a84a6650d3172eb8c07ef2fbc585b0d96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20M=C3=A4kisara?= Date: Tue, 11 Mar 2025 13:25:14 +0200 Subject: [PATCH 085/606] scsi: st: Fix array overflow in st_setup() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit a018d1cf990d0c339fe0e29b762ea5dc10567d67 ] Change the array size to follow parms size instead of a fixed value. Reported-by: Chenyuan Yang Closes: https://lore.kernel.org/linux-scsi/CALGdzuoubbra4xKOJcsyThdk5Y1BrAmZs==wbqjbkAgmKS39Aw@mail.gmail.com/ Signed-off-by: Kai Mäkisara Link: https://lore.kernel.org/r/20250311112516.5548-2-Kai.Makisara@kolumbus.fi Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin --- drivers/scsi/st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index bdbe94f30f07..900322bad4f3 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -4120,7 +4120,7 @@ static void validate_options(void) */ static int __init st_setup(char *str) { - int i, len, ints[5]; + int i, len, ints[ARRAY_SIZE(parms) + 1]; char *stp; stp = get_options(str, ARRAY_SIZE(ints), ints); From efd75512e38ac6699e0e8c020ba6b174738e352a Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Mon, 17 Mar 2025 18:22:35 +0800 Subject: [PATCH 086/606] wifi: mt76: mt76x2u: add TP-Link TL-WDN6200 ID to device table [ Upstream commit 06cccc2ebbe6c8a20f714f3a0ff3ff489d3004bb ] The TP-Link TL-WDN6200 "Driverless" version cards use a MT7612U chipset. Add the USB ID to mt76x2u driver. Signed-off-by: Icenowy Zheng Link: https://patch.msgid.link/20250317102235.1421726-1-uwu@icenowy.me Signed-off-by: Felix Fietkau Signed-off-by: Sasha Levin --- drivers/net/wireless/mediatek/mt76/mt76x2/usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c index 55068f3252ef..d80430999219 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c @@ -21,6 +21,7 @@ static const struct usb_device_id mt76x2u_device_table[] = { { USB_DEVICE(0x0846, 0x9053) }, /* Netgear A6210 */ { USB_DEVICE(0x045e, 0x02e6) }, /* XBox One Wireless Adapter */ { USB_DEVICE(0x045e, 0x02fe) }, /* XBox One Wireless Adapter */ + { USB_DEVICE(0x2357, 0x0137) }, /* TP-Link TL-WDN6200 */ { }, }; From d537859e56bcc3091805c524484a4c85386b3cc8 Mon Sep 17 00:00:00 2001 From: Stanislav Fomichev Date: Thu, 13 Mar 2025 03:06:57 -0700 Subject: [PATCH 087/606] net: vlan: don't propagate flags on open [ Upstream commit 27b918007d96402aba10ed52a6af8015230f1793 ] With the device instance lock, there is now a possibility of a deadlock: [ 1.211455] ============================================ [ 1.211571] WARNING: possible recursive locking detected [ 1.211687] 6.14.0-rc5-01215-g032756b4ca7a-dirty #5 Not tainted [ 1.211823] -------------------------------------------- [ 1.211936] ip/184 is trying to acquire lock: [ 1.212032] ffff8881024a4c30 (&dev->lock){+.+.}-{4:4}, at: dev_set_allmulti+0x4e/0xb0 [ 1.212207] [ 1.212207] but task is already holding lock: [ 1.212332] ffff8881024a4c30 (&dev->lock){+.+.}-{4:4}, at: dev_open+0x50/0xb0 [ 1.212487] [ 1.212487] other info that might help us debug this: [ 1.212626] Possible unsafe locking scenario: [ 1.212626] [ 1.212751] CPU0 [ 1.212815] ---- [ 1.212871] lock(&dev->lock); [ 1.212944] lock(&dev->lock); [ 1.213016] [ 1.213016] *** DEADLOCK *** [ 1.213016] [ 1.213143] May be due to missing lock nesting notation [ 1.213143] [ 1.213294] 3 locks held by ip/184: [ 1.213371] #0: ffffffff838b53e0 (rtnl_mutex){+.+.}-{4:4}, at: rtnl_nets_lock+0x1b/0xa0 [ 1.213543] #1: ffffffff84e5fc70 (&net->rtnl_mutex){+.+.}-{4:4}, at: rtnl_nets_lock+0x37/0xa0 [ 1.213727] #2: ffff8881024a4c30 (&dev->lock){+.+.}-{4:4}, at: dev_open+0x50/0xb0 [ 1.213895] [ 1.213895] stack backtrace: [ 1.213991] CPU: 0 UID: 0 PID: 184 Comm: ip Not tainted 6.14.0-rc5-01215-g032756b4ca7a-dirty #5 [ 1.213993] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Arch Linux 1.16.3-1-1 04/01/2014 [ 1.213994] Call Trace: [ 1.213995] [ 1.213996] dump_stack_lvl+0x8e/0xd0 [ 1.214000] print_deadlock_bug+0x28b/0x2a0 [ 1.214020] lock_acquire+0xea/0x2a0 [ 1.214027] __mutex_lock+0xbf/0xd40 [ 1.214038] dev_set_allmulti+0x4e/0xb0 # real_dev->flags & IFF_ALLMULTI [ 1.214040] vlan_dev_open+0xa5/0x170 # ndo_open on vlandev [ 1.214042] __dev_open+0x145/0x270 [ 1.214046] __dev_change_flags+0xb0/0x1e0 [ 1.214051] netif_change_flags+0x22/0x60 # IFF_UP vlandev [ 1.214053] dev_change_flags+0x61/0xb0 # for each device in group from dev->vlan_info [ 1.214055] vlan_device_event+0x766/0x7c0 # on netdevsim0 [ 1.214058] notifier_call_chain+0x78/0x120 [ 1.214062] netif_open+0x6d/0x90 [ 1.214064] dev_open+0x5b/0xb0 # locks netdevsim0 [ 1.214066] bond_enslave+0x64c/0x1230 [ 1.214075] do_set_master+0x175/0x1e0 # on netdevsim0 [ 1.214077] do_setlink+0x516/0x13b0 [ 1.214094] rtnl_newlink+0xaba/0xb80 [ 1.214132] rtnetlink_rcv_msg+0x440/0x490 [ 1.214144] netlink_rcv_skb+0xeb/0x120 [ 1.214150] netlink_unicast+0x1f9/0x320 [ 1.214153] netlink_sendmsg+0x346/0x3f0 [ 1.214157] __sock_sendmsg+0x86/0xb0 [ 1.214160] ____sys_sendmsg+0x1c8/0x220 [ 1.214164] ___sys_sendmsg+0x28f/0x2d0 [ 1.214179] __x64_sys_sendmsg+0xef/0x140 [ 1.214184] do_syscall_64+0xec/0x1d0 [ 1.214190] entry_SYSCALL_64_after_hwframe+0x77/0x7f [ 1.214191] RIP: 0033:0x7f2d1b4a7e56 Device setup: netdevsim0 (down) ^ ^ bond netdevsim1.100@netdevsim1 allmulticast=on (down) When we enslave the lower device (netdevsim0) which has a vlan, we propagate vlan's allmuti/promisc flags during ndo_open. This causes (re)locking on of the real_dev. Propagate allmulti/promisc on flags change, not on the open. There is a slight semantics change that vlans that are down now propagate the flags, but this seems unlikely to result in the real issues. Reproducer: echo 0 1 > /sys/bus/netdevsim/new_device dev_path=$(ls -d /sys/bus/netdevsim/devices/netdevsim0/net/*) dev=$(echo $dev_path | rev | cut -d/ -f1 | rev) ip link set dev $dev name netdevsim0 ip link set dev netdevsim0 up ip link add link netdevsim0 name netdevsim0.100 type vlan id 100 ip link set dev netdevsim0.100 allmulticast on down ip link add name bond1 type bond mode 802.3ad ip link set dev netdevsim0 down ip link set dev netdevsim0 master bond1 ip link set dev bond1 up ip link show Reported-by: syzbot+b0c03d76056ef6cd12a6@syzkaller.appspotmail.com Closes: https://lore.kernel.org/netdev/Z9CfXjLMKn6VLG5d@mini-arch/T/#m15ba130f53227c883e79fb969687d69d670337a0 Signed-off-by: Stanislav Fomichev Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250313100657.2287455-1-sdf@fomichev.me Signed-off-by: Paolo Abeni Signed-off-by: Sasha Levin --- net/8021q/vlan_dev.c | 31 ++++--------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 2a7f1b15714a..e9326f322d7a 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -273,17 +273,6 @@ static int vlan_dev_open(struct net_device *dev) goto out; } - if (dev->flags & IFF_ALLMULTI) { - err = dev_set_allmulti(real_dev, 1); - if (err < 0) - goto del_unicast; - } - if (dev->flags & IFF_PROMISC) { - err = dev_set_promiscuity(real_dev, 1); - if (err < 0) - goto clear_allmulti; - } - ether_addr_copy(vlan->real_dev_addr, real_dev->dev_addr); if (vlan->flags & VLAN_FLAG_GVRP) @@ -297,12 +286,6 @@ static int vlan_dev_open(struct net_device *dev) netif_carrier_on(dev); return 0; -clear_allmulti: - if (dev->flags & IFF_ALLMULTI) - dev_set_allmulti(real_dev, -1); -del_unicast: - if (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr)) - dev_uc_del(real_dev, dev->dev_addr); out: netif_carrier_off(dev); return err; @@ -315,10 +298,6 @@ static int vlan_dev_stop(struct net_device *dev) dev_mc_unsync(real_dev, dev); dev_uc_unsync(real_dev, dev); - if (dev->flags & IFF_ALLMULTI) - dev_set_allmulti(real_dev, -1); - if (dev->flags & IFF_PROMISC) - dev_set_promiscuity(real_dev, -1); if (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr)) dev_uc_del(real_dev, dev->dev_addr); @@ -490,12 +469,10 @@ static void vlan_dev_change_rx_flags(struct net_device *dev, int change) { struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; - if (dev->flags & IFF_UP) { - if (change & IFF_ALLMULTI) - dev_set_allmulti(real_dev, dev->flags & IFF_ALLMULTI ? 1 : -1); - if (change & IFF_PROMISC) - dev_set_promiscuity(real_dev, dev->flags & IFF_PROMISC ? 1 : -1); - } + if (change & IFF_ALLMULTI) + dev_set_allmulti(real_dev, dev->flags & IFF_ALLMULTI ? 1 : -1); + if (change & IFF_PROMISC) + dev_set_promiscuity(real_dev, dev->flags & IFF_PROMISC ? 1 : -1); } static void vlan_dev_set_rx_mode(struct net_device *vlan_dev) From e711501970a02e39cea48e08e1e3a6aeb0fdd603 Mon Sep 17 00:00:00 2001 From: Gabriele Paoloni Date: Fri, 21 Mar 2025 18:08:21 +0100 Subject: [PATCH 088/606] tracing: fix return value in __ftrace_event_enable_disable for TRACE_REG_UNREGISTER [ Upstream commit 0c588ac0ca6c22b774d9ad4a6594681fdfa57d9d ] When __ftrace_event_enable_disable invokes the class callback to unregister the event, the return value is not reported up to the caller, hence leading to event unregister failures being silently ignored. This patch assigns the ret variable to the invocation of the event unregister callback, so that its return value is stored and reported to the caller, and it raises a warning in case of error. Link: https://lore.kernel.org/20250321170821.101403-1-gpaoloni@redhat.com Signed-off-by: Gabriele Paoloni Signed-off-by: Steven Rostedt (Google) Signed-off-by: Sasha Levin --- kernel/trace/trace_events.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 562efd668572..1a936978c2b1 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -790,7 +790,9 @@ static int __ftrace_event_enable_disable(struct trace_event_file *file, clear_bit(EVENT_FILE_FL_RECORDED_TGID_BIT, &file->flags); } - call->class->reg(call, TRACE_REG_UNREGISTER, file); + ret = call->class->reg(call, TRACE_REG_UNREGISTER, file); + + WARN_ON_ONCE(ret); } /* If in SOFT_MODE, just set the SOFT_DISABLE_BIT, else clear it */ if (file->flags & EVENT_FILE_FL_SOFT_MODE) From 806464634e7fc6b523160defeeddb1ade2a72f81 Mon Sep 17 00:00:00 2001 From: Arseniy Krasnov Date: Thu, 30 Jan 2025 21:43:26 +0300 Subject: [PATCH 089/606] Bluetooth: hci_uart: fix race during initialization [ Upstream commit 366ceff495f902182d42b6f41525c2474caf3f9a ] 'hci_register_dev()' calls power up function, which is executed by kworker - 'hci_power_on()'. This function does access to bluetooth chip using callbacks from 'hci_ldisc.c', for example 'hci_uart_send_frame()'. Now 'hci_uart_send_frame()' checks 'HCI_UART_PROTO_READY' bit set, and if not - it fails. Problem is that 'HCI_UART_PROTO_READY' is set after 'hci_register_dev()', and there is tiny chance that 'hci_power_on()' will be executed before setting this bit. In that case HCI init logic fails. Patch moves setting of 'HCI_UART_PROTO_READY' before calling function 'hci_uart_register_dev()'. Signed-off-by: Arseniy Krasnov Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Sasha Levin --- drivers/bluetooth/hci_ldisc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 17a2f158a0df..b67023d69e03 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -704,12 +704,13 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id) hu->proto = p; + set_bit(HCI_UART_PROTO_READY, &hu->flags); + err = hci_uart_register_dev(hu); if (err) { return err; } - set_bit(HCI_UART_PROTO_READY, &hu->flags); return 0; } From fb95ab35d0e114a744416747ce081ae380d67cfc Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 7 Feb 2025 22:41:16 +0200 Subject: [PATCH 090/606] Bluetooth: qca: simplify WCN399x NVM loading [ Upstream commit 1cc41b5092e3aa511454ec882c525af311bee631 ] The WCN399x code has two separate cases for loading the NVM data. In preparation to adding support for WCN3950, which also requires similar quirk, split the "variant" to be specified explicitly and merge two snprintfs into a single one. Signed-off-by: Dmitry Baryshkov Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Sasha Levin --- drivers/bluetooth/btqca.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index 892e2540f008..5651f40db173 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -807,6 +807,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, const char *firmware_name) { struct qca_fw_config config = {}; + const char *variant = ""; int err; u8 rom_ver = 0; u32 soc_ver; @@ -901,13 +902,11 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, case QCA_WCN3990: case QCA_WCN3991: case QCA_WCN3998: - if (le32_to_cpu(ver.soc_id) == QCA_WCN3991_SOC_ID) { - snprintf(config.fwname, sizeof(config.fwname), - "qca/crnv%02xu.bin", rom_ver); - } else { - snprintf(config.fwname, sizeof(config.fwname), - "qca/crnv%02x.bin", rom_ver); - } + if (le32_to_cpu(ver.soc_id) == QCA_WCN3991_SOC_ID) + variant = "u"; + + snprintf(config.fwname, sizeof(config.fwname), + "qca/crnv%02x%s.bin", rom_ver, variant); break; case QCA_WCN3988: snprintf(config.fwname, sizeof(config.fwname), From f5b168c309a738857a6ee422747b258a814b04c7 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Wed, 11 Dec 2024 13:18:42 -0800 Subject: [PATCH 091/606] drm: allow encoder mode_set even when connectors change for crtc [ Upstream commit 7e182cb4f5567f53417b762ec0d679f0b6f0039d ] In certain use-cases, a CRTC could switch between two encoders and because the mode being programmed on the CRTC remains the same during this switch, the CRTC's mode_changed remains false. In such cases, the encoder's mode_set also gets skipped. Skipping mode_set on the encoder for such cases could cause an issue because even though the same CRTC mode was being used, the encoder type could have changed like the CRTC could have switched from a real time encoder to a writeback encoder OR vice-versa. Allow encoder's mode_set to happen even when connectors changed on a CRTC and not just when the mode changed. Signed-off-by: Abhinav Kumar Signed-off-by: Jessica Zhang Reviewed-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20241211-abhinavk-modeset-fix-v3-1-0de4bf3e7c32@quicinc.com Signed-off-by: Dmitry Baryshkov Signed-off-by: Sasha Levin --- drivers/gpu/drm/drm_atomic_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 554d4468aa7c..f3681970887c 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1373,7 +1373,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) mode = &new_crtc_state->mode; adjusted_mode = &new_crtc_state->adjusted_mode; - if (!new_crtc_state->mode_changed) + if (!new_crtc_state->mode_changed && !new_crtc_state->connectors_changed) continue; drm_dbg_atomic(dev, "modeset on [ENCODER:%d:%s]\n", From 2528ccb0f2fc9c9b73681b05c74af2a1e1c691bb Mon Sep 17 00:00:00 2001 From: Zhikai Zhai Date: Thu, 9 Jan 2025 16:11:48 +0800 Subject: [PATCH 092/606] drm/amd/display: Update Cursor request mode to the beginning prefetch always [ Upstream commit 4a4077b4b63a8404efd6d37fc2926f03fb25bace ] [Why] The double buffer cursor registers is updated by the cursor vupdate event. There is a gap between vupdate and cursor data fetch if cursor fetch data reletive to cursor position. Cursor corruption will happen if we update the cursor surface in this gap. [How] Modify the cursor request mode to the beginning prefetch always and avoid wraparound calculation issues. Reviewed-by: Nicholas Kazlauskas Signed-off-by: Zhikai Zhai Signed-off-by: Zaeem Mohamed Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 22 ++++++++----------- .../gpu/drm/amd/display/dc/dcn31/dcn31_hubp.c | 2 +- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index ff38a85c4fa2..e71b79f5a66c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1930,20 +1930,11 @@ static void delay_cursor_until_vupdate(struct dc *dc, struct pipe_ctx *pipe_ctx) dc->hwss.get_position(&pipe_ctx, 1, &position); vpos = position.vertical_count; - /* Avoid wraparound calculation issues */ - vupdate_start += stream->timing.v_total; - vupdate_end += stream->timing.v_total; - vpos += stream->timing.v_total; - if (vpos <= vupdate_start) { /* VPOS is in VACTIVE or back porch. */ lines_to_vupdate = vupdate_start - vpos; - } else if (vpos > vupdate_end) { - /* VPOS is in the front porch. */ - return; } else { - /* VPOS is in VUPDATE. */ - lines_to_vupdate = 0; + lines_to_vupdate = stream->timing.v_total - vpos + vupdate_start; } /* Calculate time until VUPDATE in microseconds. */ @@ -1951,13 +1942,18 @@ static void delay_cursor_until_vupdate(struct dc *dc, struct pipe_ctx *pipe_ctx) stream->timing.h_total * 10000u / stream->timing.pix_clk_100hz; us_to_vupdate = lines_to_vupdate * us_per_line; + /* Stall out until the cursor update completes. */ + if (vupdate_end < vupdate_start) + vupdate_end += stream->timing.v_total; + + /* Position is in the range of vupdate start and end*/ + if (lines_to_vupdate > stream->timing.v_total - vupdate_end + vupdate_start) + us_to_vupdate = 0; + /* 70 us is a conservative estimate of cursor update time*/ if (us_to_vupdate > 70) return; - /* Stall out until the cursor update completes. */ - if (vupdate_end < vupdate_start) - vupdate_end += stream->timing.v_total; us_vupdate = (vupdate_end - vupdate_start + 1) * us_per_line; udelay(us_to_vupdate + us_vupdate); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubp.c index 39a57bcd7866..576acf2ce10d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubp.c @@ -44,7 +44,7 @@ void hubp31_set_unbounded_requesting(struct hubp *hubp, bool enable) struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); REG_UPDATE(DCHUBP_CNTL, HUBP_UNBOUNDED_REQ_MODE, enable); - REG_UPDATE(CURSOR_CONTROL, CURSOR_REQ_MODE, enable); + REG_UPDATE(CURSOR_CONTROL, CURSOR_REQ_MODE, 1); } void hubp31_soft_reset(struct hubp *hubp, bool reset) From d74554965cac73f59458f283ea3f37d4205f7710 Mon Sep 17 00:00:00 2001 From: Brendan Tam Date: Thu, 23 Jan 2025 11:25:16 -0500 Subject: [PATCH 093/606] drm/amd/display: add workaround flag to link to force FFE preset [ Upstream commit 51d1b338541dea83fec8e6f95d3e46fa469a73a8 ] [Why] There have been instances of some monitors being unable to link train on their reported link speed using their selected FFE preset. If a different FFE preset is found that has a higher rate of success during link training this workaround can be used to force its FFE preset. [How] A new link workaround flag is made called force_dp_ffe_preset. The flag is checked in override_training_settings and will set lt_settings->ffe_preset which is null if the flag is not set. The flag is then set in override_lane_settings. Reviewed-by: Wenjing Liu Signed-off-by: Brendan Tam Signed-off-by: Aurabindo Pillai Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ .../gpu/drm/amd/display/dc/link/protocols/link_dp_training.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index cc5e01df1513..88e64b280c90 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1563,7 +1563,9 @@ struct dc_link { bool dongle_mode_timing_override; bool blank_stream_on_ocs_change; bool read_dpcd204h_on_irq_hpd; + bool force_dp_ffe_preset; } wa_flags; + union dc_dp_ffe_preset forced_dp_ffe_preset; struct link_mst_stream_allocation_table mst_stream_alloc_table; struct dc_link_status link_status; diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c index 9d1adfc09fb2..51e88efee11e 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c @@ -697,6 +697,8 @@ void override_training_settings( lt_settings->pre_emphasis = overrides->pre_emphasis; if (overrides->post_cursor2 != NULL) lt_settings->post_cursor2 = overrides->post_cursor2; + if (link->wa_flags.force_dp_ffe_preset && !dp_is_lttpr_present(link)) + lt_settings->ffe_preset = &link->forced_dp_ffe_preset; if (overrides->ffe_preset != NULL) lt_settings->ffe_preset = overrides->ffe_preset; /* Override HW lane settings with BIOS forced values if present */ From bfea2e6f030558b95a5ec31e92ed5186b97cef5c Mon Sep 17 00:00:00 2001 From: Andrew Wyatt Date: Thu, 13 Feb 2025 22:24:49 +0000 Subject: [PATCH 094/606] drm: panel-orientation-quirks: Add support for AYANEO 2S [ Upstream commit eb8f1e3e8ee10cff591d4a47437dfd34d850d454 ] AYANEO 2S uses the same panel and orientation as the AYANEO 2. Update the AYANEO 2 DMI match to also match AYANEO 2S. Signed-off-by: Andrew Wyatt Signed-off-by: John Edwards Tested-by: John Edwards Reviewed-by: Thomas Zimmermann Reviewed-by: Hans de Goede Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20250213222455.93533-2-uejji@uejji.net Signed-off-by: Sasha Levin --- drivers/gpu/drm/drm_panel_orientation_quirks.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index c00f6f16244c..7bf096ddeb06 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -184,10 +184,10 @@ static const struct dmi_system_id orientation_data[] = { DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T103HAF"), }, .driver_data = (void *)&lcd800x1280_rightside_up, - }, { /* AYA NEO AYANEO 2 */ + }, { /* AYA NEO AYANEO 2/2S */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"), - DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "AYANEO 2"), + DMI_MATCH(DMI_PRODUCT_NAME, "AYANEO 2"), }, .driver_data = (void *)&lcd1200x1920_rightside_up, }, { /* AYA NEO 2021 */ From 14dc15279512d435d9d0639634b433dd645af6bb Mon Sep 17 00:00:00 2001 From: Andrew Wyatt Date: Thu, 13 Feb 2025 22:24:50 +0000 Subject: [PATCH 095/606] drm: panel-orientation-quirks: Add quirks for AYA NEO Flip DS and KB [ Upstream commit 529741c331da1fbf54f86c6ec3a4558b9b0b16dc ] The AYA NEO Flip DS and KB both use a 1080x1920 portrait LCD panel. The Flip DS additionally uses a 640x960 portrait LCD panel as a second display. Add DMI matches to correctly rotate these panels. Signed-off-by: Andrew Wyatt Co-developed-by: John Edwards Signed-off-by: John Edwards Tested-by: Paco Avelar Reviewed-by: Thomas Zimmermann Reviewed-by: Hans de Goede Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20250213222455.93533-3-uejji@uejji.net Signed-off-by: Sasha Levin --- drivers/gpu/drm/drm_panel_orientation_quirks.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index 7bf096ddeb06..d9ed6214cf28 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -93,6 +93,12 @@ static const struct drm_dmi_panel_orientation_data onegx1_pro = { .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, }; +static const struct drm_dmi_panel_orientation_data lcd640x960_leftside_up = { + .width = 640, + .height = 960, + .orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP, +}; + static const struct drm_dmi_panel_orientation_data lcd720x1280_rightside_up = { .width = 720, .height = 1280, @@ -202,6 +208,18 @@ static const struct dmi_system_id orientation_data[] = { DMI_MATCH(DMI_PRODUCT_NAME, "AIR"), }, .driver_data = (void *)&lcd1080x1920_leftside_up, + }, { /* AYA NEO Flip DS Bottom Screen */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "FLIP DS"), + }, + .driver_data = (void *)&lcd640x960_leftside_up, + }, { /* AYA NEO Flip KB/DS Top Screen */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"), + DMI_MATCH(DMI_PRODUCT_NAME, "FLIP"), + }, + .driver_data = (void *)&lcd1080x1920_leftside_up, }, { /* AYA NEO Founder */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYA NEO"), From 118f95e3ff6cfb07bb022c24dbe34413c4183cab Mon Sep 17 00:00:00 2001 From: Andrew Wyatt Date: Thu, 13 Feb 2025 22:24:51 +0000 Subject: [PATCH 096/606] drm: panel-orientation-quirks: Add quirk for AYA NEO Slide [ Upstream commit 132c89ef8872e602cfb909377815111d121fe8d7 ] The AYANEO Slide uses a 1080x1920 portrait LCD panel. This is the same panel used on the AYANEO Air Plus, but the DMI data is too different to match both with one entry. Add a DMI match to correctly rotate the panel on the AYANEO Slide. This also covers the Antec Core HS, which is a rebranded AYANEO Slide with the exact same hardware and DMI strings. Signed-off-by: Andrew Wyatt Signed-off-by: John Edwards Tested-by: John Edwards Reviewed-by: Thomas Zimmermann Reviewed-by: Hans de Goede Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20250213222455.93533-4-uejji@uejji.net Signed-off-by: Sasha Levin --- drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index d9ed6214cf28..702246ee7ced 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -244,6 +244,12 @@ static const struct dmi_system_id orientation_data[] = { DMI_MATCH(DMI_BOARD_NAME, "KUN"), }, .driver_data = (void *)&lcd1600x2560_rightside_up, + }, { /* AYA NEO SLIDE */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"), + DMI_MATCH(DMI_PRODUCT_NAME, "SLIDE"), + }, + .driver_data = (void *)&lcd1080x1920_leftside_up, }, { /* AYN Loki Max */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ayn"), From 49ef9e47e72b1efb12656e5860037de3894df6d3 Mon Sep 17 00:00:00 2001 From: Andrew Wyatt Date: Thu, 13 Feb 2025 22:24:52 +0000 Subject: [PATCH 097/606] drm: panel-orientation-quirks: Add new quirk for GPD Win 2 [ Upstream commit a860eb9c6ba6cdbf32e3e01a606556e5a90a2931 ] Some GPD Win 2 units shipped with the correct DMI strings. Add a DMI match to correctly rotate the panel on these units. Signed-off-by: Andrew Wyatt Signed-off-by: John Edwards Tested-by: Paco Avelar Reviewed-by: Thomas Zimmermann Reviewed-by: Hans de Goede Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20250213222455.93533-5-uejji@uejji.net Signed-off-by: Sasha Levin --- drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index 702246ee7ced..12d547f093bd 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -339,6 +339,12 @@ static const struct dmi_system_id orientation_data[] = { DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"), }, .driver_data = (void *)&gpd_win2, + }, { /* GPD Win 2 (correct DMI strings) */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "WIN2") + }, + .driver_data = (void *)&lcd720x1280_rightside_up, }, { /* GPD Win 3 */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"), From 1e27e6050c8c790d8f610e8788a36cd79dc13a89 Mon Sep 17 00:00:00 2001 From: Andrew Wyatt Date: Thu, 13 Feb 2025 22:24:53 +0000 Subject: [PATCH 098/606] drm: panel-orientation-quirks: Add quirk for OneXPlayer Mini (Intel) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit b24dcc183583fc360ae0f0899e286a68f46abbd0 ] The Intel model of the OneXPlayer Mini uses a 1200x1920 portrait LCD panel. The DMI strings are the same as the OneXPlayer, which already has a DMI quirk, but the panel is different. Add a DMI match to correctly rotate this panel. Signed-off-by: Andrew Wyatt Co-developed-by: John Edwards Signed-off-by: John Edwards Tested-by: João Pedro Kurtz Reviewed-by: Thomas Zimmermann Reviewed-by: Hans de Goede Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20250213222455.93533-6-uejji@uejji.net Signed-off-by: Sasha Levin --- drivers/gpu/drm/drm_panel_orientation_quirks.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index 12d547f093bd..036b095c9888 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -129,6 +129,12 @@ static const struct drm_dmi_panel_orientation_data lcd1080x1920_rightside_up = { .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, }; +static const struct drm_dmi_panel_orientation_data lcd1200x1920_leftside_up = { + .width = 1200, + .height = 1920, + .orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP, +}; + static const struct drm_dmi_panel_orientation_data lcd1200x1920_rightside_up = { .width = 1200, .height = 1920, @@ -473,6 +479,12 @@ static const struct dmi_system_id orientation_data[] = { DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ONE XPLAYER"), }, .driver_data = (void *)&lcd1600x2560_leftside_up, + }, { /* OneXPlayer Mini (Intel) */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ONE-NETBOOK TECHNOLOGY CO., LTD."), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ONE XPLAYER"), + }, + .driver_data = (void *)&lcd1200x1920_leftside_up, }, { /* OrangePi Neo */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "OrangePi"), From 100cf2fa014019bb7013b805ffe18583c7ef412b Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 14 Feb 2025 13:57:44 +0100 Subject: [PATCH 099/606] drm/bridge: panel: forbid initializing a panel with unknown connector type [ Upstream commit b296955b3a740ecc8b3b08e34fd64f1ceabb8fb4 ] Having an DRM_MODE_CONNECTOR_Unknown connector type is considered bad, and drm_panel_bridge_add_typed() and derivatives are deprecated for this. drm_panel_init() won't prevent initializing a panel with a DRM_MODE_CONNECTOR_Unknown connector type. Luckily there are no in-tree users doing it, so take this as an opportinuty to document a valid connector type must be passed. Returning an error if this rule is violated is not possible because drm_panel_init() is a void function. Add at least a warning to make any violations noticeable, especially to non-upstream drivers. Reviewed-by: Dmitry Baryshkov Signed-off-by: Luca Ceresoli Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20250214-drm-assorted-cleanups-v7-5-88ca5827d7af@bootlin.com Signed-off-by: Sasha Levin --- drivers/gpu/drm/drm_panel.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index cfbe020de54e..98df4788d096 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -49,7 +49,7 @@ static LIST_HEAD(panel_list); * @dev: parent device of the panel * @funcs: panel operations * @connector_type: the connector type (DRM_MODE_CONNECTOR_*) corresponding to - * the panel interface + * the panel interface (must NOT be DRM_MODE_CONNECTOR_Unknown) * * Initialize the panel structure for subsequent registration with * drm_panel_add(). @@ -57,6 +57,9 @@ static LIST_HEAD(panel_list); void drm_panel_init(struct drm_panel *panel, struct device *dev, const struct drm_panel_funcs *funcs, int connector_type) { + if (connector_type == DRM_MODE_CONNECTOR_Unknown) + DRM_WARN("%s: %s: a valid connector type is required!\n", __func__, dev_name(dev)); + INIT_LIST_HEAD(&panel->list); INIT_LIST_HEAD(&panel->followers); mutex_init(&panel->follower_lock); From 61d1a8296eeb151192cba42f29532849ac536373 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 21 Feb 2025 16:10:41 -0800 Subject: [PATCH 100/606] drivers: base: devres: Allow to release group on device release [ Upstream commit 8e1ddfada4530939a8cb64ee9251aef780474274 ] When releasing a device, if the release action causes a group to be released, a warning is emitted because it can't find the group. This happens because devres_release_all() moves the entire list to a todo list and also move the group markers. Considering r* normal resource nodes and g1 a group resource node: g1 -----------. v v r1 -> r2 -> g1[0] -> r3-> g[1] -> r4 After devres_release_all(), dev->devres_head becomes empty and the todo list it iterates on becomes: g1 v r1 -> r2 -> r3-> r4 -> g1[0] When a call to component_del() is made and takes down the aggregate device, a warning like this happen: RIP: 0010:devres_release_group+0x362/0x530 ... Call Trace: component_unbind+0x156/0x380 component_unbind_all+0x1d0/0x270 mei_component_master_unbind+0x28/0x80 [mei_hdcp] take_down_aggregate_device+0xc1/0x160 component_del+0x1c6/0x3e0 intel_hdcp_component_fini+0xf1/0x170 [xe] xe_display_fini+0x1e/0x40 [xe] Because the devres group corresponding to the hdcp component cannot be found. Just ignore this corner case: if the dev->devres_head is empty and the caller is trying to remove a group, it's likely in the process of device cleanup so just ignore it instead of warning. Acked-by: Greg Kroah-Hartman Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20250222001051.3012936-2-lucas.demarchi@intel.com Signed-off-by: Lucas De Marchi Signed-off-by: Sasha Levin --- drivers/base/devres.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/base/devres.c b/drivers/base/devres.c index e9b0d94aeabd..8a0f00022127 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c @@ -687,6 +687,13 @@ int devres_release_group(struct device *dev, void *id) spin_unlock_irqrestore(&dev->devres_lock, flags); release_nodes(dev, &todo); + } else if (list_empty(&dev->devres_head)) { + /* + * dev is probably dying via devres_release_all(): groups + * have already been removed and are on the process of + * being released - don't touch and don't warn. + */ + spin_unlock_irqrestore(&dev->devres_lock, flags); } else { WARN_ON(1); spin_unlock_irqrestore(&dev->devres_lock, flags); From 06a1db4cb7ac62e649e735ba90afc5c46a0b8780 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Tue, 25 Feb 2025 18:08:02 -0500 Subject: [PATCH 101/606] drm/amdkfd: clamp queue size to minimum [ Upstream commit e90711946b53590371ecce32e8fcc381a99d6333 ] If queue size is less than minimum, clamp it to minimum to prevent underflow when writing queue mqd. Signed-off-by: David Yat Sin Reviewed-by: Jay Cornwall Reviewed-by: Harish Kasiviswanathan Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 10 ++++++++++ include/uapi/linux/kfd_ioctl.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 8669677662d0..35dc926f234e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -212,6 +212,11 @@ static int set_queue_properties_from_user(struct queue_properties *q_properties, return -EINVAL; } + if (args->ring_size < KFD_MIN_QUEUE_RING_SIZE) { + args->ring_size = KFD_MIN_QUEUE_RING_SIZE; + pr_debug("Size lower. clamped to KFD_MIN_QUEUE_RING_SIZE"); + } + if (!access_ok((const void __user *) args->read_pointer_address, sizeof(uint32_t))) { pr_err("Can't access read pointer\n"); @@ -477,6 +482,11 @@ static int kfd_ioctl_update_queue(struct file *filp, struct kfd_process *p, return -EINVAL; } + if (args->ring_size < KFD_MIN_QUEUE_RING_SIZE) { + args->ring_size = KFD_MIN_QUEUE_RING_SIZE; + pr_debug("Size lower. clamped to KFD_MIN_QUEUE_RING_SIZE"); + } + properties.queue_address = args->ring_base_address; properties.queue_size = args->ring_size; properties.queue_percent = args->queue_percentage & 0xFF; diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h index cd924c959d73..1f753e72fa2c 100644 --- a/include/uapi/linux/kfd_ioctl.h +++ b/include/uapi/linux/kfd_ioctl.h @@ -58,6 +58,8 @@ struct kfd_ioctl_get_version_args { #define KFD_MAX_QUEUE_PERCENTAGE 100 #define KFD_MAX_QUEUE_PRIORITY 15 +#define KFD_MIN_QUEUE_RING_SIZE 1024 + struct kfd_ioctl_create_queue_args { __u64 ring_base_address; /* to KFD */ __u64 write_pointer_address; /* from KFD */ From 89af6b39f028c130d4362f57042927f005423e6a Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Thu, 6 Feb 2025 17:50:13 -0500 Subject: [PATCH 102/606] drm/amdkfd: Fix mode1 reset crash issue [ Upstream commit f0b4440cdc1807bb6ec3dce0d6de81170803569b ] If HW scheduler hangs and mode1 reset is used to recover GPU, KFD signal user space to abort the processes. After process abort exit, user queues still use the GPU to access system memory before h/w is reset while KFD cleanup worker free system memory and free VRAM. There is use-after-free race bug that KFD allocate and reuse the freed system memory, and user queue write to the same system memory to corrupt the data structure and cause driver crash. To fix this race, KFD cleanup worker terminate user queues, then flush reset_domain wq to wait for any GPU ongoing reset complete, and then free outstanding BOs. Signed-off-by: Philip Yang Reviewed-by: Lijo Lazar Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 64346c71c62a..a6d08dee74f6 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -35,6 +35,7 @@ #include #include "amdgpu_amdkfd.h" #include "amdgpu.h" +#include "amdgpu_reset.h" struct mm_struct; @@ -1110,6 +1111,17 @@ static void kfd_process_remove_sysfs(struct kfd_process *p) p->kobj = NULL; } +/* + * If any GPU is ongoing reset, wait for reset complete. + */ +static void kfd_process_wait_gpu_reset_complete(struct kfd_process *p) +{ + int i; + + for (i = 0; i < p->n_pdds; i++) + flush_workqueue(p->pdds[i]->dev->adev->reset_domain->wq); +} + /* No process locking is needed in this function, because the process * is not findable any more. We must assume that no other thread is * using it any more, otherwise we couldn't safely free the process @@ -1123,6 +1135,11 @@ static void kfd_process_wq_release(struct work_struct *work) kfd_process_dequeue_from_all_devices(p); pqm_uninit(&p->pqm); + /* + * If GPU in reset, user queues may still running, wait for reset complete. + */ + kfd_process_wait_gpu_reset_complete(p); + /* Signal the eviction fence after user mode queues are * destroyed. This allows any BOs to be freed without * triggering pointless evictions or waiting for fences. From 864d739fbc728c1ba18d17a736b7776636f315da Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Thu, 20 Feb 2025 16:02:13 -0500 Subject: [PATCH 103/606] drm/amdkfd: Fix pqm_destroy_queue race with GPU reset [ Upstream commit 7919b4cad5545ed93778f11881ceee72e4dbed66 ] If GPU in reset, destroy_queue return -EIO, pqm_destroy_queue should delete the queue from process_queue_list and free the resource. Signed-off-by: Philip Yang Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index e057c2bc7be4..d11a71e8aa14 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -510,7 +510,7 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid) pr_err("Pasid 0x%x destroy queue %d failed, ret %d\n", pqm->process->pasid, pqn->q->properties.queue_id, retval); - if (retval != -ETIME) + if (retval != -ETIME && retval != -EIO) goto err_destroy_queue; } From a36f8d544522a19ef06ed9e84667d154dcb6be52 Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Mon, 10 Feb 2025 09:42:31 -0500 Subject: [PATCH 104/606] drm/amdkfd: debugfs hang_hws skip GPU with MES [ Upstream commit fe9d0061c413f8fb8c529b18b592b04170850ded ] debugfs hang_hws is used by GPU reset test with HWS, for MES this crash the kernel with NULL pointer access because dqm->packet_mgr is not setup for MES path. Skip GPU with MES for now, MES hang_hws debugfs interface will be supported later. Signed-off-by: Philip Yang Reviewed-by: Kent Russell Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 9d0b0bf70ad1..2786d47961e0 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -1388,6 +1388,11 @@ int kfd_debugfs_hang_hws(struct kfd_node *dev) return -EINVAL; } + if (dev->kfd->shared_resources.enable_mes) { + dev_err(dev->adev->dev, "Inducing MES hang is not supported\n"); + return -EINVAL; + } + return dqm_debugfs_hang_hws(dev->dqm); } From 50967df6e4d25580639daab4fcb4866e62ae93d0 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Mon, 17 Feb 2025 16:47:59 +0100 Subject: [PATCH 105/606] drm/mediatek: mtk_dpi: Move the input_2p_en bit to platform data [ Upstream commit c90876a695dd83e76680b88b40067275a5982811 ] In preparation for adding support for MT8195's HDMI reserved DPI instance, move the input_2p_en bit for DP_INTF to platform data. While at it, remove the input_2pixel member from platform data as having this bit implies that the 2pixel feature must be enabled. Reviewed-by: CK Hu Signed-off-by: AngeloGioacchino Del Regno Link: https://patchwork.kernel.org/project/dri-devel/patch/20250217154836.108895-7-angelogioacchino.delregno@collabora.com/ Signed-off-by: Chun-Kuang Hu Signed-off-by: Sasha Levin --- drivers/gpu/drm/mediatek/mtk_dpi.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c index bc073a6b367e..e4a3bd3989d8 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi.c +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c @@ -127,14 +127,14 @@ struct mtk_dpi_yc_limit { * @is_ck_de_pol: Support CK/DE polarity. * @swap_input_support: Support input swap function. * @support_direct_pin: IP supports direct connection to dpi panels. - * @input_2pixel: Input pixel of dp_intf is 2 pixel per round, so enable this - * config to enable this feature. * @dimension_mask: Mask used for HWIDTH, HPORCH, VSYNC_WIDTH and VSYNC_PORCH * (no shift). * @hvsize_mask: Mask of HSIZE and VSIZE mask (no shift). * @channel_swap_shift: Shift value of channel swap. * @yuv422_en_bit: Enable bit of yuv422. * @csc_enable_bit: Enable bit of CSC. + * @input_2p_en_bit: Enable bit for input two pixel per round feature. + * If present, implies that the feature must be enabled. * @pixels_per_iter: Quantity of transferred pixels per iteration. * @edge_cfg_in_mmsys: If the edge configuration for DPI's output needs to be set in MMSYS. */ @@ -148,12 +148,12 @@ struct mtk_dpi_conf { bool is_ck_de_pol; bool swap_input_support; bool support_direct_pin; - bool input_2pixel; u32 dimension_mask; u32 hvsize_mask; u32 channel_swap_shift; u32 yuv422_en_bit; u32 csc_enable_bit; + u32 input_2p_en_bit; u32 pixels_per_iter; bool edge_cfg_in_mmsys; }; @@ -610,9 +610,9 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi, mtk_dpi_dual_edge(dpi); mtk_dpi_config_disable_edge(dpi); } - if (dpi->conf->input_2pixel) { - mtk_dpi_mask(dpi, DPI_CON, DPINTF_INPUT_2P_EN, - DPINTF_INPUT_2P_EN); + if (dpi->conf->input_2p_en_bit) { + mtk_dpi_mask(dpi, DPI_CON, dpi->conf->input_2p_en_bit, + dpi->conf->input_2p_en_bit); } mtk_dpi_sw_reset(dpi, false); @@ -980,12 +980,12 @@ static const struct mtk_dpi_conf mt8195_dpintf_conf = { .output_fmts = mt8195_output_fmts, .num_output_fmts = ARRAY_SIZE(mt8195_output_fmts), .pixels_per_iter = 4, - .input_2pixel = true, .dimension_mask = DPINTF_HPW_MASK, .hvsize_mask = DPINTF_HSIZE_MASK, .channel_swap_shift = DPINTF_CH_SWAP, .yuv422_en_bit = DPINTF_YUV422_EN, .csc_enable_bit = DPINTF_CSC_ENABLE, + .input_2p_en_bit = DPINTF_INPUT_2P_EN, }; static int mtk_dpi_probe(struct platform_device *pdev) From 988705e558f0bff38dcfa4fbaaf9ed1833c028eb Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Mon, 17 Feb 2025 16:48:02 +0100 Subject: [PATCH 106/606] drm/mediatek: mtk_dpi: Explicitly manage TVD clock in power on/off [ Upstream commit 473c33f5ce651365468503c76f33158aaa1c7dd2 ] In preparation for adding support for MT8195's HDMI reserved DPI, add calls to clk_prepare_enable() / clk_disable_unprepare() for the TVD clock: in this particular case, the aforementioned clock is not (and cannot be) parented to neither pixel or engine clocks hence it won't get enabled automatically by the clock framework. Please note that on all of the currently supported MediaTek platforms, the TVD clock is always a parent of either pixel or engine clocks, and this means that the common clock framework is already enabling this clock before the children. On such platforms, this commit will only increase the refcount of the TVD clock without any functional change. Reviewed-by: CK Hu Signed-off-by: AngeloGioacchino Del Regno Link: https://patchwork.kernel.org/project/dri-devel/patch/20250217154836.108895-10-angelogioacchino.delregno@collabora.com/ Signed-off-by: Chun-Kuang Hu Signed-off-by: Sasha Levin --- drivers/gpu/drm/mediatek/mtk_dpi.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c index e4a3bd3989d8..54fc3f819577 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi.c +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c @@ -471,6 +471,7 @@ static void mtk_dpi_power_off(struct mtk_dpi *dpi) mtk_dpi_disable(dpi); clk_disable_unprepare(dpi->pixel_clk); + clk_disable_unprepare(dpi->tvd_clk); clk_disable_unprepare(dpi->engine_clk); } @@ -487,6 +488,12 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi) goto err_refcount; } + ret = clk_prepare_enable(dpi->tvd_clk); + if (ret) { + dev_err(dpi->dev, "Failed to enable tvd pll: %d\n", ret); + goto err_engine; + } + ret = clk_prepare_enable(dpi->pixel_clk); if (ret) { dev_err(dpi->dev, "Failed to enable pixel clock: %d\n", ret); @@ -496,6 +503,8 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi) return 0; err_pixel: + clk_disable_unprepare(dpi->tvd_clk); +err_engine: clk_disable_unprepare(dpi->engine_clk); err_refcount: dpi->refcount--; From f8693e1bae9c08233a2f535c3f412e157df32b33 Mon Sep 17 00:00:00 2001 From: Wentao Liang Date: Thu, 6 Mar 2025 15:51:48 +0800 Subject: [PATCH 107/606] drm/amdgpu: handle amdgpu_cgs_create_device() errors in amd_powerplay_create() [ Upstream commit 1435e895d4fc967d64e9f5bf81e992ac32f5ac76 ] Add error handling to propagate amdgpu_cgs_create_device() failures to the caller. When amdgpu_cgs_create_device() fails, release hwmgr and return -ENOMEM to prevent null pointer dereference. [v1]->[v2]: Change error code from -EINVAL to -ENOMEM. Free hwmgr. Signed-off-by: Wentao Liang Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c index 86f95a291d65..bef6578ac4bf 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c @@ -51,6 +51,11 @@ static int amd_powerplay_create(struct amdgpu_device *adev) hwmgr->adev = adev; hwmgr->not_vf = !amdgpu_sriov_vf(adev); hwmgr->device = amdgpu_cgs_create_device(adev); + if (!hwmgr->device) { + kfree(hwmgr); + return -ENOMEM; + } + mutex_init(&hwmgr->msg_lock); hwmgr->chip_family = adev->family; hwmgr->chip_id = adev->asic_type; From 13e5148f70e81991acbe0bab5b1b50ba699116e7 Mon Sep 17 00:00:00 2001 From: Ryo Takakura Date: Tue, 18 Feb 2025 09:08:30 +0100 Subject: [PATCH 108/606] PCI: vmd: Make vmd_dev::cfg_lock a raw_spinlock_t type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 18056a48669a040bef491e63b25896561ee14d90 ] The access to the PCI config space via pci_ops::read and pci_ops::write is a low-level hardware access. The functions can be accessed with disabled interrupts even on PREEMPT_RT. The pci_lock is a raw_spinlock_t for this purpose. A spinlock_t becomes a sleeping lock on PREEMPT_RT, so it cannot be acquired with disabled interrupts. The vmd_dev::cfg_lock is accessed in the same context as the pci_lock. Make vmd_dev::cfg_lock a raw_spinlock_t type so it can be used with interrupts disabled. This was reported as: BUG: sleeping function called from invalid context at kernel/locking/spinlock_rt.c:48 Call Trace: rt_spin_lock+0x4e/0x130 vmd_pci_read+0x8d/0x100 [vmd] pci_user_read_config_byte+0x6f/0xe0 pci_read_config+0xfe/0x290 sysfs_kf_bin_read+0x68/0x90 Signed-off-by: Ryo Takakura Tested-by: Luis Claudio R. Goncalves Acked-by: Luis Claudio R. Goncalves [bigeasy: reword commit message] Signed-off-by: Sebastian Andrzej Siewior Tested-off-by: Luis Claudio R. Goncalves Link: https://lore.kernel.org/r/20250218080830.ufw3IgyX@linutronix.de [kwilczynski: commit log] Signed-off-by: Krzysztof Wilczyński [bhelgaas: add back report info from https://lore.kernel.org/lkml/20241218115951.83062-1-ryotkkr98@gmail.com/] Signed-off-by: Bjorn Helgaas Signed-off-by: Sasha Levin --- drivers/pci/controller/vmd.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c index 5ff2066aa516..dfa222e02c4d 100644 --- a/drivers/pci/controller/vmd.c +++ b/drivers/pci/controller/vmd.c @@ -125,7 +125,7 @@ struct vmd_irq_list { struct vmd_dev { struct pci_dev *dev; - spinlock_t cfg_lock; + raw_spinlock_t cfg_lock; void __iomem *cfgbar; int msix_count; @@ -402,7 +402,7 @@ static int vmd_pci_read(struct pci_bus *bus, unsigned int devfn, int reg, if (!addr) return -EFAULT; - spin_lock_irqsave(&vmd->cfg_lock, flags); + raw_spin_lock_irqsave(&vmd->cfg_lock, flags); switch (len) { case 1: *value = readb(addr); @@ -417,7 +417,7 @@ static int vmd_pci_read(struct pci_bus *bus, unsigned int devfn, int reg, ret = -EINVAL; break; } - spin_unlock_irqrestore(&vmd->cfg_lock, flags); + raw_spin_unlock_irqrestore(&vmd->cfg_lock, flags); return ret; } @@ -437,7 +437,7 @@ static int vmd_pci_write(struct pci_bus *bus, unsigned int devfn, int reg, if (!addr) return -EFAULT; - spin_lock_irqsave(&vmd->cfg_lock, flags); + raw_spin_lock_irqsave(&vmd->cfg_lock, flags); switch (len) { case 1: writeb(value, addr); @@ -455,7 +455,7 @@ static int vmd_pci_write(struct pci_bus *bus, unsigned int devfn, int reg, ret = -EINVAL; break; } - spin_unlock_irqrestore(&vmd->cfg_lock, flags); + raw_spin_unlock_irqrestore(&vmd->cfg_lock, flags); return ret; } @@ -1020,7 +1020,7 @@ static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id) if (features & VMD_FEAT_OFFSET_FIRST_VECTOR) vmd->first_vec = 1; - spin_lock_init(&vmd->cfg_lock); + raw_spin_lock_init(&vmd->cfg_lock); pci_set_drvdata(dev, vmd); err = vmd_enable_domain(vmd, features); if (err) From 3ab9cd2d2e9ae89614ecf57dde11b14716f8fdaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 14 Jan 2025 13:51:39 +0100 Subject: [PATCH 109/606] drm/amdgpu: grab an additional reference on the gang fence v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 0d9a95099dcb05b5f4719c830d15bf4fdcad0dc2 ] We keep the gang submission fence around in adev, make sure that it stays alive. v2: fix memory leak on retry Signed-off-by: Christian König Acked-by: Srinivasan Shanmugam Signed-off-by: Alex Deucher Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 45dd6cbad81e..10f5a3d0f591 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -6015,6 +6015,7 @@ struct dma_fence *amdgpu_device_switch_gang(struct amdgpu_device *adev, { struct dma_fence *old = NULL; + dma_fence_get(gang); do { dma_fence_put(old); rcu_read_lock(); @@ -6024,12 +6025,19 @@ struct dma_fence *amdgpu_device_switch_gang(struct amdgpu_device *adev, if (old == gang) break; - if (!dma_fence_is_signaled(old)) + if (!dma_fence_is_signaled(old)) { + dma_fence_put(gang); return old; + } } while (cmpxchg((struct dma_fence __force **)&adev->gang_submit, old, gang) != old); + /* + * Drop it once for the exchanged reference in adev and once for the + * thread local reference acquired in amdgpu_device_get_gang(). + */ + dma_fence_put(old); dma_fence_put(old); return NULL; } From fda15c5b96b883d62fb2d84a3a1422aa87717897 Mon Sep 17 00:00:00 2001 From: Leonid Arapov Date: Tue, 18 Mar 2025 21:19:52 +0000 Subject: [PATCH 110/606] fbdev: omapfb: Add 'plane' value check [ Upstream commit 3e411827f31db7f938a30a3c7a7599839401ec30 ] Function dispc_ovl_setup is not intended to work with the value OMAP_DSS_WB of the enum parameter plane. The value of this parameter is initialized in dss_init_overlays and in the current state of the code it cannot take this value so it's not a real problem. For the purposes of defensive coding it wouldn't be superfluous to check the parameter value, because some functions down the call stack process this value correctly and some not. For example, in dispc_ovl_setup_global_alpha it may lead to buffer overflow. Add check for this value. Found by Linux Verification Center (linuxtesting.org) with SVACE static analysis tool. Signed-off-by: Leonid Arapov Signed-off-by: Helge Deller Signed-off-by: Sasha Levin --- drivers/video/fbdev/omap2/omapfb/dss/dispc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dispc.c b/drivers/video/fbdev/omap2/omapfb/dss/dispc.c index 21fef9db90d2..4f09111f8b57 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/dispc.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dispc.c @@ -2749,9 +2749,13 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, bool mem_to_mem) { int r; - enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane); + enum omap_overlay_caps caps; enum omap_channel channel; + if (plane == OMAP_DSS_WB) + return -EINVAL; + + caps = dss_feat_get_overlay_caps(plane); channel = dispc_ovl_get_channel_out(plane); DSSDBG("dispc_ovl_setup %d, pa %pad, pa_uv %pad, sw %d, %d,%d, %dx%d ->" From 14345d5d7db718a15a7c0ec14e2d0d92a59fea61 Mon Sep 17 00:00:00 2001 From: "Masami Hiramatsu (Google)" Date: Thu, 27 Mar 2025 21:19:54 +0900 Subject: [PATCH 111/606] tracing: probe-events: Add comments about entry data storing code [ Upstream commit bb9c6020f4c3a07a90dc36826cb5fbe83f09efd5 ] Add comments about entry data storing code to __store_entry_arg() and traceprobe_get_entry_data_size(). These are a bit complicated because of building the entry data storing code and scanning it. This just add comments, no behavior change. Link: https://lore.kernel.org/all/174061715004.501424.333819546601401102.stgit@devnote2/ Reported-by: Steven Rostedt Closes: https://lore.kernel.org/all/20250226102223.586d7119@gandalf.local.home/ Reviewed-by: Steven Rostedt (Google) Signed-off-by: Masami Hiramatsu (Google) Signed-off-by: Sasha Levin --- kernel/trace/trace_probe.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c index 8c73156a7eb9..606190239c87 100644 --- a/kernel/trace/trace_probe.c +++ b/kernel/trace/trace_probe.c @@ -769,6 +769,10 @@ static int check_prepare_btf_string_fetch(char *typename, #ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API +/* + * Add the entry code to store the 'argnum'th parameter and return the offset + * in the entry data buffer where the data will be stored. + */ static int __store_entry_arg(struct trace_probe *tp, int argnum) { struct probe_entry_arg *earg = tp->entry_arg; @@ -792,6 +796,20 @@ static int __store_entry_arg(struct trace_probe *tp, int argnum) tp->entry_arg = earg; } + /* + * The entry code array is repeating the pair of + * [FETCH_OP_ARG(argnum)][FETCH_OP_ST_EDATA(offset of entry data buffer)] + * and the rest of entries are filled with [FETCH_OP_END]. + * + * To reduce the redundant function parameter fetching, we scan the entry + * code array to find the FETCH_OP_ARG which already fetches the 'argnum' + * parameter. If it doesn't match, update 'offset' to find the last + * offset. + * If we find the FETCH_OP_END without matching FETCH_OP_ARG entry, we + * will save the entry with FETCH_OP_ARG and FETCH_OP_ST_EDATA, and + * return data offset so that caller can find the data offset in the entry + * data buffer. + */ offset = 0; for (i = 0; i < earg->size - 1; i++) { switch (earg->code[i].op) { @@ -825,6 +843,16 @@ int traceprobe_get_entry_data_size(struct trace_probe *tp) if (!earg) return 0; + /* + * earg->code[] array has an operation sequence which is run in + * the entry handler. + * The sequence stopped by FETCH_OP_END and each data stored in + * the entry data buffer by FETCH_OP_ST_EDATA. The FETCH_OP_ST_EDATA + * stores the data at the data buffer + its offset, and all data are + * "unsigned long" size. The offset must be increased when a data is + * stored. Thus we need to find the last FETCH_OP_ST_EDATA in the + * code array. + */ for (i = 0; i < earg->size; i++) { switch (earg->code[i].op) { case FETCH_OP_END: From 16fae241f49a76d6b6151253f7bb0e1612b2efc3 Mon Sep 17 00:00:00 2001 From: Ayush Jain Date: Fri, 7 Mar 2025 04:38:54 +0000 Subject: [PATCH 112/606] ktest: Fix Test Failures Due to Missing LOG_FILE Directories [ Upstream commit 5a1bed232781d356f842576daacc260f0d0c8d2e ] Handle missing parent directories for LOG_FILE path to prevent test failures. If the parent directories don't exist, create them to ensure the tests proceed successfully. Cc: Link: https://lore.kernel.org/20250307043854.2518539-1-Ayush.jain3@amd.com Signed-off-by: Ayush Jain Signed-off-by: Steven Rostedt Signed-off-by: Sasha Levin --- tools/testing/ktest/ktest.pl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 83d65c2abaf0..331601575743 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -4289,6 +4289,14 @@ if (defined($opt{"LOG_FILE"})) { if ($opt{"CLEAR_LOG"}) { unlink $opt{"LOG_FILE"}; } + + if (! -e $opt{"LOG_FILE"} && $opt{"LOG_FILE"} =~ m,^(.*/),) { + my $dir = $1; + if (! -d $dir) { + mkpath($dir) or die "Failed to create directories '$dir': $!"; + print "\nThe log directory $dir did not exist, so it was created.\n"; + } + } open(LOG, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; LOG->autoflush(1); } From a0171967abdde8ccbf62473481291fdc894b0953 Mon Sep 17 00:00:00 2001 From: Jonathan McDowell Date: Wed, 12 Mar 2025 07:26:18 +0200 Subject: [PATCH 113/606] tpm, tpm_tis: Workaround failed command reception on Infineon devices [ Upstream commit de9e33df7762abbfc2a1568291f2c3a3154c6a9d ] Some Infineon devices have a issue where the status register will get stuck with a quick REQUEST_USE / COMMAND_READY sequence. This is not simply a matter of requiring a longer timeout; the work around is to retry the command submission. Add appropriate logic to do this in the send path. This is fixed in later firmware revisions, but those are not always available, and cannot generally be easily updated from outside a firmware environment. Testing has been performed with a simple repeated loop of doing a TPM2_CC_GET_CAPABILITY for TPM_CAP_PROP_MANUFACTURER using the Go code at: https://the.earth.li/~noodles/tpm-stuff/timeout-reproducer-simple.go It can take several hours to reproduce, and several million operations. Signed-off-by: Jonathan McDowell Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen Signed-off-by: Sasha Levin --- drivers/char/tpm/tpm_tis_core.c | 17 ++++++++++++++--- drivers/char/tpm/tpm_tis_core.h | 1 + include/linux/tpm.h | 1 + 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index f6aa0dfadb93..7ade8bd12ab2 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -464,7 +464,10 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len) if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, &priv->int_queue, false) < 0) { - rc = -ETIME; + if (test_bit(TPM_TIS_STATUS_VALID_RETRY, &priv->flags)) + rc = -EAGAIN; + else + rc = -ETIME; goto out_err; } status = tpm_tis_status(chip); @@ -481,7 +484,10 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len) if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, &priv->int_queue, false) < 0) { - rc = -ETIME; + if (test_bit(TPM_TIS_STATUS_VALID_RETRY, &priv->flags)) + rc = -EAGAIN; + else + rc = -ETIME; goto out_err; } status = tpm_tis_status(chip); @@ -546,9 +552,11 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len) if (rc >= 0) /* Data transfer done successfully */ break; - else if (rc != -EIO) + else if (rc != -EAGAIN && rc != -EIO) /* Data transfer failed, not recoverable */ return rc; + + usleep_range(priv->timeout_min, priv->timeout_max); } /* go and do it */ @@ -1147,6 +1155,9 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, priv->timeout_max = TIS_TIMEOUT_MAX_ATML; } + if (priv->manufacturer_id == TPM_VID_IFX) + set_bit(TPM_TIS_STATUS_VALID_RETRY, &priv->flags); + if (is_bsw()) { priv->ilb_base_addr = ioremap(INTEL_LEGACY_BLK_BASE_ADDR, ILB_REMAP_SIZE); diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h index 13e99cf65efe..369496a6aebf 100644 --- a/drivers/char/tpm/tpm_tis_core.h +++ b/drivers/char/tpm/tpm_tis_core.h @@ -89,6 +89,7 @@ enum tpm_tis_flags { TPM_TIS_INVALID_STATUS = 1, TPM_TIS_DEFAULT_CANCELLATION = 2, TPM_TIS_IRQ_TESTED = 3, + TPM_TIS_STATUS_VALID_RETRY = 4, }; struct tpm_tis_data { diff --git a/include/linux/tpm.h b/include/linux/tpm.h index 4ee9d13749ad..5f4998626a98 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -272,6 +272,7 @@ enum tpm2_cc_attrs { #define TPM_VID_WINBOND 0x1050 #define TPM_VID_STM 0x104A #define TPM_VID_ATML 0x1114 +#define TPM_VID_IFX 0x15D1 enum tpm_chip_flags { TPM_CHIP_FLAG_BOOTSTRAPPED = BIT(0), From 8ddbec73ea2598d8414e8f7103241b55cf877010 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Tue, 1 Apr 2025 12:28:59 +0200 Subject: [PATCH 114/606] pwm: mediatek: Prevent divide-by-zero in pwm_mediatek_config() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 7ca59947b5fcf94e7ea4029d1bd0f7c41500a161 ] With CONFIG_COMPILE_TEST && !CONFIG_HAVE_CLK, pwm_mediatek_config() has a divide-by-zero in the following line: do_div(resolution, clk_get_rate(pc->clk_pwms[pwm->hwpwm])); due to the fact that the !CONFIG_HAVE_CLK version of clk_get_rate() returns zero. This is presumably just a theoretical problem: COMPILE_TEST overrides the dependency on RALINK which would select COMMON_CLK. Regardless it's a good idea to check for the error explicitly to avoid divide-by-zero. Fixes the following warning: drivers/pwm/pwm-mediatek.o: warning: objtool: .text: unexpected end of section Signed-off-by: Josh Poimboeuf Link: https://lore.kernel.org/r/fb56444939325cc173e752ba199abd7aeae3bf12.1742852847.git.jpoimboe@kernel.org [ukleinek: s/CONFIG_CLK/CONFIG_HAVE_CLK/] Fixes: caf065f8fd58 ("pwm: Add MediaTek PWM support") Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/9e78a0796acba3435553ed7db1c7965dcffa6215.1743501688.git.u.kleine-koenig@baylibre.com Signed-off-by: Uwe Kleine-König Signed-off-by: Sasha Levin --- drivers/pwm/pwm-mediatek.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c index 6adb0ed01906..6b1a75b6bd12 100644 --- a/drivers/pwm/pwm-mediatek.c +++ b/drivers/pwm/pwm-mediatek.c @@ -124,21 +124,25 @@ static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm, struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip); u32 clkdiv = 0, cnt_period, cnt_duty, reg_width = PWMDWIDTH, reg_thres = PWMTHRES; + unsigned long clk_rate; u64 resolution; int ret; ret = pwm_mediatek_clk_enable(chip, pwm); - if (ret < 0) return ret; + clk_rate = clk_get_rate(pc->clk_pwms[pwm->hwpwm]); + if (!clk_rate) + return -EINVAL; + /* Make sure we use the bus clock and not the 26MHz clock */ if (pc->soc->has_ck_26m_sel) writel(0, pc->regs + PWM_CK_26M_SEL); /* Using resolution in picosecond gets accuracy higher */ resolution = (u64)NSEC_PER_SEC * 1000; - do_div(resolution, clk_get_rate(pc->clk_pwms[pwm->hwpwm])); + do_div(resolution, clk_rate); cnt_period = DIV_ROUND_CLOSEST_ULL((u64)period_ns * 1000, resolution); while (cnt_period > 8191) { From d837f37cd4d9779f1fc52e41d5c7009c8f63317c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 1 Apr 2025 12:29:00 +0200 Subject: [PATCH 115/606] pwm: rcar: Improve register calculation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit e7327c193014a4d8666e9c1cda09cf2c060518e8 ] There were several issues in the function rcar_pwm_set_counter(): - The u64 values period_ns and duty_ns were cast to int on function call which might loose bits on 32 bit architectures. Fix: Make parameters to rcar_pwm_set_counter() u64 - The algorithm divided by the result of a division which looses precision. Fix: Make use of mul_u64_u64_div_u64() - The calculated values were just masked to fit the respective register fields which again might loose bits. Fix: Explicitly check for overlow Implement the respective fixes. A side effect of fixing the 2nd issue is that there is no division by 0 if clk_get_rate() returns 0. Fixes: ed6c1476bf7f ("pwm: Add support for R-Car PWM Timer") Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/ab3dac794b2216cc1cc56d65c93dd164f8bd461b.1743501688.git.u.kleine-koenig@baylibre.com [ukleinek: Added an explicit #include to please the 0day build bot] Link: https://lore.kernel.org/oe-kbuild-all/202504031354.VJtxScP5-lkp@intel.com/ Reviewed-by: Geert Uytterhoeven Signed-off-by: Uwe Kleine-König Signed-off-by: Sasha Levin --- drivers/pwm/pwm-rcar.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c index 5b5f357c44de..18fa2d40d936 100644 --- a/drivers/pwm/pwm-rcar.c +++ b/drivers/pwm/pwm-rcar.c @@ -8,6 +8,7 @@ * - The hardware cannot generate a 0% duty cycle. */ +#include #include #include #include @@ -103,23 +104,24 @@ static void rcar_pwm_set_clock_control(struct rcar_pwm_chip *rp, rcar_pwm_write(rp, value, RCAR_PWMCR); } -static int rcar_pwm_set_counter(struct rcar_pwm_chip *rp, int div, int duty_ns, - int period_ns) +static int rcar_pwm_set_counter(struct rcar_pwm_chip *rp, int div, u64 duty_ns, + u64 period_ns) { - unsigned long long one_cycle, tmp; /* 0.01 nanoseconds */ + unsigned long long tmp; unsigned long clk_rate = clk_get_rate(rp->clk); u32 cyc, ph; - one_cycle = NSEC_PER_SEC * 100ULL << div; - do_div(one_cycle, clk_rate); + /* div <= 24 == RCAR_PWM_MAX_DIVISION, so the shift doesn't overflow. */ + tmp = mul_u64_u64_div_u64(period_ns, clk_rate, (u64)NSEC_PER_SEC << div); + if (tmp > FIELD_MAX(RCAR_PWMCNT_CYC0_MASK)) + tmp = FIELD_MAX(RCAR_PWMCNT_CYC0_MASK); - tmp = period_ns * 100ULL; - do_div(tmp, one_cycle); - cyc = (tmp << RCAR_PWMCNT_CYC0_SHIFT) & RCAR_PWMCNT_CYC0_MASK; + cyc = FIELD_PREP(RCAR_PWMCNT_CYC0_MASK, tmp); - tmp = duty_ns * 100ULL; - do_div(tmp, one_cycle); - ph = tmp & RCAR_PWMCNT_PH0_MASK; + tmp = mul_u64_u64_div_u64(duty_ns, clk_rate, (u64)NSEC_PER_SEC << div); + if (tmp > FIELD_MAX(RCAR_PWMCNT_PH0_MASK)) + tmp = FIELD_MAX(RCAR_PWMCNT_PH0_MASK); + ph = FIELD_PREP(RCAR_PWMCNT_PH0_MASK, tmp); /* Avoid prohibited setting */ if (cyc == 0 || ph == 0) From 0e1816d8c27731fceadcd95db7cb7014502d6dd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 1 Apr 2025 12:29:01 +0200 Subject: [PATCH 116/606] pwm: fsl-ftm: Handle clk_get_rate() returning 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 928446a5302eee30ebb32075c0db5dda5a138fb7 ] Considering that the driver doesn't enable the used clocks (and also that clk_get_rate() returns 0 if CONFIG_HAVE_CLK is unset) better check the return value of clk_get_rate() for being non-zero before dividing by it. Fixes: 3479bbd1e1f8 ("pwm: fsl-ftm: More relaxed permissions for updating period") Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/b68351a51017035651bc62ad3146afcb706874f0.1743501688.git.u.kleine-koenig@baylibre.com Signed-off-by: Uwe Kleine-König Signed-off-by: Sasha Levin --- drivers/pwm/pwm-fsl-ftm.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/pwm/pwm-fsl-ftm.c b/drivers/pwm/pwm-fsl-ftm.c index b7c6045c5d08..2c60d67e9a4a 100644 --- a/drivers/pwm/pwm-fsl-ftm.c +++ b/drivers/pwm/pwm-fsl-ftm.c @@ -119,6 +119,9 @@ static unsigned int fsl_pwm_ticks_to_ns(struct fsl_pwm_chip *fpc, unsigned long long exval; rate = clk_get_rate(fpc->clk[fpc->period.clk_select]); + if (rate >> fpc->period.clk_ps == 0) + return 0; + exval = ticks; exval *= 1000000000UL; do_div(exval, rate >> fpc->period.clk_ps); @@ -191,6 +194,9 @@ static unsigned int fsl_pwm_calculate_duty(struct fsl_pwm_chip *fpc, unsigned int period = fpc->period.mod_period + 1; unsigned int period_ns = fsl_pwm_ticks_to_ns(fpc, period); + if (!period_ns) + return 0; + duty = (unsigned long long)duty_ns * period; do_div(duty, period_ns); From d5cba7730d7653d9f05cbf0ea1ce190c76de32da Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Tue, 8 Apr 2025 09:27:48 -0400 Subject: [PATCH 117/606] bpf: support SKF_NET_OFF and SKF_LL_OFF on skb frags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit d4bac0288a2b444e468e6df9cb4ed69479ddf14a ] Classic BPF socket filters with SKB_NET_OFF and SKB_LL_OFF fail to read when these offsets extend into frags. This has been observed with iwlwifi and reproduced with tun with IFF_NAPI_FRAGS. The below straightforward socket filter on UDP port, applied to a RAW socket, will silently miss matching packets. const int offset_proto = offsetof(struct ip6_hdr, ip6_nxt); const int offset_dport = sizeof(struct ip6_hdr) + offsetof(struct udphdr, dest); struct sock_filter filter_code[] = { BPF_STMT(BPF_LD + BPF_B + BPF_ABS, SKF_AD_OFF + SKF_AD_PKTTYPE), BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, PACKET_HOST, 0, 4), BPF_STMT(BPF_LD + BPF_B + BPF_ABS, SKF_NET_OFF + offset_proto), BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 2), BPF_STMT(BPF_LD + BPF_H + BPF_ABS, SKF_NET_OFF + offset_dport), This is unexpected behavior. Socket filter programs should be consistent regardless of environment. Silent misses are particularly concerning as hard to detect. Use skb_copy_bits for offsets outside linear, same as done for non-SKF_(LL|NET) offsets. Offset is always positive after subtracting the reference threshold SKB_(LL|NET)_OFF, so is always >= skb_(mac|network)_offset. The sum of the two is an offset against skb->data, and may be negative, but it cannot point before skb->head, as skb_(mac|network)_offset would too. This appears to go back to when frag support was introduced to sk_run_filter in linux-2.4.4, before the introduction of git. The amount of code change and 8/16/32 bit duplication are unfortunate. But any attempt I made to be smarter saved very few LoC while complicating the code. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Link: https://lore.kernel.org/netdev/20250122200402.3461154-1-maze@google.com/ Link: https://elixir.bootlin.com/linux/2.4.4/source/net/core/filter.c#L244 Reported-by: Matt Moeller Co-developed-by: Maciej Żenczykowski Signed-off-by: Maciej Żenczykowski Signed-off-by: Willem de Bruijn Acked-by: Stanislav Fomichev Link: https://lore.kernel.org/r/20250408132833.195491-2-willemdebruijn.kernel@gmail.com Signed-off-by: Alexei Starovoitov Signed-off-by: Sasha Levin --- net/core/filter.c | 80 ++++++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/net/core/filter.c b/net/core/filter.c index 84992279f4b1..39eef3370d80 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -211,24 +211,36 @@ BPF_CALL_3(bpf_skb_get_nlattr_nest, struct sk_buff *, skb, u32, a, u32, x) return 0; } +static int bpf_skb_load_helper_convert_offset(const struct sk_buff *skb, int offset) +{ + if (likely(offset >= 0)) + return offset; + + if (offset >= SKF_NET_OFF) + return offset - SKF_NET_OFF + skb_network_offset(skb); + + if (offset >= SKF_LL_OFF && skb_mac_header_was_set(skb)) + return offset - SKF_LL_OFF + skb_mac_offset(skb); + + return INT_MIN; +} + BPF_CALL_4(bpf_skb_load_helper_8, const struct sk_buff *, skb, const void *, data, int, headlen, int, offset) { - u8 tmp, *ptr; + u8 tmp; const int len = sizeof(tmp); - if (offset >= 0) { - if (headlen - offset >= len) - return *(u8 *)(data + offset); - if (!skb_copy_bits(skb, offset, &tmp, sizeof(tmp))) - return tmp; - } else { - ptr = bpf_internal_load_pointer_neg_helper(skb, offset, len); - if (likely(ptr)) - return *(u8 *)ptr; - } + offset = bpf_skb_load_helper_convert_offset(skb, offset); + if (offset == INT_MIN) + return -EFAULT; - return -EFAULT; + if (headlen - offset >= len) + return *(u8 *)(data + offset); + if (!skb_copy_bits(skb, offset, &tmp, sizeof(tmp))) + return tmp; + else + return -EFAULT; } BPF_CALL_2(bpf_skb_load_helper_8_no_cache, const struct sk_buff *, skb, @@ -241,21 +253,19 @@ BPF_CALL_2(bpf_skb_load_helper_8_no_cache, const struct sk_buff *, skb, BPF_CALL_4(bpf_skb_load_helper_16, const struct sk_buff *, skb, const void *, data, int, headlen, int, offset) { - __be16 tmp, *ptr; + __be16 tmp; const int len = sizeof(tmp); - if (offset >= 0) { - if (headlen - offset >= len) - return get_unaligned_be16(data + offset); - if (!skb_copy_bits(skb, offset, &tmp, sizeof(tmp))) - return be16_to_cpu(tmp); - } else { - ptr = bpf_internal_load_pointer_neg_helper(skb, offset, len); - if (likely(ptr)) - return get_unaligned_be16(ptr); - } + offset = bpf_skb_load_helper_convert_offset(skb, offset); + if (offset == INT_MIN) + return -EFAULT; - return -EFAULT; + if (headlen - offset >= len) + return get_unaligned_be16(data + offset); + if (!skb_copy_bits(skb, offset, &tmp, sizeof(tmp))) + return be16_to_cpu(tmp); + else + return -EFAULT; } BPF_CALL_2(bpf_skb_load_helper_16_no_cache, const struct sk_buff *, skb, @@ -268,21 +278,19 @@ BPF_CALL_2(bpf_skb_load_helper_16_no_cache, const struct sk_buff *, skb, BPF_CALL_4(bpf_skb_load_helper_32, const struct sk_buff *, skb, const void *, data, int, headlen, int, offset) { - __be32 tmp, *ptr; + __be32 tmp; const int len = sizeof(tmp); - if (likely(offset >= 0)) { - if (headlen - offset >= len) - return get_unaligned_be32(data + offset); - if (!skb_copy_bits(skb, offset, &tmp, sizeof(tmp))) - return be32_to_cpu(tmp); - } else { - ptr = bpf_internal_load_pointer_neg_helper(skb, offset, len); - if (likely(ptr)) - return get_unaligned_be32(ptr); - } + offset = bpf_skb_load_helper_convert_offset(skb, offset); + if (offset == INT_MIN) + return -EFAULT; - return -EFAULT; + if (headlen - offset >= len) + return get_unaligned_be32(data + offset); + if (!skb_copy_bits(skb, offset, &tmp, sizeof(tmp))) + return be32_to_cpu(tmp); + else + return -EFAULT; } BPF_CALL_2(bpf_skb_load_helper_32_no_cache, const struct sk_buff *, skb, From 480faed292f2bb4b8e0196596f587364d5fcf8a5 Mon Sep 17 00:00:00 2001 From: Jann Horn Date: Fri, 29 Nov 2024 21:20:53 +0100 Subject: [PATCH 118/606] ext4: don't treat fhandle lookup of ea_inode as FS corruption [ Upstream commit 642335f3ea2b3fd6dba03e57e01fa9587843a497 ] A file handle that userspace provides to open_by_handle_at() can legitimately contain an outdated inode number that has since been reused for another purpose - that's why the file handle also contains a generation number. But if the inode number has been reused for an ea_inode, check_igot_inode() will notice, __ext4_iget() will go through ext4_error_inode(), and if the inode was newly created, it will also be marked as bad by iget_failed(). This all happens before the point where the inode generation is checked. ext4_error_inode() is supposed to only be used on filesystem corruption; it should not be used when userspace just got unlucky with a stale file handle. So when this happens, let __ext4_iget() just return an error. Fixes: b3e6bcb94590 ("ext4: add EA_INODE checking to ext4_iget()") Signed-off-by: Jann Horn Reviewed-by: Jan Kara Link: https://patch.msgid.link/20241129-ext4-ignore-ea-fhandle-v1-1-e532c0d1cee0@google.com Signed-off-by: Theodore Ts'o Signed-off-by: Sasha Levin --- fs/ext4/inode.c | 68 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 19d7bcf16ebb..ddfeaf19bff1 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4692,22 +4692,43 @@ static inline void ext4_inode_set_iversion_queried(struct inode *inode, u64 val) inode_set_iversion_queried(inode, val); } -static const char *check_igot_inode(struct inode *inode, ext4_iget_flags flags) - +static int check_igot_inode(struct inode *inode, ext4_iget_flags flags, + const char *function, unsigned int line) { + const char *err_str; + if (flags & EXT4_IGET_EA_INODE) { - if (!(EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) - return "missing EA_INODE flag"; + if (!(EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) { + err_str = "missing EA_INODE flag"; + goto error; + } if (ext4_test_inode_state(inode, EXT4_STATE_XATTR) || - EXT4_I(inode)->i_file_acl) - return "ea_inode with extended attributes"; + EXT4_I(inode)->i_file_acl) { + err_str = "ea_inode with extended attributes"; + goto error; + } } else { - if ((EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) - return "unexpected EA_INODE flag"; + if ((EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) { + /* + * open_by_handle_at() could provide an old inode number + * that has since been reused for an ea_inode; this does + * not indicate filesystem corruption + */ + if (flags & EXT4_IGET_HANDLE) + return -ESTALE; + err_str = "unexpected EA_INODE flag"; + goto error; + } } - if (is_bad_inode(inode) && !(flags & EXT4_IGET_BAD)) - return "unexpected bad inode w/o EXT4_IGET_BAD"; - return NULL; + if (is_bad_inode(inode) && !(flags & EXT4_IGET_BAD)) { + err_str = "unexpected bad inode w/o EXT4_IGET_BAD"; + goto error; + } + return 0; + +error: + ext4_error_inode(inode, function, line, 0, err_str); + return -EFSCORRUPTED; } struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, @@ -4719,7 +4740,6 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, struct ext4_inode_info *ei; struct ext4_super_block *es = EXT4_SB(sb)->s_es; struct inode *inode; - const char *err_str; journal_t *journal = EXT4_SB(sb)->s_journal; long ret; loff_t size; @@ -4748,10 +4768,10 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, if (!inode) return ERR_PTR(-ENOMEM); if (!(inode->i_state & I_NEW)) { - if ((err_str = check_igot_inode(inode, flags)) != NULL) { - ext4_error_inode(inode, function, line, 0, err_str); + ret = check_igot_inode(inode, flags, function, line); + if (ret) { iput(inode); - return ERR_PTR(-EFSCORRUPTED); + return ERR_PTR(ret); } return inode; } @@ -5023,13 +5043,21 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, ret = -EFSCORRUPTED; goto bad_inode; } - if ((err_str = check_igot_inode(inode, flags)) != NULL) { - ext4_error_inode(inode, function, line, 0, err_str); - ret = -EFSCORRUPTED; - goto bad_inode; + ret = check_igot_inode(inode, flags, function, line); + /* + * -ESTALE here means there is nothing inherently wrong with the inode, + * it's just not an inode we can return for an fhandle lookup. + */ + if (ret == -ESTALE) { + brelse(iloc.bh); + unlock_new_inode(inode); + iput(inode); + return ERR_PTR(-ESTALE); } - + if (ret) + goto bad_inode; brelse(iloc.bh); + unlock_new_inode(inode); return inode; From 39cb5a29cd60866616b9378beac329ce6cc91f7a Mon Sep 17 00:00:00 2001 From: Alain Volmat Date: Mon, 10 Feb 2025 11:04:31 +0100 Subject: [PATCH 119/606] dt-bindings: media: st,stmipid02: correct lane-polarities maxItems commit 3a544a39e0a4c492e3026dfbed018321d2bd6caa upstream. The MIPID02 can use up to 2 data lanes which leads to having a maximum item number of 3 for the lane-polarities since this also contains the clock lane. CC: stable@vger.kernel.org Fixes: c2741cbe7f8a ("dt-bindings: media: st,stmipid02: Convert the text bindings to YAML") Signed-off-by: Alain Volmat Acked-by: Conor Dooley Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/media/i2c/st,st-mipid02.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/media/i2c/st,st-mipid02.yaml b/Documentation/devicetree/bindings/media/i2c/st,st-mipid02.yaml index b68141264c0e..4d40e75b4e1e 100644 --- a/Documentation/devicetree/bindings/media/i2c/st,st-mipid02.yaml +++ b/Documentation/devicetree/bindings/media/i2c/st,st-mipid02.yaml @@ -71,7 +71,7 @@ properties: description: Any lane can be inverted or not. minItems: 1 - maxItems: 2 + maxItems: 3 required: - data-lanes From fd7bb97ede487b9f075707b7408a9073e0d474b1 Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Tue, 18 Feb 2025 18:58:09 +0000 Subject: [PATCH 120/606] media: mediatek: vcodec: Fix a resource leak related to the scp device in FW initialization commit 4936cd5817af35d23e4d283f48fa59a18ef481e4 upstream. On Mediatek devices with a system companion processor (SCP) the mtk_scp structure has to be removed explicitly to avoid a resource leak. Free the structure in case the allocation of the firmware structure fails during the firmware initialization. Fixes: 53dbe0850444 ("media: mtk-vcodec: potential null pointer deference in SCP") Cc: stable@vger.kernel.org Signed-off-by: Jiasheng Jiang Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- .../platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c index 774487fb72a3..93579a7009a7 100644 --- a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c +++ b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c @@ -79,8 +79,11 @@ struct mtk_vcodec_fw *mtk_vcodec_fw_scp_init(void *priv, enum mtk_vcodec_fw_use } fw = devm_kzalloc(&plat_dev->dev, sizeof(*fw), GFP_KERNEL); - if (!fw) + if (!fw) { + scp_put(scp); return ERR_PTR(-ENOMEM); + } + fw->type = SCP; fw->ops = &mtk_vcodec_rproc_msg; fw->scp = scp; From 8895a7af84527433be521ffb281c8a413edfaa0a Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 18 Oct 2024 15:21:10 +0000 Subject: [PATCH 121/606] media: mtk-vcodec: venc: avoid -Wenum-compare-conditional warning commit 07df4f23ef3ffe6fee697cd2e03623ad27108843 upstream. This is one of three clang warnings about incompatible enum types in a conditional expression: drivers/media/platform/mediatek/vcodec/encoder/venc/venc_h264_if.c:597:29: error: conditional expression between different enumeration types ('enum scp_ipi_id' and 'enum ipi_id') [-Werror,-Wenum-compare-conditional] 597 | inst->vpu_inst.id = is_ext ? SCP_IPI_VENC_H264 : IPI_VENC_H264; | ^ ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~ The code is correct, so just rework it to avoid the warning. Fixes: 0dc4b3286125 ("media: mtk-vcodec: venc: support SCP firmware") Cc: stable@vger.kernel.org Signed-off-by: Arnd Bergmann Reviewed-by: Nathan Chancellor Reviewed-by: Alexandre Courbot Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- .../platform/mediatek/vcodec/encoder/venc/venc_h264_if.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/mediatek/vcodec/encoder/venc/venc_h264_if.c b/drivers/media/platform/mediatek/vcodec/encoder/venc/venc_h264_if.c index f8145998fcaf..8522f71fc901 100644 --- a/drivers/media/platform/mediatek/vcodec/encoder/venc/venc_h264_if.c +++ b/drivers/media/platform/mediatek/vcodec/encoder/venc/venc_h264_if.c @@ -594,7 +594,11 @@ static int h264_enc_init(struct mtk_vcodec_enc_ctx *ctx) inst->ctx = ctx; inst->vpu_inst.ctx = ctx; - inst->vpu_inst.id = is_ext ? SCP_IPI_VENC_H264 : IPI_VENC_H264; + if (is_ext) + inst->vpu_inst.id = SCP_IPI_VENC_H264; + else + inst->vpu_inst.id = IPI_VENC_H264; + inst->hw_base = mtk_vcodec_get_reg_addr(inst->ctx->dev->reg_base, VENC_SYS); ret = vpu_enc_init(&inst->vpu_inst); From 259dafed18799e8a813e4ef131119d8f82b9a6a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Tue, 21 Jan 2025 21:44:00 +0100 Subject: [PATCH 122/606] media: i2c: adv748x: Fix test pattern selection mask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 9e38acacb9d809b97a0bdc5c76e725355a47158a upstream. The mask to select the test-pattern in register ADV748X_SDP_FRP is incorrect, it's the lower 3 bits which controls the pattern. The GENMASK() macro is used incorrectly and the generated mask is 0x0e instead of 0x07. The result is that not all test patterns are selectable, and that in some cases the wrong test pattern is activated. Fix this by correcting the GENMASK(). Fixes: 3e89586a64df ("media: i2c: adv748x: add adv748x driver") Cc: stable@vger.kernel.org Signed-off-by: Niklas Söderlund Reviewed-by: Kieran Bingham Signed-off-by: Hans Verkuil [hverkuil: fixed tiny typo in commit log: my -> by] Signed-off-by: Greg Kroah-Hartman --- drivers/media/i2c/adv748x/adv748x.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/adv748x/adv748x.h b/drivers/media/i2c/adv748x/adv748x.h index 6f90f78f58cf..6e2cb95e86ca 100644 --- a/drivers/media/i2c/adv748x/adv748x.h +++ b/drivers/media/i2c/adv748x/adv748x.h @@ -322,7 +322,7 @@ struct adv748x_state { /* Free run pattern select */ #define ADV748X_SDP_FRP 0x14 -#define ADV748X_SDP_FRP_MASK GENMASK(3, 1) +#define ADV748X_SDP_FRP_MASK GENMASK(2, 0) /* Saturation */ #define ADV748X_SDP_SD_SAT_U 0xe3 /* user_map_rw_reg_e3 */ From 5af611c70fb889d46d2f654b8996746e59556750 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 20 Feb 2025 22:50:11 +0530 Subject: [PATCH 123/606] media: venus: hfi: add a check to handle OOB in sfr region commit f4b211714bcc70effa60c34d9fa613d182e3ef1e upstream. sfr->buf_size is in shared memory and can be modified by malicious user. OOB write is possible when the size is made higher than actual sfr data buffer. Cap the size to allocated size for such cases. Cc: stable@vger.kernel.org Fixes: d96d3f30c0f2 ("[media] media: venus: hfi: add Venus HFI files") Reviewed-by: Bryan O'Donoghue Signed-off-by: Vikash Garodia Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/platform/qcom/venus/hfi_venus.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index f9437b6412b9..cfd9471560cc 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -1035,18 +1035,26 @@ static void venus_sfr_print(struct venus_hfi_device *hdev) { struct device *dev = hdev->core->dev; struct hfi_sfr *sfr = hdev->sfr.kva; + u32 size; void *p; if (!sfr) return; - p = memchr(sfr->data, '\0', sfr->buf_size); + size = sfr->buf_size; + if (!size) + return; + + if (size > ALIGNED_SFR_SIZE) + size = ALIGNED_SFR_SIZE; + + p = memchr(sfr->data, '\0', size); /* * SFR isn't guaranteed to be NULL terminated since SYS_ERROR indicates * that Venus is in the process of crashing. */ if (!p) - sfr->data[sfr->buf_size - 1] = '\0'; + sfr->data[size - 1] = '\0'; dev_err_ratelimited(dev, "SFR message from FW: %s\n", sfr->data); } From 40084302f639b3fe954398c5ba5ee556b7242b54 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 20 Feb 2025 22:50:10 +0530 Subject: [PATCH 124/606] media: venus: hfi: add check to handle incorrect queue size commit 69baf245b23e20efda0079238b27fc63ecf13de1 upstream. qsize represents size of shared queued between driver and video firmware. Firmware can modify this value to an invalid large value. In such situation, empty_space will be bigger than the space actually available. Since new_wr_idx is not checked, so the following code will result in an OOB write. ... qsize = qhdr->q_size if (wr_idx >= rd_idx) empty_space = qsize - (wr_idx - rd_idx) .... if (new_wr_idx < qsize) { memcpy(wr_ptr, packet, dwords << 2) --> OOB write Add check to ensure qsize is within the allocated size while reading and writing packets into the queue. Cc: stable@vger.kernel.org Fixes: d96d3f30c0f2 ("[media] media: venus: hfi: add Venus HFI files") Reviewed-by: Bryan O'Donoghue Signed-off-by: Vikash Garodia Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/platform/qcom/venus/hfi_venus.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index cfd9471560cc..ab93757fff4b 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -187,6 +187,9 @@ static int venus_write_queue(struct venus_hfi_device *hdev, /* ensure rd/wr indices's are read from memory */ rmb(); + if (qsize > IFACEQ_QUEUE_SIZE / 4) + return -EINVAL; + if (wr_idx >= rd_idx) empty_space = qsize - (wr_idx - rd_idx); else @@ -255,6 +258,9 @@ static int venus_read_queue(struct venus_hfi_device *hdev, wr_idx = qhdr->write_idx; qsize = qhdr->q_size; + if (qsize > IFACEQ_QUEUE_SIZE / 4) + return -EINVAL; + /* make sure data is valid before using it */ rmb(); From 3e7fc0606e717063433872bd67a113bf8bf40316 Mon Sep 17 00:00:00 2001 From: Matthew Majewski Date: Wed, 19 Feb 2025 14:05:01 -0500 Subject: [PATCH 125/606] media: vim2m: print device name after registering device commit 143d75583f2427f3a97dba62413c4f0604867ebf upstream. Move the v4l2_info() call displaying the video device name after the device is actually registered. This fixes a bug where the driver was always displaying "/dev/video0" since it was reading from the vfd before it was registered. Fixes: cf7f34777a5b ("media: vim2m: Register video device after setting up internals") Cc: stable@vger.kernel.org Signed-off-by: Matthew Majewski Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/test-drivers/vim2m.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/test-drivers/vim2m.c b/drivers/media/test-drivers/vim2m.c index 3e3b424b4860..8ca6459286ba 100644 --- a/drivers/media/test-drivers/vim2m.c +++ b/drivers/media/test-drivers/vim2m.c @@ -1316,9 +1316,6 @@ static int vim2m_probe(struct platform_device *pdev) vfd->v4l2_dev = &dev->v4l2_dev; video_set_drvdata(vfd, dev); - v4l2_info(&dev->v4l2_dev, - "Device registered as /dev/video%d\n", vfd->num); - platform_set_drvdata(pdev, dev); dev->m2m_dev = v4l2_m2m_init(&m2m_ops); @@ -1345,6 +1342,9 @@ static int vim2m_probe(struct platform_device *pdev) goto error_m2m; } + v4l2_info(&dev->v4l2_dev, + "Device registered as /dev/video%d\n", vfd->num); + #ifdef CONFIG_MEDIA_CONTROLLER ret = v4l2_m2m_register_media_controller(dev->m2m_dev, vfd, MEDIA_ENT_F_PROC_VIDEO_SCALER); From 192b87608c2ccadf0c1fb239fa30334a374ff515 Mon Sep 17 00:00:00 2001 From: Yuan Can Date: Tue, 22 Oct 2024 14:50:37 +0800 Subject: [PATCH 126/606] media: siano: Fix error handling in smsdvb_module_init() commit 734ac57e47b3bdd140a1119e2c4e8e6f8ef8b33d upstream. The smsdvb_module_init() returns without checking the retval from smscore_register_hotplug(). If the smscore_register_hotplug() failed, the module failed to install, leaving the smsdvb_debugfs not unregistered. Fixes: 3f6b87cff66b ("[media] siano: allow showing the complete statistics via debugfs") Cc: stable@vger.kernel.org Signed-off-by: Yuan Can Acked-by: Ricardo Ribalda Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/common/siano/smsdvb-main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/common/siano/smsdvb-main.c b/drivers/media/common/siano/smsdvb-main.c index f80caaa333da..67c47e3d671d 100644 --- a/drivers/media/common/siano/smsdvb-main.c +++ b/drivers/media/common/siano/smsdvb-main.c @@ -1243,6 +1243,8 @@ static int __init smsdvb_module_init(void) smsdvb_debugfs_register(); rc = smscore_register_hotplug(smsdvb_hotplug); + if (rc) + smsdvb_debugfs_unregister(); pr_debug("\n"); From 9da005f884184efc3b32db675c21ed4160c5cd53 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Wed, 12 Mar 2025 16:32:45 +0100 Subject: [PATCH 127/606] xenfs/xensyms: respect hypervisor's "next" indication commit 5c4e79e29a9fe4ea132118ac40c2bc97cfe23077 upstream. The interface specifies the symnum field as an input and output; the hypervisor sets it to the next sequential symbol's index. xensyms_next() incrementing the position explicitly (and xensyms_next_sym() decrementing it to "rewind") is only correct as long as the sequence of symbol indexes is non-sparse. Use the hypervisor-supplied value instead to update the position in xensyms_next(), and use the saved incoming index in xensyms_next_sym(). Cc: stable@kernel.org Fixes: a11f4f0a4e18 ("xen: xensyms support") Signed-off-by: Jan Beulich Reviewed-by: Juergen Gross Message-ID: <15d5e7fa-ec5d-422f-9319-d28bed916349@suse.com> Signed-off-by: Juergen Gross Signed-off-by: Greg Kroah-Hartman --- drivers/xen/xenfs/xensyms.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/xen/xenfs/xensyms.c b/drivers/xen/xenfs/xensyms.c index b799bc759c15..088b7f02c358 100644 --- a/drivers/xen/xenfs/xensyms.c +++ b/drivers/xen/xenfs/xensyms.c @@ -48,7 +48,7 @@ static int xensyms_next_sym(struct xensyms *xs) return -ENOMEM; set_xen_guest_handle(symdata->name, xs->name); - symdata->symnum--; /* Rewind */ + symdata->symnum = symnum; /* Rewind */ ret = HYPERVISOR_platform_op(&xs->op); if (ret < 0) @@ -78,7 +78,7 @@ static void *xensyms_next(struct seq_file *m, void *p, loff_t *pos) { struct xensyms *xs = m->private; - xs->op.u.symdata.symnum = ++(*pos); + *pos = xs->op.u.symdata.symnum; if (xensyms_next_sym(xs)) return NULL; From 892d24d7e355d126d98b8c7569de3137a7078f0e Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 7 Jan 2025 12:06:01 -0800 Subject: [PATCH 128/606] arm64: cputype: Add MIDR_CORTEX_A76AE commit a9b5bd81b294d30a747edd125e9f6aef2def7c79 upstream. >From the TRM, MIDR_CORTEX_A76AE has a partnum of 0xDOE and an implementor of 0x41 (ARM). Add the values. Cc: stable@vger.kernel.org # dependency of the next fix in the series Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20250107120555.v4.4.I151f3b7ee323bcc3082179b8c60c3cd03308aa94@changeid Signed-off-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- arch/arm64/include/asm/cputype.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index c8058f91a5bd..2a4e686e633c 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h @@ -75,6 +75,7 @@ #define ARM_CPU_PART_CORTEX_A76 0xD0B #define ARM_CPU_PART_NEOVERSE_N1 0xD0C #define ARM_CPU_PART_CORTEX_A77 0xD0D +#define ARM_CPU_PART_CORTEX_A76AE 0xD0E #define ARM_CPU_PART_NEOVERSE_V1 0xD40 #define ARM_CPU_PART_CORTEX_A78 0xD41 #define ARM_CPU_PART_CORTEX_A78AE 0xD42 @@ -159,6 +160,7 @@ #define MIDR_CORTEX_A76 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76) #define MIDR_NEOVERSE_N1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N1) #define MIDR_CORTEX_A77 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A77) +#define MIDR_CORTEX_A76AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76AE) #define MIDR_NEOVERSE_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V1) #define MIDR_CORTEX_A78 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78) #define MIDR_CORTEX_A78AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78AE) From 1577657f5efc910fd2a100992e474b1b6c746dd5 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 7 Jan 2025 12:05:58 -0800 Subject: [PATCH 129/606] arm64: errata: Add QCOM_KRYO_4XX_GOLD to the spectre_bhb_k24_list commit ed1ce841245d8febe3badf51c57e81c3619d0a1d upstream. Qualcomm Kryo 400-series Gold cores have a derivative of an ARM Cortex A76 in them. Since A76 needs Spectre mitigation via looping then the Kyro 400-series Gold cores also need Spectre mitigation via looping. Qualcomm has confirmed that the proper "k" value for Kryo 400-series Gold cores is 24. Fixes: 558c303c9734 ("arm64: Mitigate spectre style branch history side channels") Cc: stable@vger.kernel.org Cc: Scott Bauer Signed-off-by: Douglas Anderson Acked-by: Trilok Soni Link: https://lore.kernel.org/r/20250107120555.v4.1.Ie4ef54abe02e7eb0eee50f830575719bf23bda48@changeid Signed-off-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- arch/arm64/kernel/proton-pack.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c index 57503dc4b22f..23848ba417d9 100644 --- a/arch/arm64/kernel/proton-pack.c +++ b/arch/arm64/kernel/proton-pack.c @@ -866,6 +866,7 @@ u8 spectre_bhb_loop_affected(int scope) MIDR_ALL_VERSIONS(MIDR_CORTEX_A76), MIDR_ALL_VERSIONS(MIDR_CORTEX_A77), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), + MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_GOLD), {}, }; static const struct midr_range spectre_bhb_k11_list[] = { From 3ca6b0c9171b07dd806c22ba9859e7751f754387 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 7 Jan 2025 12:05:59 -0800 Subject: [PATCH 130/606] arm64: errata: Assume that unknown CPUs _are_ vulnerable to Spectre BHB commit e403e8538359d8580cbee1976ff71813e947101e upstream. The code for detecting CPUs that are vulnerable to Spectre BHB was based on a hardcoded list of CPU IDs that were known to be affected. Unfortunately, the list mostly only contained the IDs of standard ARM cores. The IDs for many cores that are minor variants of the standard ARM cores (like many Qualcomm Kyro CPUs) weren't listed. This led the code to assume that those variants were not affected. Flip the code on its head and instead assume that a core is vulnerable if it doesn't have CSV2_3 but is unrecognized as being safe. This involves creating a "Spectre BHB safe" list. As of right now, the only CPU IDs added to the "Spectre BHB safe" list are ARM Cortex A35, A53, A55, A510, and A520. This list was created by looking for cores that weren't listed in ARM's list [1] as per review feedback on v2 of this patch [2]. Additionally Brahma A53 is added as per mailing list feedback [3]. NOTE: this patch will not actually _mitigate_ anyone, it will simply cause them to report themselves as vulnerable. If any cores in the system are reported as vulnerable but not mitigated then the whole system will be reported as vulnerable though the system will attempt to mitigate with the information it has about the known cores. [1] https://developer.arm.com/Arm%20Security%20Center/Spectre-BHB [2] https://lore.kernel.org/r/20241219175128.GA25477@willie-the-truck [3] https://lore.kernel.org/r/18dbd7d1-a46c-4112-a425-320c99f67a8d@broadcom.com Fixes: 558c303c9734 ("arm64: Mitigate spectre style branch history side channels") Cc: stable@vger.kernel.org Reviewed-by: Julius Werner Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20250107120555.v4.2.I2040fa004dafe196243f67ebcc647cbedbb516e6@changeid Signed-off-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- arch/arm64/include/asm/spectre.h | 1 - arch/arm64/kernel/proton-pack.c | 193 ++++++++++++++++--------------- 2 files changed, 97 insertions(+), 97 deletions(-) diff --git a/arch/arm64/include/asm/spectre.h b/arch/arm64/include/asm/spectre.h index 9cc501450486..0c2b47673922 100644 --- a/arch/arm64/include/asm/spectre.h +++ b/arch/arm64/include/asm/spectre.h @@ -97,7 +97,6 @@ enum mitigation_state arm64_get_meltdown_state(void); enum mitigation_state arm64_get_spectre_bhb_state(void); bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry, int scope); -u8 spectre_bhb_loop_affected(int scope); void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *__unused); bool try_emulate_el1_ssbs(struct pt_regs *regs, u32 instr); diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c index 23848ba417d9..5b27d6ef08ca 100644 --- a/arch/arm64/kernel/proton-pack.c +++ b/arch/arm64/kernel/proton-pack.c @@ -845,53 +845,70 @@ static unsigned long system_bhb_mitigations; * This must be called with SCOPE_LOCAL_CPU for each type of CPU, before any * SCOPE_SYSTEM call will give the right answer. */ -u8 spectre_bhb_loop_affected(int scope) +static bool is_spectre_bhb_safe(int scope) +{ + static const struct midr_range spectre_bhb_safe_list[] = { + MIDR_ALL_VERSIONS(MIDR_CORTEX_A35), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A53), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A55), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A510), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A520), + MIDR_ALL_VERSIONS(MIDR_BRAHMA_B53), + {}, + }; + static bool all_safe = true; + + if (scope != SCOPE_LOCAL_CPU) + return all_safe; + + if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_safe_list)) + return true; + + all_safe = false; + + return false; +} + +static u8 spectre_bhb_loop_affected(void) { u8 k = 0; - static u8 max_bhb_k; - if (scope == SCOPE_LOCAL_CPU) { - static const struct midr_range spectre_bhb_k32_list[] = { - MIDR_ALL_VERSIONS(MIDR_CORTEX_A78), - MIDR_ALL_VERSIONS(MIDR_CORTEX_A78AE), - MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C), - MIDR_ALL_VERSIONS(MIDR_CORTEX_X1), - MIDR_ALL_VERSIONS(MIDR_CORTEX_A710), - MIDR_ALL_VERSIONS(MIDR_CORTEX_X2), - MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2), - MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1), - {}, - }; - static const struct midr_range spectre_bhb_k24_list[] = { - MIDR_ALL_VERSIONS(MIDR_CORTEX_A76), - MIDR_ALL_VERSIONS(MIDR_CORTEX_A77), - MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), - MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_GOLD), - {}, - }; - static const struct midr_range spectre_bhb_k11_list[] = { - MIDR_ALL_VERSIONS(MIDR_AMPERE1), - {}, - }; - static const struct midr_range spectre_bhb_k8_list[] = { - MIDR_ALL_VERSIONS(MIDR_CORTEX_A72), - MIDR_ALL_VERSIONS(MIDR_CORTEX_A57), - {}, - }; + static const struct midr_range spectre_bhb_k32_list[] = { + MIDR_ALL_VERSIONS(MIDR_CORTEX_A78), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A78AE), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C), + MIDR_ALL_VERSIONS(MIDR_CORTEX_X1), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A710), + MIDR_ALL_VERSIONS(MIDR_CORTEX_X2), + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2), + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1), + {}, + }; + static const struct midr_range spectre_bhb_k24_list[] = { + MIDR_ALL_VERSIONS(MIDR_CORTEX_A76), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A77), + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), + MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_GOLD), + {}, + }; + static const struct midr_range spectre_bhb_k11_list[] = { + MIDR_ALL_VERSIONS(MIDR_AMPERE1), + {}, + }; + static const struct midr_range spectre_bhb_k8_list[] = { + MIDR_ALL_VERSIONS(MIDR_CORTEX_A72), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A57), + {}, + }; - if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k32_list)) - k = 32; - else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k24_list)) - k = 24; - else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k11_list)) - k = 11; - else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k8_list)) - k = 8; - - max_bhb_k = max(max_bhb_k, k); - } else { - k = max_bhb_k; - } + if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k32_list)) + k = 32; + else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k24_list)) + k = 24; + else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k11_list)) + k = 11; + else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k8_list)) + k = 8; return k; } @@ -917,29 +934,13 @@ static enum mitigation_state spectre_bhb_get_cpu_fw_mitigation_state(void) } } -static bool is_spectre_bhb_fw_affected(int scope) +static bool has_spectre_bhb_fw_mitigation(void) { - static bool system_affected; enum mitigation_state fw_state; bool has_smccc = arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_NONE; - static const struct midr_range spectre_bhb_firmware_mitigated_list[] = { - MIDR_ALL_VERSIONS(MIDR_CORTEX_A73), - MIDR_ALL_VERSIONS(MIDR_CORTEX_A75), - {}, - }; - bool cpu_in_list = is_midr_in_range_list(read_cpuid_id(), - spectre_bhb_firmware_mitigated_list); - - if (scope != SCOPE_LOCAL_CPU) - return system_affected; fw_state = spectre_bhb_get_cpu_fw_mitigation_state(); - if (cpu_in_list || (has_smccc && fw_state == SPECTRE_MITIGATED)) { - system_affected = true; - return true; - } - - return false; + return has_smccc && fw_state == SPECTRE_MITIGATED; } static bool supports_ecbhb(int scope) @@ -955,6 +956,8 @@ static bool supports_ecbhb(int scope) ID_AA64MMFR1_EL1_ECBHB_SHIFT); } +static u8 max_bhb_k; + bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry, int scope) { @@ -963,16 +966,18 @@ bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry, if (supports_csv2p3(scope)) return false; - if (supports_clearbhb(scope)) - return true; + if (is_spectre_bhb_safe(scope)) + return false; - if (spectre_bhb_loop_affected(scope)) - return true; + /* + * At this point the core isn't known to be "safe" so we're going to + * assume it's vulnerable. We still need to update `max_bhb_k` though, + * but only if we aren't mitigating with clearbhb though. + */ + if (scope == SCOPE_LOCAL_CPU && !supports_clearbhb(SCOPE_LOCAL_CPU)) + max_bhb_k = max(max_bhb_k, spectre_bhb_loop_affected()); - if (is_spectre_bhb_fw_affected(scope)) - return true; - - return false; + return true; } static void this_cpu_set_vectors(enum arm64_bp_harden_el1_vectors slot) @@ -1003,7 +1008,7 @@ early_param("nospectre_bhb", parse_spectre_bhb_param); void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *entry) { bp_hardening_cb_t cpu_cb; - enum mitigation_state fw_state, state = SPECTRE_VULNERABLE; + enum mitigation_state state = SPECTRE_VULNERABLE; struct bp_hardening_data *data = this_cpu_ptr(&bp_hardening_data); if (!is_spectre_bhb_affected(entry, SCOPE_LOCAL_CPU)) @@ -1029,7 +1034,7 @@ void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *entry) this_cpu_set_vectors(EL1_VECTOR_BHB_CLEAR_INSN); state = SPECTRE_MITIGATED; set_bit(BHB_INSN, &system_bhb_mitigations); - } else if (spectre_bhb_loop_affected(SCOPE_LOCAL_CPU)) { + } else if (spectre_bhb_loop_affected()) { /* * Ensure KVM uses the indirect vector which will have the * branchy-loop added. A57/A72-r0 will already have selected @@ -1042,32 +1047,29 @@ void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *entry) this_cpu_set_vectors(EL1_VECTOR_BHB_LOOP); state = SPECTRE_MITIGATED; set_bit(BHB_LOOP, &system_bhb_mitigations); - } else if (is_spectre_bhb_fw_affected(SCOPE_LOCAL_CPU)) { - fw_state = spectre_bhb_get_cpu_fw_mitigation_state(); - if (fw_state == SPECTRE_MITIGATED) { - /* - * Ensure KVM uses one of the spectre bp_hardening - * vectors. The indirect vector doesn't include the EL3 - * call, so needs upgrading to - * HYP_VECTOR_SPECTRE_INDIRECT. - */ - if (!data->slot || data->slot == HYP_VECTOR_INDIRECT) - data->slot += 1; + } else if (has_spectre_bhb_fw_mitigation()) { + /* + * Ensure KVM uses one of the spectre bp_hardening + * vectors. The indirect vector doesn't include the EL3 + * call, so needs upgrading to + * HYP_VECTOR_SPECTRE_INDIRECT. + */ + if (!data->slot || data->slot == HYP_VECTOR_INDIRECT) + data->slot += 1; - this_cpu_set_vectors(EL1_VECTOR_BHB_FW); + this_cpu_set_vectors(EL1_VECTOR_BHB_FW); - /* - * The WA3 call in the vectors supersedes the WA1 call - * made during context-switch. Uninstall any firmware - * bp_hardening callback. - */ - cpu_cb = spectre_v2_get_sw_mitigation_cb(); - if (__this_cpu_read(bp_hardening_data.fn) != cpu_cb) - __this_cpu_write(bp_hardening_data.fn, NULL); + /* + * The WA3 call in the vectors supersedes the WA1 call + * made during context-switch. Uninstall any firmware + * bp_hardening callback. + */ + cpu_cb = spectre_v2_get_sw_mitigation_cb(); + if (__this_cpu_read(bp_hardening_data.fn) != cpu_cb) + __this_cpu_write(bp_hardening_data.fn, NULL); - state = SPECTRE_MITIGATED; - set_bit(BHB_FW, &system_bhb_mitigations); - } + state = SPECTRE_MITIGATED; + set_bit(BHB_FW, &system_bhb_mitigations); } update_mitigation_state(&spectre_bhb_state, state); @@ -1101,7 +1103,6 @@ void noinstr spectre_bhb_patch_loop_iter(struct alt_instr *alt, { u8 rd; u32 insn; - u16 loop_count = spectre_bhb_loop_affected(SCOPE_SYSTEM); BUG_ON(nr_inst != 1); /* MOV -> MOV */ @@ -1110,7 +1111,7 @@ void noinstr spectre_bhb_patch_loop_iter(struct alt_instr *alt, insn = le32_to_cpu(*origptr); rd = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RD, insn); - insn = aarch64_insn_gen_movewide(rd, loop_count, 0, + insn = aarch64_insn_gen_movewide(rd, max_bhb_k, 0, AARCH64_INSN_VARIANT_64BIT, AARCH64_INSN_MOVEWIDE_ZERO); *updptr++ = cpu_to_le32(insn); From db8a657980e70224041796bd44232a868bd4cd87 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 7 Jan 2025 12:06:00 -0800 Subject: [PATCH 131/606] arm64: errata: Add KRYO 2XX/3XX/4XX silver cores to Spectre BHB safe list commit 0c9fc6e652cd5aed48c5f700c32b7642bea7f453 upstream. Qualcomm has confirmed that, much like Cortex A53 and A55, KRYO 2XX/3XX/4XX silver cores are unaffected by Spectre BHB. Add them to the safe list. Fixes: 558c303c9734 ("arm64: Mitigate spectre style branch history side channels") Cc: stable@vger.kernel.org Cc: Scott Bauer Signed-off-by: Douglas Anderson Acked-by: Trilok Soni Link: https://lore.kernel.org/r/20250107120555.v4.3.Iab8dbfb5c9b1e143e7a29f410bce5f9525a0ba32@changeid Signed-off-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- arch/arm64/kernel/proton-pack.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c index 5b27d6ef08ca..36a1f9a16a73 100644 --- a/arch/arm64/kernel/proton-pack.c +++ b/arch/arm64/kernel/proton-pack.c @@ -854,6 +854,9 @@ static bool is_spectre_bhb_safe(int scope) MIDR_ALL_VERSIONS(MIDR_CORTEX_A510), MIDR_ALL_VERSIONS(MIDR_CORTEX_A520), MIDR_ALL_VERSIONS(MIDR_BRAHMA_B53), + MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_2XX_SILVER), + MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_3XX_SILVER), + MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_SILVER), {}, }; static bool all_safe = true; From 5085e02362b9948f82fceca979b8f8e12acb1cc5 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 14 Mar 2025 13:34:09 +0000 Subject: [PATCH 132/606] KVM: arm64: Tear down vGIC on failed vCPU creation commit 250f25367b58d8c65a1b060a2dda037eea09a672 upstream. If kvm_arch_vcpu_create() fails to share the vCPU page with the hypervisor, we propagate the error back to the ioctl but leave the vGIC vCPU data initialised. Note only does this leak the corresponding memory when the vCPU is destroyed but it can also lead to use-after-free if the redistributor device handling tries to walk into the vCPU. Add the missing cleanup to kvm_arch_vcpu_create(), ensuring that the vGIC vCPU structures are destroyed on error. Cc: Cc: Marc Zyngier Cc: Oliver Upton Cc: Quentin Perret Signed-off-by: Will Deacon Reviewed-by: Marc Zyngier Link: https://lore.kernel.org/r/20250314133409.9123-1-will@kernel.org Signed-off-by: Oliver Upton Signed-off-by: Greg Kroah-Hartman --- arch/arm64/kvm/arm.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 9818cde948ca..fe4314af8eec 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -391,7 +391,11 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) if (err) return err; - return kvm_share_hyp(vcpu, vcpu + 1); + err = kvm_share_hyp(vcpu, vcpu + 1); + if (err) + kvm_vgic_vcpu_destroy(vcpu); + + return err; } void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) From b8e772e2d8b361307366b6a71915182219689c90 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Wed, 5 Mar 2025 21:09:32 +0100 Subject: [PATCH 133/606] spi: cadence-qspi: Fix probe on AM62A LP SK commit b8665a1b49f5498edb7b21d730030c06b7348a3c upstream. In 2020, there's been an unnoticed change which rightfully attempted to report probe deferrals upon DMA absence by checking the return value of dma_request_chan_by_mask(). By doing so, it also reported errors which were simply ignored otherwise, likely on purpose. This change actually turned a void return into an error code. Hence, not only the -EPROBE_DEFER error codes but all error codes got reported to the callers, now failing to probe in the absence of Rx DMA channel, despite the fact that DMA seems to not be supported natively by many implementations. Looking at the history, this change probably led to: ad2775dc3fc5 ("spi: cadence-quadspi: Disable the DAC for Intel LGM SoC") f724c296f2f2 ("spi: cadence-quadspi: fix Direct Access Mode disable for SoCFPGA") In my case, the AM62A LP SK core octo-SPI node from TI does not advertise any DMA channel, hinting that there is likely no support for it, but yet when the support for the am654 compatible was added, DMA seemed to be used, so just discarding its use with the CQSPI_DISABLE_DAC_MODE quirk for this compatible does not seem the correct approach. Let's get change the return condition back to: - return a probe deferral error if we get one - ignore the return value otherwise The "error" log level was however likely too high for something that is expected to fail, so let's lower it arbitrarily to the info level. Fixes: 935da5e5100f ("mtd: spi-nor: cadence-quadspi: Handle probe deferral while requesting DMA channel") Cc: stable@vger.kernel.org Signed-off-by: Miquel Raynal Link: https://patch.msgid.link/20250305200933.2512925-2-miquel.raynal@bootlin.com Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/spi/spi-cadence-quadspi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index 08811577d8f8..bf9b816637d0 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -1576,6 +1576,12 @@ static int cqspi_request_mmap_dma(struct cqspi_st *cqspi) int ret = PTR_ERR(cqspi->rx_chan); cqspi->rx_chan = NULL; + if (ret == -ENODEV) { + /* DMA support is not mandatory */ + dev_info(&cqspi->pdev->dev, "No Rx DMA available\n"); + return 0; + } + return dev_err_probe(&cqspi->pdev->dev, ret, "No Rx DMA available\n"); } init_completion(&cqspi->rx_dma_complete); From 9bd51723ab51580e077c91d494c37e80703b8524 Mon Sep 17 00:00:00 2001 From: Kamal Dasu Date: Thu, 27 Feb 2025 12:46:08 -0500 Subject: [PATCH 134/606] mtd: rawnand: brcmnand: fix PM resume warning commit ddc210cf8b8a8be68051ad958bf3e2cef6b681c2 upstream. Fixed warning on PM resume as shown below caused due to uninitialized struct nand_operation that checks chip select field : WARN_ON(op->cs >= nanddev_ntargets(&chip->base) [ 14.588522] ------------[ cut here ]------------ [ 14.588529] WARNING: CPU: 0 PID: 1392 at drivers/mtd/nand/raw/internals.h:139 nand_reset_op+0x1e0/0x1f8 [ 14.588553] Modules linked in: bdc udc_core [ 14.588579] CPU: 0 UID: 0 PID: 1392 Comm: rtcwake Tainted: G W 6.14.0-rc4-g5394eea10651 #16 [ 14.588590] Tainted: [W]=WARN [ 14.588593] Hardware name: Broadcom STB (Flattened Device Tree) [ 14.588598] Call trace: [ 14.588604] dump_backtrace from show_stack+0x18/0x1c [ 14.588622] r7:00000009 r6:0000008b r5:60000153 r4:c0fa558c [ 14.588625] show_stack from dump_stack_lvl+0x70/0x7c [ 14.588639] dump_stack_lvl from dump_stack+0x18/0x1c [ 14.588653] r5:c08d40b0 r4:c1003cb0 [ 14.588656] dump_stack from __warn+0x84/0xe4 [ 14.588668] __warn from warn_slowpath_fmt+0x18c/0x194 [ 14.588678] r7:c08d40b0 r6:c1003cb0 r5:00000000 r4:00000000 [ 14.588681] warn_slowpath_fmt from nand_reset_op+0x1e0/0x1f8 [ 14.588695] r8:70c40dff r7:89705f41 r6:36b4a597 r5:c26c9444 r4:c26b0048 [ 14.588697] nand_reset_op from brcmnand_resume+0x13c/0x150 [ 14.588714] r9:00000000 r8:00000000 r7:c24f8010 r6:c228a3f8 r5:c26c94bc r4:c26b0040 [ 14.588717] brcmnand_resume from platform_pm_resume+0x34/0x54 [ 14.588735] r5:00000010 r4:c0840a50 [ 14.588738] platform_pm_resume from dpm_run_callback+0x5c/0x14c [ 14.588757] dpm_run_callback from device_resume+0xc0/0x324 [ 14.588776] r9:c24f8054 r8:c24f80a0 r7:00000000 r6:00000000 r5:00000010 r4:c24f8010 [ 14.588779] device_resume from dpm_resume+0x130/0x160 [ 14.588799] r9:c22539e4 r8:00000010 r7:c22bebb0 r6:c24f8010 r5:c22539dc r4:c22539b0 [ 14.588802] dpm_resume from dpm_resume_end+0x14/0x20 [ 14.588822] r10:c2204e40 r9:00000000 r8:c228a3fc r7:00000000 r6:00000003 r5:c228a414 [ 14.588826] r4:00000010 [ 14.588828] dpm_resume_end from suspend_devices_and_enter+0x274/0x6f8 [ 14.588848] r5:c228a414 r4:00000000 [ 14.588851] suspend_devices_and_enter from pm_suspend+0x228/0x2bc [ 14.588868] r10:c3502910 r9:c3501f40 r8:00000004 r7:c228a438 r6:c0f95e18 r5:00000000 [ 14.588871] r4:00000003 [ 14.588874] pm_suspend from state_store+0x74/0xd0 [ 14.588889] r7:c228a438 r6:c0f934c8 r5:00000003 r4:00000003 [ 14.588892] state_store from kobj_attr_store+0x1c/0x28 [ 14.588913] r9:00000000 r8:00000000 r7:f09f9f08 r6:00000004 r5:c3502900 r4:c0283250 [ 14.588916] kobj_attr_store from sysfs_kf_write+0x40/0x4c [ 14.588936] r5:c3502900 r4:c0d92a48 [ 14.588939] sysfs_kf_write from kernfs_fop_write_iter+0x104/0x1f0 [ 14.588956] r5:c3502900 r4:c3501f40 [ 14.588960] kernfs_fop_write_iter from vfs_write+0x250/0x420 [ 14.588980] r10:c0e14b48 r9:00000000 r8:c25f5780 r7:00443398 r6:f09f9f68 r5:c34f7f00 [ 14.588983] r4:c042a88c [ 14.588987] vfs_write from ksys_write+0x74/0xe4 [ 14.589005] r10:00000004 r9:c25f5780 r8:c02002fA0 r7:00000000 r6:00000000 r5:c34f7f00 [ 14.589008] r4:c34f7f00 [ 14.589011] ksys_write from sys_write+0x10/0x14 [ 14.589029] r7:00000004 r6:004421c0 r5:00443398 r4:00000004 [ 14.589032] sys_write from ret_fast_syscall+0x0/0x5c [ 14.589044] Exception stack(0xf09f9fa8 to 0xf09f9ff0) [ 14.589050] 9fa0: 00000004 00443398 00000004 00443398 00000004 00000001 [ 14.589056] 9fc0: 00000004 00443398 004421c0 00000004 b6ecbd58 00000008 bebfbc38 0043eb78 [ 14.589062] 9fe0: 00440eb0 bebfbaf8 b6de18a0 b6e579e8 [ 14.589065] ---[ end trace 0000000000000000 ]--- The fix uses the higher level nand_reset(chip, chipnr); where chipnr = 0, when doing PM resume operation in compliance with the controller support for single die nand chip. Switching from nand_reset_op() to nand_reset() implies more than just setting the cs field op->cs, it also reconfigures the data interface (ie. the timings). Tested and confirmed the NAND chip is in sync timing wise with host after the fix. Fixes: 97d90da8a886 ("mtd: nand: provide several helpers to do common NAND operations") Cc: stable@vger.kernel.org Signed-off-by: Kamal Dasu Reviewed-by: Florian Fainelli Signed-off-by: Miquel Raynal Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 085a16148a68..03d7e26d4953 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -2974,7 +2974,7 @@ static int brcmnand_resume(struct device *dev) brcmnand_save_restore_cs_config(host, 1); /* Reset the chip, required by some chips after power-up */ - nand_reset_op(chip); + nand_reset(chip, 0); } return 0; From 3fcff11317b2714c106e2d0acca6bf91b6b2a45f Mon Sep 17 00:00:00 2001 From: Jonathan McDowell Date: Wed, 12 Mar 2025 07:31:57 +0200 Subject: [PATCH 135/606] tpm, tpm_tis: Fix timeout handling when waiting for TPM status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 7146dffa875cd00e7a7f918e1fce79c7593ac1fa upstream. The change to only use interrupts to handle supported status changes introduced an issue when it is necessary to poll for the status. Rather than checking for the status after sleeping the code now sleeps after the check. This means a correct, but slower, status change on the part of the TPM can be missed, resulting in a spurious timeout error, especially on a more loaded system. Switch back to sleeping *then* checking. An up front check of the status has been done at the start of the function, so this does not cause an additional delay when the status is already what we're looking for. Cc: stable@vger.kernel.org # v6.4+ Fixes: e87fcf0dc2b4 ("tpm, tpm_tis: Only handle supported interrupts") Signed-off-by: Jonathan McDowell Reviewed-by: Michal Suchánek Reviewed-by: Lino Sanfilippo Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm_tis_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index 7ade8bd12ab2..c71e61ccb95a 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -114,11 +114,10 @@ again: return 0; /* process status changes without irq support */ do { + usleep_range(priv->timeout_min, priv->timeout_max); status = chip->ops->status(chip); if ((status & mask) == mask) return 0; - usleep_range(priv->timeout_min, - priv->timeout_max); } while (time_before(jiffies, stop)); return -ETIME; } From 3eaf580cbaa35157aeff90cebd58edffa68ad800 Mon Sep 17 00:00:00 2001 From: Murad Masimov Date: Mon, 13 Jan 2025 13:51:31 +0300 Subject: [PATCH 136/606] media: streamzap: prevent processing IR data on URB failure commit 549f6d348167fb2f7800ed7c8d4bce9630c74498 upstream. If streamzap_callback() receives an urb with any non-critical error status, i.e. any error code other than -ECONNRESET, -ENOENT or -ESHUTDOWN, it will try to process IR data, ignoring a possible transfer failure. Make streamzap_callback() process IR data only when urb->status is 0. Move processing logic to a separate function to make code cleaner and more similar to the URB completion handlers in other RC drivers. Found by Linux Verification Center (linuxtesting.org) with Syzkaller. Fixes: 19770693c354 ("V4L/DVB: staging/lirc: add lirc_streamzap driver") Cc: stable@vger.kernel.org Signed-off-by: Murad Masimov Signed-off-by: Sean Young Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/rc/streamzap.c | 68 ++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c index 2ce62fe5d60f..d3b48a0dd1f4 100644 --- a/drivers/media/rc/streamzap.c +++ b/drivers/media/rc/streamzap.c @@ -138,39 +138,10 @@ static void sz_push_half_space(struct streamzap_ir *sz, sz_push_full_space(sz, value & SZ_SPACE_MASK); } -/* - * streamzap_callback - usb IRQ handler callback - * - * This procedure is invoked on reception of data from - * the usb remote. - */ -static void streamzap_callback(struct urb *urb) +static void sz_process_ir_data(struct streamzap_ir *sz, int len) { - struct streamzap_ir *sz; unsigned int i; - int len; - if (!urb) - return; - - sz = urb->context; - len = urb->actual_length; - - switch (urb->status) { - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* - * this urb is terminated, clean up. - * sz might already be invalid at this point - */ - dev_err(sz->dev, "urb terminated, status: %d\n", urb->status); - return; - default: - break; - } - - dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len); for (i = 0; i < len; i++) { dev_dbg(sz->dev, "sz->buf_in[%d]: %x\n", i, (unsigned char)sz->buf_in[i]); @@ -219,6 +190,43 @@ static void streamzap_callback(struct urb *urb) } ir_raw_event_handle(sz->rdev); +} + +/* + * streamzap_callback - usb IRQ handler callback + * + * This procedure is invoked on reception of data from + * the usb remote. + */ +static void streamzap_callback(struct urb *urb) +{ + struct streamzap_ir *sz; + int len; + + if (!urb) + return; + + sz = urb->context; + len = urb->actual_length; + + switch (urb->status) { + case 0: + dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len); + sz_process_ir_data(sz, len); + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* + * this urb is terminated, clean up. + * sz might already be invalid at this point + */ + dev_err(sz->dev, "urb terminated, status: %d\n", urb->status); + return; + default: + break; + } + usb_submit_urb(urb, GFP_ATOMIC); } From bedb5a7b97830dd8437e482f6433b62f2f380c0c Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Tue, 10 Dec 2024 16:02:53 -0500 Subject: [PATCH 137/606] media: visl: Fix ERANGE error when setting enum controls commit d98e9213a768a3cc3a99f5e1abe09ad3baff2104 upstream. The visl driver supports both frame and slice mode, with and without a start-code. But, the range and default for these enum controls was not set, which currently limits the decoder to enums with a value of 0. Fix this by setting the decoder mode and start code controls for both the H.264 and HEVC codecs. Fixes: 0c078e310b6d ("media: visl: add virtual stateless decoder driver") Cc: stable@vger.kernel.org Signed-off-by: Nicolas Dufresne Signed-off-by: Sebastian Fricke Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/test-drivers/visl/visl-core.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/media/test-drivers/visl/visl-core.c b/drivers/media/test-drivers/visl/visl-core.c index 9970dc739ca5..a28bb8ee21e9 100644 --- a/drivers/media/test-drivers/visl/visl-core.c +++ b/drivers/media/test-drivers/visl/visl-core.c @@ -156,9 +156,15 @@ static const struct visl_ctrl_desc visl_h264_ctrl_descs[] = { }, { .cfg.id = V4L2_CID_STATELESS_H264_DECODE_MODE, + .cfg.min = V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED, + .cfg.max = V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED, + .cfg.def = V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED, }, { .cfg.id = V4L2_CID_STATELESS_H264_START_CODE, + .cfg.min = V4L2_STATELESS_H264_START_CODE_NONE, + .cfg.max = V4L2_STATELESS_H264_START_CODE_ANNEX_B, + .cfg.def = V4L2_STATELESS_H264_START_CODE_NONE, }, { .cfg.id = V4L2_CID_STATELESS_H264_SLICE_PARAMS, @@ -193,9 +199,15 @@ static const struct visl_ctrl_desc visl_hevc_ctrl_descs[] = { }, { .cfg.id = V4L2_CID_STATELESS_HEVC_DECODE_MODE, + .cfg.min = V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED, + .cfg.max = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED, + .cfg.def = V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED, }, { .cfg.id = V4L2_CID_STATELESS_HEVC_START_CODE, + .cfg.min = V4L2_STATELESS_HEVC_START_CODE_NONE, + .cfg.max = V4L2_STATELESS_HEVC_START_CODE_ANNEX_B, + .cfg.def = V4L2_STATELESS_HEVC_START_CODE_NONE, }, { .cfg.id = V4L2_CID_STATELESS_HEVC_ENTRY_POINT_OFFSETS, From 571a1873da479bd3ac5625d96da7029eb2077fde Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Fri, 22 Nov 2024 20:46:03 +0000 Subject: [PATCH 138/606] media: platform: stm32: Add check for clk_enable() commit f883f34b6a46b1a09d44d7f94c3cd72fe0e8f93b upstream. Add check for the return value of clk_enable() to gurantee the success. Fixes: 002e8f0d5927 ("media: stm32-dma2d: STM32 DMA2D driver") Cc: stable@vger.kernel.org Signed-off-by: Jiasheng Jiang Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/platform/st/stm32/dma2d/dma2d.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/st/stm32/dma2d/dma2d.c b/drivers/media/platform/st/stm32/dma2d/dma2d.c index 92f1edee58f8..3c64e9126025 100644 --- a/drivers/media/platform/st/stm32/dma2d/dma2d.c +++ b/drivers/media/platform/st/stm32/dma2d/dma2d.c @@ -492,7 +492,8 @@ static void device_run(void *prv) dst->sequence = frm_cap->sequence++; v4l2_m2m_buf_copy_metadata(src, dst, true); - clk_enable(dev->gate); + if (clk_enable(dev->gate)) + goto end; dma2d_config_fg(dev, frm_out, vb2_dma_contig_plane_dma_addr(&src->vb2_buf, 0)); From c3d68e38aa04b23ebdcba3fadfcf5f17af51a66c Mon Sep 17 00:00:00 2001 From: Karina Yankevich Date: Wed, 21 Aug 2024 14:31:34 +0300 Subject: [PATCH 139/606] media: v4l2-dv-timings: prevent possible overflow in v4l2_detect_gtf() commit 3edd1fc48d2c045e8259561797c89fe78f01717e upstream. In v4l2_detect_gtf(), it seems safer to cast the 32-bit image_width variable to the 64-bit type u64 before multiplying to avoid a possible overflow. The resulting object code even seems to look better, at least on x86_64. Found by Linux Verification Center (linuxtesting.org) with Svace. [Sergey: rewrote the patch subject/descripition] Fixes: c9bc9f50753d ("[media] v4l2-dv-timings: fix overflow in gtf timings calculation") Cc: stable@vger.kernel.org Signed-off-by: Karina Yankevich Signed-off-by: Sergey Shtylyov Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/v4l2-core/v4l2-dv-timings.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c index 2cf5dcee0ce8..4d05873892c1 100644 --- a/drivers/media/v4l2-core/v4l2-dv-timings.c +++ b/drivers/media/v4l2-core/v4l2-dv-timings.c @@ -764,7 +764,7 @@ bool v4l2_detect_gtf(unsigned int frame_height, u64 num; u32 den; - num = ((image_width * GTF_D_C_PRIME * (u64)hfreq) - + num = (((u64)image_width * GTF_D_C_PRIME * hfreq) - ((u64)image_width * GTF_D_M_PRIME * 1000)); den = (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000) * (2 * GTF_CELL_GRAN); @@ -774,7 +774,7 @@ bool v4l2_detect_gtf(unsigned int frame_height, u64 num; u32 den; - num = ((image_width * GTF_S_C_PRIME * (u64)hfreq) - + num = (((u64)image_width * GTF_S_C_PRIME * hfreq) - ((u64)image_width * GTF_S_M_PRIME * 1000)); den = (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000) * (2 * GTF_CELL_GRAN); From 2f282e88c2aa6b5f21cb0c9450c0247c0ab793c8 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 10 Jan 2025 14:50:27 +0200 Subject: [PATCH 140/606] media: i2c: ccs: Set the device's runtime PM status correctly in remove commit e04604583095faf455b3490b004254a225fd60d4 upstream. Set the device's runtime PM status to suspended in device removal only if it wasn't suspended already. Fixes: 9447082ae666 ("[media] smiapp: Implement power-on and power-off sequences without runtime PM") Cc: stable@vger.kernel.org # for >= v5.15 Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/i2c/ccs/ccs-core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index 92ee86ca80a6..82f727dd8c75 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -3683,9 +3683,10 @@ static void ccs_remove(struct i2c_client *client) v4l2_async_unregister_subdev(subdev); pm_runtime_disable(&client->dev); - if (!pm_runtime_status_suspended(&client->dev)) + if (!pm_runtime_status_suspended(&client->dev)) { ccs_power_off(&client->dev); - pm_runtime_set_suspended(&client->dev); + pm_runtime_set_suspended(&client->dev); + } for (i = 0; i < sensor->ssds_used; i++) { v4l2_device_unregister_subdev(&sensor->ssds[i].sd); From 86c20c4ebc919a06976b188281488a8e559ea487 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 10 Jan 2025 15:54:22 +0200 Subject: [PATCH 141/606] media: i2c: ccs: Set the device's runtime PM status correctly in probe commit 80704d14f1bd3628f578510e0a88b66824990ef6 upstream. Set the device's runtime PM status to suspended in probe error paths where it was previously set to active. Fixes: 9447082ae666 ("[media] smiapp: Implement power-on and power-off sequences without runtime PM") Cc: stable@vger.kernel.org # for >= v5.15 Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/i2c/ccs/ccs-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index 82f727dd8c75..364026124257 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -3651,6 +3651,7 @@ static int ccs_probe(struct i2c_client *client) out_disable_runtime_pm: pm_runtime_put_noidle(&client->dev); pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); out_media_entity_cleanup: media_entity_cleanup(&sensor->src->sd.entity); From f249c05416ea0bef24c9dbed0e653d2fad87b127 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 17 Jan 2025 15:38:13 +0200 Subject: [PATCH 142/606] media: i2c: ov7251: Set enable GPIO low in probe commit a1963698d59cec83df640ded343af08b76c8e9c5 upstream. Set the enable GPIO low when acquiring it. Fixes: d30bb512da3d ("media: Add a driver for the ov7251 camera sensor") Cc: stable@vger.kernel.org Signed-off-by: Sakari Ailus Reviewed-by: Dave Stevenson Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/i2c/ov7251.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov7251.c b/drivers/media/i2c/ov7251.c index 675fb37a6fea..5362680fc460 100644 --- a/drivers/media/i2c/ov7251.c +++ b/drivers/media/i2c/ov7251.c @@ -1675,7 +1675,7 @@ static int ov7251_probe(struct i2c_client *client) return PTR_ERR(ov7251->analog_regulator); } - ov7251->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH); + ov7251->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); if (IS_ERR(ov7251->enable_gpio)) { dev_err(dev, "cannot get enable gpio\n"); return PTR_ERR(ov7251->enable_gpio); From 28bdf7b9140ae141b0a9d31c3ce9dd6f0944a66a Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 17 Jan 2025 16:04:02 +0200 Subject: [PATCH 143/606] media: i2c: ov7251: Introduce 1 ms delay between regulators and en GPIO commit 3d391292cdd53984ec1b9a1f6182a62a62751e03 upstream. Lift the xshutdown (enable) GPIO 1 ms after enabling the regulators, as required by the sensor's power-up sequence. Fixes: d30bb512da3d ("media: Add a driver for the ov7251 camera sensor") Cc: stable@vger.kernel.org Signed-off-by: Sakari Ailus Reviewed-by: Dave Stevenson Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/i2c/ov7251.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/i2c/ov7251.c b/drivers/media/i2c/ov7251.c index 5362680fc460..2fc52b66154c 100644 --- a/drivers/media/i2c/ov7251.c +++ b/drivers/media/i2c/ov7251.c @@ -922,6 +922,8 @@ static int ov7251_set_power_on(struct device *dev) return ret; } + usleep_range(1000, 1100); + gpiod_set_value_cansleep(ov7251->enable_gpio, 1); /* wait at least 65536 external clock cycles */ From d4d88ece4ba91df5b02f1d3f599650f9e9fc0f45 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 20 Feb 2025 22:50:08 +0530 Subject: [PATCH 144/606] media: venus: hfi_parser: add check to avoid out of bound access commit 172bf5a9ef70a399bb227809db78442dc01d9e48 upstream. There is a possibility that init_codecs is invoked multiple times during manipulated payload from video firmware. In such case, if codecs_count can get incremented to value more than MAX_CODEC_NUM, there can be OOB access. Reset the count so that it always starts from beginning. Cc: stable@vger.kernel.org Fixes: 1a73374a04e5 ("media: venus: hfi_parser: add common capability parser") Reviewed-by: Bryan O'Donoghue Signed-off-by: Vikash Garodia Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/platform/qcom/venus/hfi_parser.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/qcom/venus/hfi_parser.c b/drivers/media/platform/qcom/venus/hfi_parser.c index c43839539d4d..d11647e12fd3 100644 --- a/drivers/media/platform/qcom/venus/hfi_parser.c +++ b/drivers/media/platform/qcom/venus/hfi_parser.c @@ -19,6 +19,8 @@ static void init_codecs(struct venus_core *core) struct hfi_plat_caps *caps = core->caps, *cap; unsigned long bit; + core->codecs_count = 0; + if (hweight_long(core->dec_codecs) + hweight_long(core->enc_codecs) > MAX_CODEC_NUM) return; From 05b07e52a0d08239147ba3460045855f4fb398de Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 20 Feb 2025 22:50:09 +0530 Subject: [PATCH 145/606] media: venus: hfi_parser: refactor hfi packet parsing logic commit 9edaaa8e3e15aab1ca413ab50556de1975bcb329 upstream. words_count denotes the number of words in total payload, while data points to payload of various property within it. When words_count reaches last word, data can access memory beyond the total payload. This can lead to OOB access. With this patch, the utility api for handling individual properties now returns the size of data consumed. Accordingly remaining bytes are calculated before parsing the payload, thereby eliminates the OOB access possibilities. Cc: stable@vger.kernel.org Fixes: 1a73374a04e5 ("media: venus: hfi_parser: add common capability parser") Signed-off-by: Vikash Garodia Reviewed-by: Bryan O'Donoghue Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- .../media/platform/qcom/venus/hfi_parser.c | 98 ++++++++++++++----- 1 file changed, 72 insertions(+), 26 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi_parser.c b/drivers/media/platform/qcom/venus/hfi_parser.c index d11647e12fd3..8eb9e32031f7 100644 --- a/drivers/media/platform/qcom/venus/hfi_parser.c +++ b/drivers/media/platform/qcom/venus/hfi_parser.c @@ -64,7 +64,7 @@ fill_buf_mode(struct hfi_plat_caps *cap, const void *data, unsigned int num) cap->cap_bufs_mode_dynamic = true; } -static void +static int parse_alloc_mode(struct venus_core *core, u32 codecs, u32 domain, void *data) { struct hfi_buffer_alloc_mode_supported *mode = data; @@ -72,7 +72,7 @@ parse_alloc_mode(struct venus_core *core, u32 codecs, u32 domain, void *data) u32 *type; if (num_entries > MAX_ALLOC_MODE_ENTRIES) - return; + return -EINVAL; type = mode->data; @@ -84,6 +84,8 @@ parse_alloc_mode(struct venus_core *core, u32 codecs, u32 domain, void *data) type++; } + + return sizeof(*mode); } static void fill_profile_level(struct hfi_plat_caps *cap, const void *data, @@ -98,7 +100,7 @@ static void fill_profile_level(struct hfi_plat_caps *cap, const void *data, cap->num_pl += num; } -static void +static int parse_profile_level(struct venus_core *core, u32 codecs, u32 domain, void *data) { struct hfi_profile_level_supported *pl = data; @@ -106,12 +108,14 @@ parse_profile_level(struct venus_core *core, u32 codecs, u32 domain, void *data) struct hfi_profile_level pl_arr[HFI_MAX_PROFILE_COUNT] = {}; if (pl->profile_count > HFI_MAX_PROFILE_COUNT) - return; + return -EINVAL; memcpy(pl_arr, proflevel, pl->profile_count * sizeof(*proflevel)); for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain, fill_profile_level, pl_arr, pl->profile_count); + + return pl->profile_count * sizeof(*proflevel) + sizeof(u32); } static void @@ -126,7 +130,7 @@ fill_caps(struct hfi_plat_caps *cap, const void *data, unsigned int num) cap->num_caps += num; } -static void +static int parse_caps(struct venus_core *core, u32 codecs, u32 domain, void *data) { struct hfi_capabilities *caps = data; @@ -135,12 +139,14 @@ parse_caps(struct venus_core *core, u32 codecs, u32 domain, void *data) struct hfi_capability caps_arr[MAX_CAP_ENTRIES] = {}; if (num_caps > MAX_CAP_ENTRIES) - return; + return -EINVAL; memcpy(caps_arr, cap, num_caps * sizeof(*cap)); for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain, fill_caps, caps_arr, num_caps); + + return sizeof(*caps); } static void fill_raw_fmts(struct hfi_plat_caps *cap, const void *fmts, @@ -155,7 +161,7 @@ static void fill_raw_fmts(struct hfi_plat_caps *cap, const void *fmts, cap->num_fmts += num_fmts; } -static void +static int parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data) { struct hfi_uncompressed_format_supported *fmt = data; @@ -164,7 +170,8 @@ parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data) struct raw_formats rawfmts[MAX_FMT_ENTRIES] = {}; u32 entries = fmt->format_entries; unsigned int i = 0; - u32 num_planes; + u32 num_planes = 0; + u32 size; while (entries) { num_planes = pinfo->num_planes; @@ -174,7 +181,7 @@ parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data) i++; if (i >= MAX_FMT_ENTRIES) - return; + return -EINVAL; if (pinfo->num_planes > MAX_PLANES) break; @@ -186,9 +193,13 @@ parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data) for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain, fill_raw_fmts, rawfmts, i); + size = fmt->format_entries * (sizeof(*constr) * num_planes + 2 * sizeof(u32)) + + 2 * sizeof(u32); + + return size; } -static void parse_codecs(struct venus_core *core, void *data) +static int parse_codecs(struct venus_core *core, void *data) { struct hfi_codec_supported *codecs = data; @@ -200,21 +211,27 @@ static void parse_codecs(struct venus_core *core, void *data) core->dec_codecs &= ~HFI_VIDEO_CODEC_SPARK; core->enc_codecs &= ~HFI_VIDEO_CODEC_HEVC; } + + return sizeof(*codecs); } -static void parse_max_sessions(struct venus_core *core, const void *data) +static int parse_max_sessions(struct venus_core *core, const void *data) { const struct hfi_max_sessions_supported *sessions = data; core->max_sessions_supported = sessions->max_sessions; + + return sizeof(*sessions); } -static void parse_codecs_mask(u32 *codecs, u32 *domain, void *data) +static int parse_codecs_mask(u32 *codecs, u32 *domain, void *data) { struct hfi_codec_mask_supported *mask = data; *codecs = mask->codecs; *domain = mask->video_domains; + + return sizeof(*mask); } static void parser_init(struct venus_inst *inst, u32 *codecs, u32 *domain) @@ -283,8 +300,9 @@ static int hfi_platform_parser(struct venus_core *core, struct venus_inst *inst) u32 hfi_parser(struct venus_core *core, struct venus_inst *inst, void *buf, u32 size) { - unsigned int words_count = size >> 2; - u32 *word = buf, *data, codecs = 0, domain = 0; + u32 *words = buf, *payload, codecs = 0, domain = 0; + u32 *frame_size = buf + size; + u32 rem_bytes = size; int ret; ret = hfi_platform_parser(core, inst); @@ -301,38 +319,66 @@ u32 hfi_parser(struct venus_core *core, struct venus_inst *inst, void *buf, memset(core->caps, 0, sizeof(core->caps)); } - while (words_count) { - data = word + 1; + while (words < frame_size) { + payload = words + 1; - switch (*word) { + switch (*words) { case HFI_PROPERTY_PARAM_CODEC_SUPPORTED: - parse_codecs(core, data); + if (rem_bytes <= sizeof(struct hfi_codec_supported)) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + ret = parse_codecs(core, payload); + if (ret < 0) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + init_codecs(core); break; case HFI_PROPERTY_PARAM_MAX_SESSIONS_SUPPORTED: - parse_max_sessions(core, data); + if (rem_bytes <= sizeof(struct hfi_max_sessions_supported)) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + ret = parse_max_sessions(core, payload); break; case HFI_PROPERTY_PARAM_CODEC_MASK_SUPPORTED: - parse_codecs_mask(&codecs, &domain, data); + if (rem_bytes <= sizeof(struct hfi_codec_mask_supported)) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + ret = parse_codecs_mask(&codecs, &domain, payload); break; case HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED: - parse_raw_formats(core, codecs, domain, data); + if (rem_bytes <= sizeof(struct hfi_uncompressed_format_supported)) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + ret = parse_raw_formats(core, codecs, domain, payload); break; case HFI_PROPERTY_PARAM_CAPABILITY_SUPPORTED: - parse_caps(core, codecs, domain, data); + if (rem_bytes <= sizeof(struct hfi_capabilities)) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + ret = parse_caps(core, codecs, domain, payload); break; case HFI_PROPERTY_PARAM_PROFILE_LEVEL_SUPPORTED: - parse_profile_level(core, codecs, domain, data); + if (rem_bytes <= sizeof(struct hfi_profile_level_supported)) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + ret = parse_profile_level(core, codecs, domain, payload); break; case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE_SUPPORTED: - parse_alloc_mode(core, codecs, domain, data); + if (rem_bytes <= sizeof(struct hfi_buffer_alloc_mode_supported)) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + ret = parse_alloc_mode(core, codecs, domain, payload); break; default: + ret = sizeof(u32); break; } - word++; - words_count--; + if (ret < 0) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + words += ret / sizeof(u32); + rem_bytes -= ret; } if (!core->max_sessions_supported) From 8a19d34f1e0ae5561cc8505aac901ac48ffd2628 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 10 Jan 2025 14:53:20 +0200 Subject: [PATCH 146/606] media: i2c: imx219: Rectify runtime PM handling in probe and remove commit 42eceae9793566d0df53d509be3e416465c347f5 upstream. Set the device's runtime PM status and enable runtime PM before registering the async sub-device. This is needed to avoid the case where the device is runtime PM resumed while runtime PM has not been enabled yet. Also set the device's runtime PM status to suspended in remove only if it wasn't so already. Fixes: 1283b3b8f82b ("media: i2c: Add driver for Sony IMX219 sensor") Cc: stable@vger.kernel.org # for >= v6.6 Reviewed-by: Bingbu Cao Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/i2c/imx219.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c index a9a8cd148f4f..a14e571dc62b 100644 --- a/drivers/media/i2c/imx219.c +++ b/drivers/media/i2c/imx219.c @@ -1334,21 +1334,23 @@ static int imx219_probe(struct i2c_client *client) goto error_media_entity; } + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + ret = v4l2_async_register_subdev_sensor(&imx219->sd); if (ret < 0) { dev_err(dev, "failed to register sensor sub-device: %d\n", ret); goto error_subdev_cleanup; } - /* Enable runtime PM and turn off the device */ - pm_runtime_set_active(dev); - pm_runtime_enable(dev); pm_runtime_idle(dev); return 0; error_subdev_cleanup: v4l2_subdev_cleanup(&imx219->sd); + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); error_media_entity: media_entity_cleanup(&imx219->sd.entity); @@ -1373,9 +1375,10 @@ static void imx219_remove(struct i2c_client *client) imx219_free_controls(imx219); pm_runtime_disable(&client->dev); - if (!pm_runtime_status_suspended(&client->dev)) + if (!pm_runtime_status_suspended(&client->dev)) { imx219_power_off(&client->dev); - pm_runtime_set_suspended(&client->dev); + pm_runtime_set_suspended(&client->dev); + } } static const struct of_device_id imx219_dt_ids[] = { From 92b68442790f54f19804459ad27a6f3413815a72 Mon Sep 17 00:00:00 2001 From: "Matthieu Baerts (NGI0)" Date: Fri, 14 Mar 2025 21:11:32 +0100 Subject: [PATCH 147/606] mptcp: sockopt: fix getting IPV6_V6ONLY commit 8c39633759885b6ff85f6d96cf445560e74df5e8 upstream. When adding a socket option support in MPTCP, both the get and set parts are supposed to be implemented. IPV6_V6ONLY support for the setsockopt part has been added a while ago, but it looks like the get part got forgotten. It should have been present as a way to verify a setting has been set as expected, and not to act differently from TCP or any other socket types. Not supporting this getsockopt(IPV6_V6ONLY) blocks some apps which want to check the default value, before doing extra actions. On Linux, the default value is 0, but this can be changed with the net.ipv6.bindv6only sysctl knob. On Windows, it is set to 1 by default. So supporting the get part, like for all other socket options, is important. Everything was in place to expose it, just the last step was missing. Only new code is added to cover this specific getsockopt(), that seems safe. Fixes: c9b95a135987 ("mptcp: support IPV6_V6ONLY setsockopt") Cc: stable@vger.kernel.org Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/550 Reviewed-by: Mat Martineau Signed-off-by: Matthieu Baerts (NGI0) Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250314-net-mptcp-fix-data-stream-corr-sockopt-v1-2-122dbb249db3@kernel.org Signed-off-by: Paolo Abeni Signed-off-by: Greg Kroah-Hartman --- net/mptcp/sockopt.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c index d0f73b9180c7..8c9fd9c1dbce 100644 --- a/net/mptcp/sockopt.c +++ b/net/mptcp/sockopt.c @@ -1393,6 +1393,20 @@ static int mptcp_getsockopt_v4(struct mptcp_sock *msk, int optname, return -EOPNOTSUPP; } +static int mptcp_getsockopt_v6(struct mptcp_sock *msk, int optname, + char __user *optval, int __user *optlen) +{ + struct sock *sk = (void *)msk; + + switch (optname) { + case IPV6_V6ONLY: + return mptcp_put_int_option(msk, optval, optlen, + sk->sk_ipv6only); + } + + return -EOPNOTSUPP; +} + static int mptcp_getsockopt_sol_mptcp(struct mptcp_sock *msk, int optname, char __user *optval, int __user *optlen) { @@ -1432,6 +1446,8 @@ int mptcp_getsockopt(struct sock *sk, int level, int optname, if (level == SOL_IP) return mptcp_getsockopt_v4(msk, optname, optval, option); + if (level == SOL_IPV6) + return mptcp_getsockopt_v6(msk, optname, optval, option); if (level == SOL_TCP) return mptcp_getsockopt_sol_tcp(msk, optname, optval, option); if (level == SOL_MPTCP) From 7a083ad29fd452fbbffb6d765a7aa5ddc0c79c06 Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Wed, 5 Feb 2025 02:31:41 +0000 Subject: [PATCH 148/606] mtd: Add check for devm_kcalloc() commit 2aee30bb10d7bad0a60255059c9ce1b84cf0130e upstream. Add a check for devm_kcalloc() to ensure successful allocation. Fixes: 78c08247b9d3 ("mtd: Support kmsg dumper based on pstore/blk") Cc: stable@vger.kernel.org # v5.10+ Signed-off-by: Jiasheng Jiang Signed-off-by: Miquel Raynal Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/mtdpstore.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mtd/mtdpstore.c b/drivers/mtd/mtdpstore.c index 7ac8ac901306..b3e2ea4dd40e 100644 --- a/drivers/mtd/mtdpstore.c +++ b/drivers/mtd/mtdpstore.c @@ -423,6 +423,9 @@ static void mtdpstore_notify_add(struct mtd_info *mtd) longcnt = BITS_TO_LONGS(div_u64(mtd->size, mtd->erasesize)); cxt->badmap = kcalloc(longcnt, sizeof(long), GFP_KERNEL); + if (!cxt->rmmap || !cxt->usedmap || !cxt->badmap) + return; + /* just support dmesg right now */ cxt->dev.flags = PSTORE_FLAGS_DMESG; cxt->dev.zone.read = mtdpstore_read; From 64baf646846eb6769709aaaddcdd181a1d34a4e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Mon, 17 Mar 2025 18:32:50 +0100 Subject: [PATCH 149/606] net: dsa: mv88e6xxx: workaround RGMII transmit delay erratum for 6320 family MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 1ebc8e1ef906db9c08e9abe9776d85ddec837725 upstream. Implement the workaround for erratum 3.3 RGMII timing may be out of spec when transmit delay is enabled for the 6320 family, which says: When transmit delay is enabled via Port register 1 bit 14 = 1, duty cycle may be out of spec. Under very rare conditions this may cause the attached device receive CRC errors. Signed-off-by: Marek Behún Cc: # 5.4.x Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/20250317173250.28780-8-kabel@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- drivers/net/dsa/mv88e6xxx/chip.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 8b01ee3e684a..662509c3da1f 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3555,6 +3555,21 @@ static int mv88e6xxx_stats_setup(struct mv88e6xxx_chip *chip) return mv88e6xxx_g1_stats_clear(chip); } +static int mv88e6320_setup_errata(struct mv88e6xxx_chip *chip) +{ + u16 dummy; + int err; + + /* Workaround for erratum + * 3.3 RGMII timing may be out of spec when transmit delay is enabled + */ + err = mv88e6xxx_port_hidden_write(chip, 0, 0xf, 0x7, 0xe000); + if (err) + return err; + + return mv88e6xxx_port_hidden_read(chip, 0, 0xf, 0x7, &dummy); +} + /* Check if the errata has already been applied. */ static bool mv88e6390_setup_errata_applied(struct mv88e6xxx_chip *chip) { @@ -5005,6 +5020,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { static const struct mv88e6xxx_ops mv88e6320_ops = { /* MV88E6XXX_FAMILY_6320 */ + .setup_errata = mv88e6320_setup_errata, .ieee_pri_map = mv88e6085_g1_ieee_pri_map, .ip_pri_map = mv88e6085_g1_ip_pri_map, .irl_init_all = mv88e6352_g2_irl_init_all, @@ -5054,6 +5070,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { static const struct mv88e6xxx_ops mv88e6321_ops = { /* MV88E6XXX_FAMILY_6320 */ + .setup_errata = mv88e6320_setup_errata, .ieee_pri_map = mv88e6085_g1_ieee_pri_map, .ip_pri_map = mv88e6085_g1_ip_pri_map, .irl_init_all = mv88e6352_g2_irl_init_all, From ce6cabc080c163366a95deb4033cba30c876ac81 Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Wed, 5 Feb 2025 02:31:40 +0000 Subject: [PATCH 150/606] mtd: Replace kcalloc() with devm_kcalloc() commit 1b61a59876f0eafc19b23007c522ee407f55dbec upstream. Replace kcalloc() with devm_kcalloc() to prevent memory leaks in case of errors. Fixes: 78c08247b9d3 ("mtd: Support kmsg dumper based on pstore/blk") Cc: stable@vger.kernel.org # v5.10+ Signed-off-by: Jiasheng Jiang Signed-off-by: Miquel Raynal Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/mtdpstore.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/mtdpstore.c b/drivers/mtd/mtdpstore.c index b3e2ea4dd40e..9cf3872e37ae 100644 --- a/drivers/mtd/mtdpstore.c +++ b/drivers/mtd/mtdpstore.c @@ -417,11 +417,11 @@ static void mtdpstore_notify_add(struct mtd_info *mtd) } longcnt = BITS_TO_LONGS(div_u64(mtd->size, info->kmsg_size)); - cxt->rmmap = kcalloc(longcnt, sizeof(long), GFP_KERNEL); - cxt->usedmap = kcalloc(longcnt, sizeof(long), GFP_KERNEL); + cxt->rmmap = devm_kcalloc(&mtd->dev, longcnt, sizeof(long), GFP_KERNEL); + cxt->usedmap = devm_kcalloc(&mtd->dev, longcnt, sizeof(long), GFP_KERNEL); longcnt = BITS_TO_LONGS(div_u64(mtd->size, mtd->erasesize)); - cxt->badmap = kcalloc(longcnt, sizeof(long), GFP_KERNEL); + cxt->badmap = devm_kcalloc(&mtd->dev, longcnt, sizeof(long), GFP_KERNEL); if (!cxt->rmmap || !cxt->usedmap || !cxt->badmap) return; @@ -530,9 +530,6 @@ static void mtdpstore_notify_remove(struct mtd_info *mtd) mtdpstore_flush_removed(cxt); unregister_pstore_device(&cxt->dev); - kfree(cxt->badmap); - kfree(cxt->usedmap); - kfree(cxt->rmmap); cxt->mtd = NULL; cxt->index = -1; } From f304da69287688c3d89ad6e73706b8a8a7ae9746 Mon Sep 17 00:00:00 2001 From: Alexandre Torgue Date: Thu, 6 Mar 2025 11:25:01 +0100 Subject: [PATCH 151/606] clocksource/drivers/stm32-lptimer: Use wakeup capable instead of init wakeup commit 96bf4b89a6ab22426ad83ef76e66c72a5a8daca0 upstream. "wakeup-source" property describes a device which has wakeup capability but should not force this device as a wakeup source. Fixes: 48b41c5e2de6 ("clocksource: Add Low Power STM32 timers driver") Cc: stable@vger.kernel.org Signed-off-by: Alexandre Torgue Signed-off-by: Fabrice Gasnier Rule: add Link: https://lore.kernel.org/stable/20250306083407.2374894-1-fabrice.gasnier%40foss.st.com Link: https://lore.kernel.org/r/20250306102501.2980153-1-fabrice.gasnier@foss.st.com Signed-off-by: Daniel Lezcano Signed-off-by: Greg Kroah-Hartman --- drivers/clocksource/timer-stm32-lp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/clocksource/timer-stm32-lp.c b/drivers/clocksource/timer-stm32-lp.c index a4c95161cb22..193e4f643358 100644 --- a/drivers/clocksource/timer-stm32-lp.c +++ b/drivers/clocksource/timer-stm32-lp.c @@ -168,9 +168,7 @@ static int stm32_clkevent_lp_probe(struct platform_device *pdev) } if (of_property_read_bool(pdev->dev.parent->of_node, "wakeup-source")) { - ret = device_init_wakeup(&pdev->dev, true); - if (ret) - goto out_clk_disable; + device_set_wakeup_capable(&pdev->dev, true); ret = dev_pm_set_wake_irq(&pdev->dev, irq); if (ret) From f86e2d083753db6a8dff7b9c8c5824bd14cfd51a Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Wed, 19 Feb 2025 11:36:45 +0800 Subject: [PATCH 152/606] wifi: mt76: Add check for devm_kstrdup() commit 4bc1da524b502999da28d287de4286c986a1af57 upstream. Add check for the return value of devm_kstrdup() in mt76_get_of_data_from_mtd() to catch potential exception. Fixes: e7a6a044f9b9 ("mt76: testmode: move mtd part to mt76_dev") Cc: stable@vger.kernel.org Signed-off-by: Haoxiang Li Link: https://patch.msgid.link/20250219033645.2594753-1-haoxiang_li2024@163.com Signed-off-by: Felix Fietkau Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/mediatek/mt76/eeprom.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c index 1de3c734e136..49e6c866a57f 100644 --- a/drivers/net/wireless/mediatek/mt76/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/eeprom.c @@ -95,6 +95,10 @@ static int mt76_get_of_epprom_from_mtd(struct mt76_dev *dev, void *eep, int offs #ifdef CONFIG_NL80211_TESTMODE dev->test_mtd.name = devm_kstrdup(dev->dev, part, GFP_KERNEL); + if (!dev->test_mtd.name) { + ret = -ENOMEM; + goto out_put_node; + } dev->test_mtd.offset = offset; #endif From 21b0c54546d605acb8149b07c67b0e624b4e9e92 Mon Sep 17 00:00:00 2001 From: Gavrilov Ilia Date: Wed, 12 Feb 2025 08:21:25 +0000 Subject: [PATCH 153/606] wifi: mac80211: fix integer overflow in hwmp_route_info_get() commit d00c0c4105e5ab8a6a13ed23d701cceb285761fa upstream. Since the new_metric and last_hop_metric variables can reach the MAX_METRIC(0xffffffff) value, an integer overflow may occur when multiplying them by 10/9. It can lead to incorrect behavior. Found by InfoTeCS on behalf of Linux Verification Center (linuxtesting.org) with SVACE. Fixes: a8d418d9ac25 ("mac80211: mesh: only switch path when new metric is at least 10% better") Cc: stable@vger.kernel.org Signed-off-by: Ilia Gavrilov Link: https://patch.msgid.link/20250212082124.4078236-1-Ilia.Gavrilov@infotecs.ru Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/mesh_hwmp.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 51369072984e..c6395551f5df 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -365,6 +365,12 @@ u32 airtime_link_metric_get(struct ieee80211_local *local, return (u32)result; } +/* Check that the first metric is at least 10% better than the second one */ +static bool is_metric_better(u32 x, u32 y) +{ + return (x < y) && (x < (y - x / 10)); +} + /** * hwmp_route_info_get - Update routing info to originator and transmitter * @@ -456,8 +462,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, (mpath->sn == orig_sn && (rcu_access_pointer(mpath->next_hop) != sta ? - mult_frac(new_metric, 10, 9) : - new_metric) >= mpath->metric)) { + !is_metric_better(new_metric, mpath->metric) : + new_metric >= mpath->metric))) { process = false; fresh_info = false; } @@ -531,8 +537,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, if ((mpath->flags & MESH_PATH_FIXED) || ((mpath->flags & MESH_PATH_ACTIVE) && ((rcu_access_pointer(mpath->next_hop) != sta ? - mult_frac(last_hop_metric, 10, 9) : - last_hop_metric) > mpath->metric))) + !is_metric_better(last_hop_metric, mpath->metric) : + last_hop_metric > mpath->metric)))) fresh_info = false; } else { mpath = mesh_path_add(sdata, ta); From 35c4a652d8335d6cc3306284ab36f4f2ad031d5f Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 7 Apr 2025 07:51:23 -0600 Subject: [PATCH 154/606] io_uring/kbuf: reject zero sized provided buffers commit cf960726eb65e8d0bfecbcce6cf95f47b1ffa6cc upstream. This isn't fixing a real issue, but there's also zero point in going through group and buffer setup, when the buffers are going to be rejected once attempted to get used. Cc: stable@vger.kernel.org Reported-by: syzbot+58928048fd1416f1457c@syzkaller.appspotmail.com Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- io_uring/kbuf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c index 0d9b8a8b42c2..8c6611fe4f46 100644 --- a/io_uring/kbuf.c +++ b/io_uring/kbuf.c @@ -321,6 +321,8 @@ int io_provide_buffers_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe p->nbufs = tmp; p->addr = READ_ONCE(sqe->addr); p->len = READ_ONCE(sqe->len); + if (!p->len) + return -EINVAL; if (check_mul_overflow((unsigned long)p->len, (unsigned long)p->nbufs, &size)) From 176e7c9a0f627f298cf973d9cc8d49d42152d6ab Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 14 Mar 2025 17:47:57 +0000 Subject: [PATCH 155/606] ASoC: q6apm: add q6apm_get_hw_pointer helper commit 0badb5432fd525a00db5630c459b635e9d47f445 upstream. Implement an helper function in q6apm to be able to read the current hardware pointer for both read and write buffers. This should help q6apm-dai to get the hardware pointer consistently without it doing manual calculation, which could go wrong in some race conditions. Fixes: 9b4fe0f1cd79 ("ASoC: qdsp6: audioreach: add q6apm-dai support") Cc: stable@vger.kernel.org Signed-off-by: Srinivas Kandagatla Tested-by: Krzysztof Kozlowski Tested-by: Johan Hovold Link: https://patch.msgid.link/20250314174800.10142-3-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/qcom/qdsp6/q6apm.c | 18 +++++++++++++++++- sound/soc/qcom/qdsp6/q6apm.h | 3 +++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c index 2a2a5bd98110..ca57413cb784 100644 --- a/sound/soc/qcom/qdsp6/q6apm.c +++ b/sound/soc/qcom/qdsp6/q6apm.c @@ -494,6 +494,19 @@ int q6apm_read(struct q6apm_graph *graph) } EXPORT_SYMBOL_GPL(q6apm_read); +int q6apm_get_hw_pointer(struct q6apm_graph *graph, int dir) +{ + struct audioreach_graph_data *data; + + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + data = &graph->rx_data; + else + data = &graph->tx_data; + + return (int)atomic_read(&data->hw_ptr); +} +EXPORT_SYMBOL_GPL(q6apm_get_hw_pointer); + static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op) { struct data_cmd_rsp_rd_sh_mem_ep_data_buffer_done_v2 *rd_done; @@ -520,7 +533,8 @@ static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op) done = data->payload; phys = graph->rx_data.buf[token].phys; mutex_unlock(&graph->lock); - + /* token numbering starts at 0 */ + atomic_set(&graph->rx_data.hw_ptr, token + 1); if (lower_32_bits(phys) == done->buf_addr_lsw && upper_32_bits(phys) == done->buf_addr_msw) { graph->result.opcode = hdr->opcode; @@ -553,6 +567,8 @@ static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op) rd_done = data->payload; phys = graph->tx_data.buf[hdr->token].phys; mutex_unlock(&graph->lock); + /* token numbering starts at 0 */ + atomic_set(&graph->tx_data.hw_ptr, hdr->token + 1); if (upper_32_bits(phys) == rd_done->buf_addr_msw && lower_32_bits(phys) == rd_done->buf_addr_lsw) { diff --git a/sound/soc/qcom/qdsp6/q6apm.h b/sound/soc/qcom/qdsp6/q6apm.h index f486bd639b9f..74fa4fed881b 100644 --- a/sound/soc/qcom/qdsp6/q6apm.h +++ b/sound/soc/qcom/qdsp6/q6apm.h @@ -2,6 +2,7 @@ #ifndef __Q6APM_H__ #define __Q6APM_H__ #include +#include #include #include #include @@ -78,6 +79,7 @@ struct audioreach_graph_data { uint32_t num_periods; uint32_t dsp_buf; uint32_t mem_map_handle; + atomic_t hw_ptr; }; struct audioreach_graph { @@ -151,4 +153,5 @@ int q6apm_enable_compress_module(struct device *dev, struct q6apm_graph *graph, int q6apm_remove_initial_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples); int q6apm_remove_trailing_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples); int q6apm_set_real_module_id(struct device *dev, struct q6apm_graph *graph, uint32_t codec_id); +int q6apm_get_hw_pointer(struct q6apm_graph *graph, int dir); #endif /* __APM_GRAPH_ */ From b860a99800bc45515a7e497e755c5e019cb0d7cb Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 14 Mar 2025 17:47:59 +0000 Subject: [PATCH 156/606] ASoC: qdsp6: q6apm-dai: set 10 ms period and buffer alignment. commit 3107019501842c27334554ba9d6583b1f200f61f upstream. DSP expects the periods to be aligned to fragment sizes, currently setting up to hw constriants on periods bytes is not going to work correctly as we can endup with periods sizes aligned to 32 bytes however not aligned to fragment size. Update the constriants to use fragment size, and also set at step of 10ms for period size to accommodate DSP requirements of 10ms latency. Fixes: 9b4fe0f1cd79 ("ASoC: qdsp6: audioreach: add q6apm-dai support") Cc: stable@vger.kernel.org Signed-off-by: Srinivas Kandagatla Tested-by: Johan Hovold Link: https://patch.msgid.link/20250314174800.10142-5-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/qcom/qdsp6/q6apm-dai.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index 739856a00017..e3faf1aa7a79 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -380,13 +380,14 @@ static int q6apm_dai_open(struct snd_soc_component *component, } } - ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); + /* setup 10ms latency to accommodate DSP restrictions */ + ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 480); if (ret < 0) { dev_err(dev, "constraint for period bytes step ret = %d\n", ret); goto err; } - ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32); + ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 480); if (ret < 0) { dev_err(dev, "constraint for buffer bytes step ret = %d\n", ret); goto err; From 7ed8f978a8942b5574a6d3415bf396367d1815f8 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 14 Mar 2025 17:48:00 +0000 Subject: [PATCH 157/606] ASoC: qdsp6: q6apm-dai: fix capture pipeline overruns. commit 5d01ed9b9939b4c726be74db291a982bc984c584 upstream. Period sizes less than 6k for capture path triggers overruns in the dsp capture pipeline. Change the period size and number of periods to value which DSP is happy with. Fixes: 9b4fe0f1cd79 ("ASoC: qdsp6: audioreach: add q6apm-dai support") Cc: stable@vger.kernel.org Signed-off-by: Srinivas Kandagatla Tested-by: Krzysztof Kozlowski Tested-by: Johan Hovold Link: https://patch.msgid.link/20250314174800.10142-6-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/qcom/qdsp6/q6apm-dai.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index e3faf1aa7a79..def05ce58d17 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -24,8 +24,8 @@ #define PLAYBACK_MIN_PERIOD_SIZE 128 #define CAPTURE_MIN_NUM_PERIODS 2 #define CAPTURE_MAX_NUM_PERIODS 8 -#define CAPTURE_MAX_PERIOD_SIZE 4096 -#define CAPTURE_MIN_PERIOD_SIZE 320 +#define CAPTURE_MAX_PERIOD_SIZE 65536 +#define CAPTURE_MIN_PERIOD_SIZE 6144 #define BUFFER_BYTES_MAX (PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE) #define BUFFER_BYTES_MIN (PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE) #define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024) From 7e439ff5efabb6db40a6fd37f17eef41199ddea9 Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Thu, 27 Mar 2025 15:46:50 +0000 Subject: [PATCH 158/606] ASoC: qdsp6: q6asm-dai: fix q6asm_dai_compr_set_params error path commit 7eccc86e90f04a0d758d16c08627a620ac59604d upstream. In case of attempts to compress playback something, for instance, when audio routing is not set up correctly, the audio DSP is left in inconsistent state because we are not doing the correct things in the error path of q6asm_dai_compr_set_params(). So, when routing is not set up and compress playback is attempted the following errors are present (simplified log): q6routing routing: Routing not setup for MultiMedia-1 Session q6asm-dai dais: Stream reg failed ret:-22 q6asm-dai dais: ASoC error (-22): at snd_soc_component_compr_set_params() on 17300000.remoteproc:glink-edge:apr:service@7:dais After setting the correct routing the compress playback will always fail: q6asm-dai dais: cmd = 0x10db3 returned error = 0x9 q6asm-dai dais: DSP returned error[9] q6asm-dai dais: q6asm_open_write failed q6asm-dai dais: ASoC error (-22): at snd_soc_component_compr_set_params() on 17300000.remoteproc:glink-edge:apr:service@7:dais 0x9 here means "Operation is already processed". The CMD_OPEN here was sent the second time hence DSP responds that it was already done. Turns out the CMD_CLOSE should be sent after the q6asm_open_write() succeeded but something failed after that, for instance, routing setup. Fix this by slightly reworking the error path in q6asm_dai_compr_set_params(). Tested on QRB5165 RB5 and SDM845 RB3 boards. Cc: stable@vger.kernel.org Fixes: 5b39363e54cc ("ASoC: q6asm-dai: prepare set params to accept profile change") Cc: Srinivas Kandagatla Cc: Vinod Koul Cc: Pierre-Louis Bossart Signed-off-by: Alexey Klimov Reviewed-by: Srinivas Kandagatla Link: https://patch.msgid.link/20250327154650.337404-1-alexey.klimov@linaro.org Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/qcom/qdsp6/q6asm-dai.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index 5e14cd0a38de..82ef8fdb914e 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c @@ -902,9 +902,7 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, if (ret < 0) { dev_err(dev, "q6asm_open_write failed\n"); - q6asm_audio_client_free(prtd->audio_client); - prtd->audio_client = NULL; - return ret; + goto open_err; } } @@ -913,7 +911,7 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, prtd->session_id, dir); if (ret) { dev_err(dev, "Stream reg failed ret:%d\n", ret); - return ret; + goto q6_err; } ret = __q6asm_dai_compr_set_codec_params(component, stream, @@ -921,7 +919,7 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, prtd->stream_id); if (ret) { dev_err(dev, "codec param setup failed ret:%d\n", ret); - return ret; + goto q6_err; } ret = q6asm_map_memory_regions(dir, prtd->audio_client, prtd->phys, @@ -930,12 +928,21 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, if (ret < 0) { dev_err(dev, "Buffer Mapping failed ret:%d\n", ret); - return -ENOMEM; + ret = -ENOMEM; + goto q6_err; } prtd->state = Q6ASM_STREAM_RUNNING; return 0; + +q6_err: + q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE); + +open_err: + q6asm_audio_client_free(prtd->audio_client); + prtd->audio_client = NULL; + return ret; } static int q6asm_dai_compr_set_metadata(struct snd_soc_component *component, From 5f084993c90d9d0b4a52a349ede5120f992a7ca1 Mon Sep 17 00:00:00 2001 From: Jeff Hugo Date: Thu, 6 Mar 2025 10:29:13 -0700 Subject: [PATCH 159/606] bus: mhi: host: Fix race between unprepare and queue_buf commit 0686a818d77a431fc3ba2fab4b46bbb04e8c9380 upstream. A client driver may use mhi_unprepare_from_transfer() to quiesce incoming data during the client driver's tear down. The client driver might also be processing data at the same time, resulting in a call to mhi_queue_buf() which will invoke mhi_gen_tre(). If mhi_gen_tre() runs after mhi_unprepare_from_transfer() has torn down the channel, a panic will occur due to an invalid dereference leading to a page fault. This occurs because mhi_gen_tre() does not verify the channel state after locking it. Fix this by having mhi_gen_tre() confirm the channel state is valid, or return error to avoid accessing deinitialized data. Cc: stable@vger.kernel.org # 6.8 Fixes: b89b6a863dd5 ("bus: mhi: host: Add spinlock to protect WP access when queueing TREs") Signed-off-by: Jeffrey Hugo Signed-off-by: Jeff Hugo Reviewed-by: Krishna Chaitanya Chundru Reviewed-by: Youssef Samir Reviewed-by: Manivannan Sadhasivam Reviewed-by: Troy Hanson Link: https://lore.kernel.org/r/20250306172913.856982-1-jeff.hugo@oss.qualcomm.com [mani: added stable tag] Signed-off-by: Manivannan Sadhasivam Signed-off-by: Greg Kroah-Hartman --- drivers/bus/mhi/host/main.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/bus/mhi/host/main.c b/drivers/bus/mhi/host/main.c index d6653cbcf94a..ad1e97222a0f 100644 --- a/drivers/bus/mhi/host/main.c +++ b/drivers/bus/mhi/host/main.c @@ -1204,11 +1204,16 @@ int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan, struct mhi_ring_element *mhi_tre; struct mhi_buf_info *buf_info; int eot, eob, chain, bei; - int ret; + int ret = 0; /* Protect accesses for reading and incrementing WP */ write_lock_bh(&mhi_chan->lock); + if (mhi_chan->ch_state != MHI_CH_STATE_ENABLED) { + ret = -ENODEV; + goto out; + } + buf_ring = &mhi_chan->buf_ring; tre_ring = &mhi_chan->tre_ring; @@ -1226,10 +1231,8 @@ int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan, if (!info->pre_mapped) { ret = mhi_cntrl->map_single(mhi_cntrl, buf_info); - if (ret) { - write_unlock_bh(&mhi_chan->lock); - return ret; - } + if (ret) + goto out; } eob = !!(flags & MHI_EOB); @@ -1246,9 +1249,10 @@ int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan, mhi_add_ring_element(mhi_cntrl, tre_ring); mhi_add_ring_element(mhi_cntrl, buf_ring); +out: write_unlock_bh(&mhi_chan->lock); - return 0; + return ret; } int mhi_queue_buf(struct mhi_device *mhi_dev, enum dma_data_direction dir, From 2eeb1085bf7bd5c7ba796ca4119925fa5d336a3f Mon Sep 17 00:00:00 2001 From: Artem Sadovnikov Date: Fri, 4 Apr 2025 08:28:05 +0000 Subject: [PATCH 160/606] ext4: fix off-by-one error in do_split commit 94824ac9a8aaf2fb3c54b4bdde842db80ffa555d upstream. Syzkaller detected a use-after-free issue in ext4_insert_dentry that was caused by out-of-bounds access due to incorrect splitting in do_split. BUG: KASAN: use-after-free in ext4_insert_dentry+0x36a/0x6d0 fs/ext4/namei.c:2109 Write of size 251 at addr ffff888074572f14 by task syz-executor335/5847 CPU: 0 UID: 0 PID: 5847 Comm: syz-executor335 Not tainted 6.12.0-rc6-syzkaller-00318-ga9cda7c0ffed #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/30/2024 Call Trace: __dump_stack lib/dump_stack.c:94 [inline] dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120 print_address_description mm/kasan/report.c:377 [inline] print_report+0x169/0x550 mm/kasan/report.c:488 kasan_report+0x143/0x180 mm/kasan/report.c:601 kasan_check_range+0x282/0x290 mm/kasan/generic.c:189 __asan_memcpy+0x40/0x70 mm/kasan/shadow.c:106 ext4_insert_dentry+0x36a/0x6d0 fs/ext4/namei.c:2109 add_dirent_to_buf+0x3d9/0x750 fs/ext4/namei.c:2154 make_indexed_dir+0xf98/0x1600 fs/ext4/namei.c:2351 ext4_add_entry+0x222a/0x25d0 fs/ext4/namei.c:2455 ext4_add_nondir+0x8d/0x290 fs/ext4/namei.c:2796 ext4_symlink+0x920/0xb50 fs/ext4/namei.c:3431 vfs_symlink+0x137/0x2e0 fs/namei.c:4615 do_symlinkat+0x222/0x3a0 fs/namei.c:4641 __do_sys_symlink fs/namei.c:4662 [inline] __se_sys_symlink fs/namei.c:4660 [inline] __x64_sys_symlink+0x7a/0x90 fs/namei.c:4660 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f The following loop is located right above 'if' statement. for (i = count-1; i >= 0; i--) { /* is more than half of this entry in 2nd half of the block? */ if (size + map[i].size/2 > blocksize/2) break; size += map[i].size; move++; } 'i' in this case could go down to -1, in which case sum of active entries wouldn't exceed half the block size, but previous behaviour would also do split in half if sum would exceed at the very last block, which in case of having too many long name files in a single block could lead to out-of-bounds access and following use-after-free. Found by Linux Verification Center (linuxtesting.org) with Syzkaller. Cc: stable@vger.kernel.org Fixes: 5872331b3d91 ("ext4: fix potential negative array index in do_split()") Signed-off-by: Artem Sadovnikov Reviewed-by: Jan Kara Link: https://patch.msgid.link/20250404082804.2567-3-a.sadovnikov@ispras.ru Signed-off-by: Theodore Ts'o Signed-off-by: Greg Kroah-Hartman --- fs/ext4/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 96a048d3f51b..2e4575becd4f 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -2041,7 +2041,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, * split it in half by count; each resulting block will have at least * half the space free. */ - if (i > 0) + if (i >= 0) split = count - move; else split = count/2; From a5464ac3eeffa88333866cdaf2ecedca940137e0 Mon Sep 17 00:00:00 2001 From: Yeongjin Gil Date: Fri, 14 Mar 2025 21:06:51 +0900 Subject: [PATCH 161/606] f2fs: fix to avoid atomicity corruption of atomic file commit f098aeba04c9328571567dca45159358a250240c upstream. In the case of the following call stack for an atomic file, FI_DIRTY_INODE is set, but FI_ATOMIC_DIRTIED is not subsequently set. f2fs_file_write_iter f2fs_map_blocks f2fs_reserve_new_blocks inc_valid_block_count __mark_inode_dirty(dquot) f2fs_dirty_inode If FI_ATOMIC_DIRTIED is not set, atomic file can encounter corruption due to a mismatch between old file size and new data. To resolve this issue, I changed to set FI_ATOMIC_DIRTIED when FI_DIRTY_INODE is set. This ensures that FI_DIRTY_INODE, which was previously cleared by the Writeback thread during the commit atomic, is set and i_size is updated. Cc: Fixes: fccaa81de87e ("f2fs: prevent atomic file from being dirtied before commit") Reviewed-by: Sungjong Seo Reviewed-by: Sunmin Jeong Signed-off-by: Yeongjin Gil Reviewed-by: Daeho Jeong Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim Signed-off-by: Greg Kroah-Hartman --- fs/f2fs/inode.c | 4 +--- fs/f2fs/super.c | 4 ++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 173832fd0168..06941705e893 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -35,10 +35,8 @@ void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync) if (f2fs_inode_dirtied(inode, sync)) return; - if (f2fs_is_atomic_file(inode)) { - set_inode_flag(inode, FI_ATOMIC_DIRTIED); + if (f2fs_is_atomic_file(inode)) return; - } mark_inode_dirty_sync(inode); } diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index aa0e7cc2489a..4cc87921aac3 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1499,6 +1499,10 @@ int f2fs_inode_dirtied(struct inode *inode, bool sync) inc_page_count(sbi, F2FS_DIRTY_IMETA); } spin_unlock(&sbi->inode_lock[DIRTY_META]); + + if (!ret && f2fs_is_atomic_file(inode)) + set_inode_flag(inode, FI_ATOMIC_DIRTIED); + return ret; } From a5434db74bf2598094f6f1b4f5787c347f9da069 Mon Sep 17 00:00:00 2001 From: Si-Wei Liu Date: Thu, 20 Feb 2025 21:37:33 +0200 Subject: [PATCH 162/606] vdpa/mlx5: Fix oversized null mkey longer than 32bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit a6097e0a54a5c24f8d577ffecbc35289ae281c2e upstream. create_user_mr() has correct code to count the number of null keys used to fill in a hole for the memory map. However, fill_indir() does not follow the same to cap the range up to the 1GB limit correspondingly. Fill in more null keys for the gaps in between, so that null keys are correctly populated. Fixes: 94abbccdf291 ("vdpa/mlx5: Add shared memory registration code") Cc: stable@vger.kernel.org Reported-by: Cong Meng Signed-off-by: Si-Wei Liu Signed-off-by: Dragos Tatulea Acked-by: Eugenio Pérez Message-Id: <20250220193732.521462-2-dtatulea@nvidia.com> Signed-off-by: Michael S. Tsirkin Acked-by: Jason Wang Signed-off-by: Greg Kroah-Hartman --- drivers/vdpa/mlx5/core/mr.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/vdpa/mlx5/core/mr.c b/drivers/vdpa/mlx5/core/mr.c index aa4ab4c847fd..165730656934 100644 --- a/drivers/vdpa/mlx5/core/mr.c +++ b/drivers/vdpa/mlx5/core/mr.c @@ -166,9 +166,12 @@ again: klm->bcount = cpu_to_be32(klm_bcount(dmr->end - dmr->start)); preve = dmr->end; } else { + u64 bcount = min_t(u64, dmr->start - preve, MAX_KLM_SIZE); + klm->key = cpu_to_be32(mvdev->res.null_mkey); - klm->bcount = cpu_to_be32(klm_bcount(dmr->start - preve)); - preve = dmr->start; + klm->bcount = cpu_to_be32(klm_bcount(bcount)); + preve += bcount; + goto again; } } From a64d8972f00f592672a92f20762867d80e09436b Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 12 Mar 2025 16:18:39 +0100 Subject: [PATCH 163/606] udf: Fix inode_getblk() return value commit 6afdc60ec30b0a9390d11b7cebed79c857ce82aa upstream. Smatch noticed that inode_getblk() can return 1 on successful mapping of a block instead of expected 0 after commit b405c1e58b73 ("udf: refactor udf_next_aext() to handle error"). This could confuse some of the callers and lead to strange failures (although the one reported by Smatch in udf_mkdir() is impossible to trigger in practice). Fix the return value of inode_getblk(). Link: https://lore.kernel.org/all/cb514af7-bbe0-435b-934f-dd1d7a16d2cd@stanley.mountain Reported-by: Dan Carpenter Reviewed-by: Carlos Maiolino Fixes: b405c1e58b73 ("udf: refactor udf_next_aext() to handle error") CC: stable@vger.kernel.org Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/udf/inode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/udf/inode.c b/fs/udf/inode.c index e98c198f85b9..2f73119c7ec9 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -814,6 +814,7 @@ static int inode_getblk(struct inode *inode, struct udf_map_rq *map) } map->oflags = UDF_BLK_MAPPED; map->pblk = udf_get_lb_pblock(inode->i_sb, &eloc, offset); + ret = 0; goto out_free; } From 1404dff1e11bf927b70ac25e1de97bed9742ede4 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Fri, 7 Feb 2025 15:07:46 -0300 Subject: [PATCH 164/606] tpm: do not start chip while suspended commit 17d253af4c2c8a2acf84bb55a0c2045f150b7dfd upstream. Checking TPM_CHIP_FLAG_SUSPENDED after the call to tpm_find_get_ops() can lead to a spurious tpm_chip_start() call: [35985.503771] i2c i2c-1: Transfer while suspended [35985.503796] WARNING: CPU: 0 PID: 74 at drivers/i2c/i2c-core.h:56 __i2c_transfer+0xbe/0x810 [35985.503802] Modules linked in: [35985.503808] CPU: 0 UID: 0 PID: 74 Comm: hwrng Tainted: G W 6.13.0-next-20250203-00005-gfa0cb5642941 #19 9c3d7f78192f2d38e32010ac9c90fdc71109ef6f [35985.503814] Tainted: [W]=WARN [35985.503817] Hardware name: Google Morphius/Morphius, BIOS Google_Morphius.13434.858.0 10/26/2023 [35985.503819] RIP: 0010:__i2c_transfer+0xbe/0x810 [35985.503825] Code: 30 01 00 00 4c 89 f7 e8 40 fe d8 ff 48 8b 93 80 01 00 00 48 85 d2 75 03 49 8b 16 48 c7 c7 0a fb 7c a7 48 89 c6 e8 32 ad b0 fe <0f> 0b b8 94 ff ff ff e9 33 04 00 00 be 02 00 00 00 83 fd 02 0f 5 [35985.503828] RSP: 0018:ffffa106c0333d30 EFLAGS: 00010246 [35985.503833] RAX: 074ba64aa20f7000 RBX: ffff8aa4c1167120 RCX: 0000000000000000 [35985.503836] RDX: 0000000000000000 RSI: ffffffffa77ab0e4 RDI: 0000000000000001 [35985.503838] RBP: 0000000000000001 R08: 0000000000000001 R09: 0000000000000000 [35985.503841] R10: 0000000000000004 R11: 00000001000313d5 R12: ffff8aa4c10f1820 [35985.503843] R13: ffff8aa4c0e243c0 R14: ffff8aa4c1167250 R15: ffff8aa4c1167120 [35985.503846] FS: 0000000000000000(0000) GS:ffff8aa4eae00000(0000) knlGS:0000000000000000 [35985.503849] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [35985.503852] CR2: 00007fab0aaf1000 CR3: 0000000105328000 CR4: 00000000003506f0 [35985.503855] Call Trace: [35985.503859] [35985.503863] ? __warn+0xd4/0x260 [35985.503868] ? __i2c_transfer+0xbe/0x810 [35985.503874] ? report_bug+0xf3/0x210 [35985.503882] ? handle_bug+0x63/0xb0 [35985.503887] ? exc_invalid_op+0x16/0x50 [35985.503892] ? asm_exc_invalid_op+0x16/0x20 [35985.503904] ? __i2c_transfer+0xbe/0x810 [35985.503913] tpm_cr50_i2c_transfer_message+0x24/0xf0 [35985.503920] tpm_cr50_i2c_read+0x8e/0x120 [35985.503928] tpm_cr50_request_locality+0x75/0x170 [35985.503935] tpm_chip_start+0x116/0x160 [35985.503942] tpm_try_get_ops+0x57/0x90 [35985.503948] tpm_find_get_ops+0x26/0xd0 [35985.503955] tpm_get_random+0x2d/0x80 Don't move forward with tpm_chip_start() inside tpm_try_get_ops(), unless TPM_CHIP_FLAG_SUSPENDED is not set. tpm_find_get_ops() will return NULL in such a failure case. Fixes: 9265fed6db60 ("tpm: Lock TPM chip in tpm_pm_suspend() first") Signed-off-by: Thadeu Lima de Souza Cascardo Cc: stable@vger.kernel.org Cc: Jerry Snitselaar Cc: Mike Seo Cc: Jarkko Sakkinen Reviewed-by: Jerry Snitselaar Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm-chip.c | 5 +++++ drivers/char/tpm/tpm-interface.c | 7 ------- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 78999f7f248c..70e3fe20fdcf 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -165,6 +165,11 @@ int tpm_try_get_ops(struct tpm_chip *chip) goto out_ops; mutex_lock(&chip->tpm_mutex); + + /* tmp_chip_start may issue IO that is denied while suspended */ + if (chip->flags & TPM_CHIP_FLAG_SUSPENDED) + goto out_lock; + rc = tpm_chip_start(chip); if (rc) goto out_lock; diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index c8ea52dfa556..3a6223cafeb3 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -468,18 +468,11 @@ int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max) if (!chip) return -ENODEV; - /* Give back zero bytes, as TPM chip has not yet fully resumed: */ - if (chip->flags & TPM_CHIP_FLAG_SUSPENDED) { - rc = 0; - goto out; - } - if (chip->flags & TPM_CHIP_FLAG_TPM2) rc = tpm2_get_random(chip, out, max); else rc = tpm1_get_random(chip, out, max); -out: tpm_put_ops(chip); return rc; } From 5f80fd2ff8bfd13e41554741740e0ca8e6445ded Mon Sep 17 00:00:00 2001 From: Chenyuan Yang Date: Wed, 12 Feb 2025 15:35:18 -0600 Subject: [PATCH 165/606] soc: samsung: exynos-chipid: Add NULL pointer check in exynos_chipid_probe() commit c8222ef6cf29dd7cad21643228f96535cc02b327 upstream. soc_dev_attr->revision could be NULL, thus, a pointer check is added to prevent potential NULL pointer dereference. This is similar to the fix in commit 3027e7b15b02 ("ice: Fix some null pointer dereference issues in ice_ptp.c"). This issue is found by our static analysis tool. Signed-off-by: Chenyuan Yang Link: https://lore.kernel.org/r/20250212213518.69432-1-chenyuan0y@gmail.com Fixes: 3253b7b7cd44 ("soc: samsung: Add exynos chipid driver support") Cc: Signed-off-by: Krzysztof Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/soc/samsung/exynos-chipid.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c index 7ba45c4aff97..1307f6d61c98 100644 --- a/drivers/soc/samsung/exynos-chipid.c +++ b/drivers/soc/samsung/exynos-chipid.c @@ -130,6 +130,8 @@ static int exynos_chipid_probe(struct platform_device *pdev) soc_dev_attr->revision = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%x", soc_info.revision); + if (!soc_dev_attr->revision) + return -ENOMEM; soc_dev_attr->soc_id = product_id_to_soc_id(soc_info.product_id); if (!soc_dev_attr->soc_id) { pr_err("Unknown SoC\n"); From b00b040abfbbe227f2b8b6bdb0c825ced8afaccc Mon Sep 17 00:00:00 2001 From: Steve French Date: Sun, 6 Apr 2025 14:09:19 -0500 Subject: [PATCH 166/606] smb311 client: fix missing tcon check when mounting with linux/posix extensions commit b365b9d404b7376c60c91cd079218bfef11b7822 upstream. When mounting the same share twice, once with the "linux" mount parameter (or equivalently "posix") and then once without (or e.g. with "nolinux"), we were incorrectly reusing the same tree connection for both mounts. This meant that the first mount of the share on the client, would cause subsequent mounts of that same share on the same client to ignore that mount parm ("linux" vs. "nolinux") and incorrectly reuse the same tcon. Cc: stable@vger.kernel.org Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/smb/client/connect.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 2d2e41ac9e9d..108e4881d6a2 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -2488,6 +2488,8 @@ static int match_tcon(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) return 0; if (tcon->nodelete != ctx->nodelete) return 0; + if (tcon->posix_extensions != ctx->linux_ext) + return 0; return 1; } From c3250bdf5da9792a98be8c7c25f6814862790c3f Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Tue, 18 Mar 2025 13:36:05 +0800 Subject: [PATCH 167/606] i3c: master: svc: Use readsb helper for reading MDB commit c06acf7143bddaa3c0f7bedd8b99e48f6acb85c3 upstream. The target can send the MDB byte followed by additional data bytes. The readl on MRDATAB reads one actual byte, but the readsl advances the destination pointer by 4 bytes. This causes the subsequent payload to be copied to wrong position in the destination buffer. Cc: stable@kernel.org Fixes: dd3c52846d59 ("i3c: master: svc: Add Silvaco I3C master driver") Signed-off-by: Stanley Chu Reviewed-by: Frank Li Link: https://lore.kernel.org/r/20250318053606.3087121-3-yschu@nuvoton.com Signed-off-by: Alexandre Belloni Signed-off-by: Greg Kroah-Hartman --- drivers/i3c/master/svc-i3c-master.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c index 652a666909a5..fa1f12a89158 100644 --- a/drivers/i3c/master/svc-i3c-master.c +++ b/drivers/i3c/master/svc-i3c-master.c @@ -376,7 +376,7 @@ static int svc_i3c_master_handle_ibi(struct svc_i3c_master *master, slot->len < SVC_I3C_FIFO_SIZE) { mdatactrl = readl(master->regs + SVC_I3C_MDATACTRL); count = SVC_I3C_MDATACTRL_RXCOUNT(mdatactrl); - readsl(master->regs + SVC_I3C_MRDATAB, buf, count); + readsb(master->regs + SVC_I3C_MRDATAB, buf, count); slot->len += count; buf += count; } From 6871a676aa534e8f218279672e0445c725f81026 Mon Sep 17 00:00:00 2001 From: Manjunatha Venkatesh Date: Wed, 26 Mar 2025 18:00:46 +0530 Subject: [PATCH 168/606] i3c: Add NULL pointer check in i3c_master_queue_ibi() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit bd496a44f041da9ef3afe14d1d6193d460424e91 upstream. The I3C master driver may receive an IBI from a target device that has not been probed yet. In such cases, the master calls `i3c_master_queue_ibi()` to queue an IBI work task, leading to "Unable to handle kernel read from unreadable memory" and resulting in a kernel panic. Typical IBI handling flow: 1. The I3C master scans target devices and probes their respective drivers. 2. The target device driver calls `i3c_device_request_ibi()` to enable IBI and assigns `dev->ibi = ibi`. 3. The I3C master receives an IBI from the target device and calls `i3c_master_queue_ibi()` to queue the target device driver’s IBI handler task. However, since target device events are asynchronous to the I3C probe sequence, step 3 may occur before step 2, causing `dev->ibi` to be `NULL`, leading to a kernel panic. Add a NULL pointer check in `i3c_master_queue_ibi()` to prevent accessing an uninitialized `dev->ibi`, ensuring stability. Fixes: 3a379bbcea0af ("i3c: Add core I3C infrastructure") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/lkml/Z9gjGYudiYyl3bSe@lizhi-Precision-Tower-5810/ Signed-off-by: Manjunatha Venkatesh Reviewed-by: Frank Li Link: https://lore.kernel.org/r/20250326123047.2797946-1-manjunatha.venkatesh@nxp.com Signed-off-by: Alexandre Belloni Signed-off-by: Greg Kroah-Hartman --- drivers/i3c/master.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index c073ee74e3da..33254bc338b9 100644 --- a/drivers/i3c/master.c +++ b/drivers/i3c/master.c @@ -2512,6 +2512,9 @@ static void i3c_master_unregister_i3c_devs(struct i3c_master_controller *master) */ void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot) { + if (!dev->ibi || !slot) + return; + atomic_inc(&dev->ibi->pending_ibis); queue_work(dev->common.master->wq, &slot->work); } From c88f7328bb0fff66520fc9164f02b1d06e083c1b Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 6 Feb 2025 10:46:58 +0100 Subject: [PATCH 169/606] jbd2: remove wrong sb->s_sequence check commit e6eff39dd0fe4190c6146069cc16d160e71d1148 upstream. Journal emptiness is not determined by sb->s_sequence == 0 but rather by sb->s_start == 0 (which is set a few lines above). Furthermore 0 is a valid transaction ID so the check can spuriously trigger. Remove the invalid WARN_ON. CC: stable@vger.kernel.org Signed-off-by: Jan Kara Reviewed-by: Zhang Yi Link: https://patch.msgid.link/20250206094657.20865-3-jack@suse.cz Signed-off-by: Theodore Ts'o Signed-off-by: Greg Kroah-Hartman --- fs/jbd2/journal.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index dfbb8f73861f..ddde73299d62 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -1914,7 +1914,6 @@ int jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid, /* Log is no longer empty */ write_lock(&journal->j_state_lock); - WARN_ON(!sb->s_sequence); journal->j_flags &= ~JBD2_FLUSHED; write_unlock(&journal->j_state_lock); From 5d97ee4d8d6192e85907e5d8f4140d9cc6a587f7 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Wed, 5 Mar 2025 15:09:05 +0200 Subject: [PATCH 170/606] leds: rgb: leds-qcom-lpg: Fix pwm resolution max for Hi-Res PWMs commit b7881eacc07fdf50be3f33c662997541bb59366d upstream. Ideally, the requested duty cycle should never translate to a PWM value higher than the selected resolution (PWM size), but currently the best matched period is never reported back to the PWM consumer, so the consumer will still be using the requested period which is higher than the best matched one. This will result in PWM consumer requesting duty cycle values higher than the allowed PWM value. For example, a consumer might request a period of 5ms while the best (closest) period the PWM hardware will do is 4.26ms. For this best matched resolution, if the selected resolution is 8-bit wide, when the consumer asks for a duty cycle of 5ms, the PWM value will be 300, which is outside of what the resolution allows. This will happen with all possible resolutions when selected. Since for these Hi-Res PWMs, the current implementation is capping the PWM value at a 15-bit resolution, even when lower resolutions are selected, the value will be wrapped around by the HW internal logic to the selected resolution. Fix the issue by capping the PWM value to the maximum value allowed by the selected resolution. Cc: stable@vger.kernel.org # 6.4 Fixes: b00d2ed37617 ("leds: rgb: leds-qcom-lpg: Add support for high resolution PWM") Signed-off-by: Abel Vesa Reviewed-by: Bjorn Andersson Reviewed-by: Sebastian Reichel Link: https://lore.kernel.org/r/20250305-leds-qcom-lpg-fix-max-pwm-on-hi-res-v4-2-bfe124a53a9f@linaro.org Signed-off-by: Lee Jones Signed-off-by: Greg Kroah-Hartman --- drivers/leds/rgb/leds-qcom-lpg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c index df469aaa7e6e..2115709fca52 100644 --- a/drivers/leds/rgb/leds-qcom-lpg.c +++ b/drivers/leds/rgb/leds-qcom-lpg.c @@ -379,7 +379,7 @@ static void lpg_calc_duty(struct lpg_channel *chan, uint64_t duty) unsigned int clk_rate; if (chan->subtype == LPG_SUBTYPE_HI_RES_PWM) { - max = LPG_RESOLUTION_15BIT - 1; + max = BIT(lpg_pwm_resolution_hi_res[chan->pwm_resolution_sel]) - 1; clk_rate = lpg_clk_rates_hi_res[chan->clk_sel]; } else { max = LPG_RESOLUTION_9BIT - 1; From b20ec02fcb344bdfc77a53c381f1c9d6a87ea605 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Wed, 5 Mar 2025 15:09:06 +0200 Subject: [PATCH 171/606] leds: rgb: leds-qcom-lpg: Fix calculation of best period Hi-Res PWMs commit 2528eec7da0ec58fcae6d12cfa79a622c933d86b upstream. When determining the actual best period by looping through all possible PWM configs, the resolution currently used is based on bit shift value which is off-by-one above the possible maximum PWM value allowed. So subtract one from the resolution before determining the best period so that the maximum duty cycle requested by the PWM user won't result in a value above the maximum allowed by the selected resolution. Cc: stable@vger.kernel.org # 6.4 Fixes: b00d2ed37617 ("leds: rgb: leds-qcom-lpg: Add support for high resolution PWM") Signed-off-by: Abel Vesa Reviewed-by: Sebastian Reichel Link: https://lore.kernel.org/r/20250305-leds-qcom-lpg-fix-max-pwm-on-hi-res-v4-3-bfe124a53a9f@linaro.org Signed-off-by: Lee Jones Signed-off-by: Greg Kroah-Hartman --- drivers/leds/rgb/leds-qcom-lpg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c index 2115709fca52..a41c2b13766d 100644 --- a/drivers/leds/rgb/leds-qcom-lpg.c +++ b/drivers/leds/rgb/leds-qcom-lpg.c @@ -311,7 +311,7 @@ static int lpg_calc_freq(struct lpg_channel *chan, uint64_t period) max_res = LPG_RESOLUTION_9BIT; } - min_period = div64_u64((u64)NSEC_PER_SEC * (1 << pwm_resolution_arr[0]), + min_period = div64_u64((u64)NSEC_PER_SEC * ((1 << pwm_resolution_arr[0]) - 1), clk_rate_arr[clk_len - 1]); if (period <= min_period) return -EINVAL; @@ -332,7 +332,7 @@ static int lpg_calc_freq(struct lpg_channel *chan, uint64_t period) */ for (i = 0; i < pwm_resolution_count; i++) { - resolution = 1 << pwm_resolution_arr[i]; + resolution = (1 << pwm_resolution_arr[i]) - 1; for (clk_sel = 1; clk_sel < clk_len; clk_sel++) { u64 numerator = period * clk_rate_arr[clk_sel]; @@ -1060,7 +1060,7 @@ static int lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, if (ret) return ret; - state->period = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * (1 << resolution) * + state->period = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * ((1 << resolution) - 1) * pre_div * (1 << m), refclk); state->duty_cycle = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * pwm_value * pre_div * (1 << m), refclk); } else { From ea07760676bba49319d553af80c239da053b5fb1 Mon Sep 17 00:00:00 2001 From: Chenyuan Yang Date: Mon, 24 Feb 2025 17:37:36 -0600 Subject: [PATCH 172/606] mfd: ene-kb3930: Fix a potential NULL pointer dereference commit 4cdf1d2a816a93fa02f7b6b5492dc7f55af2a199 upstream. The off_gpios could be NULL. Add missing check in the kb3930_probe(). This is similar to the issue fixed in commit b1ba8bcb2d1f ("backlight: hx8357: Fix potential NULL pointer dereference"). This was detected by our static analysis tool. Cc: stable@vger.kernel.org Fixes: ede6b2d1dfc0 ("mfd: ene-kb3930: Add driver for ENE KB3930 Embedded Controller") Suggested-by: Lee Jones Signed-off-by: Chenyuan Yang Link: https://lore.kernel.org/r/20250224233736.1919739-1-chenyuan0y@gmail.com Signed-off-by: Lee Jones Signed-off-by: Greg Kroah-Hartman --- drivers/mfd/ene-kb3930.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/ene-kb3930.c b/drivers/mfd/ene-kb3930.c index fa0ad2f14a39..9460a67acb0b 100644 --- a/drivers/mfd/ene-kb3930.c +++ b/drivers/mfd/ene-kb3930.c @@ -162,7 +162,7 @@ static int kb3930_probe(struct i2c_client *client) devm_gpiod_get_array_optional(dev, "off", GPIOD_IN); if (IS_ERR(ddata->off_gpios)) return PTR_ERR(ddata->off_gpios); - if (ddata->off_gpios->ndescs < 2) { + if (ddata->off_gpios && ddata->off_gpios->ndescs < 2) { dev_err(dev, "invalid off-gpios property\n"); return -EINVAL; } From 388ba87816163f1a8138dab74bff70f902912400 Mon Sep 17 00:00:00 2001 From: Kartik Rajput Date: Thu, 23 Jan 2025 18:16:32 +0530 Subject: [PATCH 173/606] mailbox: tegra-hsp: Define dimensioning masks in SoC data commit bf0c9fb462038815f5f502653fb6dba06e6af415 upstream. Tegra264 has updated HSP_INT_DIMENSIONING register as follows: * nSI is now BIT17:BIT21. * nDB is now BIT12:BIT16. Currently, we are using a static macro HSP_nINT_MASK to get the values from HSP_INT_DIMENSIONING register. This results in wrong values for nSI for HSP instances that supports 16 shared interrupts. Define dimensioning masks in soc data and use them to parse nSI, nDB, nAS, nSS & nSM values. Fixes: 602dbbacc3ef ("mailbox: tegra: add support for Tegra264") Cc: stable@vger.kernel.org Signed-off-by: Kartik Rajput Acked-by: Thierry Reding Acked-by: Jon Hunter Signed-off-by: Jassi Brar Signed-off-by: Greg Kroah-Hartman --- drivers/mailbox/tegra-hsp.c | 72 ++++++++++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 12 deletions(-) diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c index 694550fdfddd..5d33cf8ec2ec 100644 --- a/drivers/mailbox/tegra-hsp.c +++ b/drivers/mailbox/tegra-hsp.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2023, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2016-2025, NVIDIA CORPORATION. All rights reserved. */ #include @@ -28,12 +28,6 @@ #define HSP_INT_FULL_MASK 0xff #define HSP_INT_DIMENSIONING 0x380 -#define HSP_nSM_SHIFT 0 -#define HSP_nSS_SHIFT 4 -#define HSP_nAS_SHIFT 8 -#define HSP_nDB_SHIFT 12 -#define HSP_nSI_SHIFT 16 -#define HSP_nINT_MASK 0xf #define HSP_DB_TRIGGER 0x0 #define HSP_DB_ENABLE 0x4 @@ -97,6 +91,20 @@ struct tegra_hsp_soc { bool has_per_mb_ie; bool has_128_bit_mb; unsigned int reg_stride; + + /* Shifts for dimensioning register. */ + unsigned int si_shift; + unsigned int db_shift; + unsigned int as_shift; + unsigned int ss_shift; + unsigned int sm_shift; + + /* Masks for dimensioning register. */ + unsigned int si_mask; + unsigned int db_mask; + unsigned int as_mask; + unsigned int ss_mask; + unsigned int sm_mask; }; struct tegra_hsp { @@ -747,11 +755,11 @@ static int tegra_hsp_probe(struct platform_device *pdev) return PTR_ERR(hsp->regs); value = tegra_hsp_readl(hsp, HSP_INT_DIMENSIONING); - hsp->num_sm = (value >> HSP_nSM_SHIFT) & HSP_nINT_MASK; - hsp->num_ss = (value >> HSP_nSS_SHIFT) & HSP_nINT_MASK; - hsp->num_as = (value >> HSP_nAS_SHIFT) & HSP_nINT_MASK; - hsp->num_db = (value >> HSP_nDB_SHIFT) & HSP_nINT_MASK; - hsp->num_si = (value >> HSP_nSI_SHIFT) & HSP_nINT_MASK; + hsp->num_sm = (value >> hsp->soc->sm_shift) & hsp->soc->sm_mask; + hsp->num_ss = (value >> hsp->soc->ss_shift) & hsp->soc->ss_mask; + hsp->num_as = (value >> hsp->soc->as_shift) & hsp->soc->as_mask; + hsp->num_db = (value >> hsp->soc->db_shift) & hsp->soc->db_mask; + hsp->num_si = (value >> hsp->soc->si_shift) & hsp->soc->si_mask; err = platform_get_irq_byname_optional(pdev, "doorbell"); if (err >= 0) @@ -917,6 +925,16 @@ static const struct tegra_hsp_soc tegra186_hsp_soc = { .has_per_mb_ie = false, .has_128_bit_mb = false, .reg_stride = 0x100, + .si_shift = 16, + .db_shift = 12, + .as_shift = 8, + .ss_shift = 4, + .sm_shift = 0, + .si_mask = 0xf, + .db_mask = 0xf, + .as_mask = 0xf, + .ss_mask = 0xf, + .sm_mask = 0xf, }; static const struct tegra_hsp_soc tegra194_hsp_soc = { @@ -924,6 +942,16 @@ static const struct tegra_hsp_soc tegra194_hsp_soc = { .has_per_mb_ie = true, .has_128_bit_mb = false, .reg_stride = 0x100, + .si_shift = 16, + .db_shift = 12, + .as_shift = 8, + .ss_shift = 4, + .sm_shift = 0, + .si_mask = 0xf, + .db_mask = 0xf, + .as_mask = 0xf, + .ss_mask = 0xf, + .sm_mask = 0xf, }; static const struct tegra_hsp_soc tegra234_hsp_soc = { @@ -931,6 +959,16 @@ static const struct tegra_hsp_soc tegra234_hsp_soc = { .has_per_mb_ie = false, .has_128_bit_mb = true, .reg_stride = 0x100, + .si_shift = 16, + .db_shift = 12, + .as_shift = 8, + .ss_shift = 4, + .sm_shift = 0, + .si_mask = 0xf, + .db_mask = 0xf, + .as_mask = 0xf, + .ss_mask = 0xf, + .sm_mask = 0xf, }; static const struct tegra_hsp_soc tegra264_hsp_soc = { @@ -938,6 +976,16 @@ static const struct tegra_hsp_soc tegra264_hsp_soc = { .has_per_mb_ie = false, .has_128_bit_mb = true, .reg_stride = 0x1000, + .si_shift = 17, + .db_shift = 12, + .as_shift = 8, + .ss_shift = 4, + .sm_shift = 0, + .si_mask = 0x1f, + .db_mask = 0x1f, + .as_mask = 0xf, + .ss_mask = 0xf, + .sm_mask = 0xf, }; static const struct of_device_id tegra_hsp_match[] = { From 8385532d4dd41befef2a235254bbb0e41407fe7c Mon Sep 17 00:00:00 2001 From: Boqun Feng Date: Wed, 26 Mar 2025 11:08:30 -0700 Subject: [PATCH 174/606] locking/lockdep: Decrease nr_unused_locks if lock unused in zap_class() commit 495f53d5cca0f939eaed9dca90b67e7e6fb0e30c upstream. Currently, when a lock class is allocated, nr_unused_locks will be increased by 1, until it gets used: nr_unused_locks will be decreased by 1 in mark_lock(). However, one scenario is missed: a lock class may be zapped without even being used once. This could result into a situation that nr_unused_locks != 0 but no unused lock class is active in the system, and when `cat /proc/lockdep_stats`, a WARN_ON() will be triggered in a CONFIG_DEBUG_LOCKDEP=y kernel: [...] DEBUG_LOCKS_WARN_ON(debug_atomic_read(nr_unused_locks) != nr_unused) [...] WARNING: CPU: 41 PID: 1121 at kernel/locking/lockdep_proc.c:283 lockdep_stats_show+0xba9/0xbd0 And as a result, lockdep will be disabled after this. Therefore, nr_unused_locks needs to be accounted correctly at zap_class() time. Signed-off-by: Boqun Feng Signed-off-by: Ingo Molnar Reviewed-by: Waiman Long Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250326180831.510348-1-boqun.feng@gmail.com Signed-off-by: Greg Kroah-Hartman --- kernel/locking/lockdep.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 3468d8230e5f..9419a79e8833 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -6141,6 +6141,9 @@ static void zap_class(struct pending_free *pf, struct lock_class *class) hlist_del_rcu(&class->hash_entry); WRITE_ONCE(class->key, NULL); WRITE_ONCE(class->name, NULL); + /* Class allocated but not used, -1 in nr_unused_locks */ + if (class->usage_mask == 0) + debug_atomic_dec(nr_unused_locks); nr_lock_classes--; __clear_bit(class - lock_classes, lock_classes_in_use); if (class - lock_classes == max_lock_class_idx) From 8ddd124f8a9e1eff0f93508d466913816e2ef199 Mon Sep 17 00:00:00 2001 From: T Pratham Date: Wed, 19 Mar 2025 16:44:38 +0530 Subject: [PATCH 175/606] lib: scatterlist: fix sg_split_phys to preserve original scatterlist offsets commit 8b46fdaea819a679da176b879e7b0674a1161a5e upstream. The split_sg_phys function was incorrectly setting the offsets of all scatterlist entries (except the first) to 0. Only the first scatterlist entry's offset and length needs to be modified to account for the skip. Setting the rest entries' offsets to 0 could lead to incorrect data access. I am using this function in a crypto driver that I'm currently developing (not yet sent to mailing list). During testing, it was observed that the output scatterlists (except the first one) contained incorrect garbage data. I narrowed this issue down to the call of sg_split(). Upon debugging inside this function, I found that this resetting of offset is the cause of the problem, causing the subsequent scatterlists to point to incorrect memory locations in a page. By removing this code, I am obtaining expected data in all the split output scatterlists. Thus, this was indeed causing observable runtime effects! This patch removes the offending code, ensuring that the page offsets in the input scatterlist are preserved in the output scatterlist. Link: https://lkml.kernel.org/r/20250319111437.1969903-1-t-pratham@ti.com Fixes: f8bcbe62acd0 ("lib: scatterlist: add sg splitting function") Signed-off-by: T Pratham Cc: Robert Jarzmik Cc: Jens Axboe Cc: Kamlesh Gurudasani Cc: Praneeth Bajjuri Cc: Vignesh Raghavendra Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- lib/sg_split.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/sg_split.c b/lib/sg_split.c index 60a0babebf2e..0f89aab5c671 100644 --- a/lib/sg_split.c +++ b/lib/sg_split.c @@ -88,8 +88,6 @@ static void sg_split_phys(struct sg_splitter *splitters, const int nb_splits) if (!j) { out_sg->offset += split->skip_sg0; out_sg->length -= split->skip_sg0; - } else { - out_sg->offset = 0; } sg_dma_address(out_sg) = 0; sg_dma_len(out_sg) = 0; From 7f9ae060ed64aef8f174c5f1ea513825b1be9af1 Mon Sep 17 00:00:00 2001 From: Gang Yan Date: Fri, 28 Mar 2025 15:27:16 +0100 Subject: [PATCH 176/606] mptcp: fix NULL pointer in can_accept_new_subflow commit 443041deb5ef6a1289a99ed95015ec7442f141dc upstream. When testing valkey benchmark tool with MPTCP, the kernel panics in 'mptcp_can_accept_new_subflow' because subflow_req->msk is NULL. Call trace: mptcp_can_accept_new_subflow (./net/mptcp/subflow.c:63 (discriminator 4)) (P) subflow_syn_recv_sock (./net/mptcp/subflow.c:854) tcp_check_req (./net/ipv4/tcp_minisocks.c:863) tcp_v4_rcv (./net/ipv4/tcp_ipv4.c:2268) ip_protocol_deliver_rcu (./net/ipv4/ip_input.c:207) ip_local_deliver_finish (./net/ipv4/ip_input.c:234) ip_local_deliver (./net/ipv4/ip_input.c:254) ip_rcv_finish (./net/ipv4/ip_input.c:449) ... According to the debug log, the same req received two SYN-ACK in a very short time, very likely because the client retransmits the syn ack due to multiple reasons. Even if the packets are transmitted with a relevant time interval, they can be processed by the server on different CPUs concurrently). The 'subflow_req->msk' ownership is transferred to the subflow the first, and there will be a risk of a null pointer dereference here. This patch fixes this issue by moving the 'subflow_req->msk' under the `own_req == true` conditional. Note that the !msk check in subflow_hmac_valid() can be dropped, because the same check already exists under the own_req mpj branch where the code has been moved to. Fixes: 9466a1ccebbe ("mptcp: enable JOIN requests even if cookies are in use") Cc: stable@vger.kernel.org Suggested-by: Paolo Abeni Signed-off-by: Gang Yan Reviewed-by: Matthieu Baerts (NGI0) Signed-off-by: Matthieu Baerts (NGI0) Link: https://patch.msgid.link/20250328-net-mptcp-misc-fixes-6-15-v1-1-34161a482a7f@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- net/mptcp/subflow.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index b3eeeb948b61..2dfaf93008a9 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -731,8 +731,6 @@ static bool subflow_hmac_valid(const struct request_sock *req, subflow_req = mptcp_subflow_rsk(req); msk = subflow_req->msk; - if (!msk) - return false; subflow_generate_hmac(msk->remote_key, msk->local_key, subflow_req->remote_nonce, @@ -828,12 +826,8 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, } else if (subflow_req->mp_join) { mptcp_get_options(skb, &mp_opt); - if (!(mp_opt.suboptions & OPTION_MPTCP_MPJ_ACK) || - !subflow_hmac_valid(req, &mp_opt) || - !mptcp_can_accept_new_subflow(subflow_req->msk)) { - SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC); + if (!(mp_opt.suboptions & OPTION_MPTCP_MPJ_ACK)) fallback = true; - } } create_child: @@ -883,6 +877,13 @@ create_child: goto dispose_child; } + if (!subflow_hmac_valid(req, &mp_opt) || + !mptcp_can_accept_new_subflow(subflow_req->msk)) { + SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC); + subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT); + goto dispose_child; + } + /* move the msk reference ownership to the subflow */ subflow_req->msk = NULL; ctx->conn = (struct sock *)owner; From 29b21145721a6431b77728b59088f111aa9d1608 Mon Sep 17 00:00:00 2001 From: "Matthieu Baerts (NGI0)" Date: Mon, 7 Apr 2025 20:26:32 +0200 Subject: [PATCH 177/606] mptcp: only inc MPJoinAckHMacFailure for HMAC failures commit 21c02e8272bc95ba0dd44943665c669029b42760 upstream. Recently, during a debugging session using local MPTCP connections, I noticed MPJoinAckHMacFailure was not zero on the server side. The counter was in fact incremented when the PM rejected new subflows, because the 'subflow' limit was reached. The fix is easy, simply dissociating the two cases: only the HMAC validation check should increase MPTCP_MIB_JOINACKMAC counter. Fixes: 4cf8b7e48a09 ("subflow: introduce and use mptcp_can_accept_new_subflow()") Cc: stable@vger.kernel.org Reviewed-by: Geliang Tang Signed-off-by: Matthieu Baerts (NGI0) Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250407-net-mptcp-hmac-failure-mib-v1-1-3c9ecd0a3a50@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- net/mptcp/subflow.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 2dfaf93008a9..f4b8ca8be81e 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -877,13 +877,17 @@ create_child: goto dispose_child; } - if (!subflow_hmac_valid(req, &mp_opt) || - !mptcp_can_accept_new_subflow(subflow_req->msk)) { + if (!subflow_hmac_valid(req, &mp_opt)) { SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC); subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT); goto dispose_child; } + if (!mptcp_can_accept_new_subflow(owner)) { + subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT); + goto dispose_child; + } + /* move the msk reference ownership to the subflow */ subflow_req->msk = NULL; ctx->conn = (struct sock *)owner; From 7772621041ee78823ccc5f1fe38f6faa22af7023 Mon Sep 17 00:00:00 2001 From: Wentao Liang Date: Wed, 2 Apr 2025 11:16:43 +0800 Subject: [PATCH 178/606] mtd: inftlcore: Add error check for inftl_read_oob() commit d027951dc85cb2e15924c980dc22a6754d100c7c upstream. In INFTL_findwriteunit(), the return value of inftl_read_oob() need to be checked. A proper implementation can be found in INFTL_deleteblock(). The status will be set as SECTOR_IGNORE to break from the while-loop correctly if the inftl_read_oob() fails. Fixes: 8593fbc68b0d ("[MTD] Rework the out of band handling completely") Cc: stable@vger.kernel.org # v2.6+ Signed-off-by: Wentao Liang Signed-off-by: Miquel Raynal Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/inftlcore.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index 9739387cff8c..58c6e1743f5c 100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c @@ -482,10 +482,11 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block) silly = MAX_LOOPS; while (thisEUN <= inftl->lastEUN) { - inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) + - blockofs, 8, &retlen, (char *)&bci); - - status = bci.Status | bci.Status1; + if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) + + blockofs, 8, &retlen, (char *)&bci) < 0) + status = SECTOR_IGNORE; + else + status = bci.Status | bci.Status1; pr_debug("INFTL: status of block %d in EUN %d is %x\n", block , writeEUN, status); From bfbbef7f1d3845f98db9405d44bc2965bd2c85fe Mon Sep 17 00:00:00 2001 From: Wentao Liang Date: Wed, 2 Apr 2025 15:56:23 +0800 Subject: [PATCH 179/606] mtd: rawnand: Add status chack in r852_ready() commit b79fe1829975556854665258cf4d2476784a89db upstream. In r852_ready(), the dev get from r852_get_dev() need to be checked. An unstable device should not be ready. A proper implementation can be found in r852_read_byte(). Add a status check and return 0 when it is unstable. Fixes: 50a487e7719c ("mtd: rawnand: Pass a nand_chip object to chip->dev_ready()") Cc: stable@vger.kernel.org # v4.20+ Signed-off-by: Wentao Liang Signed-off-by: Miquel Raynal Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/raw/r852.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c index ed0cf732d20e..36cfe03cd4ac 100644 --- a/drivers/mtd/nand/raw/r852.c +++ b/drivers/mtd/nand/raw/r852.c @@ -387,6 +387,9 @@ static int r852_wait(struct nand_chip *chip) static int r852_ready(struct nand_chip *chip) { struct r852_device *dev = r852_get_dev(nand_to_mtd(chip)); + if (dev->card_unstable) + return 0; + return !(r852_read_reg(dev, R852_CARD_STA) & R852_CARD_STA_BUSY); } From 8db1206d834b90105422e8c992158b3a632f8d5d Mon Sep 17 00:00:00 2001 From: Zhenhua Huang Date: Fri, 21 Mar 2025 15:00:19 +0800 Subject: [PATCH 180/606] arm64: mm: Correct the update of max_pfn commit 89f43e1ce6f60d4f44399059595ac47f7a90a393 upstream. Hotplugged memory can be smaller than the original memory. For example, on my target: root@genericarmv8:~# cat /sys/kernel/debug/memblock/memory 0: 0x0000000064005000..0x0000000064023fff 0 NOMAP 1: 0x0000000064400000..0x00000000647fffff 0 NOMAP 2: 0x0000000068000000..0x000000006fffffff 0 DRV_MNG 3: 0x0000000088800000..0x0000000094ffefff 0 NONE 4: 0x0000000094fff000..0x0000000094ffffff 0 NOMAP max_pfn will affect read_page_owner. Therefore, it should first compare and then select the larger value for max_pfn. Fixes: 8fac67ca236b ("arm64: mm: update max_pfn after memory hotplug") Cc: # 6.1.x Signed-off-by: Zhenhua Huang Acked-by: David Hildenbrand Reviewed-by: Anshuman Khandual Link: https://lore.kernel.org/r/20250321070019.1271859-1-quic_zhenhuah@quicinc.com Signed-off-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- arch/arm64/mm/mmu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 38f3fe2e6bf6..bc97916a035a 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -1328,7 +1328,8 @@ int arch_add_memory(int nid, u64 start, u64 size, __remove_pgd_mapping(swapper_pg_dir, __phys_to_virt(start), size); else { - max_pfn = PFN_UP(start + size); + /* Address of hotplugged memory can be smaller */ + max_pfn = max(max_pfn, PFN_UP(start + size)); max_low_pfn = max_pfn; } From c8fa7ffc1c23b889b8f12dedb6e1600f9a564878 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 8 Jan 2025 16:34:22 +0800 Subject: [PATCH 181/606] arm64: dts: mediatek: mt8173: Fix disp-pwm compatible string commit 46ad36002088eff8fc5cae200aa42ae9f9310ddd upstream. The MT8173 disp-pwm device should have only one compatible string, based on the following DT validation error: arch/arm64/boot/dts/mediatek/mt8173-elm.dtb: pwm@1401e000: compatible: 'oneOf' conditional failed, one must be fixed: ['mediatek,mt8173-disp-pwm', 'mediatek,mt6595-disp-pwm'] is too long 'mediatek,mt8173-disp-pwm' is not one of ['mediatek,mt6795-disp-pwm', 'mediatek,mt8167-disp-pwm'] 'mediatek,mt8173-disp-pwm' is not one of ['mediatek,mt8186-disp-pwm', 'mediatek,mt8188-disp-pwm', 'mediatek,mt8192-disp-pwm', 'mediatek,mt8195-disp-pwm', 'mediatek,mt8365-disp-pwm'] 'mediatek,mt8173-disp-pwm' was expected 'mediatek,mt8183-disp-pwm' was expected from schema $id: http://devicetree.org/schemas/pwm/mediatek,pwm-disp.yaml# arch/arm64/boot/dts/mediatek/mt8173-elm.dtb: pwm@1401f000: compatible: 'oneOf' conditional failed, one must be fixed: ['mediatek,mt8173-disp-pwm', 'mediatek,mt6595-disp-pwm'] is too long 'mediatek,mt8173-disp-pwm' is not one of ['mediatek,mt6795-disp-pwm', 'mediatek,mt8167-disp-pwm'] 'mediatek,mt8173-disp-pwm' is not one of ['mediatek,mt8186-disp-pwm', 'mediatek,mt8188-disp-pwm', 'mediatek,mt8192-disp-pwm', 'mediatek,mt8195-disp-pwm', 'mediatek,mt8365-disp-pwm'] 'mediatek,mt8173-disp-pwm' was expected 'mediatek,mt8183-disp-pwm' was expected from schema $id: http://devicetree.org/schemas/pwm/mediatek,pwm-disp.yaml# Drop the extra "mediatek,mt6595-disp-pwm" compatible string. Fixes: 61aee9342514 ("arm64: dts: mt8173: add MT8173 display PWM driver support node") Cc: YH Huang Cc: stable@vger.kernel.org # v4.5+ Signed-off-by: Chen-Yu Tsai Reviewed-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20250108083424.2732375-2-wenst@chromium.org Signed-off-by: AngeloGioacchino Del Regno Signed-off-by: Greg Kroah-Hartman --- arch/arm64/boot/dts/mediatek/mt8173.dtsi | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index c47d7d900f28..0582d75349ba 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -1246,8 +1246,7 @@ }; pwm0: pwm@1401e000 { - compatible = "mediatek,mt8173-disp-pwm", - "mediatek,mt6595-disp-pwm"; + compatible = "mediatek,mt8173-disp-pwm"; reg = <0 0x1401e000 0 0x1000>; #pwm-cells = <2>; clocks = <&mmsys CLK_MM_DISP_PWM026M>, @@ -1257,8 +1256,7 @@ }; pwm1: pwm@1401f000 { - compatible = "mediatek,mt8173-disp-pwm", - "mediatek,mt6595-disp-pwm"; + compatible = "mediatek,mt8173-disp-pwm"; reg = <0 0x1401f000 0 0x1000>; #pwm-cells = <2>; clocks = <&mmsys CLK_MM_DISP_PWM126M>, From 1c82f5a393d8b9a5c1ea032413719862098afd4b Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Wed, 22 Jan 2025 10:19:14 +0100 Subject: [PATCH 182/606] backlight: led_bl: Hold led_access lock when calling led_sysfs_disable() commit 276822a00db3c1061382b41e72cafc09d6a0ec30 upstream. Lockdep detects the following issue on led-backlight removal: [ 142.315935] ------------[ cut here ]------------ [ 142.315954] WARNING: CPU: 2 PID: 292 at drivers/leds/led-core.c:455 led_sysfs_enable+0x54/0x80 ... [ 142.500725] Call trace: [ 142.503176] led_sysfs_enable+0x54/0x80 (P) [ 142.507370] led_bl_remove+0x80/0xa8 [led_bl] [ 142.511742] platform_remove+0x30/0x58 [ 142.515501] device_remove+0x54/0x90 ... Indeed, led_sysfs_enable() has to be called with the led_access lock held. Hold the lock when calling led_sysfs_disable(). Fixes: ae232e45acf9 ("backlight: add led-backlight driver") Cc: stable@vger.kernel.org Signed-off-by: Herve Codina Link: https://lore.kernel.org/r/20250122091914.309533-1-herve.codina@bootlin.com Signed-off-by: Lee Jones Signed-off-by: Greg Kroah-Hartman --- drivers/video/backlight/led_bl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/video/backlight/led_bl.c b/drivers/video/backlight/led_bl.c index 032f8bddf872..0e53e427a91d 100644 --- a/drivers/video/backlight/led_bl.c +++ b/drivers/video/backlight/led_bl.c @@ -229,8 +229,11 @@ static void led_bl_remove(struct platform_device *pdev) backlight_device_unregister(bl); led_bl_power_off(priv); - for (i = 0; i < priv->nb_leds; i++) + for (i = 0; i < priv->nb_leds; i++) { + mutex_lock(&priv->leds[i]->led_access); led_sysfs_enable(priv->leds[i]); + mutex_unlock(&priv->leds[i]->led_access); + } } static const struct of_device_id led_bl_of_match[] = { From 897ad7f70dd7d8e9dc3277b52c15b88284e2f90d Mon Sep 17 00:00:00 2001 From: Filipe Manana Date: Wed, 5 Mar 2025 16:52:26 +0000 Subject: [PATCH 183/606] btrfs: fix non-empty delayed iputs list on unmount due to compressed write workers commit 4c782247b89376a83fa132f7d45d6977edae0629 upstream. At close_ctree() after we have ran delayed iputs either through explicitly calling btrfs_run_delayed_iputs() or later during the call to btrfs_commit_super() or btrfs_error_commit_super(), we assert that the delayed iputs list is empty. When we have compressed writes this assertion may fail because delayed iputs may have been added to the list after we last ran delayed iputs. This happens like this: 1) We have a compressed write bio executing; 2) We enter close_ctree() and flush the fs_info->endio_write_workers queue which is the queue used for running ordered extent completion; 3) The compressed write bio finishes and enters btrfs_finish_compressed_write_work(), where it calls btrfs_finish_ordered_extent() which in turn calls btrfs_queue_ordered_fn(), which queues a work item in the fs_info->endio_write_workers queue that we have flushed before; 4) At close_ctree() we proceed, run all existing delayed iputs and call btrfs_commit_super() (which also runs delayed iputs), but before we run the following assertion below: ASSERT(list_empty(&fs_info->delayed_iputs)) A delayed iput is added by the step below... 5) The ordered extent completion job queued in step 3 runs and results in creating a delayed iput when dropping the last reference of the ordered extent (a call to btrfs_put_ordered_extent() made from btrfs_finish_one_ordered()); 6) At this point the delayed iputs list is not empty, so the assertion at close_ctree() fails. Fix this by flushing the fs_info->compressed_write_workers queue at close_ctree() before flushing the fs_info->endio_write_workers queue, respecting the queue dependency as the later is responsible for the execution of ordered extent completion. CC: stable@vger.kernel.org # 5.15+ Reviewed-by: Qu Wenruo Signed-off-by: Filipe Manana Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/disk-io.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 967c6b5dd0a4..2387210231f2 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -4333,6 +4333,18 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info) */ btrfs_flush_workqueue(fs_info->delalloc_workers); + /* + * When finishing a compressed write bio we schedule a work queue item + * to finish an ordered extent - btrfs_finish_compressed_write_work() + * calls btrfs_finish_ordered_extent() which in turns does a call to + * btrfs_queue_ordered_fn(), and that queues the ordered extent + * completion either in the endio_write_workers work queue or in the + * fs_info->endio_freespace_worker work queue. We flush those queues + * below, so before we flush them we must flush this queue for the + * workers of compressed writes. + */ + flush_workqueue(fs_info->compressed_write_workers); + /* * After we parked the cleaner kthread, ordered extents may have * completed and created new delayed iputs. If one of the async reclaim From fa55f2a31ba234dc58e9fd8215b0221fbf0b9f57 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Mon, 17 Mar 2025 12:24:58 +0100 Subject: [PATCH 184/606] btrfs: zoned: fix zone activation with missing devices commit 2bbc4a45e5eb6b868357c1045bf6f38f6ba576e0 upstream. If btrfs_zone_activate() is called with a filesystem that has missing devices (e.g. a RAID file system mounted in degraded mode) it is accessing the btrfs_device::zone_info pointer, which will not be set if the device in question is missing. Check if the device is present (by checking if it has a valid block device pointer associated) and if not, skip zone activation for it. Fixes: f9a912a3c45f ("btrfs: zoned: make zone activation multi stripe capable") CC: stable@vger.kernel.org # 6.1+ Reviewed-by: Naohiro Aota Reviewed-by: Anand Jain Signed-off-by: Johannes Thumshirn Reviewed-by: David Sterba Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/zoned.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c index c4463c3f2068..f2662ffcb72c 100644 --- a/fs/btrfs/zoned.c +++ b/fs/btrfs/zoned.c @@ -2006,6 +2006,9 @@ bool btrfs_zone_activate(struct btrfs_block_group *block_group) physical = map->stripes[i].physical; zinfo = device->zone_info; + if (!device->bdev) + continue; + if (zinfo->max_active_zones == 0) continue; From e921fce3a295f356299ef0aebb27bc8ce9a3e2dc Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Mon, 17 Mar 2025 12:24:59 +0100 Subject: [PATCH 185/606] btrfs: zoned: fix zone finishing with missing devices commit 35fec1089ebb5617f85884d3fa6a699ce6337a75 upstream. If do_zone_finish() is called with a filesystem that has missing devices (e.g. a RAID file system mounted in degraded mode) it is accessing the btrfs_device::zone_info pointer, which will not be set if the device in question is missing. Check if the device is present (by checking if it has a valid block device pointer associated) and if not, skip zone finishing for it. Fixes: 4dcbb8ab31c1 ("btrfs: zoned: make zone finishing multi stripe capable") CC: stable@vger.kernel.org # 6.1+ Reviewed-by: Naohiro Aota Reviewed-by: Anand Jain Signed-off-by: Johannes Thumshirn Reviewed-by: David Sterba Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/zoned.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c index f2662ffcb72c..197dfafbf401 100644 --- a/fs/btrfs/zoned.c +++ b/fs/btrfs/zoned.c @@ -2168,6 +2168,9 @@ static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_writ const u64 physical = map->stripes[i].physical; struct btrfs_zoned_device_info *zinfo = device->zone_info; + if (!device->bdev) + continue; + if (zinfo->max_active_zones == 0) continue; From e02c44b6ecfd096a1bc4656a016a0b26186806f8 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Thu, 27 Feb 2025 12:07:29 -0800 Subject: [PATCH 186/606] iommufd: Fix uninitialized rc in iommufd_access_rw() commit a05df03a88bc1088be8e9d958f208d6484691e43 upstream. Reported by smatch: drivers/iommu/iommufd/device.c:1392 iommufd_access_rw() error: uninitialized symbol 'rc'. Fixes: 8d40205f6093 ("iommufd: Add kAPI toward external drivers for kernel access") Link: https://patch.msgid.link/r/20250227200729.85030-1-nicolinc@nvidia.com Cc: stable@vger.kernel.org Reported-by: kernel test robot Reported-by: Dan Carpenter Closes: https://lore.kernel.org/r/202502271339.a2nWr9UA-lkp@intel.com/ [nicolinc: can't find an original report but only in "old smatch warnings"] Signed-off-by: Nicolin Chen Signed-off-by: Jason Gunthorpe Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/iommufd/device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c index ce78c3671539..cf76a0eeeded 100644 --- a/drivers/iommu/iommufd/device.c +++ b/drivers/iommu/iommufd/device.c @@ -1076,7 +1076,7 @@ int iommufd_access_rw(struct iommufd_access *access, unsigned long iova, struct io_pagetable *iopt; struct iopt_area *area; unsigned long last_iova; - int rc; + int rc = -EINVAL; if (!length) return -EINVAL; From b266dd4d2256c95db2f45a40cea414baebe4b748 Mon Sep 17 00:00:00 2001 From: Ryan Roberts Date: Mon, 3 Mar 2025 14:15:37 +0000 Subject: [PATCH 187/606] sparc/mm: disable preemption in lazy mmu mode commit a1d416bf9faf4f4871cb5a943614a07f80a7d70f upstream. Since commit 38e0edb15bd0 ("mm/apply_to_range: call pte function with lazy updates") it's been possible for arch_[enter|leave]_lazy_mmu_mode() to be called without holding a page table lock (for the kernel mappings case), and therefore it is possible that preemption may occur while in the lazy mmu mode. The Sparc lazy mmu implementation is not robust to preemption since it stores the lazy mode state in a per-cpu structure and does not attempt to manage that state on task switch. Powerpc had the same issue and fixed it by explicitly disabling preemption in arch_enter_lazy_mmu_mode() and re-enabling in arch_leave_lazy_mmu_mode(). See commit b9ef323ea168 ("powerpc/64s: Disable preemption in hash lazy mmu mode"). Given Sparc's lazy mmu mode is based on powerpc's, let's fix it in the same way here. Link: https://lkml.kernel.org/r/20250303141542.3371656-4-ryan.roberts@arm.com Fixes: 38e0edb15bd0 ("mm/apply_to_range: call pte function with lazy updates") Signed-off-by: Ryan Roberts Acked-by: David Hildenbrand Acked-by: Andreas Larsson Acked-by: Juergen Gross Cc: Borislav Betkov Cc: Boris Ostrovsky Cc: Catalin Marinas Cc: Dave Hansen Cc: David S. Miller Cc: "H. Peter Anvin" Cc: Ingo Molnar Cc: Juegren Gross Cc: Matthew Wilcow (Oracle) Cc: Thomas Gleinxer Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- arch/sparc/mm/tlb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c index ef69127d7e5e..148e1c85abb2 100644 --- a/arch/sparc/mm/tlb.c +++ b/arch/sparc/mm/tlb.c @@ -52,8 +52,10 @@ out: void arch_enter_lazy_mmu_mode(void) { - struct tlb_batch *tb = this_cpu_ptr(&tlb_batch); + struct tlb_batch *tb; + preempt_disable(); + tb = this_cpu_ptr(&tlb_batch); tb->active = 1; } @@ -64,6 +66,7 @@ void arch_leave_lazy_mmu_mode(void) if (tb->tlb_nr) flush_tlb_pending(); tb->active = 0; + preempt_enable(); } static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr, From 70ec7d13bbd478a2d9cc6502516c3a36cbff7e28 Mon Sep 17 00:00:00 2001 From: Ryan Roberts Date: Mon, 3 Mar 2025 14:15:38 +0000 Subject: [PATCH 188/606] sparc/mm: avoid calling arch_enter/leave_lazy_mmu() in set_ptes commit eb61ad14c459b54f71f76331ca35d12fa3eb8f98 upstream. With commit 1a10a44dfc1d ("sparc64: implement the new page table range API") set_ptes was added to the sparc architecture. The implementation included calling arch_enter/leave_lazy_mmu() calls. The patch removes the usage of arch_enter/leave_lazy_mmu() since this implies nesting of lazy mmu regions which is not supported. Without this fix, lazy mmu mode is effectively disabled because we exit the mode after the first set_ptes: remap_pte_range() -> arch_enter_lazy_mmu() -> set_ptes() -> arch_enter_lazy_mmu() -> arch_leave_lazy_mmu() -> arch_leave_lazy_mmu() Powerpc suffered the same problem and fixed it in a corresponding way with commit 47b8def9358c ("powerpc/mm: Avoid calling arch_enter/leave_lazy_mmu() in set_ptes"). Link: https://lkml.kernel.org/r/20250303141542.3371656-5-ryan.roberts@arm.com Fixes: 1a10a44dfc1d ("sparc64: implement the new page table range API") Signed-off-by: Ryan Roberts Acked-by: David Hildenbrand Acked-by: Andreas Larsson Acked-by: Juergen Gross Cc: Borislav Betkov Cc: Boris Ostrovsky Cc: Catalin Marinas Cc: Dave Hansen Cc: David S. Miller Cc: "H. Peter Anvin" Cc: Ingo Molnar Cc: Juegren Gross Cc: Matthew Wilcow (Oracle) Cc: Thomas Gleinxer Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- arch/sparc/include/asm/pgtable_64.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index 5e41033bf4ca..01aaee703c6c 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h @@ -931,7 +931,6 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, static inline void set_ptes(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte, unsigned int nr) { - arch_enter_lazy_mmu_mode(); for (;;) { __set_pte_at(mm, addr, ptep, pte, 0); if (--nr == 0) @@ -940,7 +939,6 @@ static inline void set_ptes(struct mm_struct *mm, unsigned long addr, pte_val(pte) += PAGE_SIZE; addr += PAGE_SIZE; } - arch_leave_lazy_mmu_mode(); } #define set_ptes set_ptes From e09661ac0b84b81be4e326fa940d2096f8360d52 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Mon, 10 Feb 2025 20:37:44 +0100 Subject: [PATCH 189/606] mm/rmap: reject hugetlb folios in folio_make_device_exclusive() commit bc3fe6805cf09a25a086573a17d40e525208c5d8 upstream. Even though FOLL_SPLIT_PMD on hugetlb now always fails with -EOPNOTSUPP, let's add a safety net in case FOLL_SPLIT_PMD usage would ever be reworked. In particular, before commit 9cb28da54643 ("mm/gup: handle hugetlb in the generic follow_page_mask code"), GUP(FOLL_SPLIT_PMD) would just have returned a page. In particular, hugetlb folios that are not PMD-sized would never have been prone to FOLL_SPLIT_PMD. hugetlb folios can be anonymous, and page_make_device_exclusive_one() is not really prepared for handling them at all. So let's spell that out. Link: https://lkml.kernel.org/r/20250210193801.781278-3-david@redhat.com Fixes: b756a3b5e7ea ("mm: device exclusive memory access") Signed-off-by: David Hildenbrand Reviewed-by: Alistair Popple Tested-by: Alistair Popple Cc: Alex Shi Cc: Danilo Krummrich Cc: Dave Airlie Cc: Jann Horn Cc: Jason Gunthorpe Cc: Jerome Glisse Cc: John Hubbard Cc: Jonathan Corbet Cc: Karol Herbst Cc: Liam Howlett Cc: Lorenzo Stoakes Cc: Lyude Cc: "Masami Hiramatsu (Google)" Cc: Oleg Nesterov Cc: Pasha Tatashin Cc: Peter Xu Cc: Peter Zijlstra (Intel) Cc: SeongJae Park Cc: Simona Vetter Cc: Vlastimil Babka Cc: Yanteng Si Cc: Barry Song Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- mm/rmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/rmap.c b/mm/rmap.c index 9f795b93cf40..968b85a67b1a 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -2296,7 +2296,7 @@ static bool folio_make_device_exclusive(struct folio *folio, * Restrict to anonymous folios for now to avoid potential writeback * issues. */ - if (!folio_test_anon(folio)) + if (!folio_test_anon(folio) || folio_test_hugetlb(folio)) return false; rmap_walk(folio, &rwc); From 402769cde5ebac6b0db6b0d6be79b16bc751b297 Mon Sep 17 00:00:00 2001 From: Jane Chu Date: Mon, 24 Feb 2025 14:14:45 -0700 Subject: [PATCH 190/606] mm: make page_mapped_in_vma() hugetlb walk aware commit 442b1eca223b4860cc85ef970ae602d125aec5a4 upstream. When a process consumes a UE in a page, the memory failure handler attempts to collect information for a potential SIGBUS. If the page is an anonymous page, page_mapped_in_vma(page, vma) is invoked in order to 1. retrieve the vaddr from the process' address space, 2. verify that the vaddr is indeed mapped to the poisoned page, where 'page' is the precise small page with UE. It's been observed that when injecting poison to a non-head subpage of an anonymous hugetlb page, no SIGBUS shows up, while injecting to the head page produces a SIGBUS. The cause is that, though hugetlb_walk() returns a valid pmd entry (on x86), but check_pte() detects mismatch between the head page per the pmd and the input subpage. Thus the vaddr is considered not mapped to the subpage and the process is not collected for SIGBUS purpose. This is the calling stack: collect_procs_anon page_mapped_in_vma page_vma_mapped_walk hugetlb_walk huge_pte_lock check_pte check_pte() header says that it "check if [pvmw->pfn, @pvmw->pfn + @pvmw->nr_pages) is mapped at the @pvmw->pte" but practically works only if pvmw->pfn is the head page pfn at pvmw->pte. Hindsight acknowledging that some pvmw->pte could point to a hugepage of some sort such that it makes sense to make check_pte() work for hugepage. Link: https://lkml.kernel.org/r/20250224211445.2663312-1-jane.chu@oracle.com Signed-off-by: Jane Chu Cc: Hugh Dickins Cc: Kirill A. Shuemov Cc: linmiaohe Cc: Matthew Wilcow (Oracle) Cc: Peter Xu Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- mm/page_vma_mapped.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/mm/page_vma_mapped.c b/mm/page_vma_mapped.c index e0b368e545ed..dcc1ee3d059e 100644 --- a/mm/page_vma_mapped.c +++ b/mm/page_vma_mapped.c @@ -77,6 +77,7 @@ static bool map_pte(struct page_vma_mapped_walk *pvmw, spinlock_t **ptlp) * mapped at the @pvmw->pte * @pvmw: page_vma_mapped_walk struct, includes a pair pte and pfn range * for checking + * @pte_nr: the number of small pages described by @pvmw->pte. * * page_vma_mapped_walk() found a place where pfn range is *potentially* * mapped. check_pte() has to validate this. @@ -93,7 +94,7 @@ static bool map_pte(struct page_vma_mapped_walk *pvmw, spinlock_t **ptlp) * Otherwise, return false. * */ -static bool check_pte(struct page_vma_mapped_walk *pvmw) +static bool check_pte(struct page_vma_mapped_walk *pvmw, unsigned long pte_nr) { unsigned long pfn; pte_t ptent = ptep_get(pvmw->pte); @@ -126,7 +127,11 @@ static bool check_pte(struct page_vma_mapped_walk *pvmw) pfn = pte_pfn(ptent); } - return (pfn - pvmw->pfn) < pvmw->nr_pages; + if ((pfn + pte_nr - 1) < pvmw->pfn) + return false; + if (pfn > (pvmw->pfn + pvmw->nr_pages - 1)) + return false; + return true; } /* Returns true if the two ranges overlap. Careful to not overflow. */ @@ -201,7 +206,7 @@ bool page_vma_mapped_walk(struct page_vma_mapped_walk *pvmw) return false; pvmw->ptl = huge_pte_lock(hstate, mm, pvmw->pte); - if (!check_pte(pvmw)) + if (!check_pte(pvmw, pages_per_huge_page(hstate))) return not_found(pvmw); return true; } @@ -283,7 +288,7 @@ restart: goto next_pte; } this_pte: - if (check_pte(pvmw)) + if (check_pte(pvmw, 1)) return true; next_pte: do { From f4bc11b3c55fa0aa73f94880931aae03daeab1a6 Mon Sep 17 00:00:00 2001 From: Ryan Roberts Date: Mon, 3 Mar 2025 14:15:35 +0000 Subject: [PATCH 191/606] mm: fix lazy mmu docs and usage commit 691ee97e1a9de0cdb3efb893c1f180e3f4a35e32 upstream. Patch series "Fix lazy mmu mode", v2. I'm planning to implement lazy mmu mode for arm64 to optimize vmalloc. As part of that, I will extend lazy mmu mode to cover kernel mappings in vmalloc table walkers. While lazy mmu mode is already used for kernel mappings in a few places, this will extend it's use significantly. Having reviewed the existing lazy mmu implementations in powerpc, sparc and x86, it looks like there are a bunch of bugs, some of which may be more likely to trigger once I extend the use of lazy mmu. So this series attempts to clarify the requirements and fix all the bugs in advance of that series. See patch #1 commit log for all the details. This patch (of 5): The docs, implementations and use of arch_[enter|leave]_lazy_mmu_mode() is a bit of a mess (to put it politely). There are a number of issues related to nesting of lazy mmu regions and confusion over whether the task, when in a lazy mmu region, is preemptible or not. Fix all the issues relating to the core-mm. Follow up commits will fix the arch-specific implementations. 3 arches implement lazy mmu; powerpc, sparc and x86. When arch_[enter|leave]_lazy_mmu_mode() was first introduced by commit 6606c3e0da53 ("[PATCH] paravirt: lazy mmu mode hooks.patch"), it was expected that lazy mmu regions would never nest and that the appropriate page table lock(s) would be held while in the region, thus ensuring the region is non-preemptible. Additionally lazy mmu regions were only used during manipulation of user mappings. Commit 38e0edb15bd0 ("mm/apply_to_range: call pte function with lazy updates") started invoking the lazy mmu mode in apply_to_pte_range(), which is used for both user and kernel mappings. For kernel mappings the region is no longer protected by any lock so there is no longer any guarantee about non-preemptibility. Additionally, for RT configs, the holding the PTL only implies no CPU migration, it doesn't prevent preemption. Commit bcc6cc832573 ("mm: add default definition of set_ptes()") added arch_[enter|leave]_lazy_mmu_mode() to the default implementation of set_ptes(), used by x86. So after this commit, lazy mmu regions can be nested. Additionally commit 1a10a44dfc1d ("sparc64: implement the new page table range API") and commit 9fee28baa601 ("powerpc: implement the new page table range API") did the same for the sparc and powerpc set_ptes() overrides. powerpc couldn't deal with preemption so avoids it in commit b9ef323ea168 ("powerpc/64s: Disable preemption in hash lazy mmu mode"), which explicitly disables preemption for the whole region in its implementation. x86 can support preemption (or at least it could until it tried to add support nesting; more on this below). Sparc looks to be totally broken in the face of preemption, as far as I can tell. powerpc can't deal with nesting, so avoids it in commit 47b8def9358c ("powerpc/mm: Avoid calling arch_enter/leave_lazy_mmu() in set_ptes"), which removes the lazy mmu calls from its implementation of set_ptes(). x86 attempted to support nesting in commit 49147beb0ccb ("x86/xen: allow nesting of same lazy mode") but as far as I can tell, this breaks its support for preemption. In short, it's all a mess; the semantics for arch_[enter|leave]_lazy_mmu_mode() are not clearly defined and as a result the implementations all have different expectations, sticking plasters and bugs. arm64 is aiming to start using these hooks, so let's clean everything up before adding an arm64 implementation. Update the documentation to state that lazy mmu regions can never be nested, must not be called in interrupt context and preemption may or may not be enabled for the duration of the region. And fix the generic implementation of set_ptes() to avoid nesting. arch-specific fixes to conform to the new spec will proceed this one. These issues were spotted by code review and I have no evidence of issues being reported in the wild. Link: https://lkml.kernel.org/r/20250303141542.3371656-1-ryan.roberts@arm.com Link: https://lkml.kernel.org/r/20250303141542.3371656-2-ryan.roberts@arm.com Fixes: bcc6cc832573 ("mm: add default definition of set_ptes()") Signed-off-by: Ryan Roberts Acked-by: David Hildenbrand Acked-by: Juergen Gross Cc: Andreas Larsson Cc: Borislav Betkov Cc: Boris Ostrovsky Cc: Catalin Marinas Cc: Dave Hansen Cc: David S. Miller Cc: "H. Peter Anvin" Cc: Ingo Molnar Cc: Juegren Gross Cc: Matthew Wilcow (Oracle) Cc: Thomas Gleinxer Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- include/linux/pgtable.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h index 3c3a7dede0ef..e2c9a0c259df 100644 --- a/include/linux/pgtable.h +++ b/include/linux/pgtable.h @@ -194,10 +194,14 @@ static inline int pmd_young(pmd_t pmd) * hazard could result in the direct mode hypervisor case, since the actual * write to the page tables may not yet have taken place, so reads though * a raw PTE pointer after it has been modified are not guaranteed to be - * up to date. This mode can only be entered and left under the protection of - * the page table locks for all page tables which may be modified. In the UP - * case, this is required so that preemption is disabled, and in the SMP case, - * it must synchronize the delayed page table writes properly on other CPUs. + * up to date. + * + * In the general case, no lock is guaranteed to be held between entry and exit + * of the lazy mode. So the implementation must assume preemption may be enabled + * and cpu migration is possible; it must take steps to be robust against this. + * (In practice, for user PTE updates, the appropriate page table lock(s) are + * held, but for kernel PTE updates, no lock is held). Nesting is not permitted + * and the mode cannot be used in interrupt context. */ #ifndef __HAVE_ARCH_ENTER_LAZY_MMU_MODE #define arch_enter_lazy_mmu_mode() do {} while (0) @@ -233,7 +237,6 @@ static inline void set_ptes(struct mm_struct *mm, unsigned long addr, { page_table_check_ptes_set(mm, ptep, pte, nr); - arch_enter_lazy_mmu_mode(); for (;;) { set_pte(ptep, pte); if (--nr == 0) @@ -241,7 +244,6 @@ static inline void set_ptes(struct mm_struct *mm, unsigned long addr, ptep++; pte = pte_next_pfn(pte); } - arch_leave_lazy_mmu_mode(); } #endif #define set_pte_at(mm, addr, ptep, pte) set_ptes(mm, addr, ptep, pte, 1) From e351ffc48b5e8a18ff93ec078c0f9b0454eff4f7 Mon Sep 17 00:00:00 2001 From: Lorenzo Stoakes Date: Mon, 10 Mar 2025 20:50:34 +0000 Subject: [PATCH 192/606] mm/mremap: correctly handle partial mremap() of VMA starting at 0 commit 937582ee8e8d227c30ec147629a0179131feaa80 upstream. Patch series "refactor mremap and fix bug", v3. The existing mremap() logic has grown organically over a very long period of time, resulting in code that is in many parts, very difficult to follow and full of subtleties and sources of confusion. In addition, it is difficult to thread state through the operation correctly, as function arguments have expanded, some parameters are expected to be temporarily altered during the operation, others are intended to remain static and some can be overridden. This series completely refactors the mremap implementation, sensibly separating functions, adding comments to explain the more subtle aspects of the implementation and making use of small structs to thread state through everything. The reason for doing so is to lay the groundwork for planned future changes to the mremap logic, changes which require the ability to easily pass around state. Additionally, it would be unhelpful to add yet more logic to code that is already difficult to follow without first refactoring it like this. The first patch in this series additionally fixes a bug when a VMA with start address zero is partially remapped. Tested on real hardware under heavy workload and all self tests are passing. This patch (of 3): Consider the case of a partial mremap() (that results in a VMA split) of an accountable VMA (i.e. which has the VM_ACCOUNT flag set) whose start address is zero, with the MREMAP_MAYMOVE flag specified and a scenario where a move does in fact occur: addr end | | v v |-------------| | vma | |-------------| 0 This move is affected by unmapping the range [addr, end). In order to prevent an incorrect decrement of accounted memory which has already been determined, the mremap() code in move_vma() clears VM_ACCOUNT from the VMA prior to doing so, before reestablishing it in each of the VMAs post-split: addr end | | v v |---| |---| | A | | B | |---| |---| Commit 6b73cff239e5 ("mm: change munmap splitting order and move_vma()") changed this logic such as to determine whether there is a need to do so by establishing account_start and account_end and, in the instance where such an operation is required, assigning them to vma->vm_start and vma->vm_end. Later the code checks if the operation is required for 'A' referenced above thusly: if (account_start) { ... } However, if the VMA described above has vma->vm_start == 0, which is now assigned to account_start, this branch will not be executed. As a result, the VMA 'A' above will remain stripped of its VM_ACCOUNT flag, incorrectly. The fix is to simply convert these variables to booleans and set them as required. Link: https://lkml.kernel.org/r/cover.1741639347.git.lorenzo.stoakes@oracle.com Link: https://lkml.kernel.org/r/dc55cb6db25d97c3d9e460de4986a323fa959676.1741639347.git.lorenzo.stoakes@oracle.com Fixes: 6b73cff239e5 ("mm: change munmap splitting order and move_vma()") Signed-off-by: Lorenzo Stoakes Reviewed-by: Harry Yoo Reviewed-by: Liam R. Howlett Reviewed-by: Vlastimil Babka Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- mm/mremap.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mm/mremap.c b/mm/mremap.c index df71010baabe..d458ef218a37 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -599,8 +599,8 @@ static unsigned long move_vma(struct vm_area_struct *vma, unsigned long vm_flags = vma->vm_flags; unsigned long new_pgoff; unsigned long moved_len; - unsigned long account_start = 0; - unsigned long account_end = 0; + bool account_start = false; + bool account_end = false; unsigned long hiwater_vm; int err = 0; bool need_rmap_locks; @@ -684,9 +684,9 @@ static unsigned long move_vma(struct vm_area_struct *vma, if (vm_flags & VM_ACCOUNT && !(flags & MREMAP_DONTUNMAP)) { vm_flags_clear(vma, VM_ACCOUNT); if (vma->vm_start < old_addr) - account_start = vma->vm_start; + account_start = true; if (vma->vm_end > old_addr + old_len) - account_end = vma->vm_end; + account_end = true; } /* @@ -726,7 +726,7 @@ static unsigned long move_vma(struct vm_area_struct *vma, /* OOM: unable to split vma, just get accounts right */ if (vm_flags & VM_ACCOUNT && !(flags & MREMAP_DONTUNMAP)) vm_acct_memory(old_len >> PAGE_SHIFT); - account_start = account_end = 0; + account_start = account_end = false; } if (vm_flags & VM_LOCKED) { From 376183178f4276036e62316a268bab2fca0173ae Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Wed, 12 Mar 2025 10:10:13 -0400 Subject: [PATCH 193/606] mm: add missing release barrier on PGDAT_RECLAIM_LOCKED unlock commit c0ebbb3841e07c4493e6fe351698806b09a87a37 upstream. The PGDAT_RECLAIM_LOCKED bit is used to provide mutual exclusion of node reclaim for struct pglist_data using a single bit. It is "locked" with a test_and_set_bit (similarly to a try lock) which provides full ordering with respect to loads and stores done within __node_reclaim(). It is "unlocked" with clear_bit(), which does not provide any ordering with respect to loads and stores done before clearing the bit. The lack of clear_bit() memory ordering with respect to stores within __node_reclaim() can cause a subsequent CPU to fail to observe stores from a prior node reclaim. This is not an issue in practice on TSO (e.g. x86), but it is an issue on weakly-ordered architectures (e.g. arm64). Fix this by using clear_bit_unlock rather than clear_bit to clear PGDAT_RECLAIM_LOCKED with a release memory ordering semantic. This provides stronger memory ordering (release rather than relaxed). Link: https://lkml.kernel.org/r/20250312141014.129725-1-mathieu.desnoyers@efficios.com Fixes: d773ed6b856a ("mm: test and set zone reclaim lock before starting reclaim") Signed-off-by: Mathieu Desnoyers Cc: Lorenzo Stoakes Cc: Matthew Wilcox Cc: Alan Stern Cc: Andrea Parri Cc: Will Deacon Cc: Peter Zijlstra Cc: Boqun Feng Cc: Nicholas Piggin Cc: David Howells Cc: Jade Alglave Cc: Luc Maranget Cc: "Paul E. McKenney" Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- mm/vmscan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 49456b725755..258f5472f1e9 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -8115,7 +8115,7 @@ int node_reclaim(struct pglist_data *pgdat, gfp_t gfp_mask, unsigned int order) return NODE_RECLAIM_NOSCAN; ret = __node_reclaim(pgdat, gfp_mask, order); - clear_bit(PGDAT_RECLAIM_LOCKED, &pgdat->flags); + clear_bit_unlock(PGDAT_RECLAIM_LOCKED, &pgdat->flags); if (!ret) count_vm_event(PGSCAN_ZONE_RECLAIM_FAILED); From 0b83b941d387e17f48d4f1058a885449484cd59d Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Wed, 12 Mar 2025 10:51:31 -0400 Subject: [PATCH 194/606] mm/userfaultfd: fix release hang over concurrent GUP commit fe4cdc2c4e248f48de23bc778870fd71e772a274 upstream. This patch should fix a possible userfaultfd release() hang during concurrent GUP. This problem was initially reported by Dimitris Siakavaras in July 2023 [1] in a firecracker use case. Firecracker has a separate process handling page faults remotely, and when the process releases the userfaultfd it can race with a concurrent GUP from KVM trying to fault in a guest page during the secondary MMU page fault process. A similar problem was reported recently again by Jinjiang Tu in March 2025 [2], even though the race happened this time with a mlockall() operation, which does GUP in a similar fashion. In 2017, commit 656710a60e36 ("userfaultfd: non-cooperative: closing the uffd without triggering SIGBUS") was trying to fix this issue. AFAIU, that fixes well the fault paths but may not work yet for GUP. In GUP, the issue is NOPAGE will be almost treated the same as "page fault resolved" in faultin_page(), then the GUP will follow page again, seeing page missing, and it'll keep going into a live lock situation as reported. This change makes core mm return RETRY instead of NOPAGE for both the GUP and fault paths, proactively releasing the mmap read lock. This should guarantee the other release thread make progress on taking the write lock and avoid the live lock even for GUP. When at it, rearrange the comments to make sure it's uptodate. [1] https://lore.kernel.org/r/79375b71-db2e-3e66-346b-254c90d915e2@cslab.ece.ntua.gr [2] https://lore.kernel.org/r/20250307072133.3522652-1-tujinjiang@huawei.com Link: https://lkml.kernel.org/r/20250312145131.1143062-1-peterx@redhat.com Signed-off-by: Peter Xu Cc: Andrea Arcangeli Cc: Mike Rapoport (IBM) Cc: Axel Rasmussen Cc: Jinjiang Tu Cc: Dimitris Siakavaras Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- fs/userfaultfd.c | 51 ++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c index 5d3e595f9da9..5ceb1fa8eb11 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c @@ -451,32 +451,6 @@ vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason) if (!(vmf->flags & FAULT_FLAG_USER) && (ctx->flags & UFFD_USER_MODE_ONLY)) goto out; - /* - * If it's already released don't get it. This avoids to loop - * in __get_user_pages if userfaultfd_release waits on the - * caller of handle_userfault to release the mmap_lock. - */ - if (unlikely(READ_ONCE(ctx->released))) { - /* - * Don't return VM_FAULT_SIGBUS in this case, so a non - * cooperative manager can close the uffd after the - * last UFFDIO_COPY, without risking to trigger an - * involuntary SIGBUS if the process was starting the - * userfaultfd while the userfaultfd was still armed - * (but after the last UFFDIO_COPY). If the uffd - * wasn't already closed when the userfault reached - * this point, that would normally be solved by - * userfaultfd_must_wait returning 'false'. - * - * If we were to return VM_FAULT_SIGBUS here, the non - * cooperative manager would be instead forced to - * always call UFFDIO_UNREGISTER before it can safely - * close the uffd. - */ - ret = VM_FAULT_NOPAGE; - goto out; - } - /* * Check that we can return VM_FAULT_RETRY. * @@ -513,6 +487,31 @@ vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason) if (vmf->flags & FAULT_FLAG_RETRY_NOWAIT) goto out; + if (unlikely(READ_ONCE(ctx->released))) { + /* + * If a concurrent release is detected, do not return + * VM_FAULT_SIGBUS or VM_FAULT_NOPAGE, but instead always + * return VM_FAULT_RETRY with lock released proactively. + * + * If we were to return VM_FAULT_SIGBUS here, the non + * cooperative manager would be instead forced to + * always call UFFDIO_UNREGISTER before it can safely + * close the uffd, to avoid involuntary SIGBUS triggered. + * + * If we were to return VM_FAULT_NOPAGE, it would work for + * the fault path, in which the lock will be released + * later. However for GUP, faultin_page() does nothing + * special on NOPAGE, so GUP would spin retrying without + * releasing the mmap read lock, causing possible livelock. + * + * Here only VM_FAULT_RETRY would make sure the mmap lock + * be released immediately, so that the thread concurrently + * releasing the userfault would always make progress. + */ + release_fault_lock(vmf); + goto out; + } + /* take the reference before dropping the mmap_lock */ userfaultfd_ctx_get(ctx); From 94b3a19cedb371c69c06eb9b4299d618eb0f7e02 Mon Sep 17 00:00:00 2001 From: Shuai Xue Date: Wed, 12 Mar 2025 19:28:51 +0800 Subject: [PATCH 195/606] mm/hwpoison: do not send SIGBUS to processes with recovered clean pages commit aaf99ac2ceb7c974f758a635723eeaf48596388e upstream. When an uncorrected memory error is consumed there is a race between the CMCI from the memory controller reporting an uncorrected error with a UCNA signature, and the core reporting and SRAR signature machine check when the data is about to be consumed. - Background: why *UN*corrected errors tied to *C*MCI in Intel platform [1] Prior to Icelake memory controllers reported patrol scrub events that detected a previously unseen uncorrected error in memory by signaling a broadcast machine check with an SRAO (Software Recoverable Action Optional) signature in the machine check bank. This was overkill because it's not an urgent problem that no core is on the verge of consuming that bad data. It's also found that multi SRAO UCE may cause nested MCE interrupts and finally become an IERR. Hence, Intel downgrades the machine check bank signature of patrol scrub from SRAO to UCNA (Uncorrected, No Action required), and signal changed to #CMCI. Just to add to the confusion, Linux does take an action (in uc_decode_notifier()) to try to offline the page despite the UC*NA* signature name. - Background: why #CMCI and #MCE race when poison is consuming in Intel platform [1] Having decided that CMCI/UCNA is the best action for patrol scrub errors, the memory controller uses it for reads too. But the memory controller is executing asynchronously from the core, and can't tell the difference between a "real" read and a speculative read. So it will do CMCI/UCNA if an error is found in any read. Thus: 1) Core is clever and thinks address A is needed soon, issues a speculative read. 2) Core finds it is going to use address A soon after sending the read request 3) The CMCI from the memory controller is in a race with MCE from the core that will soon try to retire the load from address A. Quite often (because speculation has got better) the CMCI from the memory controller is delivered before the core is committed to the instruction reading address A, so the interrupt is taken, and Linux offlines the page (marking it as poison). - Why user process is killed for instr case Commit 046545a661af ("mm/hwpoison: fix error page recovered but reported "not recovered"") tries to fix noise message "Memory error not recovered" and skips duplicate SIGBUSs due to the race. But it also introduced a bug that kill_accessing_process() return -EHWPOISON for instr case, as result, kill_me_maybe() send a SIGBUS to user process. If the CMCI wins that race, the page is marked poisoned when uc_decode_notifier() calls memory_failure(). For dirty pages, memory_failure() invokes try_to_unmap() with the TTU_HWPOISON flag, converting the PTE to a hwpoison entry. As a result, kill_accessing_process(): - call walk_page_range() and return 1 regardless of whether try_to_unmap() succeeds or fails, - call kill_proc() to make sure a SIGBUS is sent - return -EHWPOISON to indicate that SIGBUS is already sent to the process and kill_me_maybe() doesn't have to send it again. However, for clean pages, the TTU_HWPOISON flag is cleared, leaving the PTE unchanged and not converted to a hwpoison entry. Conversely, for clean pages where PTE entries are not marked as hwpoison, kill_accessing_process() returns -EFAULT, causing kill_me_maybe() to send a SIGBUS. Console log looks like this: Memory failure: 0x827ca68: corrupted page was clean: dropped without side effects Memory failure: 0x827ca68: recovery action for clean LRU page: Recovered Memory failure: 0x827ca68: already hardware poisoned mce: Memory error not recovered To fix it, return 0 for "corrupted page was clean", preventing an unnecessary SIGBUS to user process. [1] https://lore.kernel.org/lkml/20250217063335.22257-1-xueshuai@linux.alibaba.com/T/#mba94f1305b3009dd340ce4114d3221fe810d1871 Link: https://lkml.kernel.org/r/20250312112852.82415-3-xueshuai@linux.alibaba.com Fixes: 046545a661af ("mm/hwpoison: fix error page recovered but reported "not recovered"") Signed-off-by: Shuai Xue Tested-by: Tony Luck Acked-by: Miaohe Lin Cc: Baolin Wang Cc: Borislav Betkov Cc: Catalin Marinas Cc: Dave Hansen Cc: "H. Peter Anvin" Cc: Ingo Molnar Cc: Jane Chu Cc: Jarkko Sakkinen Cc: Jonathan Cameron Cc: Josh Poimboeuf Cc: Naoya Horiguchi Cc: Peter Zijlstra Cc: Ruidong Tian Cc: Thomas Gleinxer Cc: Yazen Ghannam Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- mm/memory-failure.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 9018a1162efc..a96840c41581 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -869,12 +869,17 @@ static int kill_accessing_process(struct task_struct *p, unsigned long pfn, mmap_read_lock(p->mm); ret = walk_page_range(p->mm, 0, TASK_SIZE, &hwpoison_walk_ops, (void *)&priv); + /* + * ret = 1 when CMCI wins, regardless of whether try_to_unmap() + * succeeds or fails, then kill the process with SIGBUS. + * ret = 0 when poison page is a clean page and it's dropped, no + * SIGBUS is needed. + */ if (ret == 1 && priv.tk.addr) kill_proc(&priv.tk, pfn, flags); - else - ret = 0; mmap_read_unlock(p->mm); - return ret > 0 ? -EHWPOISON : -EFAULT; + + return ret > 0 ? -EHWPOISON : 0; } static const char *action_name[] = { From b5681a8b997eccc6a6db0eb8dc8f5b9fcf18196d Mon Sep 17 00:00:00 2001 From: Marc Herbert Date: Wed, 19 Mar 2025 06:00:30 +0000 Subject: [PATCH 196/606] mm/hugetlb: move hugetlb_sysctl_init() to the __init section commit 1ca77ff1837249701053a7fcbdedabc41f4ae67c upstream. hugetlb_sysctl_init() is only invoked once by an __init function and is merely a wrapper around another __init function so there is not reason to keep it. Fixes the following warning when toning down some GCC inline options: WARNING: modpost: vmlinux: section mismatch in reference: hugetlb_sysctl_init+0x1b (section: .text) -> __register_sysctl_init (section: .init.text) Link: https://lkml.kernel.org/r/20250319060041.2737320-1-marc.herbert@linux.intel.com Signed-off-by: Marc Herbert Reviewed-by: Anshuman Khandual Reviewed-by: Muchun Song Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- mm/hugetlb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index faded25b19be..7c196b754071 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -4695,7 +4695,7 @@ static struct ctl_table hugetlb_table[] = { { } }; -static void hugetlb_sysctl_init(void) +static void __init hugetlb_sysctl_init(void) { register_sysctl_init("vm", hugetlb_table); } From c6fefcb71d246baaf3bacdad1af7ff50ebcfe652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Ca=C3=B1uelo=20Navarro?= Date: Fri, 4 Apr 2025 16:53:21 +0200 Subject: [PATCH 197/606] sctp: detect and prevent references to a freed transport in sendmsg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f1a69a940de58b16e8249dff26f74c8cc59b32be upstream. sctp_sendmsg() re-uses associations and transports when possible by doing a lookup based on the socket endpoint and the message destination address, and then sctp_sendmsg_to_asoc() sets the selected transport in all the message chunks to be sent. There's a possible race condition if another thread triggers the removal of that selected transport, for instance, by explicitly unbinding an address with setsockopt(SCTP_SOCKOPT_BINDX_REM), after the chunks have been set up and before the message is sent. This can happen if the send buffer is full, during the period when the sender thread temporarily releases the socket lock in sctp_wait_for_sndbuf(). This causes the access to the transport data in sctp_outq_select_transport(), when the association outqueue is flushed, to result in a use-after-free read. This change avoids this scenario by having sctp_transport_free() signal the freeing of the transport, tagging it as "dead". In order to do this, the patch restores the "dead" bit in struct sctp_transport, which was removed in commit 47faa1e4c50e ("sctp: remove the dead field of sctp_transport"). Then, in the scenario where the sender thread has released the socket lock in sctp_wait_for_sndbuf(), the bit is checked again after re-acquiring the socket lock to detect the deletion. This is done while holding a reference to the transport to prevent it from being freed in the process. If the transport was deleted while the socket lock was relinquished, sctp_sendmsg_to_asoc() will return -EAGAIN to let userspace retry the send. The bug was found by a private syzbot instance (see the error report [1] and the C reproducer that triggers it [2]). Link: https://people.igalia.com/rcn/kernel_logs/20250402__KASAN_slab-use-after-free_Read_in_sctp_outq_select_transport.txt [1] Link: https://people.igalia.com/rcn/kernel_logs/20250402__KASAN_slab-use-after-free_Read_in_sctp_outq_select_transport__repro.c [2] Cc: stable@vger.kernel.org Fixes: df132eff4638 ("sctp: clear the transport of some out_chunk_list chunks in sctp_assoc_rm_peer") Suggested-by: Xin Long Signed-off-by: Ricardo Cañuelo Navarro Acked-by: Xin Long Link: https://patch.msgid.link/20250404-kasan_slab-use-after-free_read_in_sctp_outq_select_transport__20250404-v1-1-5ce4a0b78ef2@igalia.com Signed-off-by: Paolo Abeni Signed-off-by: Greg Kroah-Hartman --- include/net/sctp/structs.h | 3 ++- net/sctp/socket.c | 22 ++++++++++++++-------- net/sctp/transport.c | 2 ++ 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 5a24d6d8522a..d943bb454b17 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -778,6 +778,7 @@ struct sctp_transport { /* Reference counting. */ refcount_t refcnt; + __u32 dead:1, /* RTO-Pending : A flag used to track if one of the DATA * chunks sent to this address is currently being * used to compute a RTT. If this flag is 0, @@ -787,7 +788,7 @@ struct sctp_transport { * calculation completes (i.e. the DATA chunk * is SACK'd) clear this flag. */ - __u32 rto_pending:1, + rto_pending:1, /* * hb_sent : a flag that signals that we have a pending diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 108a0745c0c3..b84c5e0a76f5 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -71,8 +71,9 @@ /* Forward declarations for internal helper functions. */ static bool sctp_writeable(const struct sock *sk); static void sctp_wfree(struct sk_buff *skb); -static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, - size_t msg_len); +static int sctp_wait_for_sndbuf(struct sctp_association *asoc, + struct sctp_transport *transport, + long *timeo_p, size_t msg_len); static int sctp_wait_for_packet(struct sock *sk, int *err, long *timeo_p); static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p); static int sctp_wait_for_accept(struct sock *sk, long timeo); @@ -1827,7 +1828,7 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc, if (sctp_wspace(asoc) <= 0 || !sk_wmem_schedule(sk, msg_len)) { timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); - err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len); + err = sctp_wait_for_sndbuf(asoc, transport, &timeo, msg_len); if (err) goto err; if (unlikely(sinfo->sinfo_stream >= asoc->stream.outcnt)) { @@ -9208,8 +9209,9 @@ void sctp_sock_rfree(struct sk_buff *skb) /* Helper function to wait for space in the sndbuf. */ -static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, - size_t msg_len) +static int sctp_wait_for_sndbuf(struct sctp_association *asoc, + struct sctp_transport *transport, + long *timeo_p, size_t msg_len) { struct sock *sk = asoc->base.sk; long current_timeo = *timeo_p; @@ -9219,7 +9221,9 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, pr_debug("%s: asoc:%p, timeo:%ld, msg_len:%zu\n", __func__, asoc, *timeo_p, msg_len); - /* Increment the association's refcnt. */ + /* Increment the transport and association's refcnt. */ + if (transport) + sctp_transport_hold(transport); sctp_association_hold(asoc); /* Wait on the association specific sndbuf space. */ @@ -9228,7 +9232,7 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, TASK_INTERRUPTIBLE); if (asoc->base.dead) goto do_dead; - if (!*timeo_p) + if ((!*timeo_p) || (transport && transport->dead)) goto do_nonblock; if (sk->sk_err || asoc->state >= SCTP_STATE_SHUTDOWN_PENDING) goto do_error; @@ -9253,7 +9257,9 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, out: finish_wait(&asoc->wait, &wait); - /* Release the association's refcnt. */ + /* Release the transport and association's refcnt. */ + if (transport) + sctp_transport_put(transport); sctp_association_put(asoc); return err; diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 2abe45af98e7..31eca29b6cfb 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -117,6 +117,8 @@ fail: */ void sctp_transport_free(struct sctp_transport *transport) { + transport->dead = 1; + /* Try to delete the heartbeat timer. */ if (del_timer(&transport->hb_timer)) sctp_transport_put(transport); From 8d4750f063597ebd8f0009d5e5b5a4ef87b8449a Mon Sep 17 00:00:00 2001 From: Roger Pau Monne Date: Mon, 7 Apr 2025 10:28:37 +0200 Subject: [PATCH 198/606] x86/xen: fix balloon target initialization for PVH dom0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 87af633689ce16ddb166c80f32b120e50b1295de upstream. PVH dom0 re-uses logic from PV dom0, in which RAM ranges not assigned to dom0 are re-used as scratch memory to map foreign and grant pages. Such logic relies on reporting those unpopulated ranges as RAM to Linux, and mark them as reserved. This way Linux creates the underlying page structures required for metadata management. Such approach works fine on PV because the initial balloon target is calculated using specific Xen data, that doesn't take into account the memory type changes described above. However on HVM and PVH the initial balloon target is calculated using get_num_physpages(), and that function does take into account the unpopulated RAM regions used as scratch space for remote domain mappings. This leads to PVH dom0 having an incorrect initial balloon target, which causes malfunction (excessive memory freeing) of the balloon driver if the dom0 memory target is later adjusted from the toolstack. Fix this by using xen_released_pages to account for any pages that are part of the memory map, but are already unpopulated when the balloon driver is initialized. This accounts for any regions used for scratch remote mappings. Note on x86 xen_released_pages definition is moved to enlighten.c so it's uniformly available for all Xen-enabled builds. Take the opportunity to unify PV with PVH/HVM guests regarding the usage of get_num_physpages(), as that avoids having to add different logic for PV vs PVH in both balloon_add_regions() and arch_xen_unpopulated_init(). Much like a6aa4eb994ee, the code in this changeset should have been part of 38620fc4e893. Fixes: a6aa4eb994ee ('xen/x86: add extra pages to unpopulated-alloc if available') Signed-off-by: Roger Pau Monné Reviewed-by: Juergen Gross Cc: stable@vger.kernel.org Signed-off-by: Juergen Gross Message-ID: <20250407082838.65495-1-roger.pau@citrix.com> Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/enlighten.c | 10 ++++++++++ arch/x86/xen/setup.c | 3 --- drivers/xen/balloon.c | 34 ++++++++++++++++++++++++---------- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 0219f1c90202..638de313fc4e 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -75,6 +75,9 @@ EXPORT_SYMBOL(xen_start_flags); */ struct shared_info *HYPERVISOR_shared_info = &xen_dummy_shared_info; +/* Number of pages released from the initial allocation. */ +unsigned long xen_released_pages; + static __ref void xen_get_vendor(void) { init_cpu_devs(); @@ -471,6 +474,13 @@ int __init arch_xen_unpopulated_init(struct resource **res) xen_free_unpopulated_pages(1, &pg); } + /* + * Account for the region being in the physmap but unpopulated. + * The value in xen_released_pages is used by the balloon + * driver to know how much of the physmap is unpopulated and + * set an accurate initial memory target. + */ + xen_released_pages += xen_extra_mem[i].n_pfns; /* Zero so region is not also added to the balloon driver. */ xen_extra_mem[i].n_pfns = 0; } diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index dc822124cacb..ec3ffb94807d 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -38,9 +38,6 @@ #define GB(x) ((uint64_t)(x) * 1024 * 1024 * 1024) -/* Number of pages released from the initial allocation. */ -unsigned long xen_released_pages; - /* Memory map would allow PCI passthrough. */ bool xen_pv_pci_possible; diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index db61bcb3aab1..b0b52fa8fba6 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -671,7 +671,7 @@ void xen_free_ballooned_pages(unsigned int nr_pages, struct page **pages) } EXPORT_SYMBOL(xen_free_ballooned_pages); -static void __init balloon_add_regions(void) +static int __init balloon_add_regions(void) { unsigned long start_pfn, pages; unsigned long pfn, extra_pfn_end; @@ -694,26 +694,38 @@ static void __init balloon_add_regions(void) for (pfn = start_pfn; pfn < extra_pfn_end; pfn++) balloon_append(pfn_to_page(pfn)); - balloon_stats.total_pages += extra_pfn_end - start_pfn; + /* + * Extra regions are accounted for in the physmap, but need + * decreasing from current_pages to balloon down the initial + * allocation, because they are already accounted for in + * total_pages. + */ + if (extra_pfn_end - start_pfn >= balloon_stats.current_pages) { + WARN(1, "Extra pages underflow current target"); + return -ERANGE; + } + balloon_stats.current_pages -= extra_pfn_end - start_pfn; } + + return 0; } static int __init balloon_init(void) { struct task_struct *task; + int rc; if (!xen_domain()) return -ENODEV; pr_info("Initialising balloon driver\n"); -#ifdef CONFIG_XEN_PV - balloon_stats.current_pages = xen_pv_domain() - ? min(xen_start_info->nr_pages - xen_released_pages, max_pfn) - : get_num_physpages(); -#else - balloon_stats.current_pages = get_num_physpages(); -#endif + if (xen_released_pages >= get_num_physpages()) { + WARN(1, "Released pages underflow current target"); + return -ERANGE; + } + + balloon_stats.current_pages = get_num_physpages() - xen_released_pages; balloon_stats.target_pages = balloon_stats.current_pages; balloon_stats.balloon_low = 0; balloon_stats.balloon_high = 0; @@ -730,7 +742,9 @@ static int __init balloon_init(void) register_sysctl_init("xen/balloon", balloon_table); #endif - balloon_add_regions(); + rc = balloon_add_regions(); + if (rc) + return rc; task = kthread_run(balloon_thread, NULL, "xen-balloon"); if (IS_ERR(task)) { From 233b9cef917c6c8f23f7122a1bdf3b0554c4ccbf Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 7 Apr 2025 15:41:39 -0400 Subject: [PATCH 199/606] tracing: Do not add length to print format in synthetic events commit e1a453a57bc76be678bd746f84e3d73f378a9511 upstream. The following causes a vsnprintf fault: # echo 's:wake_lat char[] wakee; u64 delta;' >> /sys/kernel/tracing/dynamic_events # echo 'hist:keys=pid:ts=common_timestamp.usecs if !(common_flags & 0x18)' > /sys/kernel/tracing/events/sched/sched_waking/trigger # echo 'hist:keys=next_pid:delta=common_timestamp.usecs-$ts:onmatch(sched.sched_waking).trace(wake_lat,next_comm,$delta)' > /sys/kernel/tracing/events/sched/sched_switch/trigger Because the synthetic event's "wakee" field is created as a dynamic string (even though the string copied is not). The print format to print the dynamic string changed from "%*s" to "%s" because another location (__set_synth_event_print_fmt()) exported this to user space, and user space did not need that. But it is still used in print_synth_event(), and the output looks like: -0 [001] d..5. 193.428167: wake_lat: wakee=(efault)sshd-sessiondelta=155 sshd-session-879 [001] d..5. 193.811080: wake_lat: wakee=(efault)kworker/u34:5delta=58 -0 [002] d..5. 193.811198: wake_lat: wakee=(efault)bashdelta=91 bash-880 [002] d..5. 193.811371: wake_lat: wakee=(efault)kworker/u35:2delta=21 -0 [001] d..5. 193.811516: wake_lat: wakee=(efault)sshd-sessiondelta=129 sshd-session-879 [001] d..5. 193.967576: wake_lat: wakee=(efault)kworker/u34:5delta=50 The length isn't needed as the string is always nul terminated. Just print the string and not add the length (which was hard coded to the max string length anyway). Cc: stable@vger.kernel.org Cc: Mathieu Desnoyers Cc: Tom Zanussi Cc: Douglas Raillard Acked-by: Masami Hiramatsu (Google) Link: https://lore.kernel.org/20250407154139.69955768@gandalf.local.home Fixes: 4d38328eb442d ("tracing: Fix synth event printk format for str fields"); Signed-off-by: Steven Rostedt (Google) Signed-off-by: Greg Kroah-Hartman --- kernel/trace/trace_events_synth.c | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/trace/trace_events_synth.c b/kernel/trace/trace_events_synth.c index ccd6703ac50b..794e72dbb12d 100644 --- a/kernel/trace/trace_events_synth.c +++ b/kernel/trace/trace_events_synth.c @@ -377,7 +377,6 @@ static enum print_line_t print_synth_event(struct trace_iterator *iter, union trace_synth_field *data = &entry->fields[n_u64]; trace_seq_printf(s, print_fmt, se->fields[i]->name, - STR_VAR_LEN_MAX, (char *)entry + data->as_dynamic.offset, i == se->n_fields - 1 ? "" : " "); n_u64++; From f75eb9acf9dfd8f4961947b8c30980985368dd58 Mon Sep 17 00:00:00 2001 From: Trevor Woerner Date: Fri, 7 Feb 2025 12:50:47 -0500 Subject: [PATCH 200/606] thermal/drivers/rockchip: Add missing rk3328 mapping entry commit ee022e5cae052e0c67ca7c5fec0f2e7bc897c70e upstream. The mapping table for the rk3328 is missing the entry for -25C which is found in the TRM section 9.5.2 "Temperature-to-code mapping". NOTE: the kernel uses the tsadc_q_sel=1'b1 mode which is defined as: 4096-. Whereas the table in the TRM gives the code "3774" for -25C, the kernel uses 4096-3774=322. [Dragan Simic] : "After going through the RK3308 and RK3328 TRMs, as well as through the downstream kernel code, it seems we may have some troubles at our hands. Let me explain, please. To sum it up, part 1 of the RK3308 TRM v1.1 says on page 538 that the equation for the output when tsadc_q_sel equals 1 is (4096 - tsadc_q), while part 1 of the RK3328 TRM v1.2 says that the output equation is (1024 - tsadc_q) in that case. The downstream kernel code, however, treats the RK3308 and RK3328 tables and their values as being the same. It even mentions 1024 as the "offset" value in a comment block for the rk_tsadcv3_control() function, just like the upstream code does, which is obviously wrong "offset" value when correlated with the table on page 544 of part 1 of the RK3308 TRM v1.1. With all this in mind, it's obvious that more work is needed to make it clear where's the actual mistake (it could be that the TRM is wrong), which I'll volunteer for as part of the SoC binning project. In the meantime, this patch looks fine as-is to me, by offering what's a clear improvement to the current state of the upstream code" Link: https://opensource.rock-chips.com/images/9/97/Rockchip_RK3328TRM_V1.1-Part1-20170321.pdf Cc: stable@vger.kernel.org Fixes: eda519d5f73e ("thermal: rockchip: Support the RK3328 SOC in thermal driver") Signed-off-by: Trevor Woerner Reviewed-by: Dragan Simic Link: https://lore.kernel.org/r/20250207175048.35959-1-twoerner@gmail.com Signed-off-by: Daniel Lezcano Signed-off-by: Greg Kroah-Hartman --- drivers/thermal/rockchip_thermal.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index 77231a9d28ff..d306ca9a9902 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c @@ -386,6 +386,7 @@ static const struct tsadc_table rk3328_code_table[] = { {296, -40000}, {304, -35000}, {313, -30000}, + {322, -25000}, {331, -20000}, {340, -15000}, {349, -10000}, From 864ba5c651b03830f36f0906c21af05b15c1aaa6 Mon Sep 17 00:00:00 2001 From: Alexandra Diupina Date: Wed, 19 Mar 2025 17:28:58 +0300 Subject: [PATCH 201/606] cifs: avoid NULL pointer dereference in dbg call commit b4885bd5935bb26f0a414ad55679a372e53f9b9b upstream. cifs_server_dbg() implies server to be non-NULL so move call under condition to avoid NULL pointer dereference. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: e79b0332ae06 ("cifs: ignore cached share root handle closing errors") Cc: stable@vger.kernel.org Signed-off-by: Alexandra Diupina Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/smb/client/smb2misc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/smb/client/smb2misc.c b/fs/smb/client/smb2misc.c index 677ef6f99a5b..fadc5fc274eb 100644 --- a/fs/smb/client/smb2misc.c +++ b/fs/smb/client/smb2misc.c @@ -816,11 +816,12 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid, WARN_ONCE(tcon->tc_count < 0, "tcon refcount is negative"); spin_unlock(&cifs_tcp_ses_lock); - if (tcon->ses) + if (tcon->ses) { server = tcon->ses->server; - - cifs_server_dbg(FYI, "tid=0x%x: tcon is closing, skipping async close retry of fid %llu %llu\n", - tcon->tid, persistent_fid, volatile_fid); + cifs_server_dbg(FYI, + "tid=0x%x: tcon is closing, skipping async close retry of fid %llu %llu\n", + tcon->tid, persistent_fid, volatile_fid); + } return 0; } From b350dab6d4f42cf5dc6db871f05332f751dc88f7 Mon Sep 17 00:00:00 2001 From: Roman Smirnov Date: Mon, 31 Mar 2025 11:22:49 +0300 Subject: [PATCH 202/606] cifs: fix integer overflow in match_server() commit 2510859475d7f46ed7940db0853f3342bf1b65ee upstream. The echo_interval is not limited in any way during mounting, which makes it possible to write a large number to it. This can cause an overflow when multiplying ctx->echo_interval by HZ in match_server(). Add constraints for echo_interval to smb3_fs_context_parse_param(). Found by Linux Verification Center (linuxtesting.org) with Svace. Fixes: adfeb3e00e8e1 ("cifs: Make echo interval tunable") Cc: stable@vger.kernel.org Signed-off-by: Roman Smirnov Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/smb/client/fs_context.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c index b90cc918de7a..d2e291ef104e 100644 --- a/fs/smb/client/fs_context.c +++ b/fs/smb/client/fs_context.c @@ -1299,6 +1299,11 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, ctx->closetimeo = HZ * result.uint_32; break; case Opt_echo_interval: + if (result.uint_32 < SMB_ECHO_INTERVAL_MIN || + result.uint_32 > SMB_ECHO_INTERVAL_MAX) { + cifs_errorf(fc, "echo interval is out of bounds\n"); + goto cifs_parse_mount_err; + } ctx->echo_interval = result.uint_32; break; case Opt_snapshot: From 5569a2c557805ad6b6e31c9d4a233d4c826a277c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Sat, 5 Apr 2025 19:51:07 +0200 Subject: [PATCH 203/606] cifs: Ensure that all non-client-specific reparse points are processed by the server MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 6f8a394aa952257575910d57cf0a63627fa949a2 upstream. Fix regression in mounts to e.g. onedrive shares. Generally, reparse points are processed by the SMB server during the SMB OPEN request, but there are few reparse points which do not have OPEN-like meaning for the SMB server and has to be processed by the SMB client. Those are symlinks and special files (fifo, socket, block, char). For Linux SMB client, it is required to process also name surrogate reparse points as they represent another entity on the SMB server system. Linux client will mark them as separate mount points. Examples of name surrogate reparse points are NTFS junction points (e.g. created by the "mklink" tool on Windows servers). So after processing the name surrogate reparse points, clear the -EOPNOTSUPP error code returned from the parse_reparse_point() to let SMB server to process reparse points. And remove printing misleading error message "unhandled reparse tag:" as reparse points are handled by SMB server and hence unhandled fact is normal operation. Fixes: cad3fc0a4c8c ("cifs: Throw -EOPNOTSUPP error on unsupported reparse point type from parse_reparse_point()") Fixes: b587fd128660 ("cifs: Treat unhandled directory name surrogate reparse points as mount directory nodes") Cc: stable@vger.kernel.org Reported-by: Junwen Sun Tested-by: Junwen Sun Signed-off-by: Pali Rohár Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/smb/client/inode.c | 10 ++++++++++ fs/smb/client/reparse.c | 4 ---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c index b9cf05e0940d..d93ebd58ecae 100644 --- a/fs/smb/client/inode.c +++ b/fs/smb/client/inode.c @@ -1145,6 +1145,16 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data, cifs_create_junction_fattr(fattr, sb); goto out; } + /* + * If the reparse point is unsupported by the Linux SMB + * client then let it process by the SMB server. So mask + * the -EOPNOTSUPP error code. This will allow Linux SMB + * client to send SMB OPEN request to server. If server + * does not support this reparse point too then server + * will return error during open the path. + */ + if (rc == -EOPNOTSUPP) + rc = 0; } break; } diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c index bb246ef0458f..b6556fe3dfa1 100644 --- a/fs/smb/client/reparse.c +++ b/fs/smb/client/reparse.c @@ -633,8 +633,6 @@ int parse_reparse_point(struct reparse_data_buffer *buf, const char *full_path, bool unicode, struct cifs_open_info_data *data) { - struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); - data->reparse.buf = buf; /* See MS-FSCC 2.1.2 */ @@ -658,8 +656,6 @@ int parse_reparse_point(struct reparse_data_buffer *buf, } return 0; default: - cifs_tcon_dbg(VFS | ONCE, "unhandled reparse tag: 0x%08x\n", - le32_to_cpu(buf->ReparseTag)); return -EOPNOTSUPP; } } From 541c1a5554ee2c76f0cfc248121e62cdf725cde1 Mon Sep 17 00:00:00 2001 From: Ajit Pandey Date: Tue, 28 Jan 2025 17:08:35 +0530 Subject: [PATCH 204/606] clk: qcom: clk-branch: Fix invert halt status bit check for votable clocks commit 5eac348182d2b5ed1066459abedb7bc6b5466f81 upstream. BRANCH_HALT_ENABLE and BRANCH_HALT_ENABLE_VOTED flags are used to check halt status of branch clocks, which have an inverted logic for the halt bit in CBCR register. However, the current logic in the _check_halt() method only compares the BRANCH_HALT_ENABLE flags, ignoring the votable branch clocks. Update the logic to correctly handle the invert logic for votable clocks using the BRANCH_HALT_ENABLE_VOTED flags. Fixes: 9092d1083a62 ("clk: qcom: branch: Extend the invert logic for branch2 clocks") Cc: stable@vger.kernel.org Signed-off-by: Ajit Pandey Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250128-push_fix-v1-1-fafec6747881@quicinc.com Signed-off-by: Bjorn Andersson Signed-off-by: Greg Kroah-Hartman --- drivers/clk/qcom/clk-branch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/clk-branch.c b/drivers/clk/qcom/clk-branch.c index fc4735f74f0f..fefbfe7c42e7 100644 --- a/drivers/clk/qcom/clk-branch.c +++ b/drivers/clk/qcom/clk-branch.c @@ -27,7 +27,7 @@ static bool clk_branch_in_hwcg_mode(const struct clk_branch *br) static bool clk_branch_check_halt(const struct clk_branch *br, bool enabling) { - bool invert = (br->halt_check == BRANCH_HALT_ENABLE); + bool invert = (br->halt_check & BRANCH_HALT_ENABLE); u32 val; regmap_read(br->clkr.regmap, br->halt_reg, &val); @@ -43,7 +43,7 @@ static bool clk_branch2_check_halt(const struct clk_branch *br, bool enabling) { u32 val; u32 mask; - bool invert = (br->halt_check == BRANCH_HALT_ENABLE); + bool invert = (br->halt_check & BRANCH_HALT_ENABLE); mask = CBCR_NOC_FSM_STATUS; mask |= CBCR_CLK_OFF; From 1be6fe9527b1a1fe645d75b168bea2aded163084 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Fri, 17 Jan 2025 13:54:07 +0000 Subject: [PATCH 205/606] clk: qcom: gdsc: Release pm subdomains in reverse add order commit 0e6dfde439df0bb977cddd3cf7fff150a084a9bf upstream. gdsc_unregister() should release subdomains in the reverse order to the order in which those subdomains were added. I've made this patch a standalone patch because it facilitates a subsequent fix to stable. Fixes: 1b771839de05 ("clk: qcom: gdsc: enable optional power domain support") Cc: stable@vger.kernel.org Signed-off-by: Bryan O'Donoghue Link: https://lore.kernel.org/r/20250117-b4-linux-next-24-11-18-clock-multiple-power-domains-v10-1-13f2bb656dad@linaro.org Signed-off-by: Bjorn Andersson Signed-off-by: Greg Kroah-Hartman --- drivers/clk/qcom/gdsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c index 5358e28122ab..50926ddeedfd 100644 --- a/drivers/clk/qcom/gdsc.c +++ b/drivers/clk/qcom/gdsc.c @@ -525,7 +525,7 @@ void gdsc_unregister(struct gdsc_desc *desc) size_t num = desc->num; /* Remove subdomains */ - for (i = 0; i < num; i++) { + for (i = num - 1; i >= 0; i--) { if (!scs[i]) continue; if (scs[i]->parent) From fe25487f2dd128fe311e263977ba69e952fd6792 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Fri, 17 Jan 2025 13:54:08 +0000 Subject: [PATCH 206/606] clk: qcom: gdsc: Capture pm_genpd_add_subdomain result code commit 65a733464553ea192797b889d1533a1a37216f32 upstream. Adding a new clause to this if/else I noticed the existing usage of pm_genpd_add_subdomain() wasn't capturing and returning the result code. pm_genpd_add_subdomain() returns an int and can fail. Capture that result code and throw it up the call stack if something goes wrong. Fixes: 1b771839de05 ("clk: qcom: gdsc: enable optional power domain support") Cc: stable@vger.kernel.org Signed-off-by: Bryan O'Donoghue Link: https://lore.kernel.org/r/20250117-b4-linux-next-24-11-18-clock-multiple-power-domains-v10-2-13f2bb656dad@linaro.org Signed-off-by: Bjorn Andersson Signed-off-by: Greg Kroah-Hartman --- drivers/clk/qcom/gdsc.c | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c index 50926ddeedfd..361741f3e243 100644 --- a/drivers/clk/qcom/gdsc.c +++ b/drivers/clk/qcom/gdsc.c @@ -465,6 +465,23 @@ err_disable_supply: return ret; } +static void gdsc_pm_subdomain_remove(struct gdsc_desc *desc, size_t num) +{ + struct device *dev = desc->dev; + struct gdsc **scs = desc->scs; + int i; + + /* Remove subdomains */ + for (i = num - 1; i >= 0; i--) { + if (!scs[i]) + continue; + if (scs[i]->parent) + pm_genpd_remove_subdomain(scs[i]->parent, &scs[i]->pd); + else if (!IS_ERR_OR_NULL(dev->pm_domain)) + pm_genpd_remove_subdomain(pd_to_genpd(dev->pm_domain), &scs[i]->pd); + } +} + int gdsc_register(struct gdsc_desc *desc, struct reset_controller_dev *rcdev, struct regmap *regmap) { @@ -509,30 +526,27 @@ int gdsc_register(struct gdsc_desc *desc, if (!scs[i]) continue; if (scs[i]->parent) - pm_genpd_add_subdomain(scs[i]->parent, &scs[i]->pd); + ret = pm_genpd_add_subdomain(scs[i]->parent, &scs[i]->pd); else if (!IS_ERR_OR_NULL(dev->pm_domain)) - pm_genpd_add_subdomain(pd_to_genpd(dev->pm_domain), &scs[i]->pd); + ret = pm_genpd_add_subdomain(pd_to_genpd(dev->pm_domain), &scs[i]->pd); + if (ret) + goto err_pm_subdomain_remove; } return of_genpd_add_provider_onecell(dev->of_node, data); + +err_pm_subdomain_remove: + gdsc_pm_subdomain_remove(desc, i); + + return ret; } void gdsc_unregister(struct gdsc_desc *desc) { - int i; struct device *dev = desc->dev; - struct gdsc **scs = desc->scs; size_t num = desc->num; - /* Remove subdomains */ - for (i = num - 1; i >= 0; i--) { - if (!scs[i]) - continue; - if (scs[i]->parent) - pm_genpd_remove_subdomain(scs[i]->parent, &scs[i]->pd); - else if (!IS_ERR_OR_NULL(dev->pm_domain)) - pm_genpd_remove_subdomain(pd_to_genpd(dev->pm_domain), &scs[i]->pd); - } + gdsc_pm_subdomain_remove(desc, num); of_genpd_del_provider(dev->of_node); } From ecc44297ac4c68086897255222a9a864c2bd9486 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 14 Feb 2025 09:56:59 +0530 Subject: [PATCH 207/606] clk: qcom: gdsc: Set retain_ff before moving to HW CTRL commit 25708f73ff171bb4171950c9f4be5aa8504b8459 upstream. Enable the retain_ff_enable bit of GDSCR only if the GDSC is already ON. Once the GDSCR moves to HW control, SW no longer can determine the state of the GDSCR and setting the retain_ff bit could destroy all the register contents we intended to save. Therefore, move the retain_ff configuration before switching the GDSC to HW trigger mode. Cc: stable@vger.kernel.org Fixes: 173722995cdb ("clk: qcom: gdsc: Add support to enable retention of GSDCR") Signed-off-by: Taniya Das Reviewed-by: Imran Shaik Tested-by: Imran Shaik # on QCS8300 Link: https://lore.kernel.org/r/20250214-gdsc_fixes-v1-1-73e56d68a80f@quicinc.com Signed-off-by: Bjorn Andersson Signed-off-by: Greg Kroah-Hartman --- drivers/clk/qcom/gdsc.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c index 361741f3e243..5a8c93b12efa 100644 --- a/drivers/clk/qcom/gdsc.c +++ b/drivers/clk/qcom/gdsc.c @@ -292,6 +292,9 @@ static int gdsc_enable(struct generic_pm_domain *domain) */ udelay(1); + if (sc->flags & RETAIN_FF_ENABLE) + gdsc_retain_ff_on(sc); + /* Turn on HW trigger mode if supported */ if (sc->flags & HW_CTRL) { ret = gdsc_hwctrl(sc, true); @@ -308,9 +311,6 @@ static int gdsc_enable(struct generic_pm_domain *domain) udelay(1); } - if (sc->flags & RETAIN_FF_ENABLE) - gdsc_retain_ff_on(sc); - return 0; } @@ -420,13 +420,6 @@ static int gdsc_init(struct gdsc *sc) goto err_disable_supply; } - /* Turn on HW trigger mode if supported */ - if (sc->flags & HW_CTRL) { - ret = gdsc_hwctrl(sc, true); - if (ret < 0) - goto err_disable_supply; - } - /* * Make sure the retain bit is set if the GDSC is already on, * otherwise we end up turning off the GDSC and destroying all @@ -434,6 +427,14 @@ static int gdsc_init(struct gdsc *sc) */ if (sc->flags & RETAIN_FF_ENABLE) gdsc_retain_ff_on(sc); + + /* Turn on HW trigger mode if supported */ + if (sc->flags & HW_CTRL) { + ret = gdsc_hwctrl(sc, true); + if (ret < 0) + goto err_disable_supply; + } + } else if (sc->flags & ALWAYS_ON) { /* If ALWAYS_ON GDSCs are not ON, turn them ON */ gdsc_enable(&sc->pd); From 5baddc08066a230968e75b2b3d56ce866c21602c Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Fri, 17 Jan 2025 17:05:47 -0600 Subject: [PATCH 208/606] crypto: ccp - Fix check for the primary ASP device commit 07bb097b92b987db518e72525b515d77904e966e upstream. Currently, the ASP primary device check does not have support for PCI domains, and, as a result, when the system is configured with PCI domains (PCI segments) the wrong device can be selected as primary. This results in commands submitted to the device timing out and failing. The device check also relies on specific device and function assignments that may not hold in the future. Fix the primary ASP device check to include support for PCI domains and to perform proper checking of the Bus/Device/Function positions. Fixes: 2a6170dfe755 ("crypto: ccp: Add Platform Security Processor (PSP) device support") Cc: stable@vger.kernel.org Signed-off-by: Tom Lendacky Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/crypto/ccp/sp-pci.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c index b6ab56abeb68..0caa57dafc52 100644 --- a/drivers/crypto/ccp/sp-pci.c +++ b/drivers/crypto/ccp/sp-pci.c @@ -243,14 +243,17 @@ static bool sp_pci_is_master(struct sp_device *sp) pdev_new = to_pci_dev(dev_new); pdev_cur = to_pci_dev(dev_cur); - if (pdev_new->bus->number < pdev_cur->bus->number) - return true; + if (pci_domain_nr(pdev_new->bus) != pci_domain_nr(pdev_cur->bus)) + return pci_domain_nr(pdev_new->bus) < pci_domain_nr(pdev_cur->bus); - if (PCI_SLOT(pdev_new->devfn) < PCI_SLOT(pdev_cur->devfn)) - return true; + if (pdev_new->bus->number != pdev_cur->bus->number) + return pdev_new->bus->number < pdev_cur->bus->number; - if (PCI_FUNC(pdev_new->devfn) < PCI_FUNC(pdev_cur->devfn)) - return true; + if (PCI_SLOT(pdev_new->devfn) != PCI_SLOT(pdev_cur->devfn)) + return PCI_SLOT(pdev_new->devfn) < PCI_SLOT(pdev_cur->devfn); + + if (PCI_FUNC(pdev_new->devfn) != PCI_FUNC(pdev_cur->devfn)) + return PCI_FUNC(pdev_new->devfn) < PCI_FUNC(pdev_cur->devfn); return false; } From 841ca9e9224cf7624f846610652a6da3e7fe7b0a Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Fri, 28 Mar 2025 16:19:07 +0100 Subject: [PATCH 209/606] dm-ebs: fix prefetch-vs-suspend race commit 9c565428788fb9b49066f94ab7b10efc686a0a4c upstream. There's a possible race condition in dm-ebs - dm bufio prefetch may be in progress while the device is suspended. Fix this by calling dm_bufio_client_reset in the postsuspend hook. Signed-off-by: Mikulas Patocka Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-ebs-target.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/md/dm-ebs-target.c b/drivers/md/dm-ebs-target.c index 66d9622b684d..aead2215d780 100644 --- a/drivers/md/dm-ebs-target.c +++ b/drivers/md/dm-ebs-target.c @@ -390,6 +390,12 @@ static int ebs_map(struct dm_target *ti, struct bio *bio) return DM_MAPIO_REMAPPED; } +static void ebs_postsuspend(struct dm_target *ti) +{ + struct ebs_c *ec = ti->private; + dm_bufio_client_reset(ec->bufio); +} + static void ebs_status(struct dm_target *ti, status_type_t type, unsigned int status_flags, char *result, unsigned int maxlen) { @@ -447,6 +453,7 @@ static struct target_type ebs_target = { .ctr = ebs_ctr, .dtr = ebs_dtr, .map = ebs_map, + .postsuspend = ebs_postsuspend, .status = ebs_status, .io_hints = ebs_io_hints, .prepare_ioctl = ebs_prepare_ioctl, From 7958b71d8baaf5a1afaeb34130e6da3172e7401b Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Mon, 10 Feb 2025 16:14:22 +0100 Subject: [PATCH 210/606] dm-integrity: set ti->error on memory allocation failure commit 00204ae3d6712ee053353920e3ce2b00c35ef75b upstream. The dm-integrity target didn't set the error string when memory allocation failed. This patch fixes it. Signed-off-by: Mikulas Patocka Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-integrity.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c index a36dd749c688..eb2b44f4a61f 100644 --- a/drivers/md/dm-integrity.c +++ b/drivers/md/dm-integrity.c @@ -4594,16 +4594,19 @@ try_smaller_buffer: ic->recalc_bitmap = dm_integrity_alloc_page_list(n_bitmap_pages); if (!ic->recalc_bitmap) { + ti->error = "Could not allocate memory for bitmap"; r = -ENOMEM; goto bad; } ic->may_write_bitmap = dm_integrity_alloc_page_list(n_bitmap_pages); if (!ic->may_write_bitmap) { + ti->error = "Could not allocate memory for bitmap"; r = -ENOMEM; goto bad; } ic->bbs = kvmalloc_array(ic->n_bitmap_blocks, sizeof(struct bitmap_block_status), GFP_KERNEL); if (!ic->bbs) { + ti->error = "Could not allocate memory for bitmap"; r = -ENOMEM; goto bad; } From f46260c3dd4462b44d8ee7ad59ab992548bfaa29 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Fri, 28 Mar 2025 16:17:45 +0100 Subject: [PATCH 211/606] dm-verity: fix prefetch-vs-suspend race commit 2de510fccbca3d1906b55f4be5f1de83fa2424ef upstream. There's a possible race condition in dm-verity - the prefetch work item may race with suspend and it is possible that prefetch continues to run while the device is suspended. Fix this by calling flush_workqueue and dm_bufio_client_reset in the postsuspend hook. Signed-off-by: Mikulas Patocka Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-verity-target.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c index 3636387ce565..6ae97da741bb 100644 --- a/drivers/md/dm-verity-target.c +++ b/drivers/md/dm-verity-target.c @@ -836,6 +836,13 @@ static int verity_map(struct dm_target *ti, struct bio *bio) return DM_MAPIO_SUBMITTED; } +static void verity_postsuspend(struct dm_target *ti) +{ + struct dm_verity *v = ti->private; + flush_workqueue(v->verify_wq); + dm_bufio_client_reset(v->bufio); +} + /* * Status: V (valid) or C (corruption found) */ @@ -1557,6 +1564,7 @@ static struct target_type verity_target = { .ctr = verity_ctr, .dtr = verity_dtr, .map = verity_map, + .postsuspend = verity_postsuspend, .status = verity_status, .prepare_ioctl = verity_prepare_ioctl, .iterate_devices = verity_iterate_devices, From 39cf18f8ec42da1d5bda91a5f329eef34adb3f4d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 26 Feb 2025 12:29:13 +0100 Subject: [PATCH 212/606] dt-bindings: coresight: qcom,coresight-tpda: Fix too many 'reg' commit d72deaf05ac18e421d7e52a6be8966fd6ee185f4 upstream. Binding listed variable number of IO addresses without defining them, however example DTS code, all in-tree DTS and Linux kernel driver mention only one address space, so drop the second to make binding precise and correctly describe the hardware. Fixes: a8fbe1442c2b ("dt-bindings: arm: Adds CoreSight TPDA hardware definitions") Cc: stable@vger.kernel.org Signed-off-by: Krzysztof Kozlowski Signed-off-by: Suzuki K Poulose Link: https://lore.kernel.org/r/20250226112914.94361-1-krzysztof.kozlowski@linaro.org Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/arm/qcom,coresight-tpda.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-tpda.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-tpda.yaml index ea3c5db6b52d..0f7e1b6ea81e 100644 --- a/Documentation/devicetree/bindings/arm/qcom,coresight-tpda.yaml +++ b/Documentation/devicetree/bindings/arm/qcom,coresight-tpda.yaml @@ -55,8 +55,7 @@ properties: - const: arm,primecell reg: - minItems: 1 - maxItems: 2 + maxItems: 1 clocks: maxItems: 1 From 2eec9e2eb6e39598a0c8ae79dccf182bddb56799 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 26 Feb 2025 12:29:14 +0100 Subject: [PATCH 213/606] dt-bindings: coresight: qcom,coresight-tpdm: Fix too many 'reg' commit 1e4e454223f770748775f211455513c79cb3121e upstream. Binding listed variable number of IO addresses without defining them, however example DTS code, all in-tree DTS and Linux kernel driver mention only one address space, so drop the second to make binding precise and correctly describe the hardware. Fixes: 6c781a35133d ("dt-bindings: arm: Add CoreSight TPDM hardware") Cc: stable@vger.kernel.org Signed-off-by: Krzysztof Kozlowski Signed-off-by: Suzuki K Poulose Link: https://lore.kernel.org/r/20250226112914.94361-2-krzysztof.kozlowski@linaro.org Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml index 3bad47b7b02b..0b4afb4078ef 100644 --- a/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml +++ b/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml @@ -41,8 +41,7 @@ properties: - const: arm,primecell reg: - minItems: 1 - maxItems: 2 + maxItems: 1 clocks: maxItems: 1 From 5d336ac215e5c76e43ef4bca9ba699835e53e2fd Mon Sep 17 00:00:00 2001 From: zhoumin Date: Tue, 1 Apr 2025 01:00:34 +0800 Subject: [PATCH 214/606] ftrace: Add cond_resched() to ftrace_graph_set_hash() commit 42ea22e754ba4f2b86f8760ca27f6f71da2d982c upstream. When the kernel contains a large number of functions that can be traced, the loop in ftrace_graph_set_hash() may take a lot of time to execute. This may trigger the softlockup watchdog. Add cond_resched() within the loop to allow the kernel to remain responsive even when processing a large number of functions. This matches the cond_resched() that is used in other locations of the code that iterates over all functions that can be traced. Cc: stable@vger.kernel.org Fixes: b9b0c831bed26 ("ftrace: Convert graph filter to use hash tables") Link: https://lore.kernel.org/tencent_3E06CE338692017B5809534B9C5C03DA7705@qq.com Signed-off-by: zhoumin Signed-off-by: Steven Rostedt (Google) Signed-off-by: Greg Kroah-Hartman --- kernel/trace/ftrace.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 99fdeee3bcd8..580ceb75f8c3 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -6325,6 +6325,7 @@ ftrace_graph_set_hash(struct ftrace_hash *hash, char *buffer) } } } + cond_resched(); } while_for_each_ftrace_rec(); out: mutex_unlock(&ftrace_lock); From 4009ad6c7695c5e21677b9b80c557fe92127bb4e Mon Sep 17 00:00:00 2001 From: Guixin Liu Date: Thu, 27 Mar 2025 11:23:49 +0800 Subject: [PATCH 215/606] gpio: tegra186: fix resource handling in ACPI probe path commit 8323f3a69de6f6e96bf22f32dd8e2920766050c2 upstream. When the Tegra186 GPIO controller is probed through ACPI matching, the driver emits two error messages during probing: "tegra186-gpio NVDA0508:00: invalid resource (null)" "tegra186-gpio NVDA0508:00: invalid resource (null)" Fix this by getting resource first and then do the ioremap. Fixes: 2606e7c9f5fc ("gpio: tegra186: Add ACPI support") Cc: stable@vger.kernel.org Signed-off-by: Guixin Liu Link: https://lore.kernel.org/r/20250327032349.78809-1-kanie@linux.alibaba.com Signed-off-by: Bartosz Golaszewski Signed-off-by: Greg Kroah-Hartman --- drivers/gpio/gpio-tegra186.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index 9130c691a2dd..58648949f7ba 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c @@ -822,6 +822,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev) struct gpio_irq_chip *irq; struct tegra_gpio *gpio; struct device_node *np; + struct resource *res; char **names; int err; @@ -841,19 +842,19 @@ static int tegra186_gpio_probe(struct platform_device *pdev) gpio->num_banks++; /* get register apertures */ - gpio->secure = devm_platform_ioremap_resource_byname(pdev, "security"); - if (IS_ERR(gpio->secure)) { - gpio->secure = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(gpio->secure)) - return PTR_ERR(gpio->secure); - } + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "security"); + if (!res) + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + gpio->secure = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(gpio->secure)) + return PTR_ERR(gpio->secure); - gpio->base = devm_platform_ioremap_resource_byname(pdev, "gpio"); - if (IS_ERR(gpio->base)) { - gpio->base = devm_platform_ioremap_resource(pdev, 1); - if (IS_ERR(gpio->base)) - return PTR_ERR(gpio->base); - } + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gpio"); + if (!res) + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + gpio->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(gpio->base)) + return PTR_ERR(gpio->base); err = platform_irq_count(pdev); if (err < 0) From bbc702d73f716f2e20b62fb3e2c093c239a0e2ce Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 6 Apr 2025 22:22:45 +0200 Subject: [PATCH 216/606] gpio: zynq: Fix wakeup source leaks on device unbind commit c5672e310ad971d408752fce7596ed27adc6008f upstream. Device can be unbound, so driver must also release memory for the wakeup source. Cc: stable@vger.kernel.org Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20250406202245.53854-2-krzysztof.kozlowski@linaro.org Signed-off-by: Bartosz Golaszewski Signed-off-by: Greg Kroah-Hartman --- drivers/gpio/gpio-zynq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 324e942c0650..f70b72fe6edf 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -1018,6 +1018,7 @@ static int zynq_gpio_remove(struct platform_device *pdev) ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) dev_warn(&pdev->dev, "pm_runtime_get_sync() Failed\n"); + device_init_wakeup(&pdev->dev, 0); gpiochip_remove(&gpio->chip); clk_disable_unprepare(gpio->clk); device_set_wakeup_capable(&pdev->dev, 0); From 504464fd01dc10e7579eb849de39a5285e9360c7 Mon Sep 17 00:00:00 2001 From: Joshua Washington Date: Wed, 2 Apr 2025 00:10:37 +0000 Subject: [PATCH 217/606] gve: handle overflow when reporting TX consumed descriptors commit 15970e1b23f5c25db88c613fddf9131de086f28e upstream. When the tx tail is less than the head (in cases of wraparound), the TX consumed descriptor statistic in DQ will be reported as UINT32_MAX - head + tail, which is incorrect. Mask the difference of head and tail according to the ring size when reporting the statistic. Cc: stable@vger.kernel.org Fixes: 2c9198356d56 ("gve: Add consumed counts to ethtool stats") Signed-off-by: Joshua Washington Signed-off-by: Harshitha Ramamurthy Reviewed-by: Michal Swiatkowski Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250402001037.2717315-1-hramamurthy@google.com Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/google/gve/gve_ethtool.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c index 233e5946905e..22317acf16ba 100644 --- a/drivers/net/ethernet/google/gve/gve_ethtool.c +++ b/drivers/net/ethernet/google/gve/gve_ethtool.c @@ -356,7 +356,9 @@ gve_get_ethtool_stats(struct net_device *netdev, */ data[i++] = 0; data[i++] = 0; - data[i++] = tx->dqo_tx.tail - tx->dqo_tx.head; + data[i++] = + (tx->dqo_tx.tail - tx->dqo_tx.head) & + tx->mask; } do { start = From 8cb249d56e63aebbfcfdc970e5f53f73a6435997 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 14 Mar 2025 19:41:02 -0700 Subject: [PATCH 218/606] KVM: x86: Explicitly zero-initialize on-stack CPUID unions commit bc52ae0a708cb6fa3926d11c88e3c55e1171b4a1 upstream. Explicitly zero/empty-initialize the unions used for PMU related CPUID entries, instead of manually zeroing all fields (hopefully), or in the case of 0x80000022, relying on the compiler to clobber the uninitialized bitfields. Signed-off-by: Sean Christopherson Reviewed-by: Jim Mattson Message-ID: <20250315024102.2361628-1-seanjc@google.com> Cc: stable@vger.kernel.org Signed-off-by: Paolo Bonzini Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/cpuid.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 5fb12d9c71be..a6cffeff75d4 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -1011,8 +1011,8 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) } break; case 0xa: { /* Architectural Performance Monitoring */ - union cpuid10_eax eax; - union cpuid10_edx edx; + union cpuid10_eax eax = { }; + union cpuid10_edx edx = { }; if (!enable_pmu || !static_cpu_has(X86_FEATURE_ARCH_PERFMON)) { entry->eax = entry->ebx = entry->ecx = entry->edx = 0; @@ -1028,8 +1028,6 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) if (kvm_pmu_cap.version) edx.split.anythread_deprecated = 1; - edx.split.reserved1 = 0; - edx.split.reserved2 = 0; entry->eax = eax.full; entry->ebx = kvm_pmu_cap.events_mask; @@ -1303,7 +1301,7 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) break; /* AMD Extended Performance Monitoring and Debug */ case 0x80000022: { - union cpuid_0x80000022_ebx ebx; + union cpuid_0x80000022_ebx ebx = { }; entry->ecx = entry->edx = 0; if (!enable_pmu || !kvm_cpu_cap_has(X86_FEATURE_PERFMON_V2)) { From 8a3df0aa1087a89f5ce55f4aba816bfcb1ecf1be Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Tue, 1 Apr 2025 08:05:04 -0700 Subject: [PATCH 219/606] KVM: x86: Acquire SRCU in KVM_GET_MP_STATE to protect guest memory accesses commit ef01cac401f18647d62720cf773d7bb0541827da upstream. Acquire a lock on kvm->srcu when userspace is getting MP state to handle a rather extreme edge case where "accepting" APIC events, i.e. processing pending INIT or SIPI, can trigger accesses to guest memory. If the vCPU is in L2 with INIT *and* a TRIPLE_FAULT request pending, then getting MP state will trigger a nested VM-Exit by way of ->check_nested_events(), and emuating the nested VM-Exit can access guest memory. The splat was originally hit by syzkaller on a Google-internal kernel, and reproduced on an upstream kernel by hacking the triple_fault_event_test selftest to stuff a pending INIT, store an MSR on VM-Exit (to generate a memory access on VMX), and do vcpu_mp_state_get() to trigger the scenario. ============================= WARNING: suspicious RCU usage 6.14.0-rc3-b112d356288b-vmx/pi_lockdep_false_pos-lock #3 Not tainted ----------------------------- include/linux/kvm_host.h:1058 suspicious rcu_dereference_check() usage! other info that might help us debug this: rcu_scheduler_active = 2, debug_locks = 1 1 lock held by triple_fault_ev/1256: #0: ffff88810df5a330 (&vcpu->mutex){+.+.}-{4:4}, at: kvm_vcpu_ioctl+0x8b/0x9a0 [kvm] stack backtrace: CPU: 11 UID: 1000 PID: 1256 Comm: triple_fault_ev Not tainted 6.14.0-rc3-b112d356288b-vmx #3 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 Call Trace: dump_stack_lvl+0x7f/0x90 lockdep_rcu_suspicious+0x144/0x190 kvm_vcpu_gfn_to_memslot+0x156/0x180 [kvm] kvm_vcpu_read_guest+0x3e/0x90 [kvm] read_and_check_msr_entry+0x2e/0x180 [kvm_intel] __nested_vmx_vmexit+0x550/0xde0 [kvm_intel] kvm_check_nested_events+0x1b/0x30 [kvm] kvm_apic_accept_events+0x33/0x100 [kvm] kvm_arch_vcpu_ioctl_get_mpstate+0x30/0x1d0 [kvm] kvm_vcpu_ioctl+0x33e/0x9a0 [kvm] __x64_sys_ioctl+0x8b/0xb0 do_syscall_64+0x6c/0x170 entry_SYSCALL_64_after_hwframe+0x4b/0x53 Cc: stable@vger.kernel.org Signed-off-by: Sean Christopherson Message-ID: <20250401150504.829812-1-seanjc@google.com> Signed-off-by: Paolo Bonzini Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/x86.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index dcd0c12c308e..2a2dbeb56897 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -11396,6 +11396,8 @@ int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu, if (kvm_mpx_supported()) kvm_load_guest_fpu(vcpu); + kvm_vcpu_srcu_read_lock(vcpu); + r = kvm_apic_accept_events(vcpu); if (r < 0) goto out; @@ -11409,6 +11411,8 @@ int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu, mp_state->mp_state = vcpu->arch.mp_state; out: + kvm_vcpu_srcu_read_unlock(vcpu); + if (kvm_mpx_supported()) kvm_put_guest_fpu(vcpu); vcpu_put(vcpu); From 6ea67933af7c02427603dee0d163e50c8fd01d11 Mon Sep 17 00:00:00 2001 From: Fedor Pchelkin Date: Wed, 15 Jan 2025 21:28:17 +0300 Subject: [PATCH 220/606] ntb: use 64-bit arithmetic for the MSI doorbell mask commit fd5625fc86922f36bedee5846fefd647b7e72751 upstream. msi_db_mask is of type 'u64', still the standard 'int' arithmetic is performed to compute its value. While most of the ntb_hw drivers actually don't utilize the higher 32 bits of the doorbell mask now, this may be the case for Switchtec - see switchtec_ntb_init_db(). Found by Linux Verification Center (linuxtesting.org) with SVACE static analysis tool. Fixes: 2b0569b3b7e6 ("NTB: Add MSI interrupt support to ntb_transport") Cc: stable@vger.kernel.org Signed-off-by: Fedor Pchelkin Reviewed-by: Dave Jiang Signed-off-by: Jon Mason Signed-off-by: Greg Kroah-Hartman --- drivers/ntb/ntb_transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c index c84fadfc63c5..76cc5b49a5f1 100644 --- a/drivers/ntb/ntb_transport.c +++ b/drivers/ntb/ntb_transport.c @@ -1351,7 +1351,7 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev) qp_count = ilog2(qp_bitmap); if (nt->use_msi) { qp_count -= 1; - nt->msi_db_mask = 1 << qp_count; + nt->msi_db_mask = BIT_ULL(qp_count); ntb_db_clear_mask(ndev, nt->msi_db_mask); } From 77e3fd88037638b06f7b567af49df4183e3012f9 Mon Sep 17 00:00:00 2001 From: Zijun Hu Date: Sun, 9 Feb 2025 20:58:55 +0800 Subject: [PATCH 221/606] of/irq: Fix device node refcount leakage in API of_irq_parse_one() commit 0cb58d6c7b558a69957fabe159bfb184196e1e8d upstream. of_irq_parse_one(@int_gen_dev, i, ...) will leak refcount of @i_th_phandle int_gen_dev { ... interrupts-extended = ..., <&i_th_phandle ...>, ...; ... }; Refcount of @i_th_phandle is increased by of_parse_phandle_with_args() but is not decreased by API of_irq_parse_one() before return, so causes refcount leakage. Rework the refcounting to use __free() cleanup and simplify the code to have a single call to of_irq_parse_raw(). Also add comments about refcount of node @out_irq->np got by the API. Fixes: 79d9701559a9 ("of/irq: create interrupts-extended property") Cc: stable@vger.kernel.org Signed-off-by: Zijun Hu Link: https://lore.kernel.org/r/20250209-of_irq_fix-v2-2-93e3a2659aa7@quicinc.com [robh: Use __free() to do puts] Signed-off-by: Rob Herring (Arm) Signed-off-by: Greg Kroah-Hartman --- drivers/of/irq.c | 57 ++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/drivers/of/irq.c b/drivers/of/irq.c index e54f003c1aaa..1fd049d6a437 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -16,6 +16,7 @@ #define pr_fmt(fmt) "OF: " fmt +#include #include #include #include @@ -339,10 +340,12 @@ EXPORT_SYMBOL_GPL(of_irq_parse_raw); * This function resolves an interrupt for a node by walking the interrupt tree, * finding which interrupt controller node it is attached to, and returning the * interrupt specifier that can be used to retrieve a Linux IRQ number. + * + * Note: refcount of node @out_irq->np is increased by 1 on success. */ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_args *out_irq) { - struct device_node *p; + struct device_node __free(device_node) *p = NULL; const __be32 *addr; u32 intsize; int i, res, addr_len; @@ -367,41 +370,33 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar /* Try the new-style interrupts-extended first */ res = of_parse_phandle_with_args(device, "interrupts-extended", "#interrupt-cells", index, out_irq); - if (!res) - return of_irq_parse_raw(addr_buf, out_irq); + if (!res) { + p = out_irq->np; + } else { + /* Look for the interrupt parent. */ + p = of_irq_find_parent(device); + /* Get size of interrupt specifier */ + if (!p || of_property_read_u32(p, "#interrupt-cells", &intsize)) + return -EINVAL; - /* Look for the interrupt parent. */ - p = of_irq_find_parent(device); - if (p == NULL) - return -EINVAL; + pr_debug(" parent=%pOF, intsize=%d\n", p, intsize); - /* Get size of interrupt specifier */ - if (of_property_read_u32(p, "#interrupt-cells", &intsize)) { - res = -EINVAL; - goto out; + /* Copy intspec into irq structure */ + out_irq->np = p; + out_irq->args_count = intsize; + for (i = 0; i < intsize; i++) { + res = of_property_read_u32_index(device, "interrupts", + (index * intsize) + i, + out_irq->args + i); + if (res) + return res; + } + + pr_debug(" intspec=%d\n", *out_irq->args); } - pr_debug(" parent=%pOF, intsize=%d\n", p, intsize); - - /* Copy intspec into irq structure */ - out_irq->np = p; - out_irq->args_count = intsize; - for (i = 0; i < intsize; i++) { - res = of_property_read_u32_index(device, "interrupts", - (index * intsize) + i, - out_irq->args + i); - if (res) - goto out; - } - - pr_debug(" intspec=%d\n", *out_irq->args); - - /* Check if there are any interrupt-map translations to process */ - res = of_irq_parse_raw(addr_buf, out_irq); - out: - of_node_put(p); - return res; + return of_irq_parse_raw(addr_buf, out_irq); } EXPORT_SYMBOL_GPL(of_irq_parse_one); From 37ff581ddfea7893ec1a2130eb911d2c1e866a10 Mon Sep 17 00:00:00 2001 From: Zijun Hu Date: Sun, 9 Feb 2025 20:58:57 +0800 Subject: [PATCH 222/606] of/irq: Fix device node refcount leakage in API of_irq_parse_raw() commit ff93e7213d6cc8d9a7b0bc64f70ed26094e168f3 upstream. if the node @out_irq->np got by of_irq_parse_raw() is a combo node which consists of both controller and nexus, namely, of_irq_parse_raw() returns due to condition (@ipar == @newpar), then the node's refcount was increased twice, hence causes refcount leakage. Fix by putting @out_irq->np refcount before returning due to the condition. Also add comments about refcount of node @out_irq->np got by the API. Fixes: 041284181226 ("of/irq: Allow matching of an interrupt-map local to an interrupt controller") Cc: stable@vger.kernel.org Signed-off-by: Zijun Hu Link: https://lore.kernel.org/r/20250209-of_irq_fix-v2-4-93e3a2659aa7@quicinc.com Signed-off-by: Rob Herring (Arm) Signed-off-by: Greg Kroah-Hartman --- drivers/of/irq.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 1fd049d6a437..bf01b9064e29 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -166,6 +166,8 @@ const __be32 *of_irq_parse_imap_parent(const __be32 *imap, int len, struct of_ph * the specifier for each map, and then returns the translated map. * * Return: 0 on success and a negative number on error + * + * Note: refcount of node @out_irq->np is increased by 1 on success. */ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) { @@ -311,6 +313,12 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) addrsize = (imap - match_array) - intsize; if (ipar == newpar) { + /* + * We got @ipar's refcount, but the refcount was + * gotten again by of_irq_parse_imap_parent() via its + * alias @newpar. + */ + of_node_put(ipar); pr_debug("%pOF interrupt-map entry to self\n", ipar); return 0; } From eac3d34101ab97e9b558b12173a9038829ca3c67 Mon Sep 17 00:00:00 2001 From: Zijun Hu Date: Sun, 9 Feb 2025 20:58:58 +0800 Subject: [PATCH 223/606] of/irq: Fix device node refcount leakages in of_irq_count() commit bbf71f44aaf241d853759a71de7e7ebcdb89be3d upstream. of_irq_count() invokes of_irq_parse_one() to count IRQs, and successful invocation of the later will get device node @irq.np refcount, but the former does not put the refcount before next iteration invocation, hence causes device node refcount leakages. Fix by putting @irq.np refcount before the next iteration invocation. Fixes: 3da5278727a8 ("of/irq: Rework of_irq_count()") Cc: stable@vger.kernel.org Signed-off-by: Zijun Hu Link: https://lore.kernel.org/r/20250209-of_irq_fix-v2-5-93e3a2659aa7@quicinc.com Signed-off-by: Rob Herring (Arm) Signed-off-by: Greg Kroah-Hartman --- drivers/of/irq.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/of/irq.c b/drivers/of/irq.c index bf01b9064e29..e264e395cbee 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -509,8 +509,10 @@ int of_irq_count(struct device_node *dev) struct of_phandle_args irq; int nr = 0; - while (of_irq_parse_one(dev, nr, &irq) == 0) + while (of_irq_parse_one(dev, nr, &irq) == 0) { + of_node_put(irq.np); nr++; + } return nr; } From b48732849dbb80665c2a8f77c4ea28d12bbfb4db Mon Sep 17 00:00:00 2001 From: Zijun Hu Date: Sun, 9 Feb 2025 20:58:59 +0800 Subject: [PATCH 224/606] of/irq: Fix device node refcount leakage in API irq_of_parse_and_map() commit 962a2805e47b933876ba0e4c488d9e89ced2dd29 upstream. In irq_of_parse_and_map(), refcount of device node @oirq.np was got by successful of_irq_parse_one() invocation, but it does not put the refcount before return, so causes @oirq.np refcount leakage. Fix by putting @oirq.np refcount before return. Fixes: e3873444990d ("of/irq: Move irq_of_parse_and_map() to common code") Cc: stable@vger.kernel.org Signed-off-by: Zijun Hu Link: https://lore.kernel.org/r/20250209-of_irq_fix-v2-6-93e3a2659aa7@quicinc.com Signed-off-by: Rob Herring (Arm) Signed-off-by: Greg Kroah-Hartman --- drivers/of/irq.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/of/irq.c b/drivers/of/irq.c index e264e395cbee..097795001f9e 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -39,11 +39,15 @@ unsigned int irq_of_parse_and_map(struct device_node *dev, int index) { struct of_phandle_args oirq; + unsigned int ret; if (of_irq_parse_one(dev, index, &oirq)) return 0; - return irq_create_of_mapping(&oirq); + ret = irq_create_of_mapping(&oirq); + of_node_put(oirq.np); + + return ret; } EXPORT_SYMBOL_GPL(irq_of_parse_and_map); From 468773325ec18fba8f79636451cdc307ed27d091 Mon Sep 17 00:00:00 2001 From: Zijun Hu Date: Sun, 9 Feb 2025 20:59:00 +0800 Subject: [PATCH 225/606] of/irq: Fix device node refcount leakages in of_irq_init() commit 708124d9e6e7ac5ebf927830760679136b23fdf0 upstream. of_irq_init() will leak interrupt controller device node refcounts in two places as explained below: 1) Leak refcounts of both @desc->dev and @desc->interrupt_parent when suffers @desc->irq_init_cb() failure. 2) Leak refcount of @desc->interrupt_parent when cleans up list @intc_desc_list in the end. Refcounts of both @desc->dev and @desc->interrupt_parent were got in the first loop, but of_irq_init() does not put them before kfree(@desc) in places mentioned above, so causes refcount leakages. Fix by putting refcounts involved before kfree(@desc). Fixes: 8363ccb917c6 ("of/irq: add missing of_node_put") Fixes: c71a54b08201 ("of/irq: introduce of_irq_init") Cc: stable@vger.kernel.org Signed-off-by: Zijun Hu Link: https://lore.kernel.org/r/20250209-of_irq_fix-v2-7-93e3a2659aa7@quicinc.com Signed-off-by: Rob Herring (Arm) Signed-off-by: Greg Kroah-Hartman --- drivers/of/irq.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 097795001f9e..1ec2a198c669 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -633,6 +633,8 @@ void __init of_irq_init(const struct of_device_id *matches) __func__, desc->dev, desc->dev, desc->interrupt_parent); of_node_clear_flag(desc->dev, OF_POPULATED); + of_node_put(desc->interrupt_parent); + of_node_put(desc->dev); kfree(desc); continue; } @@ -663,6 +665,7 @@ void __init of_irq_init(const struct of_device_id *matches) err: list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) { list_del(&desc->list); + of_node_put(desc->interrupt_parent); of_node_put(desc->dev); kfree(desc); } From 1fea7726276e5d6526ecd4e7ccb4c91a6135deb5 Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Thu, 23 Jan 2025 00:29:55 +0200 Subject: [PATCH 226/606] PCI: brcmstb: Fix missing of_node_put() in brcm_pcie_probe() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 2df181e1aea4628a8fd257f866026625d0519627 upstream. A call to of_parse_phandle() is incrementing the refcount, and as such, the of_node_put() must be called when the reference is no longer needed. Thus, refactor the existing code and add a missing of_node_put() call following the check to ensure that "msi_np" matches "pcie->np" and after MSI initialization, but only if the MSI support is enabled system-wide. Cc: stable@vger.kernel.org # v5.10+ Fixes: 40ca1bf580ef ("PCI: brcmstb: Add MSI support") Signed-off-by: Stanimir Varbanov Reviewed-by: Florian Fainelli Reviewed-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20250122222955.1752778-1-svarbanov@suse.de [kwilczynski: commit log] Signed-off-by: Krzysztof Wilczyński Signed-off-by: Greg Kroah-Hartman --- drivers/pci/controller/pcie-brcmstb.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c index 44d385f5c27c..940af934ce1b 100644 --- a/drivers/pci/controller/pcie-brcmstb.c +++ b/drivers/pci/controller/pcie-brcmstb.c @@ -1501,7 +1501,7 @@ static struct pci_ops brcm7425_pcie_ops = { static int brcm_pcie_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node, *msi_np; + struct device_node *np = pdev->dev.of_node; struct pci_host_bridge *bridge; const struct pcie_cfg_data *data; struct brcm_pcie *pcie; @@ -1576,9 +1576,14 @@ static int brcm_pcie_probe(struct platform_device *pdev) goto fail; } - msi_np = of_parse_phandle(pcie->np, "msi-parent", 0); - if (pci_msi_enabled() && msi_np == pcie->np) { - ret = brcm_pcie_enable_msi(pcie); + if (pci_msi_enabled()) { + struct device_node *msi_np = of_parse_phandle(pcie->np, "msi-parent", 0); + + if (msi_np == pcie->np) + ret = brcm_pcie_enable_msi(pcie); + + of_node_put(msi_np); + if (ret) { dev_err(pcie->dev, "probe of internal MSI failed"); goto fail; From 6176fa57dd3096dedf343ec8b45aefbb4738e705 Mon Sep 17 00:00:00 2001 From: Ma Ke Date: Sun, 2 Feb 2025 14:23:57 +0800 Subject: [PATCH 227/606] PCI: Fix reference leak in pci_alloc_child_bus() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 1f2768b6a3ee77a295106e3a5d68458064923ede upstream. If device_register(&child->dev) fails, call put_device() to explicitly release child->dev, per the comment at device_register(). Found by code review. Link: https://lore.kernel.org/r/20250202062357.872971-1-make24@iscas.ac.cn Fixes: 4f535093cf8f ("PCI: Put pci_dev in device tree as early as possible") Signed-off-by: Ma Ke Signed-off-by: Bjorn Helgaas Reviewed-by: Ilpo Järvinen Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/pci/probe.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index bcd1ba829e1f..8e5d818c29a9 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1145,7 +1145,10 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, add_dev: pci_set_bus_msi_domain(child); ret = device_register(&child->dev); - WARN_ON(ret < 0); + if (WARN_ON(ret < 0)) { + put_device(&child->dev); + return NULL; + } pcibios_add_bus(child); From d118391566535d8e5d5c9e61e00bf928fe53eae7 Mon Sep 17 00:00:00 2001 From: Stefan Eichenberger Date: Wed, 5 Mar 2025 15:43:16 +0100 Subject: [PATCH 228/606] phy: freescale: imx8m-pcie: assert phy reset and perst in power off commit aecb63e88c5e5fb9afb782a1577264c76f179af9 upstream. Ensure the PHY reset and perst is asserted during power-off to guarantee it is in a reset state upon repeated power-on calls. This resolves an issue where the PHY may not properly initialize during subsequent power-on cycles. Power-on will deassert the reset at the appropriate time after tuning the PHY parameters. During suspend/resume cycles, we observed that the PHY PLL failed to lock during resume when the CPU temperature increased from 65C to 75C. The observed errors were: phy phy-32f00000.pcie-phy.3: phy poweron failed --> -110 imx6q-pcie 33800000.pcie: waiting for PHY ready timeout! imx6q-pcie 33800000.pcie: PM: dpm_run_callback(): genpd_resume_noirq+0x0/0x80 returns -110 imx6q-pcie 33800000.pcie: PM: failed to resume noirq: error -110 This resulted in a complete CPU freeze, which is resolved by ensuring the PHY is in reset during power-on, thus preventing PHY PLL failures. Cc: stable@vger.kernel.org Fixes: 1aa97b002258 ("phy: freescale: pcie: Initialize the imx8 pcie standalone phy driver") Signed-off-by: Stefan Eichenberger Reviewed-by: Frank Li Link: https://lore.kernel.org/r/20250305144355.20364-3-eichest@gmail.com Signed-off-by: Vinod Koul Signed-off-by: Greg Kroah-Hartman --- drivers/phy/freescale/phy-fsl-imx8m-pcie.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c index e98361dcdead..afd52392cd53 100644 --- a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c +++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c @@ -162,6 +162,16 @@ static int imx8_pcie_phy_power_on(struct phy *phy) return ret; } +static int imx8_pcie_phy_power_off(struct phy *phy) +{ + struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy); + + reset_control_assert(imx8_phy->reset); + reset_control_assert(imx8_phy->perst); + + return 0; +} + static int imx8_pcie_phy_init(struct phy *phy) { struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy); @@ -182,6 +192,7 @@ static const struct phy_ops imx8_pcie_phy_ops = { .init = imx8_pcie_phy_init, .exit = imx8_pcie_phy_exit, .power_on = imx8_pcie_phy_power_on, + .power_off = imx8_pcie_phy_power_off, .owner = THIS_MODULE, }; From 0d527afa7698729d2f9cc9c48af011265bb44452 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Wed, 12 Mar 2025 14:19:27 +0100 Subject: [PATCH 229/606] pinctrl: qcom: Clear latched interrupt status when changing IRQ type commit e225128c3f8be879e7d4eb71a25949e188b420ae upstream. When submitting the TLMM test driver, Bjorn reported that some of the test cases are failing for GPIOs that not are backed by PDC (i.e. "non-wakeup" GPIOs that are handled directly in pinctrl-msm). Basically, lingering latched interrupt state is still being delivered at IRQ request time, e.g.: ok 1 tlmm_test_silent_rising tlmm_test_silent_falling: ASSERTION FAILED at drivers/pinctrl/qcom/tlmm-test.c:178 Expected atomic_read(&priv->intr_count) == 0, but atomic_read(&priv->intr_count) == 1 (0x1) not ok 2 tlmm_test_silent_falling tlmm_test_silent_low: ASSERTION FAILED at drivers/pinctrl/qcom/tlmm-test.c:178 Expected atomic_read(&priv->intr_count) == 0, but atomic_read(&priv->intr_count) == 1 (0x1) not ok 3 tlmm_test_silent_low ok 4 tlmm_test_silent_high Whether to report interrupts that came in while the IRQ was unclaimed doesn't seem to be well-defined in the Linux IRQ API. However, looking closer at these specific cases, we're actually reporting events that do not match the interrupt type requested by the driver: 1. After "ok 1 tlmm_test_silent_rising", the GPIO is in low state and configured for IRQF_TRIGGER_RISING. 2. (a) In preparation for "tlmm_test_silent_falling", the GPIO is switched to high state. The rising interrupt gets latched. (b) The GPIO is re-configured for IRQF_TRIGGER_FALLING, but the latched interrupt isn't cleared. (c) The IRQ handler is called for the latched interrupt, but there wasn't any falling edge. 3. (a) For "tlmm_test_silent_low", the GPIO remains in high state. (b) The GPIO is re-configured for IRQF_TRIGGER_LOW. This seems to result in a phantom interrupt that gets latched. (c) The IRQ handler is called for the latched interrupt, but the GPIO isn't in low state. 4. (a) For "tlmm_test_silent_high", the GPIO is switched to low state. (b) This doesn't result in a latched interrupt, because RAW_STATUS_EN was cleared when masking the level-triggered interrupt. Fix this by clearing the interrupt state whenever making any changes to the interrupt configuration. This includes previously disabled interrupts, but also any changes to interrupt polarity or detection type. With this change, all 16 test cases are now passing for the non-wakeup GPIOs in the TLMM. Cc: stable@vger.kernel.org Fixes: cf9d052aa600 ("pinctrl: qcom: Don't clear pending interrupts when enabling") Reported-by: Bjorn Andersson Closes: https://lore.kernel.org/r/20250227-tlmm-test-v1-1-d18877b4a5db@oss.qualcomm.com/ Signed-off-by: Stephan Gerhold Tested-by: Bjorn Andersson Reviewed-by: Bjorn Andersson Link: https://lore.kernel.org/20250312-pinctrl-msm-type-latch-v1-1-ce87c561d3d7@linaro.org Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/pinctrl/qcom/pinctrl-msm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index 115b83e2d8e6..b252fc22f64e 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -1040,8 +1040,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type) const struct msm_pingroup *g; u32 intr_target_mask = GENMASK(2, 0); unsigned long flags; - bool was_enabled; - u32 val; + u32 val, oldval; if (msm_gpio_needs_dual_edge_parent_workaround(d, type)) { set_bit(d->hwirq, pctrl->dual_edge_irqs); @@ -1103,8 +1102,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type) * internal circuitry of TLMM, toggling the RAW_STATUS * could cause the INTR_STATUS to be set for EDGE interrupts. */ - val = msm_readl_intr_cfg(pctrl, g); - was_enabled = val & BIT(g->intr_raw_status_bit); + val = oldval = msm_readl_intr_cfg(pctrl, g); val |= BIT(g->intr_raw_status_bit); if (g->intr_detection_width == 2) { val &= ~(3 << g->intr_detection_bit); @@ -1157,9 +1155,11 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type) /* * The first time we set RAW_STATUS_EN it could trigger an interrupt. * Clear the interrupt. This is safe because we have - * IRQCHIP_SET_TYPE_MASKED. + * IRQCHIP_SET_TYPE_MASKED. When changing the interrupt type, we could + * also still have a non-matching interrupt latched, so clear whenever + * making changes to the interrupt configuration. */ - if (!was_enabled) + if (val != oldval) msm_ack_intr_status(pctrl, g); if (test_bit(d->hwirq, pctrl->dual_edge_irqs)) From 970688e64df97de6756b57063b7167878a25b404 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Fri, 28 Mar 2025 15:27:18 +0100 Subject: [PATCH 230/606] selftests: mptcp: close fd_in before returning in main_loop commit c183165f87a486d5879f782c05a23c179c3794ab upstream. The file descriptor 'fd_in' is opened when cfg_input is configured, but not closed in main_loop(), this patch fixes it. Fixes: 05be5e273c84 ("selftests: mptcp: add disconnect tests") Cc: stable@vger.kernel.org Co-developed-by: Cong Liu Signed-off-by: Cong Liu Signed-off-by: Geliang Tang Reviewed-by: Matthieu Baerts (NGI0) Signed-off-by: Matthieu Baerts (NGI0) Link: https://patch.msgid.link/20250328-net-mptcp-misc-fixes-6-15-v1-3-34161a482a7f@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- tools/testing/selftests/net/mptcp/mptcp_connect.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c index d240d02fa443..14851e1b185d 100644 --- a/tools/testing/selftests/net/mptcp/mptcp_connect.c +++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c @@ -1299,7 +1299,7 @@ again: ret = copyfd_io(fd_in, fd, 1, 0, &winfo); if (ret) - return ret; + goto out; if (cfg_truncate > 0) { shutdown(fd, SHUT_WR); @@ -1320,7 +1320,10 @@ again: close(fd); } - return 0; +out: + if (cfg_input) + close(fd_in); + return ret; } int parse_proto(const char *proto) From d784cb189035c67f9729b88defaa14f2e6def649 Mon Sep 17 00:00:00 2001 From: Cong Liu Date: Fri, 28 Mar 2025 15:27:17 +0100 Subject: [PATCH 231/606] selftests: mptcp: fix incorrect fd checks in main_loop commit 7335d4ac812917c16e04958775826d12d481c92d upstream. Fix a bug where the code was checking the wrong file descriptors when opening the input files. The code was checking 'fd' instead of 'fd_in', which could lead to incorrect error handling. Fixes: 05be5e273c84 ("selftests: mptcp: add disconnect tests") Cc: stable@vger.kernel.org Fixes: ca7ae8916043 ("selftests: mptcp: mptfo Initiator/Listener") Co-developed-by: Geliang Tang Signed-off-by: Geliang Tang Signed-off-by: Cong Liu Reviewed-by: Matthieu Baerts (NGI0) Signed-off-by: Matthieu Baerts (NGI0) Link: https://patch.msgid.link/20250328-net-mptcp-misc-fixes-6-15-v1-2-34161a482a7f@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- tools/testing/selftests/net/mptcp/mptcp_connect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c index 14851e1b185d..c83a8b47bbdf 100644 --- a/tools/testing/selftests/net/mptcp/mptcp_connect.c +++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c @@ -1270,7 +1270,7 @@ int main_loop(void) if (cfg_input && cfg_sockopt_types.mptfo) { fd_in = open(cfg_input, O_RDONLY); - if (fd < 0) + if (fd_in < 0) xerror("can't open %s:%d", cfg_input, errno); } @@ -1293,7 +1293,7 @@ again: if (cfg_input && !cfg_sockopt_types.mptfo) { fd_in = open(cfg_input, O_RDONLY); - if (fd < 0) + if (fd_in < 0) xerror("can't open %s:%d", cfg_input, errno); } From 4117975672c4743cffaf32b6fd018cfacd1b420e Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 7 Jan 2025 12:06:02 -0800 Subject: [PATCH 232/606] arm64: errata: Add newer ARM cores to the spectre_bhb_loop_affected() lists commit a5951389e58d2e816eed3dbec5877de9327fd881 upstream. When comparing to the ARM list [1], it appears that several ARM cores were missing from the lists in spectre_bhb_loop_affected(). Add them. NOTE: for some of these cores it may not matter since other ways of clearing the BHB may be used (like the CLRBHB instruction or ECBHB), but it still seems good to have all the info from ARM's whitepaper included. [1] https://developer.arm.com/Arm%20Security%20Center/Spectre-BHB Fixes: 558c303c9734 ("arm64: Mitigate spectre style branch history side channels") Cc: stable@vger.kernel.org Signed-off-by: Douglas Anderson Reviewed-by: James Morse Link: https://lore.kernel.org/r/20250107120555.v4.5.I4a9a527e03f663040721c5401c41de587d015c82@changeid Signed-off-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- arch/arm64/kernel/proton-pack.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c index 36a1f9a16a73..ecfbff6991bb 100644 --- a/arch/arm64/kernel/proton-pack.c +++ b/arch/arm64/kernel/proton-pack.c @@ -876,6 +876,14 @@ static u8 spectre_bhb_loop_affected(void) { u8 k = 0; + static const struct midr_range spectre_bhb_k132_list[] = { + MIDR_ALL_VERSIONS(MIDR_CORTEX_X3), + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V2), + }; + static const struct midr_range spectre_bhb_k38_list[] = { + MIDR_ALL_VERSIONS(MIDR_CORTEX_A715), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A720), + }; static const struct midr_range spectre_bhb_k32_list[] = { MIDR_ALL_VERSIONS(MIDR_CORTEX_A78), MIDR_ALL_VERSIONS(MIDR_CORTEX_A78AE), @@ -889,6 +897,7 @@ static u8 spectre_bhb_loop_affected(void) }; static const struct midr_range spectre_bhb_k24_list[] = { MIDR_ALL_VERSIONS(MIDR_CORTEX_A76), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A76AE), MIDR_ALL_VERSIONS(MIDR_CORTEX_A77), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_GOLD), @@ -904,7 +913,11 @@ static u8 spectre_bhb_loop_affected(void) {}, }; - if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k32_list)) + if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k132_list)) + k = 132; + else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k38_list)) + k = 38; + else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k32_list)) k = 32; else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k24_list)) k = 24; From 8d25a8e275bb0b74fe84367e83f23bf8fc0de5ce Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Fri, 28 Feb 2025 01:44:14 +0000 Subject: [PATCH 233/606] x86/paravirt: Move halt paravirt calls under CONFIG_PARAVIRT commit 22cc5ca5de52bbfc36a7d4a55323f91fb4492264 upstream. CONFIG_PARAVIRT_XXL is mainly defined/used by XEN PV guests. For other VM guest types, features supported under CONFIG_PARAVIRT are self sufficient. CONFIG_PARAVIRT mainly provides support for TLB flush operations and time related operations. For TDX guest as well, paravirt calls under CONFIG_PARVIRT meets most of its requirement except the need of HLT and SAFE_HLT paravirt calls, which is currently defined under CONFIG_PARAVIRT_XXL. Since enabling CONFIG_PARAVIRT_XXL is too bloated for TDX guest like platforms, move HLT and SAFE_HLT paravirt calls under CONFIG_PARAVIRT. Moving HLT and SAFE_HLT paravirt calls are not fatal and should not break any functionality for current users of CONFIG_PARAVIRT. Fixes: bfe6ed0c6727 ("x86/tdx: Add HLT support for TDX guests") Co-developed-by: Kuppuswamy Sathyanarayanan Signed-off-by: Kuppuswamy Sathyanarayanan Signed-off-by: Kirill A. Shutemov Signed-off-by: Vishal Annapurve Signed-off-by: Ingo Molnar Reviewed-by: Andi Kleen Reviewed-by: Tony Luck Reviewed-by: Juergen Gross Tested-by: Ryan Afranji Cc: Andy Lutomirski Cc: Brian Gerst Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Josh Poimboeuf Cc: stable@kernel.org Link: https://lore.kernel.org/r/20250228014416.3925664-2-vannapurve@google.com Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/irqflags.h | 40 +++++++++++++++------------ arch/x86/include/asm/paravirt.h | 20 +++++++------- arch/x86/include/asm/paravirt_types.h | 3 +- arch/x86/kernel/paravirt.c | 14 ++++++---- 4 files changed, 41 insertions(+), 36 deletions(-) diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h index 8c5ae649d2df..9acfe2bcf1fd 100644 --- a/arch/x86/include/asm/irqflags.h +++ b/arch/x86/include/asm/irqflags.h @@ -56,6 +56,28 @@ static __always_inline void native_halt(void) #endif +#ifndef CONFIG_PARAVIRT +#ifndef __ASSEMBLY__ +/* + * Used in the idle loop; sti takes one instruction cycle + * to complete: + */ +static __always_inline void arch_safe_halt(void) +{ + native_safe_halt(); +} + +/* + * Used when interrupts are already enabled or to + * shutdown the processor: + */ +static __always_inline void halt(void) +{ + native_halt(); +} +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_PARAVIRT */ + #ifdef CONFIG_PARAVIRT_XXL #include #else @@ -77,24 +99,6 @@ static __always_inline void arch_local_irq_enable(void) native_irq_enable(); } -/* - * Used in the idle loop; sti takes one instruction cycle - * to complete: - */ -static __always_inline void arch_safe_halt(void) -{ - native_safe_halt(); -} - -/* - * Used when interrupts are already enabled or to - * shutdown the processor: - */ -static __always_inline void halt(void) -{ - native_halt(); -} - /* * For spinlocks, etc: */ diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 6c8ff12140ae..d8537e30cee1 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -103,6 +103,16 @@ static inline void notify_page_enc_status_changed(unsigned long pfn, PVOP_VCALL3(mmu.notify_page_enc_status_changed, pfn, npages, enc); } +static __always_inline void arch_safe_halt(void) +{ + PVOP_VCALL0(irq.safe_halt); +} + +static inline void halt(void) +{ + PVOP_VCALL0(irq.halt); +} + #ifdef CONFIG_PARAVIRT_XXL static inline void load_sp0(unsigned long sp0) { @@ -168,16 +178,6 @@ static inline void __write_cr4(unsigned long x) PVOP_VCALL1(cpu.write_cr4, x); } -static __always_inline void arch_safe_halt(void) -{ - PVOP_VCALL0(irq.safe_halt); -} - -static inline void halt(void) -{ - PVOP_VCALL0(irq.halt); -} - extern noinstr void pv_native_wbinvd(void); static __always_inline void wbinvd(void) diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h index 772d03487520..4149df559aae 100644 --- a/arch/x86/include/asm/paravirt_types.h +++ b/arch/x86/include/asm/paravirt_types.h @@ -130,10 +130,9 @@ struct pv_irq_ops { struct paravirt_callee_save save_fl; struct paravirt_callee_save irq_disable; struct paravirt_callee_save irq_enable; - +#endif void (*safe_halt)(void); void (*halt)(void); -#endif } __no_randomize_layout; struct pv_mmu_ops { diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 8d51c86caa41..234851fe0ef8 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -142,6 +142,11 @@ int paravirt_disable_iospace(void) return request_resource(&ioport_resource, &reserve_ioports); } +static noinstr void pv_native_safe_halt(void) +{ + native_safe_halt(); +} + #ifdef CONFIG_PARAVIRT_XXL static noinstr void pv_native_write_cr2(unsigned long val) { @@ -162,11 +167,6 @@ noinstr void pv_native_wbinvd(void) { native_wbinvd(); } - -static noinstr void pv_native_safe_halt(void) -{ - native_safe_halt(); -} #endif struct pv_info pv_info = { @@ -224,9 +224,11 @@ struct paravirt_patch_template pv_ops = { .irq.save_fl = __PV_IS_CALLEE_SAVE(pv_native_save_fl), .irq.irq_disable = __PV_IS_CALLEE_SAVE(pv_native_irq_disable), .irq.irq_enable = __PV_IS_CALLEE_SAVE(pv_native_irq_enable), +#endif /* CONFIG_PARAVIRT_XXL */ + + /* Irq HLT ops. */ .irq.safe_halt = pv_native_safe_halt, .irq.halt = native_halt, -#endif /* CONFIG_PARAVIRT_XXL */ /* Mmu ops. */ .mmu.flush_tlb_user = native_flush_tlb_local, From e5eadb652014727028fe2744774cfbd3e5da56fe Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Mon, 10 Feb 2025 21:28:25 -0500 Subject: [PATCH 234/606] ACPI: platform-profile: Fix CFI violation when accessing sysfs files commit dd4f730b557ce701a2cd4f604bf1e57667bd8b6e upstream. When an attribute group is created with sysfs_create_group(), the ->sysfs_ops() callback is set to kobj_sysfs_ops, which sets the ->show() and ->store() callbacks to kobj_attr_show() and kobj_attr_store() respectively. These functions use container_of() to get the respective callback from the passed attribute, meaning that these callbacks need to be of the same type as the callbacks in 'struct kobj_attribute'. However, ->show() and ->store() in the platform_profile driver are defined for struct device_attribute with the help of DEVICE_ATTR_RO() and DEVICE_ATTR_RW(), which results in a CFI violation when accessing platform_profile or platform_profile_choices under /sys/firmware/acpi because the types do not match: CFI failure at kobj_attr_show+0x19/0x30 (target: platform_profile_choices_show+0x0/0x140; expected type: 0x7a69590c) There is no functional issue from the type mismatch because the layout of 'struct kobj_attribute' and 'struct device_attribute' are the same, so the container_of() cast does not break anything aside from CFI. Change the type of platform_profile_choices_show() and platform_profile_{show,store}() to match the callbacks in 'struct kobj_attribute' and update the attribute variables to match, which resolves the CFI violation. Cc: All applicable Fixes: a2ff95e018f1 ("ACPI: platform: Add platform profile support") Reported-by: John Rowley Closes: https://github.com/ClangBuiltLinux/linux/issues/2047 Tested-by: John Rowley Reviewed-by: Sami Tolvanen Signed-off-by: Nathan Chancellor Acked-by: Greg Kroah-Hartman Reviewed-by: Mark Pearson Tested-by: Mark Pearson Link: https://patch.msgid.link/20250210-acpi-platform_profile-fix-cfi-violation-v3-1-ed9e9901c33a@kernel.org [ rjw: Changelog edits ] Signed-off-by: Rafael J. Wysocki [nathan: Fix conflicts in older stable branches] Signed-off-by: Nathan Chancellor Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/platform_profile.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index d418462ab791..89f34310237c 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -22,8 +22,8 @@ static const char * const profile_names[] = { }; static_assert(ARRAY_SIZE(profile_names) == PLATFORM_PROFILE_LAST); -static ssize_t platform_profile_choices_show(struct device *dev, - struct device_attribute *attr, +static ssize_t platform_profile_choices_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { int len = 0; @@ -49,8 +49,8 @@ static ssize_t platform_profile_choices_show(struct device *dev, return len; } -static ssize_t platform_profile_show(struct device *dev, - struct device_attribute *attr, +static ssize_t platform_profile_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { enum platform_profile_option profile = PLATFORM_PROFILE_BALANCED; @@ -77,8 +77,8 @@ static ssize_t platform_profile_show(struct device *dev, return sysfs_emit(buf, "%s\n", profile_names[profile]); } -static ssize_t platform_profile_store(struct device *dev, - struct device_attribute *attr, +static ssize_t platform_profile_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) { int err, i; @@ -115,12 +115,12 @@ static ssize_t platform_profile_store(struct device *dev, return count; } -static DEVICE_ATTR_RO(platform_profile_choices); -static DEVICE_ATTR_RW(platform_profile); +static struct kobj_attribute attr_platform_profile_choices = __ATTR_RO(platform_profile_choices); +static struct kobj_attribute attr_platform_profile = __ATTR_RW(platform_profile); static struct attribute *platform_profile_attrs[] = { - &dev_attr_platform_profile_choices.attr, - &dev_attr_platform_profile.attr, + &attr_platform_profile_choices.attr, + &attr_platform_profile.attr, NULL }; From bf56f45b167ee0e8ea88b43e503b86cd294abd5a Mon Sep 17 00:00:00 2001 From: Yi Liu Date: Wed, 5 Mar 2025 19:48:42 -0800 Subject: [PATCH 235/606] iommufd: Fail replace if device has not been attached commit 55c85fa7579dc2e3f5399ef5bad67a44257c1a48 upstream. The current implementation of iommufd_device_do_replace() implicitly assumes that the input device has already been attached. However, there is no explicit check to verify this assumption. If another device within the same group has been attached, the replace operation might succeed, but the input device itself may not have been attached yet. As a result, the input device might not be tracked in the igroup->device_list, and its reserved IOVA might not be added. Despite this, the caller might incorrectly assume that the device has been successfully replaced, which could lead to unexpected behavior or errors. To address this issue, add a check to ensure that the input device has been attached before proceeding with the replace operation. This check will help maintain the integrity of the device tracking system and prevent potential issues arising from incorrect assumptions about the device's attachment status. Fixes: e88d4ec154a8 ("iommufd: Add iommufd_device_replace()") Link: https://patch.msgid.link/r/20250306034842.5950-1-yi.l.liu@intel.com Cc: stable@vger.kernel.org Reviewed-by: Kevin Tian Signed-off-by: Yi Liu Signed-off-by: Jason Gunthorpe Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/iommufd/device.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c index cf76a0eeeded..ff6386fd1e8f 100644 --- a/drivers/iommu/iommufd/device.c +++ b/drivers/iommu/iommufd/device.c @@ -407,6 +407,17 @@ iommufd_device_do_attach(struct iommufd_device *idev, return NULL; } +/* Check if idev is attached to igroup->hwpt */ +static bool iommufd_device_is_attached(struct iommufd_device *idev) +{ + struct iommufd_device *cur; + + list_for_each_entry(cur, &idev->igroup->device_list, group_item) + if (cur == idev) + return true; + return false; +} + static struct iommufd_hw_pagetable * iommufd_device_do_replace(struct iommufd_device *idev, struct iommufd_hw_pagetable *hwpt) @@ -424,6 +435,11 @@ iommufd_device_do_replace(struct iommufd_device *idev, goto err_unlock; } + if (!iommufd_device_is_attached(idev)) { + rc = -EINVAL; + goto err_unlock; + } + if (hwpt == igroup->hwpt) { mutex_unlock(&idev->igroup->lock); return NULL; From 5029c8f2d7eaa3e2e601fd4f8c476ade627d16dd Mon Sep 17 00:00:00 2001 From: Myrrh Periwinkle Date: Sun, 6 Apr 2025 11:45:22 +0700 Subject: [PATCH 236/606] x86/e820: Fix handling of subpage regions when calculating nosave ranges in e820__register_nosave_regions() commit f2f29da9f0d4367f6ff35e0d9d021257bb53e273 upstream. While debugging kexec/hibernation hangs and crashes, it turned out that the current implementation of e820__register_nosave_regions() suffers from multiple serious issues: - The end of last region is tracked by PFN, causing it to find holes that aren't there if two consecutive subpage regions are present - The nosave PFN ranges derived from holes are rounded out (instead of rounded in) which makes it inconsistent with how explicitly reserved regions are handled Fix this by: - Treating reserved regions as if they were holes, to ensure consistent handling (rounding out nosave PFN ranges is more correct as the kernel does not use partial pages) - Tracking the end of the last RAM region by address instead of pages to detect holes more precisely These bugs appear to have been introduced about ~18 years ago with the very first version of e820_mark_nosave_regions(), and its flawed assumptions were carried forward uninterrupted through various waves of rewrites and renames. [ mingo: Added Git archeology details, for kicks and giggles. ] Fixes: e8eff5ac294e ("[PATCH] Make swsusp avoid memory holes and reserved memory regions on x86_64") Reported-by: Roberto Ricci Tested-by: Roberto Ricci Signed-off-by: Myrrh Periwinkle Signed-off-by: Ingo Molnar Cc: Rafael J. Wysocki Cc: Ard Biesheuvel Cc: H. Peter Anvin Cc: Kees Cook Cc: Linus Torvalds Cc: David Woodhouse Cc: Len Brown Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250406-fix-e820-nosave-v3-1-f3787bc1ee1d@qtmlabs.xyz Closes: https://lore.kernel.org/all/Z4WFjBVHpndct7br@desktop0a/ Signed-off-by: Myrrh Periwinkle Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/e820.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index b66f540de054..1f6fb8e85e0f 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -753,22 +753,21 @@ void __init e820__memory_setup_extended(u64 phys_addr, u32 data_len) void __init e820__register_nosave_regions(unsigned long limit_pfn) { int i; - unsigned long pfn = 0; + u64 last_addr = 0; for (i = 0; i < e820_table->nr_entries; i++) { struct e820_entry *entry = &e820_table->entries[i]; - if (pfn < PFN_UP(entry->addr)) - register_nosave_region(pfn, PFN_UP(entry->addr)); - - pfn = PFN_DOWN(entry->addr + entry->size); - if (entry->type != E820_TYPE_RAM && entry->type != E820_TYPE_RESERVED_KERN) - register_nosave_region(PFN_UP(entry->addr), pfn); + continue; - if (pfn >= limit_pfn) - break; + if (last_addr < entry->addr) + register_nosave_region(PFN_DOWN(last_addr), PFN_UP(entry->addr)); + + last_addr = entry->addr + entry->size; } + + register_nosave_region(PFN_DOWN(last_addr), limit_pfn); } #ifdef CONFIG_ACPI From fa43166f2e8bac4616db14a4ef6e07eaea227ba0 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 18 Oct 2024 15:14:42 +0000 Subject: [PATCH 237/606] media: mediatek: vcodec: mark vdec_vp9_slice_map_counts_eob_coef noinline commit 8b55f8818900c99dd4f55a59a103f5b29e41eb2c upstream. With KASAN enabled, clang fails to optimize the inline version of vdec_vp9_slice_map_counts_eob_coef() properly, leading to kilobytes of temporary values spilled to the stack: drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c:1526:12: error: stack frame size (2160) exceeds limit (2048) in 'vdec_vp9_slice_update_prob' [-Werror,-Wframe-larger-than] This seems to affect all versions of clang including the latest (clang-20), but the degree of stack overhead is different per release. Marking the function as noinline_for_stack is harmless here and avoids the problem completely. Signed-off-by: Arnd Bergmann Reviewed-by: Nathan Chancellor Signed-off-by: Sebastian Fricke Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman --- .../mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c index e393e3e668f8..3fe192a1d5a1 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c @@ -1189,7 +1189,8 @@ err: return ret; } -static +/* clang stack usage explodes if this is inlined */ +static noinline_for_stack void vdec_vp9_slice_map_counts_eob_coef(unsigned int i, unsigned int j, unsigned int k, struct vdec_vp9_slice_frame_counts *counts, struct v4l2_vp9_frame_symbol_counts *counts_helper) From 02e1bcdfdf769974e7e9fa285e295cd9852e2a38 Mon Sep 17 00:00:00 2001 From: Arseniy Krasnov Date: Wed, 12 Feb 2025 18:59:46 +0300 Subject: [PATCH 238/606] Bluetooth: hci_uart: Fix another race during initialization commit 5df5dafc171b90d0b8d51547a82657cd5a1986c7 upstream. Do not set 'HCI_UART_PROTO_READY' before call 'hci_uart_register_dev()'. Possible race is when someone calls 'hci_tty_uart_close()' after this bit is set, but 'hci_uart_register_dev()' wasn't done. This leads to access to uninitialized fields. To fix it let's set this bit after device was registered (as before patch c411c62cc133) and to fix previous problem let's add one more bit in addition to 'HCI_UART_PROTO_READY' which allows to perform power up without original bit set (pls see commit c411c62cc133). Crash backtrace from syzbot report: RIP: 0010:skb_queue_empty_lockless include/linux/skbuff.h:1887 [inline] RIP: 0010:skb_queue_purge_reason+0x6d/0x140 net/core/skbuff.c:3936 Call Trace: skb_queue_purge include/linux/skbuff.h:3364 [inline] mrvl_close+0x2f/0x90 drivers/bluetooth/hci_mrvl.c:100 hci_uart_tty_close+0xb6/0x120 drivers/bluetooth/hci_ldisc.c:557 tty_ldisc_close drivers/tty/tty_ldisc.c:455 [inline] tty_ldisc_kill+0x66/0xc0 drivers/tty/tty_ldisc.c:613 tty_ldisc_release+0xc9/0x120 drivers/tty/tty_ldisc.c:781 tty_release_struct+0x10/0x80 drivers/tty/tty_io.c:1690 tty_release+0x4ef/0x640 drivers/tty/tty_io.c:1861 __fput+0x86/0x2a0 fs/file_table.c:450 task_work_run+0x82/0xb0 kernel/task_work.c:239 resume_user_mode_work include/linux/resume_user_mode.h:50 [inline] exit_to_user_mode_loop kernel/entry/common.c:114 [inline] exit_to_user_mode_prepare include/linux/entry-common.h:329 [inline] __syscall_exit_to_user_mode_work kernel/entry/common.c:207 [inline] syscall_exit_to_user_mode+0xa3/0x1b0 kernel/entry/common.c:218 do_syscall_64+0x9a/0x190 arch/x86/entry/common.c:89 entry_SYSCALL_64_after_hwframe+0x77/0x7f Signed-off-by: Arseniy Krasnov Reported-by: syzbot+683f8cb11b94b1824c77@syzkaller.appspotmail.com Tested-by: syzbot+683f8cb11b94b1824c77@syzkaller.appspotmail.com Closes: https://lore.kernel.org/linux-bluetooth/d159c57f-8490-4c26-79da-6ad3612c4a14@salutedevices.com/ Fixes: 366ceff495f9 ("Bluetooth: hci_uart: fix race during initialization") Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Greg Kroah-Hartman --- drivers/bluetooth/hci_ldisc.c | 20 ++++++++++++++------ drivers/bluetooth/hci_uart.h | 1 + 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index b67023d69e03..70320b8f1aa1 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -102,7 +102,8 @@ static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu) if (!skb) { percpu_down_read(&hu->proto_lock); - if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) + if (test_bit(HCI_UART_PROTO_READY, &hu->flags) || + test_bit(HCI_UART_PROTO_INIT, &hu->flags)) skb = hu->proto->dequeue(hu); percpu_up_read(&hu->proto_lock); @@ -124,7 +125,8 @@ int hci_uart_tx_wakeup(struct hci_uart *hu) if (!percpu_down_read_trylock(&hu->proto_lock)) return 0; - if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) && + !test_bit(HCI_UART_PROTO_INIT, &hu->flags)) goto no_schedule; set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state); @@ -278,7 +280,8 @@ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb) percpu_down_read(&hu->proto_lock); - if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) { + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) && + !test_bit(HCI_UART_PROTO_INIT, &hu->flags)) { percpu_up_read(&hu->proto_lock); return -EUNATCH; } @@ -582,7 +585,8 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty) if (tty != hu->tty) return; - if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) + if (test_bit(HCI_UART_PROTO_READY, &hu->flags) || + test_bit(HCI_UART_PROTO_INIT, &hu->flags)) hci_uart_tx_wakeup(hu); } @@ -608,7 +612,8 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, percpu_down_read(&hu->proto_lock); - if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) { + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags) && + !test_bit(HCI_UART_PROTO_INIT, &hu->flags)) { percpu_up_read(&hu->proto_lock); return; } @@ -704,13 +709,16 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id) hu->proto = p; - set_bit(HCI_UART_PROTO_READY, &hu->flags); + set_bit(HCI_UART_PROTO_INIT, &hu->flags); err = hci_uart_register_dev(hu); if (err) { return err; } + set_bit(HCI_UART_PROTO_READY, &hu->flags); + clear_bit(HCI_UART_PROTO_INIT, &hu->flags); + return 0; } diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h index 00bf7ae82c5b..39f39704be41 100644 --- a/drivers/bluetooth/hci_uart.h +++ b/drivers/bluetooth/hci_uart.h @@ -89,6 +89,7 @@ struct hci_uart { #define HCI_UART_REGISTERED 1 #define HCI_UART_PROTO_READY 2 #define HCI_UART_NO_SUSPEND_NOTIFIER 3 +#define HCI_UART_PROTO_INIT 4 /* TX states */ #define HCI_UART_SENDING 1 From 58eb29dba712ab0f13af59ca2fe545f5ce360e78 Mon Sep 17 00:00:00 2001 From: Kaixin Wang Date: Wed, 18 Sep 2024 20:07:50 +0800 Subject: [PATCH 239/606] HSI: ssi_protocol: Fix use after free vulnerability in ssi_protocol Driver Due to Race Condition commit e3f88665a78045fe35c7669d2926b8d97b892c11 upstream. In the ssi_protocol_probe() function, &ssi->work is bound with ssip_xmit_work(), In ssip_pn_setup(), the ssip_pn_xmit() function within the ssip_pn_ops structure is capable of starting the work. If we remove the module which will call ssi_protocol_remove() to make a cleanup, it will free ssi through kfree(ssi), while the work mentioned above will be used. The sequence of operations that may lead to a UAF bug is as follows: CPU0 CPU1 | ssip_xmit_work ssi_protocol_remove | kfree(ssi); | | struct hsi_client *cl = ssi->cl; | // use ssi Fix it by ensuring that the work is canceled before proceeding with the cleanup in ssi_protocol_remove(). Signed-off-by: Kaixin Wang Acked-by: Andy Shevchenko Link: https://lore.kernel.org/r/20240918120749.1730-1-kxwang23@m.fudan.edu.cn Signed-off-by: Sebastian Reichel Signed-off-by: Greg Kroah-Hartman --- drivers/hsi/clients/ssi_protocol.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c index da6a7abd584f..f8ccb29c6380 100644 --- a/drivers/hsi/clients/ssi_protocol.c +++ b/drivers/hsi/clients/ssi_protocol.c @@ -401,6 +401,7 @@ static void ssip_reset(struct hsi_client *cl) del_timer(&ssi->rx_wd); del_timer(&ssi->tx_wd); del_timer(&ssi->keep_alive); + cancel_work_sync(&ssi->work); ssi->main_state = 0; ssi->send_state = 0; ssi->recv_state = 0; From a70ea9296419161d25ce586a8e91f0a5f5d48742 Mon Sep 17 00:00:00 2001 From: Xingui Yang Date: Wed, 12 Mar 2025 17:51:34 +0800 Subject: [PATCH 240/606] scsi: hisi_sas: Enable force phy when SATA disk directly connected [ Upstream commit 8aa580cd92843b60d4d6331f3b0a9e8409bb70eb ] when a SATA disk is directly connected the SAS controller determines the disk to which I/Os are delivered based on the port ID in the DQ entry. When many phys are disconnected and reconnect, the port ID of phys were changed and used by other link, resulting in I/O being sent to incorrect disk. Data inconsistency on the SATA disk may occur during I/O retries using the old port ID. So enable force phy, then force the command to be executed in a certain phy, and if the actual phy ID of the port does not match the phy configured in the command, the chip will stop delivering the I/O to disk. Fixes: ce60689e12dd ("scsi: hisi_sas: add v3 code to send ATA frame") Signed-off-by: Xingui Yang Link: https://lore.kernel.org/r/20250312095135.3048379-2-yangxingui@huawei.com Reviewed-by: Yihang Li Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 9 +++++++-- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 14 ++++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 73b378837da7..e6bcc3171391 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -2501,6 +2501,7 @@ static void prep_ata_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_port *port = to_hisi_sas_port(sas_port); struct sas_ata_task *ata_task = &task->ata_task; struct sas_tmf_task *tmf = slot->tmf; + int phy_id; u8 *buf_cmd; int has_data = 0, hdr_tag = 0; u32 dw0, dw1 = 0, dw2 = 0; @@ -2508,10 +2509,14 @@ static void prep_ata_v2_hw(struct hisi_hba *hisi_hba, /* create header */ /* dw0 */ dw0 = port->id << CMD_HDR_PORT_OFF; - if (parent_dev && dev_is_expander(parent_dev->dev_type)) + if (parent_dev && dev_is_expander(parent_dev->dev_type)) { dw0 |= 3 << CMD_HDR_CMD_OFF; - else + } else { + phy_id = device->phy->identify.phy_identifier; + dw0 |= (1U << phy_id) << CMD_HDR_PHY_ID_OFF; + dw0 |= CMD_HDR_FORCE_PHY_MSK; dw0 |= 4 << CMD_HDR_CMD_OFF; + } if (tmf && ata_task->force_phy) { dw0 |= CMD_HDR_FORCE_PHY_MSK; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index ff5f86867dbf..596b5426d995 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -358,6 +358,10 @@ #define CMD_HDR_RESP_REPORT_MSK (0x1 << CMD_HDR_RESP_REPORT_OFF) #define CMD_HDR_TLR_CTRL_OFF 6 #define CMD_HDR_TLR_CTRL_MSK (0x3 << CMD_HDR_TLR_CTRL_OFF) +#define CMD_HDR_PHY_ID_OFF 8 +#define CMD_HDR_PHY_ID_MSK (0x1ff << CMD_HDR_PHY_ID_OFF) +#define CMD_HDR_FORCE_PHY_OFF 17 +#define CMD_HDR_FORCE_PHY_MSK (0x1U << CMD_HDR_FORCE_PHY_OFF) #define CMD_HDR_PORT_OFF 18 #define CMD_HDR_PORT_MSK (0xf << CMD_HDR_PORT_OFF) #define CMD_HDR_PRIORITY_OFF 27 @@ -1425,15 +1429,21 @@ static void prep_ata_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr; struct asd_sas_port *sas_port = device->port; struct hisi_sas_port *port = to_hisi_sas_port(sas_port); + int phy_id; u8 *buf_cmd; int has_data = 0, hdr_tag = 0; u32 dw1 = 0, dw2 = 0; hdr->dw0 = cpu_to_le32(port->id << CMD_HDR_PORT_OFF); - if (parent_dev && dev_is_expander(parent_dev->dev_type)) + if (parent_dev && dev_is_expander(parent_dev->dev_type)) { hdr->dw0 |= cpu_to_le32(3 << CMD_HDR_CMD_OFF); - else + } else { + phy_id = device->phy->identify.phy_identifier; + hdr->dw0 |= cpu_to_le32((1U << phy_id) + << CMD_HDR_PHY_ID_OFF); + hdr->dw0 |= CMD_HDR_FORCE_PHY_MSK; hdr->dw0 |= cpu_to_le32(4U << CMD_HDR_CMD_OFF); + } switch (task->data_dir) { case DMA_TO_DEVICE: From 7ca513631fa6ad3011b8b9197cdde0f351103704 Mon Sep 17 00:00:00 2001 From: Abdun Nihaal Date: Sun, 30 Mar 2025 16:01:10 +0530 Subject: [PATCH 241/606] wifi: at76c50x: fix use after free access in at76_disconnect [ Upstream commit 27c7e63b3cb1a20bb78ed4a36c561ea4579fd7da ] The memory pointed to by priv is freed at the end of at76_delete_device function (using ieee80211_free_hw). But the code then accesses the udev field of the freed object to put the USB device. This may also lead to a memory leak of the usb device. Fix this by using udev from interface. Fixes: 29e20aa6c6af ("at76c50x-usb: fix use after free on failure path in at76_probe()") Signed-off-by: Abdun Nihaal Link: https://patch.msgid.link/20250330103110.44080-1-abdun.nihaal@gmail.com Signed-off-by: Johannes Berg Signed-off-by: Sasha Levin --- drivers/net/wireless/atmel/at76c50x-usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/atmel/at76c50x-usb.c b/drivers/net/wireless/atmel/at76c50x-usb.c index 447b51cff8f9..c1a92c7f0f8e 100644 --- a/drivers/net/wireless/atmel/at76c50x-usb.c +++ b/drivers/net/wireless/atmel/at76c50x-usb.c @@ -2554,7 +2554,7 @@ static void at76_disconnect(struct usb_interface *interface) wiphy_info(priv->hw->wiphy, "disconnecting\n"); at76_delete_device(priv); - usb_put_dev(priv->udev); + usb_put_dev(interface_to_usbdev(interface)); dev_info(&interface->dev, "disconnected\n"); } From 7fa75affe2a97abface2b0d9b95e15728967dda7 Mon Sep 17 00:00:00 2001 From: Remi Pommarel Date: Mon, 24 Mar 2025 17:28:20 +0100 Subject: [PATCH 242/606] wifi: mac80211: Update skb's control block key in ieee80211_tx_dequeue() [ Upstream commit a104042e2bf6528199adb6ca901efe7b60c2c27f ] The ieee80211 skb control block key (set when skb was queued) could have been removed before ieee80211_tx_dequeue() call. ieee80211_tx_dequeue() already called ieee80211_tx_h_select_key() to get the current key, but the latter do not update the key in skb control block in case it is NULL. Because some drivers actually use this key in their TX callbacks (e.g. ath1{1,2}k_mac_op_tx()) this could lead to the use after free below: BUG: KASAN: slab-use-after-free in ath11k_mac_op_tx+0x590/0x61c Read of size 4 at addr ffffff803083c248 by task kworker/u16:4/1440 CPU: 3 UID: 0 PID: 1440 Comm: kworker/u16:4 Not tainted 6.13.0-ge128f627f404 #2 Hardware name: HW (DT) Workqueue: bat_events batadv_send_outstanding_bcast_packet Call trace: show_stack+0x14/0x1c (C) dump_stack_lvl+0x58/0x74 print_report+0x164/0x4c0 kasan_report+0xac/0xe8 __asan_report_load4_noabort+0x1c/0x24 ath11k_mac_op_tx+0x590/0x61c ieee80211_handle_wake_tx_queue+0x12c/0x1c8 ieee80211_queue_skb+0xdcc/0x1b4c ieee80211_tx+0x1ec/0x2bc ieee80211_xmit+0x224/0x324 __ieee80211_subif_start_xmit+0x85c/0xcf8 ieee80211_subif_start_xmit+0xc0/0xec4 dev_hard_start_xmit+0xf4/0x28c __dev_queue_xmit+0x6ac/0x318c batadv_send_skb_packet+0x38c/0x4b0 batadv_send_outstanding_bcast_packet+0x110/0x328 process_one_work+0x578/0xc10 worker_thread+0x4bc/0xc7c kthread+0x2f8/0x380 ret_from_fork+0x10/0x20 Allocated by task 1906: kasan_save_stack+0x28/0x4c kasan_save_track+0x1c/0x40 kasan_save_alloc_info+0x3c/0x4c __kasan_kmalloc+0xac/0xb0 __kmalloc_noprof+0x1b4/0x380 ieee80211_key_alloc+0x3c/0xb64 ieee80211_add_key+0x1b4/0x71c nl80211_new_key+0x2b4/0x5d8 genl_family_rcv_msg_doit+0x198/0x240 <...> Freed by task 1494: kasan_save_stack+0x28/0x4c kasan_save_track+0x1c/0x40 kasan_save_free_info+0x48/0x94 __kasan_slab_free+0x48/0x60 kfree+0xc8/0x31c kfree_sensitive+0x70/0x80 ieee80211_key_free_common+0x10c/0x174 ieee80211_free_keys+0x188/0x46c ieee80211_stop_mesh+0x70/0x2cc ieee80211_leave_mesh+0x1c/0x60 cfg80211_leave_mesh+0xe0/0x280 cfg80211_leave+0x1e0/0x244 <...> Reset SKB control block key before calling ieee80211_tx_h_select_key() to avoid that. Fixes: bb42f2d13ffc ("mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue") Signed-off-by: Remi Pommarel Link: https://patch.msgid.link/06aa507b853ca385ceded81c18b0a6dd0f081bc8.1742833382.git.repk@triplefau.lt Signed-off-by: Johannes Berg Signed-off-by: Sasha Levin --- net/mac80211/tx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 45a093d3f1fa..8c46498152d7 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -3877,6 +3877,7 @@ begin: * The key can be removed while the packet was queued, so need to call * this here to get the current key. */ + info->control.hw_key = NULL; r = ieee80211_tx_h_select_key(&tx); if (r != TX_CONTINUE) { ieee80211_free_txskb(&local->hw, skb); From c74b84544dee27298a71715b3ce2c40d372b5a23 Mon Sep 17 00:00:00 2001 From: Remi Pommarel Date: Mon, 24 Mar 2025 17:28:21 +0100 Subject: [PATCH 243/606] wifi: mac80211: Purge vif txq in ieee80211_do_stop() [ Upstream commit 378677eb8f44621ecc9ce659f7af61e5baa94d81 ] After ieee80211_do_stop() SKB from vif's txq could still be processed. Indeed another concurrent vif schedule_and_wake_txq call could cause those packets to be dequeued (see ieee80211_handle_wake_tx_queue()) without checking the sdata current state. Because vif.drv_priv is now cleared in this function, this could lead to driver crash. For example in ath12k, ahvif is store in vif.drv_priv. Thus if ath12k_mac_op_tx() is called after ieee80211_do_stop(), ahvif->ah can be NULL, leading the ath12k_warn(ahvif->ah,...) call in this function to trigger the NULL deref below. Unable to handle kernel paging request at virtual address dfffffc000000001 KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] batman_adv: bat0: Interface deactivated: brbh1337 Mem abort info: ESR = 0x0000000096000004 EC = 0x25: DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 FSC = 0x04: level 0 translation fault Data abort info: ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000 CM = 0, WnR = 0, TnD = 0, TagAccess = 0 GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 [dfffffc000000001] address between user and kernel address ranges Internal error: Oops: 0000000096000004 [#1] SMP CPU: 1 UID: 0 PID: 978 Comm: lbd Not tainted 6.13.0-g633f875b8f1e #114 Hardware name: HW (DT) pstate: 10000005 (nzcV daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : ath12k_mac_op_tx+0x6cc/0x29b8 [ath12k] lr : ath12k_mac_op_tx+0x174/0x29b8 [ath12k] sp : ffffffc086ace450 x29: ffffffc086ace450 x28: 0000000000000000 x27: 1ffffff810d59ca4 x26: ffffff801d05f7c0 x25: 0000000000000000 x24: 000000004000001e x23: ffffff8009ce4926 x22: ffffff801f9c0800 x21: ffffff801d05f7f0 x20: ffffff8034a19f40 x19: 0000000000000000 x18: ffffff801f9c0958 x17: ffffff800bc0a504 x16: dfffffc000000000 x15: ffffffc086ace4f8 x14: ffffff801d05f83c x13: 0000000000000000 x12: ffffffb003a0bf03 x11: 0000000000000000 x10: ffffffb003a0bf02 x9 : ffffff8034a19f40 x8 : ffffff801d05f818 x7 : 1ffffff0069433dc x6 : ffffff8034a19ee0 x5 : ffffff801d05f7f0 x4 : 0000000000000000 x3 : 0000000000000001 x2 : 0000000000000000 x1 : dfffffc000000000 x0 : 0000000000000008 Call trace: ath12k_mac_op_tx+0x6cc/0x29b8 [ath12k] (P) ieee80211_handle_wake_tx_queue+0x16c/0x260 ieee80211_queue_skb+0xeec/0x1d20 ieee80211_tx+0x200/0x2c8 ieee80211_xmit+0x22c/0x338 __ieee80211_subif_start_xmit+0x7e8/0xc60 ieee80211_subif_start_xmit+0xc4/0xee0 __ieee80211_subif_start_xmit_8023.isra.0+0x854/0x17a0 ieee80211_subif_start_xmit_8023+0x124/0x488 dev_hard_start_xmit+0x160/0x5a8 __dev_queue_xmit+0x6f8/0x3120 br_dev_queue_push_xmit+0x120/0x4a8 __br_forward+0xe4/0x2b0 deliver_clone+0x5c/0xd0 br_flood+0x398/0x580 br_dev_xmit+0x454/0x9f8 dev_hard_start_xmit+0x160/0x5a8 __dev_queue_xmit+0x6f8/0x3120 ip6_finish_output2+0xc28/0x1b60 __ip6_finish_output+0x38c/0x638 ip6_output+0x1b4/0x338 ip6_local_out+0x7c/0xa8 ip6_send_skb+0x7c/0x1b0 ip6_push_pending_frames+0x94/0xd0 rawv6_sendmsg+0x1a98/0x2898 inet_sendmsg+0x94/0xe0 __sys_sendto+0x1e4/0x308 __arm64_sys_sendto+0xc4/0x140 do_el0_svc+0x110/0x280 el0_svc+0x20/0x60 el0t_64_sync_handler+0x104/0x138 el0t_64_sync+0x154/0x158 To avoid that, empty vif's txq at ieee80211_do_stop() so no packet could be dequeued after ieee80211_do_stop() (new packets cannot be queued because SDATA_STATE_RUNNING is cleared at this point). Fixes: ba8c3d6f16a1 ("mac80211: add an intermediate software queue implementation") Signed-off-by: Remi Pommarel Link: https://patch.msgid.link/ff7849e268562456274213c0476e09481a48f489.1742833382.git.repk@triplefau.lt Signed-off-by: Johannes Berg Signed-off-by: Sasha Levin --- net/mac80211/iface.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index fae701248f05..eaa4e5c6a5c3 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -682,6 +682,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) ieee80211_txq_remove_vlan(local, sdata); + if (sdata->vif.txq) + ieee80211_txq_purge(sdata->local, to_txq_info(sdata->vif.txq)); + sdata->bss = NULL; if (local->open_count == 0) From 4a43fd36710669d67dbb5c16287a58412582ca26 Mon Sep 17 00:00:00 2001 From: Abdun Nihaal Date: Sun, 30 Mar 2025 16:15:32 +0530 Subject: [PATCH 244/606] wifi: wl1251: fix memory leak in wl1251_tx_work [ Upstream commit a0f0dc96de03ffeefc2a177b7f8acde565cb77f4 ] The skb dequeued from tx_queue is lost when wl1251_ps_elp_wakeup fails with a -ETIMEDOUT error. Fix that by queueing the skb back to tx_queue. Fixes: c5483b719363 ("wl12xx: check if elp wakeup failed") Signed-off-by: Abdun Nihaal Reviewed-by: Michael Nemanov Link: https://patch.msgid.link/20250330104532.44935-1-abdun.nihaal@gmail.com Signed-off-by: Johannes Berg Signed-off-by: Sasha Levin --- drivers/net/wireless/ti/wl1251/tx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ti/wl1251/tx.c b/drivers/net/wireless/ti/wl1251/tx.c index e9dc3c72bb11..06dc74cc6cb5 100644 --- a/drivers/net/wireless/ti/wl1251/tx.c +++ b/drivers/net/wireless/ti/wl1251/tx.c @@ -342,8 +342,10 @@ void wl1251_tx_work(struct work_struct *work) while ((skb = skb_dequeue(&wl->tx_queue))) { if (!woken_up) { ret = wl1251_ps_elp_wakeup(wl); - if (ret < 0) + if (ret < 0) { + skb_queue_head(&wl->tx_queue, skb); goto out; + } woken_up = true; } From b0348f33940f126bfbeea5e90c2baf7e41ea1493 Mon Sep 17 00:00:00 2001 From: Miaoqian Lin Date: Tue, 18 Mar 2025 17:43:43 +0800 Subject: [PATCH 245/606] scsi: iscsi: Fix missing scsi_host_put() in error path [ Upstream commit 72eea84a1092b50a10eeecfeba4b28ac9f1312ab ] Add goto to ensure scsi_host_put() is called in all error paths of iscsi_set_host_param() function. This fixes a potential memory leak when strlen() check fails. Fixes: ce51c8170084 ("scsi: iscsi: Add strlen() check in iscsi_if_set{_host}_param()") Signed-off-by: Miaoqian Lin Link: https://lore.kernel.org/r/20250318094344.91776-1-linmq006@gmail.com Reviewed-by: Mike Christie Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin --- drivers/scsi/scsi_transport_iscsi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index deeb657981a6..0c30fec55547 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -3208,11 +3208,14 @@ iscsi_set_host_param(struct iscsi_transport *transport, } /* see similar check in iscsi_if_set_param() */ - if (strlen(data) > ev->u.set_host_param.len) - return -EINVAL; + if (strlen(data) > ev->u.set_host_param.len) { + err = -EINVAL; + goto out; + } err = transport->set_host_param(shost, ev->u.set_host_param.param, data, ev->u.set_host_param.len); +out: scsi_host_put(shost); return err; } From f10aa9bc94de0aa334380b3903dd2f5ec1f48231 Mon Sep 17 00:00:00 2001 From: Yu Kuai Date: Tue, 25 Mar 2025 09:57:46 +0800 Subject: [PATCH 246/606] md/raid10: fix missing discard IO accounting [ Upstream commit d05af90d6218e9c8f1c2026990c3f53c1b41bfb0 ] md_account_bio() is not called from raid10_handle_discard(), now that we handle bitmap inside md_account_bio(), also fix missing bitmap_startwrite for discard. Test whole disk discard for 20G raid10: Before: Device d/s dMB/s drqm/s %drqm d_await dareq-sz md0 48.00 16.00 0.00 0.00 5.42 341.33 After: Device d/s dMB/s drqm/s %drqm d_await dareq-sz md0 68.00 20462.00 0.00 0.00 2.65 308133.65 Link: https://lore.kernel.org/linux-raid/20250325015746.3195035-1-yukuai1@huaweicloud.com Fixes: 528bc2cf2fcc ("md/raid10: enable io accounting") Signed-off-by: Yu Kuai Acked-by: Coly Li Signed-off-by: Sasha Levin --- drivers/md/raid10.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index c300fd609ef0..36b6bf3f8b29 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1756,6 +1756,7 @@ retry_discard: * The discard bio returns only first r10bio finishes */ if (first_copy) { + md_account_bio(mddev, &bio); r10_bio->master_bio = bio; set_bit(R10BIO_Discard, &r10_bio->state); first_copy = false; From 0b5390aeaa85eb2f15e0e2ea0731c0995285db5e Mon Sep 17 00:00:00 2001 From: Zheng Qixing Date: Thu, 3 Apr 2025 09:53:22 +0800 Subject: [PATCH 247/606] md/md-bitmap: fix stats collection for external bitmaps [ Upstream commit 6ec1f0239485028445d213d91cfee5242f3211ba ] The bitmap_get_stats() function incorrectly returns -ENOENT for external bitmaps. Remove the external bitmap check as the statistics should be available regardless of bitmap storage location. Return -EINVAL only for invalid bitmap with no storage (neither in superblock nor in external file). Note: "bitmap_info.external" here refers to a bitmap stored in a separate file (bitmap_file), not to external metadata. Fixes: 8d28d0ddb986 ("md/md-bitmap: Synchronize bitmap_get_stats() with bitmap lifetime") Signed-off-by: Zheng Qixing Link: https://lore.kernel.org/linux-raid/20250403015322.2873369-1-zhengqixing@huaweicloud.com Signed-off-by: Yu Kuai Signed-off-by: Sasha Levin --- drivers/md/md-bitmap.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c index deb40a8ba399..8317e07b326d 100644 --- a/drivers/md/md-bitmap.c +++ b/drivers/md/md-bitmap.c @@ -2119,9 +2119,8 @@ int md_bitmap_get_stats(struct bitmap *bitmap, struct md_bitmap_stats *stats) if (!bitmap) return -ENOENT; - if (bitmap->mddev->bitmap_info.external) - return -ENOENT; - if (!bitmap->storage.sb_page) /* no superblock */ + if (!bitmap->mddev->bitmap_info.external && + !bitmap->storage.sb_page) return -EINVAL; sb = kmap_local_page(bitmap->storage.sb_page); stats->sync_size = le64_to_cpu(sb->sync_size); From 4a655ba2830a55dd2927e9e47878317ffb731d54 Mon Sep 17 00:00:00 2001 From: Brady Norander Date: Sun, 30 Mar 2025 09:08:54 -0400 Subject: [PATCH 248/606] ASoC: dwc: always enable/disable i2s irqs [ Upstream commit 2b727b3f8a04fe52f55316ccb8792cfd9b2dd05d ] Commit a42e988 ("ASoC: dwc: add DMA handshake control") changed the behavior of the driver to not enable or disable i2s irqs if using DMA. This breaks platforms such as AMD ACP. Audio playback appears to work but no audio can be heard. Revert to the old behavior by always enabling and disabling i2s irqs while keeping DMA handshake control. Fixes: a42e988b626 ("ASoC: dwc: add DMA handshake control") Signed-off-by: Brady Norander Link: https://patch.msgid.link/20250330130852.37881-3-bradynorander@gmail.com Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/dwc/dwc-i2s.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/sound/soc/dwc/dwc-i2s.c b/sound/soc/dwc/dwc-i2s.c index 9ea4be56d3b7..43edad6c887d 100644 --- a/sound/soc/dwc/dwc-i2s.c +++ b/sound/soc/dwc/dwc-i2s.c @@ -199,12 +199,10 @@ static void i2s_start(struct dw_i2s_dev *dev, else i2s_write_reg(dev->i2s_base, IRER, 1); - /* I2S needs to enable IRQ to make a handshake with DMAC on the JH7110 SoC */ - if (dev->use_pio || dev->is_jh7110) - i2s_enable_irqs(dev, substream->stream, config->chan_nr); - else + if (!(dev->use_pio || dev->is_jh7110)) i2s_enable_dma(dev, substream->stream); + i2s_enable_irqs(dev, substream->stream, config->chan_nr); i2s_write_reg(dev->i2s_base, CER, 1); } @@ -218,11 +216,12 @@ static void i2s_stop(struct dw_i2s_dev *dev, else i2s_write_reg(dev->i2s_base, IRER, 0); - if (dev->use_pio || dev->is_jh7110) - i2s_disable_irqs(dev, substream->stream, 8); - else + if (!(dev->use_pio || dev->is_jh7110)) i2s_disable_dma(dev, substream->stream); + i2s_disable_irqs(dev, substream->stream, 8); + + if (!dev->active) { i2s_write_reg(dev->i2s_base, CER, 0); i2s_write_reg(dev->i2s_base, IER, 0); From aaa93b8846101461de815759d39979661b82d5a5 Mon Sep 17 00:00:00 2001 From: Henry Martin Date: Wed, 2 Apr 2025 22:14:11 +0800 Subject: [PATCH 249/606] ASoC: Intel: avs: Fix null-ptr-deref in avs_component_probe() [ Upstream commit 95f723cf141b95e3b3a5b92cf2ea98a863fe7275 ] devm_kasprintf() returns NULL when memory allocation fails. Currently, avs_component_probe() does not check for this case, which results in a NULL pointer dereference. Fixes: 739c031110da ("ASoC: Intel: avs: Provide support for fallback topology") Reviewed-by: Cezary Rojewski Reviewed-by: Ethan Carter Edwards Signed-off-by: Henry Martin Link: https://patch.msgid.link/20250402141411.44972-1-bsdhenrymartin@gmail.com Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/intel/avs/pcm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c index bb1e77ac78e0..781019685b94 100644 --- a/sound/soc/intel/avs/pcm.c +++ b/sound/soc/intel/avs/pcm.c @@ -808,7 +808,8 @@ static int avs_component_probe(struct snd_soc_component *component) else mach->tplg_filename = devm_kasprintf(adev->dev, GFP_KERNEL, "hda-generic-tplg.bin"); - + if (!mach->tplg_filename) + return -ENOMEM; filename = kasprintf(GFP_KERNEL, "%s/%s", component->driver->topology_name_prefix, mach->tplg_filename); if (!filename) From 4f7b6029ae8e22169c8a002ca0431865e63011c5 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Mon, 10 Feb 2025 13:07:55 +0100 Subject: [PATCH 250/606] ovl: remove unused forward declaration [ Upstream commit a6eb9a4a69cc360b930dad9dc8513f8fd9b3577f ] The ovl_get_verity_xattr() function was never added, only its declaration. Signed-off-by: Giuseppe Scrivano Fixes: 184996e92e86 ("ovl: Validate verity xattr when resolving lowerdata") Reviewed-by: Amir Goldstein Reviewed-by: Alexander Larsson Reviewed-by: Christian Brauner Signed-off-by: Miklos Szeredi Signed-off-by: Sasha Levin --- fs/overlayfs/overlayfs.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 981967e507b3..23b5c5f9c782 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -506,8 +506,6 @@ int ovl_set_metacopy_xattr(struct ovl_fs *ofs, struct dentry *d, bool ovl_is_metacopy_dentry(struct dentry *dentry); char *ovl_get_redirect_xattr(struct ovl_fs *ofs, const struct path *path, int padding); int ovl_ensure_verity_loaded(struct path *path); -int ovl_get_verity_xattr(struct ovl_fs *ofs, const struct path *path, - u8 *digest_buf, int *buf_length); int ovl_validate_verity(struct ovl_fs *ofs, struct path *metapath, struct path *datapath); From 344baf8c1fb1f9a488f2b186fc458114902f9a69 Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Mon, 24 Mar 2025 20:31:32 +0800 Subject: [PATCH 251/606] RDMA/usnic: Fix passing zero to PTR_ERR in usnic_ib_pci_probe() [ Upstream commit 95ba3850fed03e01b422ab5d7943aeba130c9723 ] drivers/infiniband/hw/usnic/usnic_ib_main.c:590 usnic_ib_pci_probe() warn: passing zero to 'PTR_ERR' Make usnic_ib_device_add() return NULL on fail path, also remove useless NULL check for usnic_ib_discover_pf() Fixes: e3cf00d0a87f ("IB/usnic: Add Cisco VIC low-level hardware driver") Link: https://patch.msgid.link/r/20250324123132.2392077-1-yuehaibing@huawei.com Signed-off-by: Yue Haibing Reviewed-by: Zhu Yanjun Reviewed-by: Jason Gunthorpe Signed-off-by: Jason Gunthorpe Signed-off-by: Sasha Levin --- drivers/infiniband/hw/usnic/usnic_ib_main.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/infiniband/hw/usnic/usnic_ib_main.c b/drivers/infiniband/hw/usnic/usnic_ib_main.c index 13b654ddd3cc..bcf7d8607d56 100644 --- a/drivers/infiniband/hw/usnic/usnic_ib_main.c +++ b/drivers/infiniband/hw/usnic/usnic_ib_main.c @@ -380,7 +380,7 @@ static void *usnic_ib_device_add(struct pci_dev *dev) if (!us_ibdev) { usnic_err("Device %s context alloc failed\n", netdev_name(pci_get_drvdata(dev))); - return ERR_PTR(-EFAULT); + return NULL; } us_ibdev->ufdev = usnic_fwd_dev_alloc(dev); @@ -500,8 +500,8 @@ static struct usnic_ib_dev *usnic_ib_discover_pf(struct usnic_vnic *vnic) } us_ibdev = usnic_ib_device_add(parent_pci); - if (IS_ERR_OR_NULL(us_ibdev)) { - us_ibdev = us_ibdev ? us_ibdev : ERR_PTR(-EFAULT); + if (!us_ibdev) { + us_ibdev = ERR_PTR(-EFAULT); goto out; } @@ -569,10 +569,10 @@ static int usnic_ib_pci_probe(struct pci_dev *pdev, } pf = usnic_ib_discover_pf(vf->vnic); - if (IS_ERR_OR_NULL(pf)) { - usnic_err("Failed to discover pf of vnic %s with err%ld\n", - pci_name(pdev), PTR_ERR(pf)); - err = pf ? PTR_ERR(pf) : -EFAULT; + if (IS_ERR(pf)) { + err = PTR_ERR(pf); + usnic_err("Failed to discover pf of vnic %s with err%d\n", + pci_name(pdev), err); goto out_clean_vnic; } From efeddd8acecf6f65f110799aeb403fdb0ef100d2 Mon Sep 17 00:00:00 2001 From: Chengchang Tang Date: Thu, 27 Mar 2025 19:47:24 +0800 Subject: [PATCH 252/606] RDMA/hns: Fix wrong maximum DMA segment size [ Upstream commit 9beb2c91fb86e0be70a5833c6730441fa3c9efa8 ] Set maximum DMA segment size to 2G instead of UINT_MAX due to HW limit. Fixes: e0477b34d9d1 ("RDMA: Explicitly pass in the dma_device to ib_register_device") Link: https://patch.msgid.link/r/20250327114724.3454268-3-huangjunxian6@hisilicon.com Signed-off-by: Chengchang Tang Signed-off-by: Junxian Huang Signed-off-by: Jason Gunthorpe Signed-off-by: Sasha Levin --- drivers/infiniband/hw/hns/hns_roce_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c index dcd763dbb636..a7e4c951f8fe 100644 --- a/drivers/infiniband/hw/hns/hns_roce_main.c +++ b/drivers/infiniband/hw/hns/hns_roce_main.c @@ -731,7 +731,7 @@ static int hns_roce_register_device(struct hns_roce_dev *hr_dev) if (ret) return ret; } - dma_set_max_seg_size(dev, UINT_MAX); + dma_set_max_seg_size(dev, SZ_2G); ret = ib_register_device(ib_dev, "hns_%d", dev); if (ret) { dev_err(dev, "ib_register_device failed!\n"); From d1d6fa08b1efc02d979421c6332d43f41f2054f4 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 9 Apr 2025 13:07:17 +0100 Subject: [PATCH 253/606] ASoC: cs42l43: Reset clamp override on jack removal [ Upstream commit 5fc7d2b5cab47f2ac712f689140b1fed978fb91c ] Some of the manually selected jack configurations will disable the headphone clamp override. Restore this on jack removal, such that the state is consistent for a new insert. Fixes: fc918cbe874e ("ASoC: cs42l43: Add support for the cs42l43") Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20250409120717.1294528-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/codecs/cs42l43-jack.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/cs42l43-jack.c b/sound/soc/codecs/cs42l43-jack.c index 9f5f1a92561d..0b8e88b19888 100644 --- a/sound/soc/codecs/cs42l43-jack.c +++ b/sound/soc/codecs/cs42l43-jack.c @@ -690,6 +690,9 @@ static void cs42l43_clear_jack(struct cs42l43_codec *priv) CS42L43_PGA_WIDESWING_MODE_EN_MASK, 0); regmap_update_bits(cs42l43->regmap, CS42L43_STEREO_MIC_CTRL, CS42L43_JACK_STEREO_CONFIG_MASK, 0); + regmap_update_bits(cs42l43->regmap, CS42L43_STEREO_MIC_CLAMP_CTRL, + CS42L43_SMIC_HPAMP_CLAMP_DIS_FRC_MASK, + CS42L43_SMIC_HPAMP_CLAMP_DIS_FRC_MASK); regmap_update_bits(cs42l43->regmap, CS42L43_HS2, CS42L43_HSDET_MODE_MASK | CS42L43_HSDET_MANUAL_MODE_MASK, 0x2 << CS42L43_HSDET_MODE_SHIFT); From ae470d06320dea4002d441784d691f0a26b4322d Mon Sep 17 00:00:00 2001 From: Shay Drory Date: Wed, 19 Mar 2025 14:42:21 +0200 Subject: [PATCH 254/606] RDMA/core: Silence oversized kvmalloc() warning [ Upstream commit 9a0e6f15029e1a8a21e40f06fd05aa52b7f063de ] syzkaller triggered an oversized kvmalloc() warning. Silence it by adding __GFP_NOWARN. syzkaller log: WARNING: CPU: 7 PID: 518 at mm/util.c:665 __kvmalloc_node_noprof+0x175/0x180 CPU: 7 UID: 0 PID: 518 Comm: c_repro Not tainted 6.11.0-rc6+ #6 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 RIP: 0010:__kvmalloc_node_noprof+0x175/0x180 RSP: 0018:ffffc90001e67c10 EFLAGS: 00010246 RAX: 0000000000000100 RBX: 0000000000000400 RCX: ffffffff8149d46b RDX: 0000000000000000 RSI: ffff8881030fae80 RDI: 0000000000000002 RBP: 000000712c800000 R08: 0000000000000100 R09: 0000000000000000 R10: ffffc90001e67c10 R11: 0030ae0601000000 R12: 0000000000000000 R13: 0000000000000000 R14: 00000000ffffffff R15: 0000000000000000 FS: 00007fde79159740(0000) GS:ffff88813bdc0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000020000180 CR3: 0000000105eb4005 CR4: 00000000003706b0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: ib_umem_odp_get+0x1f6/0x390 mlx5_ib_reg_user_mr+0x1e8/0x450 ib_uverbs_reg_mr+0x28b/0x440 ib_uverbs_write+0x7d3/0xa30 vfs_write+0x1ac/0x6c0 ksys_write+0x134/0x170 ? __sanitizer_cov_trace_pc+0x1c/0x50 do_syscall_64+0x50/0x110 entry_SYSCALL_64_after_hwframe+0x76/0x7e Fixes: 37824952dc8f ("RDMA/odp: Use kvcalloc for the dma_list and page_list") Signed-off-by: Shay Drory Link: https://patch.msgid.link/c6cb92379de668be94894f49c2cfa40e73f94d56.1742388096.git.leonro@nvidia.com Signed-off-by: Leon Romanovsky Signed-off-by: Sasha Levin --- drivers/infiniband/core/umem_odp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/umem_odp.c index e9fa22d31c23..c48ef6083020 100644 --- a/drivers/infiniband/core/umem_odp.c +++ b/drivers/infiniband/core/umem_odp.c @@ -76,12 +76,14 @@ static inline int ib_init_umem_odp(struct ib_umem_odp *umem_odp, npfns = (end - start) >> PAGE_SHIFT; umem_odp->pfn_list = kvcalloc( - npfns, sizeof(*umem_odp->pfn_list), GFP_KERNEL); + npfns, sizeof(*umem_odp->pfn_list), + GFP_KERNEL | __GFP_NOWARN); if (!umem_odp->pfn_list) return -ENOMEM; umem_odp->dma_list = kvcalloc( - ndmas, sizeof(*umem_odp->dma_list), GFP_KERNEL); + ndmas, sizeof(*umem_odp->dma_list), + GFP_KERNEL | __GFP_NOWARN); if (!umem_odp->dma_list) { ret = -ENOMEM; goto out_pfn_list; From fd1621f38fbe0316bc3ddecdac4ca30063f120f6 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 1 Apr 2025 13:02:08 -0400 Subject: [PATCH 255/606] Bluetooth: hci_event: Fix sending MGMT_EV_DEVICE_FOUND for invalid address [ Upstream commit eb73b5a9157221f405b4fe32751da84ee46b7a25 ] This fixes sending MGMT_EV_DEVICE_FOUND for invalid address (00:00:00:00:00:00) which is a regression introduced by a2ec905d1e16 ("Bluetooth: fix kernel oops in store_pending_adv_report") since in the attempt to skip storing data for extended advertisement it actually made the code to skip the entire if statement supposed to send MGMT_EV_DEVICE_FOUND without attempting to use the last_addr_adv which is garanteed to be invalid for extended advertisement since we never store anything on it. Link: https://github.com/bluez/bluez/issues/1157 Link: https://github.com/bluez/bluez/issues/1149#issuecomment-2767215658 Fixes: a2ec905d1e16 ("Bluetooth: fix kernel oops in store_pending_adv_report") Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Sasha Levin --- net/bluetooth/hci_event.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 1e689d8c00a5..4029330e29a9 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -6149,11 +6149,12 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, * event or send an immediate device found event if the data * should not be stored for later. */ - if (!ext_adv && !has_pending_adv_report(hdev)) { + if (!has_pending_adv_report(hdev)) { /* If the report will trigger a SCAN_REQ store it for * later merging. */ - if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) { + if (!ext_adv && (type == LE_ADV_IND || + type == LE_ADV_SCAN_IND)) { store_pending_adv_report(hdev, bdaddr, bdaddr_type, rssi, flags, data, len); return; From 3db6605043b50c8bb768547b23e0222f67ceef3e Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 2 Apr 2025 14:01:41 +0300 Subject: [PATCH 256/606] Bluetooth: btrtl: Prevent potential NULL dereference [ Upstream commit 324dddea321078a6eeb535c2bff5257be74c9799 ] The btrtl_initialize() function checks that rtl_load_file() either had an error or it loaded a zero length file. However, if it loaded a zero length file then the error code is not set correctly. It results in an error pointer vs NULL bug, followed by a NULL pointer dereference. This was detected by Smatch: drivers/bluetooth/btrtl.c:592 btrtl_initialize() warn: passing zero to 'ERR_PTR' Fixes: 26503ad25de8 ("Bluetooth: btrtl: split the device initialization into smaller parts") Signed-off-by: Dan Carpenter Reviewed-by: Hans de Goede Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Sasha Levin --- drivers/bluetooth/btrtl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index 1e7c1f9db9e4..7f67e460f7f4 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -1194,6 +1194,8 @@ next: rtl_dev_err(hdev, "mandatory config file %s not found", btrtl_dev->ic_info->cfg_name); ret = btrtl_dev->cfg_len; + if (!ret) + ret = -EINVAL; goto err_free; } } From 9e3114958d87ea88383cbbf38c89e04b8ea1bce5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Danis?= Date: Wed, 9 Apr 2025 10:53:06 +0200 Subject: [PATCH 257/606] Bluetooth: l2cap: Check encryption key size on incoming connection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 522e9ed157e3c21b4dd623c79967f72c21e45b78 ] This is required for passing GAP/SEC/SEM/BI-04-C PTS test case: Security Mode 4 Level 4, Responder - Invalid Encryption Key Size - 128 bit This tests the security key with size from 1 to 15 bytes while the Security Mode 4 Level 4 requests 16 bytes key size. Currently PTS fails with the following logs: - expected:Connection Response: Code: [3 (0x03)] Code Identifier: (lt)WildCard: Exists(gt) Length: [8 (0x0008)] Destination CID: (lt)WildCard: Exists(gt) Source CID: [64 (0x0040)] Result: [3 (0x0003)] Connection refused - Security block Status: (lt)WildCard: Exists(gt), but received:Connection Response: Code: [3 (0x03)] Code Identifier: [1 (0x01)] Length: [8 (0x0008)] Destination CID: [64 (0x0040)] Source CID: [64 (0x0040)] Result: [0 (0x0000)] Connection Successful Status: [0 (0x0000)] No further information available And HCI logs: < HCI Command: Read Encrypti.. (0x05|0x0008) plen 2 Handle: 14 Address: 00:1B:DC:F2:24:10 (Vencer Co., Ltd.) > HCI Event: Command Complete (0x0e) plen 7 Read Encryption Key Size (0x05|0x0008) ncmd 1 Status: Success (0x00) Handle: 14 Address: 00:1B:DC:F2:24:10 (Vencer Co., Ltd.) Key size: 7 > ACL Data RX: Handle 14 flags 0x02 dlen 12 L2CAP: Connection Request (0x02) ident 1 len 4 PSM: 4097 (0x1001) Source CID: 64 < ACL Data TX: Handle 14 flags 0x00 dlen 16 L2CAP: Connection Response (0x03) ident 1 len 8 Destination CID: 64 Source CID: 64 Result: Connection successful (0x0000) Status: No further information available (0x0000) Fixes: 288c06973daa ("Bluetooth: Enforce key size of 16 bytes on FIPS level") Signed-off-by: Frédéric Danis Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Sasha Levin --- net/bluetooth/l2cap_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 8d6fc1869503..1258532228bb 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -3954,7 +3954,8 @@ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, /* Check if the ACL is secure enough (if not SDP) */ if (psm != cpu_to_le16(L2CAP_PSM_SDP) && - !hci_conn_check_link_mode(conn->hcon)) { + (!hci_conn_check_link_mode(conn->hcon) || + !l2cap_check_enc_key_size(conn->hcon))) { conn->disc_reason = HCI_ERROR_AUTH_FAILURE; result = L2CAP_CR_SEC_BLOCK; goto response; From 6f1ac9b5a9ceb87e5859f2e647f592a52f400170 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 11 Apr 2025 16:13:34 +0200 Subject: [PATCH 258/606] Revert "wifi: mac80211: Update skb's control block key in ieee80211_tx_dequeue()" [ Upstream commit 0937cb5f345c79d702b4d0d744e2a2529b551cb2 ] This reverts commit a104042e2bf6528199adb6ca901efe7b60c2c27f. Since the original bug seems to have been around for years, but a new issue was report with the fix, revert the fix for now. We have a couple of weeks to figure it out for this release, if needed. Reported-by: Bert Karwatzki Closes: https://lore.kernel.org/linux-wireless/20250410215527.3001-1-spasswolf@web.de Fixes: a104042e2bf6 ("wifi: mac80211: Update skb's control block key in ieee80211_tx_dequeue()") Signed-off-by: Johannes Berg Signed-off-by: Sasha Levin --- net/mac80211/tx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 8c46498152d7..45a093d3f1fa 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -3877,7 +3877,6 @@ begin: * The key can be removed while the packet was queued, so need to call * this here to get the current key. */ - info->control.hw_key = NULL; r = ieee80211_tx_h_select_key(&tx); if (r != TX_CONTINUE) { ieee80211_free_txskb(&local->hw, skb); From 16194ca3f3b4448a062650c869a7b3b206c6f5d3 Mon Sep 17 00:00:00 2001 From: Christopher S M Hall Date: Tue, 1 Apr 2025 16:35:29 -0700 Subject: [PATCH 259/606] igc: fix PTM cycle trigger logic [ Upstream commit 8e404ad95d2c10c261e2ef6992c7c12dde03df0e ] Writing to clear the PTM status 'valid' bit while the PTM cycle is triggered results in unreliable PTM operation. To fix this, clear the PTM 'trigger' and status after each PTM transaction. The issue can be reproduced with the following: $ sudo phc2sys -R 1000 -O 0 -i tsn0 -m Note: 1000 Hz (-R 1000) is unrealistically large, but provides a way to quickly reproduce the issue. PHC2SYS exits with: "ioctl PTP_OFFSET_PRECISE: Connection timed out" when the PTM transaction fails This patch also fixes a hang in igc_probe() when loading the igc driver in the kdump kernel on systems supporting PTM. The igc driver running in the base kernel enables PTM trigger in igc_probe(). Therefore the driver is always in PTM trigger mode, except in brief periods when manually triggering a PTM cycle. When a crash occurs, the NIC is reset while PTM trigger is enabled. Due to a hardware problem, the NIC is subsequently in a bad busmaster state and doesn't handle register reads/writes. When running igc_probe() in the kdump kernel, the first register access to a NIC register hangs driver probing and ultimately breaks kdump. With this patch, igc has PTM trigger disabled most of the time, and the trigger is only enabled for very brief (10 - 100 us) periods when manually triggering a PTM cycle. Chances that a crash occurs during a PTM trigger are not 0, but extremely reduced. Fixes: a90ec8483732 ("igc: Add support for PTP getcrosststamp()") Reviewed-by: Michal Swiatkowski Tested-by: Mor Bar-Gabay Tested-by: Avigail Dahan Signed-off-by: Christopher S M Hall Reviewed-by: Corinna Vinschen Signed-off-by: Jacob Keller Tested-by: Corinna Vinschen Acked-by: Vinicius Costa Gomes Signed-off-by: Tony Nguyen Signed-off-by: Sasha Levin --- drivers/net/ethernet/intel/igc/igc_defines.h | 1 + drivers/net/ethernet/intel/igc/igc_ptp.c | 70 ++++++++++++-------- 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h index a18af5c87cde..2a84beaf5e68 100644 --- a/drivers/net/ethernet/intel/igc/igc_defines.h +++ b/drivers/net/ethernet/intel/igc/igc_defines.h @@ -581,6 +581,7 @@ #define IGC_PTM_STAT_T4M1_OVFL BIT(3) /* T4 minus T1 overflow */ #define IGC_PTM_STAT_ADJUST_1ST BIT(4) /* 1588 timer adjusted during 1st PTM cycle */ #define IGC_PTM_STAT_ADJUST_CYC BIT(5) /* 1588 timer adjusted during non-1st PTM cycle */ +#define IGC_PTM_STAT_ALL GENMASK(5, 0) /* Used to clear all status */ /* PCIe PTM Cycle Control */ #define IGC_PTM_CYCLE_CTRL_CYC_TIME(msec) ((msec) & 0x3ff) /* PTM Cycle Time (msec) */ diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c index 928f38792203..097a481e6b73 100644 --- a/drivers/net/ethernet/intel/igc/igc_ptp.c +++ b/drivers/net/ethernet/intel/igc/igc_ptp.c @@ -943,13 +943,40 @@ static void igc_ptm_log_error(struct igc_adapter *adapter, u32 ptm_stat) } } +static void igc_ptm_trigger(struct igc_hw *hw) +{ + u32 ctrl; + + /* To "manually" start the PTM cycle we need to set the + * trigger (TRIG) bit + */ + ctrl = rd32(IGC_PTM_CTRL); + ctrl |= IGC_PTM_CTRL_TRIG; + wr32(IGC_PTM_CTRL, ctrl); + /* Perform flush after write to CTRL register otherwise + * transaction may not start + */ + wrfl(); +} + +static void igc_ptm_reset(struct igc_hw *hw) +{ + u32 ctrl; + + ctrl = rd32(IGC_PTM_CTRL); + ctrl &= ~IGC_PTM_CTRL_TRIG; + wr32(IGC_PTM_CTRL, ctrl); + /* Write to clear all status */ + wr32(IGC_PTM_STAT, IGC_PTM_STAT_ALL); +} + static int igc_phc_get_syncdevicetime(ktime_t *device, struct system_counterval_t *system, void *ctx) { - u32 stat, t2_curr_h, t2_curr_l, ctrl; struct igc_adapter *adapter = ctx; struct igc_hw *hw = &adapter->hw; + u32 stat, t2_curr_h, t2_curr_l; int err, count = 100; ktime_t t1, t2_curr; @@ -963,25 +990,13 @@ static int igc_phc_get_syncdevicetime(ktime_t *device, * are transitory. Repeating the process returns valid * data eventually. */ - - /* To "manually" start the PTM cycle we need to clear and - * then set again the TRIG bit. - */ - ctrl = rd32(IGC_PTM_CTRL); - ctrl &= ~IGC_PTM_CTRL_TRIG; - wr32(IGC_PTM_CTRL, ctrl); - ctrl |= IGC_PTM_CTRL_TRIG; - wr32(IGC_PTM_CTRL, ctrl); - - /* The cycle only starts "for real" when software notifies - * that it has read the registers, this is done by setting - * VALID bit. - */ - wr32(IGC_PTM_STAT, IGC_PTM_STAT_VALID); + igc_ptm_trigger(hw); err = readx_poll_timeout(rd32, IGC_PTM_STAT, stat, stat, IGC_PTM_STAT_SLEEP, IGC_PTM_STAT_TIMEOUT); + igc_ptm_reset(hw); + if (err < 0) { netdev_err(adapter->netdev, "Timeout reading IGC_PTM_STAT register\n"); return err; @@ -990,15 +1005,7 @@ static int igc_phc_get_syncdevicetime(ktime_t *device, if ((stat & IGC_PTM_STAT_VALID) == IGC_PTM_STAT_VALID) break; - if (stat & ~IGC_PTM_STAT_VALID) { - /* An error occurred, log it. */ - igc_ptm_log_error(adapter, stat); - /* The STAT register is write-1-to-clear (W1C), - * so write the previous error status to clear it. - */ - wr32(IGC_PTM_STAT, stat); - continue; - } + igc_ptm_log_error(adapter, stat); } while (--count); if (!count) { @@ -1202,7 +1209,7 @@ void igc_ptp_stop(struct igc_adapter *adapter) void igc_ptp_reset(struct igc_adapter *adapter) { struct igc_hw *hw = &adapter->hw; - u32 cycle_ctrl, ctrl; + u32 cycle_ctrl, ctrl, stat; unsigned long flags; u32 timadj; @@ -1237,14 +1244,19 @@ void igc_ptp_reset(struct igc_adapter *adapter) ctrl = IGC_PTM_CTRL_EN | IGC_PTM_CTRL_START_NOW | IGC_PTM_CTRL_SHRT_CYC(IGC_PTM_SHORT_CYC_DEFAULT) | - IGC_PTM_CTRL_PTM_TO(IGC_PTM_TIMEOUT_DEFAULT) | - IGC_PTM_CTRL_TRIG; + IGC_PTM_CTRL_PTM_TO(IGC_PTM_TIMEOUT_DEFAULT); wr32(IGC_PTM_CTRL, ctrl); /* Force the first cycle to run. */ - wr32(IGC_PTM_STAT, IGC_PTM_STAT_VALID); + igc_ptm_trigger(hw); + if (readx_poll_timeout_atomic(rd32, IGC_PTM_STAT, stat, + stat, IGC_PTM_STAT_SLEEP, + IGC_PTM_STAT_TIMEOUT)) + netdev_err(adapter->netdev, "Timeout reading IGC_PTM_STAT register\n"); + + igc_ptm_reset(hw); break; default: /* No work to do. */ From b1f3e69dc984ae795b85d2d99424cb8b6e8f60be Mon Sep 17 00:00:00 2001 From: Christopher S M Hall Date: Tue, 1 Apr 2025 16:35:30 -0700 Subject: [PATCH 260/606] igc: increase wait time before retrying PTM [ Upstream commit 714cd033da6fea4cf54a11b3cfd070afde3f31df ] The i225/i226 hardware retries if it receives an inappropriate response from the upstream device. If the device retries too quickly, the root port does not respond. The wait between attempts was reduced from 10us to 1us in commit 6b8aa753a9f9 ("igc: Decrease PTM short interval from 10 us to 1 us"), which said: With the 10us interval, we were seeing PTM transactions take around 12us. Hardware team suggested this interval could be lowered to 1us which was confirmed with PCIe sniffer. With the 1us interval, PTM dialogs took around 2us. While a 1us short cycle time was thought to be theoretically sufficient, it turns out in practice it is not quite long enough. It is unclear if the problem is in the root port or an issue in i225/i226. Increase the wait from 1us to 4us. Increasing to 2us appeared to work in practice on the setups we have available. A value of 4us was chosen due to the limited hardware available for testing, with a goal of ensuring we wait long enough without overly penalizing the response time when unnecessary. The issue can be reproduced with the following: $ sudo phc2sys -R 1000 -O 0 -i tsn0 -m Note: 1000 Hz (-R 1000) is unrealistically large, but provides a way to quickly reproduce the issue. PHC2SYS exits with: "ioctl PTP_OFFSET_PRECISE: Connection timed out" when the PTM transaction fails Fixes: 6b8aa753a9f9 ("igc: Decrease PTM short interval from 10 us to 1 us") Reviewed-by: Michal Swiatkowski Tested-by: Mor Bar-Gabay Tested-by: Avigail Dahan Signed-off-by: Christopher S M Hall Reviewed-by: Corinna Vinschen Signed-off-by: Jacob Keller Acked-by: Vinicius Costa Gomes Signed-off-by: Tony Nguyen Signed-off-by: Sasha Levin --- drivers/net/ethernet/intel/igc/igc_defines.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h index 2a84beaf5e68..cf8b5ac51caa 100644 --- a/drivers/net/ethernet/intel/igc/igc_defines.h +++ b/drivers/net/ethernet/intel/igc/igc_defines.h @@ -562,7 +562,10 @@ #define IGC_PTM_CTRL_SHRT_CYC(usec) (((usec) & 0x3f) << 2) #define IGC_PTM_CTRL_PTM_TO(usec) (((usec) & 0xff) << 8) -#define IGC_PTM_SHORT_CYC_DEFAULT 1 /* Default short cycle interval */ +/* A short cycle time of 1us theoretically should work, but appears to be too + * short in practice. + */ +#define IGC_PTM_SHORT_CYC_DEFAULT 4 /* Default short cycle interval */ #define IGC_PTM_CYC_TIME_DEFAULT 5 /* Default PTM cycle time */ #define IGC_PTM_TIMEOUT_DEFAULT 255 /* Default timeout for PTM errors */ From 5262d34f5e40304f8632ff7aaa738683184da0dc Mon Sep 17 00:00:00 2001 From: Christopher S M Hall Date: Tue, 1 Apr 2025 16:35:31 -0700 Subject: [PATCH 261/606] igc: move ktime snapshot into PTM retry loop [ Upstream commit cd7f7328d691937102732f39f97ead35b15bf803 ] Move ktime_get_snapshot() into the loop. If a retry does occur, a more recent snapshot will result in a more accurate cross-timestamp. Fixes: a90ec8483732 ("igc: Add support for PTP getcrosststamp()") Reviewed-by: Michal Swiatkowski Tested-by: Mor Bar-Gabay Tested-by: Avigail Dahan Signed-off-by: Christopher S M Hall Reviewed-by: Corinna Vinschen Signed-off-by: Jacob Keller Acked-by: Vinicius Costa Gomes Signed-off-by: Tony Nguyen Signed-off-by: Sasha Levin --- drivers/net/ethernet/intel/igc/igc_ptp.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c index 097a481e6b73..adb31cccaf9a 100644 --- a/drivers/net/ethernet/intel/igc/igc_ptp.c +++ b/drivers/net/ethernet/intel/igc/igc_ptp.c @@ -980,16 +980,16 @@ static int igc_phc_get_syncdevicetime(ktime_t *device, int err, count = 100; ktime_t t1, t2_curr; - /* Get a snapshot of system clocks to use as historic value. */ - ktime_get_snapshot(&adapter->snapshot); - + /* Doing this in a loop because in the event of a + * badly timed (ha!) system clock adjustment, we may + * get PTM errors from the PCI root, but these errors + * are transitory. Repeating the process returns valid + * data eventually. + */ do { - /* Doing this in a loop because in the event of a - * badly timed (ha!) system clock adjustment, we may - * get PTM errors from the PCI root, but these errors - * are transitory. Repeating the process returns valid - * data eventually. - */ + /* Get a snapshot of system clocks to use as historic value. */ + ktime_get_snapshot(&adapter->snapshot); + igc_ptm_trigger(hw); err = readx_poll_timeout(rd32, IGC_PTM_STAT, stat, From bcb2d6bfa5e2db9c19c09ebc696c5aa7f649370c Mon Sep 17 00:00:00 2001 From: Christopher S M Hall Date: Tue, 1 Apr 2025 16:35:32 -0700 Subject: [PATCH 262/606] igc: handle the IGC_PTP_ENABLED flag correctly [ Upstream commit 26a3910afd111f7c1a96dace6dc02f3225063896 ] All functions in igc_ptp.c called from igc_main.c should check the IGC_PTP_ENABLED flag. Adding check for this flag to stop and reset functions. Fixes: 5f2958052c58 ("igc: Add basic skeleton for PTP") Signed-off-by: Christopher S M Hall Reviewed-by: Corinna Vinschen Signed-off-by: Jacob Keller Tested-by: Mor Bar-Gabay Acked-by: Vinicius Costa Gomes Signed-off-by: Tony Nguyen Signed-off-by: Sasha Levin --- drivers/net/ethernet/intel/igc/igc_ptp.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c index adb31cccaf9a..c5387610ca3d 100644 --- a/drivers/net/ethernet/intel/igc/igc_ptp.c +++ b/drivers/net/ethernet/intel/igc/igc_ptp.c @@ -1191,8 +1191,12 @@ void igc_ptp_suspend(struct igc_adapter *adapter) **/ void igc_ptp_stop(struct igc_adapter *adapter) { + if (!(adapter->ptp_flags & IGC_PTP_ENABLED)) + return; + igc_ptp_suspend(adapter); + adapter->ptp_flags &= ~IGC_PTP_ENABLED; if (adapter->ptp_clock) { ptp_clock_unregister(adapter->ptp_clock); netdev_info(adapter->netdev, "PHC removed\n"); @@ -1213,6 +1217,9 @@ void igc_ptp_reset(struct igc_adapter *adapter) unsigned long flags; u32 timadj; + if (!(adapter->ptp_flags & IGC_PTP_ENABLED)) + return; + /* reset the tstamp_config */ igc_ptp_set_timestamp_mode(adapter, &adapter->tstamp_config); From d8dde48a1ca6d14833d617b1885e21ca0da592c8 Mon Sep 17 00:00:00 2001 From: Christopher S M Hall Date: Tue, 1 Apr 2025 16:35:33 -0700 Subject: [PATCH 263/606] igc: cleanup PTP module if probe fails [ Upstream commit 1f025759ba394dd53e434d2668cb0597886d9b69 ] Make sure that the PTP module is cleaned up if the igc_probe() fails by calling igc_ptp_stop() on exit. Fixes: d89f88419f99 ("igc: Add skeletal frame for Intel(R) 2.5G Ethernet Controller support") Signed-off-by: Christopher S M Hall Reviewed-by: Corinna Vinschen Signed-off-by: Jacob Keller Tested-by: Mor Bar-Gabay Acked-by: Vinicius Costa Gomes Signed-off-by: Tony Nguyen Signed-off-by: Sasha Levin --- drivers/net/ethernet/intel/igc/igc_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index ae93b45cf55e..e2f5c4384455 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -6951,6 +6951,7 @@ static int igc_probe(struct pci_dev *pdev, err_register: igc_release_hw_control(adapter); + igc_ptp_stop(adapter); err_eeprom: if (!igc_check_reset_block(hw)) igc_reset_phy(hw); From b45b7a0bb88fb9306985f73feb8ebdac9c313a31 Mon Sep 17 00:00:00 2001 From: Christopher S M Hall Date: Tue, 1 Apr 2025 16:35:34 -0700 Subject: [PATCH 264/606] igc: add lock preventing multiple simultaneous PTM transactions [ Upstream commit 1a931c4f5e6862e61a4b130cb76b422e1415f644 ] Add a mutex around the PTM transaction to prevent multiple transactors Multiple processes try to initiate a PTM transaction, one or all may fail. This can be reproduced by running two instances of the following: $ sudo phc2sys -O 0 -i tsn0 -m PHC2SYS exits with: "ioctl PTP_OFFSET_PRECISE: Connection timed out" when the PTM transaction fails Note: Normally two instance of PHC2SYS will not run, but one process should not break another. Fixes: a90ec8483732 ("igc: Add support for PTP getcrosststamp()") Signed-off-by: Christopher S M Hall Reviewed-by: Corinna Vinschen Signed-off-by: Jacob Keller Tested-by: Mor Bar-Gabay Acked-by: Vinicius Costa Gomes Signed-off-by: Tony Nguyen Signed-off-by: Sasha Levin --- drivers/net/ethernet/intel/igc/igc.h | 1 + drivers/net/ethernet/intel/igc/igc_ptp.c | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h index 85cc16396506..49702169a3d8 100644 --- a/drivers/net/ethernet/intel/igc/igc.h +++ b/drivers/net/ethernet/intel/igc/igc.h @@ -266,6 +266,7 @@ struct igc_adapter { struct timespec64 prev_ptp_time; /* Pre-reset PTP clock */ ktime_t ptp_reset_start; /* Reset time in clock mono */ struct system_time_snapshot snapshot; + struct mutex ptm_lock; /* Only allow one PTM transaction at a time */ char fw_version[32]; diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c index c5387610ca3d..b6bb01a486d9 100644 --- a/drivers/net/ethernet/intel/igc/igc_ptp.c +++ b/drivers/net/ethernet/intel/igc/igc_ptp.c @@ -943,6 +943,7 @@ static void igc_ptm_log_error(struct igc_adapter *adapter, u32 ptm_stat) } } +/* The PTM lock: adapter->ptm_lock must be held when calling igc_ptm_trigger() */ static void igc_ptm_trigger(struct igc_hw *hw) { u32 ctrl; @@ -959,6 +960,7 @@ static void igc_ptm_trigger(struct igc_hw *hw) wrfl(); } +/* The PTM lock: adapter->ptm_lock must be held when calling igc_ptm_reset() */ static void igc_ptm_reset(struct igc_hw *hw) { u32 ctrl; @@ -1037,9 +1039,16 @@ static int igc_ptp_getcrosststamp(struct ptp_clock_info *ptp, { struct igc_adapter *adapter = container_of(ptp, struct igc_adapter, ptp_caps); + int ret; - return get_device_system_crosststamp(igc_phc_get_syncdevicetime, - adapter, &adapter->snapshot, cts); + /* This blocks until any in progress PTM transactions complete */ + mutex_lock(&adapter->ptm_lock); + + ret = get_device_system_crosststamp(igc_phc_get_syncdevicetime, + adapter, &adapter->snapshot, cts); + mutex_unlock(&adapter->ptm_lock); + + return ret; } /** @@ -1116,6 +1125,7 @@ void igc_ptp_init(struct igc_adapter *adapter) spin_lock_init(&adapter->ptp_tx_lock); spin_lock_init(&adapter->tmreg_lock); + mutex_init(&adapter->ptm_lock); adapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE; adapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF; @@ -1128,6 +1138,7 @@ void igc_ptp_init(struct igc_adapter *adapter) if (IS_ERR(adapter->ptp_clock)) { adapter->ptp_clock = NULL; netdev_err(netdev, "ptp_clock_register failed\n"); + mutex_destroy(&adapter->ptm_lock); } else if (adapter->ptp_clock) { netdev_info(netdev, "PHC added\n"); adapter->ptp_flags |= IGC_PTP_ENABLED; @@ -1157,10 +1168,12 @@ static void igc_ptm_stop(struct igc_adapter *adapter) struct igc_hw *hw = &adapter->hw; u32 ctrl; + mutex_lock(&adapter->ptm_lock); ctrl = rd32(IGC_PTM_CTRL); ctrl &= ~IGC_PTM_CTRL_EN; wr32(IGC_PTM_CTRL, ctrl); + mutex_unlock(&adapter->ptm_lock); } /** @@ -1202,6 +1215,7 @@ void igc_ptp_stop(struct igc_adapter *adapter) netdev_info(adapter->netdev, "PHC removed\n"); adapter->ptp_flags &= ~IGC_PTP_ENABLED; } + mutex_destroy(&adapter->ptm_lock); } /** @@ -1241,6 +1255,7 @@ void igc_ptp_reset(struct igc_adapter *adapter) if (!igc_is_crosststamp_supported(adapter)) break; + mutex_lock(&adapter->ptm_lock); wr32(IGC_PCIE_DIG_DELAY, IGC_PCIE_DIG_DELAY_DEFAULT); wr32(IGC_PCIE_PHY_DELAY, IGC_PCIE_PHY_DELAY_DEFAULT); @@ -1264,6 +1279,7 @@ void igc_ptp_reset(struct igc_adapter *adapter) netdev_err(adapter->netdev, "Timeout reading IGC_PTM_STAT register\n"); igc_ptm_reset(hw); + mutex_unlock(&adapter->ptm_lock); break; default: /* No work to do. */ From 86dc3a05fa704544b250e49bcabdcc3048ab1ab1 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Wed, 2 Apr 2025 20:33:11 -0400 Subject: [PATCH 265/606] test suite: use %zu to print size_t [ Upstream commit a30951d09c33c899f0e4aca80eb87fad5f10ecfa ] On 32-bit, we can't use %lu to print a size_t variable and gcc warns us about it. Shame it doesn't warn about it on 64-bit. Link: https://lkml.kernel.org/r/20250403003311.359917-1-Liam.Howlett@oracle.com Fixes: cc86e0c2f306 ("radix tree test suite: add support for slab bulk APIs") Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: Liam R. Howlett Signed-off-by: Andrew Morton Signed-off-by: Sasha Levin --- tools/testing/radix-tree/linux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/radix-tree/linux.c b/tools/testing/radix-tree/linux.c index d587a558997f..11149bd12a1f 100644 --- a/tools/testing/radix-tree/linux.c +++ b/tools/testing/radix-tree/linux.c @@ -121,7 +121,7 @@ void kmem_cache_free(struct kmem_cache *cachep, void *objp) void kmem_cache_free_bulk(struct kmem_cache *cachep, size_t size, void **list) { if (kmalloc_verbose) - pr_debug("Bulk free %p[0-%lu]\n", list, size - 1); + pr_debug("Bulk free %p[0-%zu]\n", list, size - 1); pthread_mutex_lock(&cachep->lock); for (int i = 0; i < size; i++) @@ -139,7 +139,7 @@ int kmem_cache_alloc_bulk(struct kmem_cache *cachep, gfp_t gfp, size_t size, size_t i; if (kmalloc_verbose) - pr_debug("Bulk alloc %lu\n", size); + pr_debug("Bulk alloc %zu\n", size); if (!(gfp & __GFP_DIRECT_RECLAIM)) { if (cachep->non_kernel < size) From 9027e073567091ed62e313012b7f905db81d0cf1 Mon Sep 17 00:00:00 2001 From: Abdun Nihaal Date: Wed, 9 Apr 2025 11:14:48 +0530 Subject: [PATCH 266/606] pds_core: fix memory leak in pdsc_debugfs_add_qcq() [ Upstream commit 8b82f656826c741d032490b089a5638c33f2c91d ] The memory allocated for intr_ctrl_regset, which is passed to debugfs_create_regset32() may not be cleaned up when the driver is removed. Fix that by using device managed allocation for it. Fixes: 45d76f492938 ("pds_core: set up device and adminq") Signed-off-by: Abdun Nihaal Reviewed-by: Michal Swiatkowski Reviewed-by: Shannon Nelson Link: https://patch.msgid.link/20250409054450.48606-1-abdun.nihaal@gmail.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/amd/pds_core/debugfs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/amd/pds_core/debugfs.c b/drivers/net/ethernet/amd/pds_core/debugfs.c index 4e8579ca1c8c..51f3f73a839a 100644 --- a/drivers/net/ethernet/amd/pds_core/debugfs.c +++ b/drivers/net/ethernet/amd/pds_core/debugfs.c @@ -154,8 +154,9 @@ void pdsc_debugfs_add_qcq(struct pdsc *pdsc, struct pdsc_qcq *qcq) debugfs_create_u32("index", 0400, intr_dentry, &intr->index); debugfs_create_u32("vector", 0400, intr_dentry, &intr->vector); - intr_ctrl_regset = kzalloc(sizeof(*intr_ctrl_regset), - GFP_KERNEL); + intr_ctrl_regset = devm_kzalloc(pdsc->dev, + sizeof(*intr_ctrl_regset), + GFP_KERNEL); if (!intr_ctrl_regset) return; intr_ctrl_regset->regs = intr_ctrl_regs; From a8a3b61ce140e2b0a72a779e8d70f60c0cf1e47a Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Thu, 10 Apr 2025 11:53:19 +0800 Subject: [PATCH 267/606] net: mctp: Set SOCK_RCU_FREE [ Upstream commit 52024cd6ec71a6ca934d0cc12452bd8d49850679 ] Bind lookup runs under RCU, so ensure that a socket doesn't go away in the middle of a lookup. Fixes: 833ef3b91de6 ("mctp: Populate socket implementation") Signed-off-by: Matt Johnston Link: https://patch.msgid.link/20250410-mctp-rcu-sock-v1-1-872de9fdc877@codeconstruct.com.au Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- net/mctp/af_mctp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/mctp/af_mctp.c b/net/mctp/af_mctp.c index 28be85d05533..8032cfba22d1 100644 --- a/net/mctp/af_mctp.c +++ b/net/mctp/af_mctp.c @@ -550,6 +550,9 @@ static int mctp_sk_hash(struct sock *sk) { struct net *net = sock_net(sk); + /* Bind lookup runs under RCU, remain live during that. */ + sock_set_flag(sk, SOCK_RCU_FREE); + mutex_lock(&net->mctp.bind_lock); sk_add_node_rcu(sk, &net->mctp.binds); mutex_unlock(&net->mctp.bind_lock); From 549cbbd14bbec12469ceb279b79c763c8a24224e Mon Sep 17 00:00:00 2001 From: Zheng Qixing Date: Sat, 12 Apr 2025 17:25:54 +0800 Subject: [PATCH 268/606] block: fix resource leak in blk_register_queue() error path [ Upstream commit 40f2eb9b531475dd01b683fdaf61ca3cfd03a51e ] When registering a queue fails after blk_mq_sysfs_register() is successful but the function later encounters an error, we need to clean up the blk_mq_sysfs resources. Add the missing blk_mq_sysfs_unregister() call in the error path to properly clean up these resources and prevent a memory leak. Fixes: 320ae51feed5 ("blk-mq: new multi-queue block IO queueing mechanism") Signed-off-by: Zheng Qixing Reviewed-by: Christoph Hellwig Reviewed-by: Yu Kuai Link: https://lore.kernel.org/r/20250412092554.475218-1-zhengqixing@huaweicloud.com Signed-off-by: Jens Axboe Signed-off-by: Sasha Levin --- block/blk-sysfs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 4990a19e6013..74839f6f2e0c 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -854,6 +854,8 @@ out_unregister_ia_ranges: out_debugfs_remove: blk_debugfs_remove(disk); mutex_unlock(&q->sysfs_lock); + if (queue_is_mq(q)) + blk_mq_sysfs_unregister(disk); out_put_queue_kobj: kobject_put(&disk->queue_kobj); mutex_unlock(&q->sysfs_dir_lock); From 824a7c2df5127b2402b68a21a265d413e78dcad7 Mon Sep 17 00:00:00 2001 From: Ilya Maximets Date: Sat, 12 Apr 2025 12:40:18 +0200 Subject: [PATCH 269/606] net: openvswitch: fix nested key length validation in the set() action [ Upstream commit 65d91192aa66f05710cfddf6a14b5a25ee554dba ] It's not safe to access nla_len(ovs_key) if the data is smaller than the netlink header. Check that the attribute is OK first. Fixes: ccb1352e76cf ("net: Add Open vSwitch kernel components.") Reported-by: syzbot+b07a9da40df1576b8048@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=b07a9da40df1576b8048 Tested-by: syzbot+b07a9da40df1576b8048@syzkaller.appspotmail.com Signed-off-by: Ilya Maximets Reviewed-by: Eelco Chaudron Acked-by: Aaron Conole Link: https://patch.msgid.link/20250412104052.2073688-1-i.maximets@ovn.org Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- net/openvswitch/flow_netlink.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index 9c13e14034d3..089ab1826e1d 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c @@ -2862,7 +2862,8 @@ static int validate_set(const struct nlattr *a, size_t key_len; /* There can be only one key in a action */ - if (nla_total_size(nla_len(ovs_key)) != nla_len(a)) + if (!nla_ok(ovs_key, nla_len(a)) || + nla_total_size(nla_len(ovs_key)) != nla_len(a)) return -EINVAL; key_len = nla_len(ovs_key); From 7c2b66a31c7a4866400f7e6fb43cb32021bfca01 Mon Sep 17 00:00:00 2001 From: Abdun Nihaal Date: Sat, 12 Apr 2025 21:19:24 +0530 Subject: [PATCH 270/606] net: ngbe: fix memory leak in ngbe_probe() error path [ Upstream commit 88fa80021b77732bc98f73fb69d69c7cc37b9f0d ] When ngbe_sw_init() is called, memory is allocated for wx->rss_key in wx_init_rss_key(). However, in ngbe_probe() function, the subsequent error paths after ngbe_sw_init() don't free the rss_key. Fix that by freeing it in error path along with wx->mac_table. Also change the label to which execution jumps when ngbe_sw_init() fails, because otherwise, it could lead to a double free for rss_key, when the mac_table allocation fails in wx_sw_init(). Fixes: 02338c484ab6 ("net: ngbe: Initialize sw info and register netdev") Signed-off-by: Abdun Nihaal Reviewed-by: Kory Maincent Reviewed-by: Jiawen Wu Link: https://patch.msgid.link/20250412154927.25908-1-abdun.nihaal@gmail.com Signed-off-by: Paolo Abeni Signed-off-by: Sasha Levin --- drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c index a4d63d2f3c5b..91f0f23c176a 100644 --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c @@ -589,7 +589,7 @@ static int ngbe_probe(struct pci_dev *pdev, /* setup the private structure */ err = ngbe_sw_init(wx); if (err) - goto err_free_mac_table; + goto err_pci_release_regions; /* check if flash load is done after hw power up */ err = wx_check_flash_load(wx, NGBE_SPI_ILDR_STATUS_PERST); @@ -687,6 +687,7 @@ err_register: err_clear_interrupt_scheme: wx_clear_interrupt_scheme(wx); err_free_mac_table: + kfree(wx->rss_key); kfree(wx->mac_table); err_pci_release_regions: pci_release_selected_regions(pdev, From 422b7b9d1362b691d30eaa9b912a45fddb50df4d Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Tue, 28 May 2024 09:59:49 +0200 Subject: [PATCH 271/606] net: ethernet: ti: am65-cpsw-nuss: rename phy_node -> port_np [ Upstream commit 78269025e192ec8122ddd87a1ec2805598d8a1ab ] Rename phy_node to port_np to better reflect what it actually is, because the new phylink API takes netdev node (or DSA port node), and resolves the phandle internally. Signed-off-by: Alexander Sverdlin Link: https://lore.kernel.org/r/20240528075954.3608118-2-alexander.sverdlin@siemens.com Signed-off-by: Jakub Kicinski Stable-dep-of: 903d2b9f9efc ("net: ethernet: ti: am65-cpsw: fix port_np reference counting") Signed-off-by: Sasha Levin --- drivers/net/ethernet/ti/am65-cpsw-nuss.c | 6 +++--- drivers/net/ethernet/ti/am65-cpsw-nuss.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c index 8ffc1fbb036f..dbca0b2889bc 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c @@ -626,7 +626,7 @@ static int am65_cpsw_nuss_ndo_slave_open(struct net_device *ndev) /* mac_sl should be configured via phy-link interface */ am65_cpsw_sl_ctl_reset(port); - ret = phylink_of_phy_connect(port->slave.phylink, port->slave.phy_node, 0); + ret = phylink_of_phy_connect(port->slave.phylink, port->slave.port_np, 0); if (ret) goto error_cleanup; @@ -2076,7 +2076,7 @@ static int am65_cpsw_nuss_init_slave_ports(struct am65_cpsw_common *common) of_property_read_bool(port_np, "ti,mac-only"); /* get phy/link info */ - port->slave.phy_node = port_np; + port->slave.port_np = port_np; ret = of_get_phy_mode(port_np, &port->slave.phy_if); if (ret) { dev_err(dev, "%pOF read phy-mode err %d\n", @@ -2217,7 +2217,7 @@ am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx) } phylink = phylink_create(&port->slave.phylink_config, - of_node_to_fwnode(port->slave.phy_node), + of_node_to_fwnode(port->slave.port_np), port->slave.phy_if, &am65_cpsw_phylink_mac_ops); if (IS_ERR(phylink)) diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.h b/drivers/net/ethernet/ti/am65-cpsw-nuss.h index f3dad2ab9828..f107198e2572 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.h +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.h @@ -29,7 +29,7 @@ struct am65_cpts; struct am65_cpsw_slave_data { bool mac_only; struct cpsw_sl *mac_sl; - struct device_node *phy_node; + struct device_node *port_np; phy_interface_t phy_if; struct phy *ifphy; struct phy *serdes_phy; From 94d5809c7fa8608c60dc538cf2236c4418da14f0 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Mon, 14 Apr 2025 10:39:42 +0200 Subject: [PATCH 272/606] net: ethernet: ti: am65-cpsw: fix port_np reference counting [ Upstream commit 903d2b9f9efc5b3339d74015fcfc0d9fff276c4c ] A reference to the device tree node is stored in a private struct, thus the reference count has to be incremented. Also, decrement the count on device removal and in the error path. Fixes: 93a76530316a ("net: ethernet: ti: introduce am65x/j721e gigabit eth subsystem driver") Signed-off-by: Michael Walle Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250414083942.4015060-1-mwalle@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/ti/am65-cpsw-nuss.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c index dbca0b2889bc..9c8376b27189 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c @@ -2076,7 +2076,7 @@ static int am65_cpsw_nuss_init_slave_ports(struct am65_cpsw_common *common) of_property_read_bool(port_np, "ti,mac-only"); /* get phy/link info */ - port->slave.port_np = port_np; + port->slave.port_np = of_node_get(port_np); ret = of_get_phy_mode(port_np, &port->slave.phy_if); if (ret) { dev_err(dev, "%pOF read phy-mode err %d\n", @@ -2134,6 +2134,17 @@ static void am65_cpsw_nuss_phylink_cleanup(struct am65_cpsw_common *common) } } +static void am65_cpsw_remove_dt(struct am65_cpsw_common *common) +{ + struct am65_cpsw_port *port; + int i; + + for (i = 0; i < common->port_num; i++) { + port = &common->ports[i]; + of_node_put(port->slave.port_np); + } +} + static int am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx) { @@ -3009,6 +3020,7 @@ static int am65_cpsw_nuss_probe(struct platform_device *pdev) err_free_phylink: am65_cpsw_nuss_phylink_cleanup(common); am65_cpts_release(common->cpts); + am65_cpsw_remove_dt(common); err_of_clear: if (common->mdio_dev) of_platform_device_destroy(common->mdio_dev, NULL); @@ -3040,6 +3052,7 @@ static int am65_cpsw_nuss_remove(struct platform_device *pdev) am65_cpsw_nuss_phylink_cleanup(common); am65_cpts_release(common->cpts); am65_cpsw_disable_serdes_phy(common); + am65_cpsw_remove_dt(common); if (common->mdio_dev) of_platform_device_destroy(common->mdio_dev, NULL); From e729dd9602e3e43082822e99ef951ab907a30b40 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Tue, 15 Apr 2025 09:30:15 +0200 Subject: [PATCH 273/606] ata: libata-sata: Save all fields from sense data descriptor [ Upstream commit 399eab7f92fb73ffe621294a2d6bec8fc9f3b36b ] When filling the taskfile result for a successful NCQ command, we use the SDB FIS from the FIS Receive Area, see e.g. ahci_qc_ncq_fill_rtf(). However, the SDB FIS only has fields STATUS and ERROR. For a successful NCQ command that has sense data, we will have a successful sense data descriptor, in the Sense Data for Successful NCQ Commands log. Since we have access to additional taskfile result fields, fill in these additional fields in qc->result_tf. This matches how for failing/aborted NCQ commands, we will use e.g. ahci_qc_fill_rtf() to fill in some fields, but then for the command that actually caused the NCQ error, we will use ata_eh_read_log_10h(), which provides additional fields, saving additional fields/overriding the qc->result_tf that was fetched using ahci_qc_fill_rtf(). Fixes: 18bd7718b5c4 ("scsi: ata: libata: Handle completion of CDL commands using policy 0xD") Signed-off-by: Niklas Cassel Reviewed-by: Igor Pylypiv Reviewed-by: Hannes Reinecke Signed-off-by: Damien Le Moal Signed-off-by: Sasha Levin --- drivers/ata/libata-sata.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c index a701e1538482..be72030a500d 100644 --- a/drivers/ata/libata-sata.c +++ b/drivers/ata/libata-sata.c @@ -1365,6 +1365,8 @@ int ata_eh_read_sense_success_ncq_log(struct ata_link *link) unsigned int err_mask, tag; u8 *sense, sk = 0, asc = 0, ascq = 0; u64 sense_valid, val; + u16 extended_sense; + bool aux_icc_valid; int ret = 0; err_mask = ata_read_log_page(dev, ATA_LOG_SENSE_NCQ, 0, buf, 2); @@ -1384,6 +1386,8 @@ int ata_eh_read_sense_success_ncq_log(struct ata_link *link) sense_valid = (u64)buf[8] | ((u64)buf[9] << 8) | ((u64)buf[10] << 16) | ((u64)buf[11] << 24); + extended_sense = get_unaligned_le16(&buf[14]); + aux_icc_valid = extended_sense & BIT(15); ata_qc_for_each_raw(ap, qc, tag) { if (!(qc->flags & ATA_QCFLAG_EH) || @@ -1411,6 +1415,17 @@ int ata_eh_read_sense_success_ncq_log(struct ata_link *link) continue; } + qc->result_tf.nsect = sense[6]; + qc->result_tf.hob_nsect = sense[7]; + qc->result_tf.lbal = sense[8]; + qc->result_tf.lbam = sense[9]; + qc->result_tf.lbah = sense[10]; + qc->result_tf.hob_lbal = sense[11]; + qc->result_tf.hob_lbam = sense[12]; + qc->result_tf.hob_lbah = sense[13]; + if (aux_icc_valid) + qc->result_tf.auxiliary = get_unaligned_le32(&sense[16]); + /* Set sense without also setting scsicmd->result */ scsi_build_sense_buffer(dev->flags & ATA_DFLAG_D_SENSE, qc->scsicmd->sense_buffer, sk, From 08aa59c0be768596467552c129e9f82166779a67 Mon Sep 17 00:00:00 2001 From: Abdun Nihaal Date: Mon, 14 Apr 2025 22:36:46 +0530 Subject: [PATCH 274/606] cxgb4: fix memory leak in cxgb4_init_ethtool_filters() error path [ Upstream commit 00ffb3724ce743578163f5ade2884374554ca021 ] In the for loop used to allocate the loc_array and bmap for each port, a memory leak is possible when the allocation for loc_array succeeds, but the allocation for bmap fails. This is because when the control flow goes to the label free_eth_finfo, only the allocations starting from (i-1)th iteration are freed. Fix that by freeing the loc_array in the bmap allocation error path. Fixes: d915c299f1da ("cxgb4: add skeleton for ethtool n-tuple filters") Signed-off-by: Abdun Nihaal Reviewed-by: Simon Horman Reviewed-by: Jacob Keller Link: https://patch.msgid.link/20250414170649.89156-1-abdun.nihaal@gmail.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c index 8477a93cee6b..b77897aa06c4 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c @@ -2273,6 +2273,7 @@ int cxgb4_init_ethtool_filters(struct adapter *adap) eth_filter->port[i].bmap = bitmap_zalloc(nentries, GFP_KERNEL); if (!eth_filter->port[i].bmap) { ret = -ENOMEM; + kvfree(eth_filter->port[i].loc_array); goto free_eth_finfo; } } From 2f6e52cab1d46fb2134c077c194e2b035e150fda Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 14 Apr 2025 14:18:48 -0700 Subject: [PATCH 275/606] netlink: specs: rt-link: add an attr layer around alt-ifname [ Upstream commit acf4da17deada7f8b120e051aa6c9cac40dbd83b ] alt-ifname attr is directly placed in requests (as an alternative to ifname) but in responses its wrapped up in IFLA_PROP_LIST and only there is may be multi-attr. See rtnl_fill_prop_list(). Fixes: b2f63d904e72 ("doc/netlink: Add spec for rt link messages") Reviewed-by: Donald Hunter Reviewed-by: Jacob Keller Link: https://patch.msgid.link/20250414211851.602096-6-kuba@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- Documentation/netlink/specs/rt_link.yaml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Documentation/netlink/specs/rt_link.yaml b/Documentation/netlink/specs/rt_link.yaml index d86a68f8475c..34f74c451dcd 100644 --- a/Documentation/netlink/specs/rt_link.yaml +++ b/Documentation/netlink/specs/rt_link.yaml @@ -892,11 +892,10 @@ attribute-sets: - name: prop-list type: nest - nested-attributes: link-attrs + nested-attributes: prop-list-link-attrs - name: alt-ifname type: string - multi-attr: true - name: perm-address type: binary @@ -931,6 +930,13 @@ attribute-sets: - name: gro-ipv4-max-size type: u32 + - + name: prop-list-link-attrs + subset-of: link-attrs + attributes: + - + name: alt-ifname + multi-attr: true - name: af-spec-attrs attributes: @@ -1362,7 +1368,6 @@ operations: - min-mtu - max-mtu - prop-list - - alt-ifname - perm-address - proto-down-reason - parent-dev-name From 2315cfaf478242b97ae9e3595b000e874a57c9cd Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 14 Apr 2025 14:18:50 -0700 Subject: [PATCH 276/606] netlink: specs: rt-link: adjust mctp attribute naming [ Upstream commit beb3c5ad8829b52057f48a776a9d9558b98c157f ] MCTP attribute naming is inconsistent. In C we have: IFLA_MCTP_NET, IFLA_MCTP_PHYS_BINDING, ^^^^ but in YAML: - mctp-net - phys-binding ^ no "mctp" It's unclear whether the "mctp" part of the name is supposed to be a prefix or part of attribute name. Make it a prefix, seems cleaner, even tho technically phys-binding was added later. Fixes: b2f63d904e72 ("doc/netlink: Add spec for rt link messages") Reviewed-by: Donald Hunter Reviewed-by: Jacob Keller Link: https://patch.msgid.link/20250414211851.602096-8-kuba@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- Documentation/netlink/specs/rt_link.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/netlink/specs/rt_link.yaml b/Documentation/netlink/specs/rt_link.yaml index 34f74c451dcd..a8a1466adf17 100644 --- a/Documentation/netlink/specs/rt_link.yaml +++ b/Documentation/netlink/specs/rt_link.yaml @@ -1199,9 +1199,10 @@ attribute-sets: type: u32 - name: mctp-attrs + name-prefix: ifla-mctp- attributes: - - name: mctp-net + name: net type: u32 - name: stats-attrs From c9dbc7ec442f19b30e689518da3d800ba7e4dc0b Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Mon, 14 Apr 2025 22:04:34 +0200 Subject: [PATCH 277/606] net: b53: enable BPDU reception for management port [ Upstream commit 36355ddfe8955f226a88a543ed354b9f6b84cd70 ] For STP to work, receiving BPDUs is essential, but the appropriate bit was never set. Without GC_RX_BPDU_EN, the switch chip will filter all BPDUs, even if an appropriate PVID VLAN was setup. Fixes: ff39c2d68679 ("net: dsa: b53: Add bridge support") Signed-off-by: Jonas Gorski Link: https://patch.msgid.link/20250414200434.194422-1-jonas.gorski@gmail.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/dsa/b53/b53_common.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 4a2c9a9134d8..cfcda893f1a1 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -724,6 +724,15 @@ static void b53_enable_mib(struct b53_device *dev) b53_write8(dev, B53_MGMT_PAGE, B53_GLOBAL_CONFIG, gc); } +static void b53_enable_stp(struct b53_device *dev) +{ + u8 gc; + + b53_read8(dev, B53_MGMT_PAGE, B53_GLOBAL_CONFIG, &gc); + gc |= GC_RX_BPDU_EN; + b53_write8(dev, B53_MGMT_PAGE, B53_GLOBAL_CONFIG, gc); +} + static u16 b53_default_pvid(struct b53_device *dev) { if (is5325(dev) || is5365(dev)) @@ -863,6 +872,7 @@ static int b53_switch_reset(struct b53_device *dev) } b53_enable_mib(dev); + b53_enable_stp(dev); return b53_flush_arl(dev, FAST_AGE_STATIC); } From 0f0284285ad36068545c047f63e09ca7152788c9 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Mon, 14 Apr 2025 22:00:20 +0200 Subject: [PATCH 278/606] net: bridge: switchdev: do not notify new brentries as changed [ Upstream commit eb25de13bd9cf025413a04f25e715d0e99847e30 ] When adding a bridge vlan that is pvid or untagged after the vlan has already been added to any other switchdev backed port, the vlan change will be propagated as changed, since the flags change. This causes the vlan to not be added to the hardware for DSA switches, since the DSA handler ignores any vlans for the CPU or DSA ports that are changed. E.g. the following order of operations would work: $ ip link add swbridge type bridge vlan_filtering 1 vlan_default_pvid 0 $ ip link set lan1 master swbridge $ bridge vlan add dev swbridge vid 1 pvid untagged self $ bridge vlan add dev lan1 vid 1 pvid untagged but this order would break: $ ip link add swbridge type bridge vlan_filtering 1 vlan_default_pvid 0 $ ip link set lan1 master swbridge $ bridge vlan add dev lan1 vid 1 pvid untagged $ bridge vlan add dev swbridge vid 1 pvid untagged self Additionally, the vlan on the bridge itself would become undeletable: $ bridge vlan port vlan-id lan1 1 PVID Egress Untagged swbridge 1 PVID Egress Untagged $ bridge vlan del dev swbridge vid 1 self $ bridge vlan port vlan-id lan1 1 PVID Egress Untagged swbridge 1 Egress Untagged since the vlan was never added to DSA's vlan list, so deleting it will cause an error, causing the bridge code to not remove it. Fix this by checking if flags changed only for vlans that are already brentry and pass changed as false for those that become brentries, as these are a new vlan (member) from the switchdev point of view. Since *changed is set to true for becomes_brentry = true regardless of would_change's value, this will not change any rtnetlink notification delivery, just the value passed on to switchdev in vlan->changed. Fixes: 8d23a54f5bee ("net: bridge: switchdev: differentiate new VLANs from changed ones") Reviewed-by: Vladimir Oltean Signed-off-by: Jonas Gorski Reviewed-by: Ido Schimmel Acked-by: Nikolay Aleksandrov Link: https://patch.msgid.link/20250414200020.192715-1-jonas.gorski@gmail.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- net/bridge/br_vlan.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index be714b4d7b43..a1c22eab71ff 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -715,8 +715,8 @@ static int br_vlan_add_existing(struct net_bridge *br, u16 flags, bool *changed, struct netlink_ext_ack *extack) { - bool would_change = __vlan_flags_would_change(vlan, flags); bool becomes_brentry = false; + bool would_change = false; int err; if (!br_vlan_is_brentry(vlan)) { @@ -725,6 +725,8 @@ static int br_vlan_add_existing(struct net_bridge *br, return -EINVAL; becomes_brentry = true; + } else { + would_change = __vlan_flags_would_change(vlan, flags); } /* Master VLANs that aren't brentries weren't notified before, From bbb80f004f7a90c3dcaacc982c59967457254a05 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 15 Apr 2025 00:28:50 +0300 Subject: [PATCH 279/606] net: dsa: mv88e6xxx: avoid unregistering devlink regions which were never registered [ Upstream commit c84f6ce918a9e6f4996597cbc62536bbf2247c96 ] Russell King reports that a system with mv88e6xxx dereferences a NULL pointer when unbinding this driver: https://lore.kernel.org/netdev/Z_lRkMlTJ1KQ0kVX@shell.armlinux.org.uk/ The crash seems to be in devlink_region_destroy(), which is not NULL tolerant but is given a NULL devlink global region pointer. At least on some chips, some devlink regions are conditionally registered since the blamed commit, see mv88e6xxx_setup_devlink_regions_global(): if (cond && !cond(chip)) continue; These are MV88E6XXX_REGION_STU and MV88E6XXX_REGION_PVT. If the chip does not have an STU or PVT, it should crash like this. To fix the issue, avoid unregistering those regions which are NULL, i.e. were skipped at mv88e6xxx_setup_devlink_regions_global() time. Fixes: 836021a2d0e0 ("net: dsa: mv88e6xxx: Export cross-chip PVT as devlink region") Tested-by: Russell King (Oracle) Signed-off-by: Vladimir Oltean Link: https://patch.msgid.link/20250414212850.2953957-1-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/dsa/mv88e6xxx/devlink.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/mv88e6xxx/devlink.c b/drivers/net/dsa/mv88e6xxx/devlink.c index a08dab75e0c0..f57fde02077d 100644 --- a/drivers/net/dsa/mv88e6xxx/devlink.c +++ b/drivers/net/dsa/mv88e6xxx/devlink.c @@ -743,7 +743,8 @@ void mv88e6xxx_teardown_devlink_regions_global(struct dsa_switch *ds) int i; for (i = 0; i < ARRAY_SIZE(mv88e6xxx_regions); i++) - dsa_devlink_region_destroy(chip->regions[i]); + if (chip->regions[i]) + dsa_devlink_region_destroy(chip->regions[i]); } void mv88e6xxx_teardown_devlink_regions_port(struct dsa_switch *ds, int port) From afae9087301471970254a9180e5a26d3d8e8af09 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 15 Apr 2025 00:29:13 +0300 Subject: [PATCH 280/606] net: dsa: mv88e6xxx: fix -ENOENT when deleting VLANs and MST is unsupported [ Upstream commit ea08dfc35f83cfc73493c52f63ae4f2e29edfe8d ] Russell King reports that on the ZII dev rev B, deleting a bridge VLAN from a user port fails with -ENOENT: https://lore.kernel.org/netdev/Z_lQXNP0s5-IiJzd@shell.armlinux.org.uk/ This comes from mv88e6xxx_port_vlan_leave() -> mv88e6xxx_mst_put(), which tries to find an MST entry in &chip->msts associated with the SID, but fails and returns -ENOENT as such. But we know that this chip does not support MST at all, so that is not surprising. The question is why does the guard in mv88e6xxx_mst_put() not exit early: if (!sid) return 0; And the answer seems to be simple: the sid comes from vlan.sid which supposedly was previously populated by mv88e6xxx_vtu_get(). But some chip->info->ops->vtu_getnext() implementations do not populate vlan.sid, for example see mv88e6185_g1_vtu_getnext(). In that case, later in mv88e6xxx_port_vlan_leave() we are using a garbage sid which is just residual stack memory. Testing for sid == 0 covers all cases of a non-bridge VLAN or a bridge VLAN mapped to the default MSTI. For some chips, SID 0 is valid and installed by mv88e6xxx_stu_setup(). A chip which does not support the STU would implicitly only support mapping all VLANs to the default MSTI, so although SID 0 is not valid, it would be sufficient, if we were to zero-initialize the vlan structure, to fix the bug, due to the coincidence that a test for vlan.sid == 0 already exists and leads to the same (correct) behavior. Another option which would be sufficient would be to add a test for mv88e6xxx_has_stu() inside mv88e6xxx_mst_put(), symmetric to the one which already exists in mv88e6xxx_mst_get(). But that placement means the caller will have to dereference vlan.sid, which means it will access uninitialized memory, which is not nice even if it ignores it later. So we end up making both modifications, in order to not rely just on the sid == 0 coincidence, but also to avoid having uninitialized structure fields which might get temporarily accessed. Fixes: acaf4d2e36b3 ("net: dsa: mv88e6xxx: MST Offloading") Signed-off-by: Vladimir Oltean Link: https://patch.msgid.link/20250414212913.2955253-1-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/dsa/mv88e6xxx/chip.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 662509c3da1f..da7260e505a2 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1742,6 +1742,8 @@ static int mv88e6xxx_vtu_get(struct mv88e6xxx_chip *chip, u16 vid, if (!chip->info->ops->vtu_getnext) return -EOPNOTSUPP; + memset(entry, 0, sizeof(*entry)); + entry->vid = vid ? vid - 1 : mv88e6xxx_max_vid(chip); entry->valid = false; @@ -1877,7 +1879,16 @@ static int mv88e6xxx_mst_put(struct mv88e6xxx_chip *chip, u8 sid) struct mv88e6xxx_mst *mst, *tmp; int err; - if (!sid) + /* If the SID is zero, it is for a VLAN mapped to the default MSTI, + * and mv88e6xxx_stu_setup() made sure it is always present, and thus, + * should not be removed here. + * + * If the chip lacks STU support, numerically the "sid" variable will + * happen to also be zero, but we don't want to rely on that fact, so + * we explicitly test that first. In that case, there is also nothing + * to do here. + */ + if (!mv88e6xxx_has_stu(chip) || !sid) return 0; list_for_each_entry_safe(mst, tmp, &chip->msts, node) { From 86c6613a69bca815f1865ed8cedfd4b9142621ab Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 15 Apr 2025 00:29:30 +0300 Subject: [PATCH 281/606] net: dsa: clean up FDB, MDB, VLAN entries on unbind [ Upstream commit 7afb5fb42d4950f33af2732b8147c552659f79b7 ] As explained in many places such as commit b117e1e8a86d ("net: dsa: delete dsa_legacy_fdb_add and dsa_legacy_fdb_del"), DSA is written given the assumption that higher layers have balanced additions/deletions. As such, it only makes sense to be extremely vocal when those assumptions are violated and the driver unbinds with entries still present. But Ido Schimmel points out a very simple situation where that is wrong: https://lore.kernel.org/netdev/ZDazSM5UsPPjQuKr@shredder/ (also briefly discussed by me in the aforementioned commit). Basically, while the bridge bypass operations are not something that DSA explicitly documents, and for the majority of DSA drivers this API simply causes them to go to promiscuous mode, that isn't the case for all drivers. Some have the necessary requirements for bridge bypass operations to do something useful - see dsa_switch_supports_uc_filtering(). Although in tools/testing/selftests/net/forwarding/local_termination.sh, we made an effort to popularize better mechanisms to manage address filters on DSA interfaces from user space - namely macvlan for unicast, and setsockopt(IP_ADD_MEMBERSHIP) - through mtools - for multicast, the fact is that 'bridge fdb add ... self static local' also exists as kernel UAPI, and might be useful to someone, even if only for a quick hack. It seems counter-productive to block that path by implementing shim .ndo_fdb_add and .ndo_fdb_del operations which just return -EOPNOTSUPP in order to prevent the ndo_dflt_fdb_add() and ndo_dflt_fdb_del() from running, although we could do that. Accepting that cleanup is necessary seems to be the only option. Especially since we appear to be coming back at this from a different angle as well. Russell King is noticing that the WARN_ON() triggers even for VLANs: https://lore.kernel.org/netdev/Z_li8Bj8bD4-BYKQ@shell.armlinux.org.uk/ What happens in the bug report above is that dsa_port_do_vlan_del() fails, then the VLAN entry lingers on, and then we warn on unbind and leak it. This is not a straight revert of the blamed commit, but we now add an informational print to the kernel log (to still have a way to see that bugs exist), and some extra comments gathered from past years' experience, to justify the logic. Fixes: 0832cd9f1f02 ("net: dsa: warn if port lists aren't empty in dsa_port_teardown") Signed-off-by: Vladimir Oltean Link: https://patch.msgid.link/20250414212930.2956310-1-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- net/dsa/dsa.c | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index ccbdb98109f8..399675c5fcc7 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -1483,12 +1483,44 @@ static int dsa_switch_parse(struct dsa_switch *ds, struct dsa_chip_data *cd) static void dsa_switch_release_ports(struct dsa_switch *ds) { + struct dsa_mac_addr *a, *tmp; struct dsa_port *dp, *next; + struct dsa_vlan *v, *n; dsa_switch_for_each_port_safe(dp, next, ds) { - WARN_ON(!list_empty(&dp->fdbs)); - WARN_ON(!list_empty(&dp->mdbs)); - WARN_ON(!list_empty(&dp->vlans)); + /* These are either entries that upper layers lost track of + * (probably due to bugs), or installed through interfaces + * where one does not necessarily have to remove them, like + * ndo_dflt_fdb_add(). + */ + list_for_each_entry_safe(a, tmp, &dp->fdbs, list) { + dev_info(ds->dev, + "Cleaning up unicast address %pM vid %u from port %d\n", + a->addr, a->vid, dp->index); + list_del(&a->list); + kfree(a); + } + + list_for_each_entry_safe(a, tmp, &dp->mdbs, list) { + dev_info(ds->dev, + "Cleaning up multicast address %pM vid %u from port %d\n", + a->addr, a->vid, dp->index); + list_del(&a->list); + kfree(a); + } + + /* These are entries that upper layers have lost track of, + * probably due to bugs, but also due to dsa_port_do_vlan_del() + * having failed and the VLAN entry still lingering on. + */ + list_for_each_entry_safe(v, n, &dp->vlans, list) { + dev_info(ds->dev, + "Cleaning up vid %u from port %d\n", + v->vid, dp->index); + list_del(&v->list); + kfree(v); + } + list_del(&dp->list); kfree(dp); } From fb12b460ec46c9efad98de6d9ba349691db51dc7 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 15 Apr 2025 00:30:01 +0300 Subject: [PATCH 282/606] net: dsa: free routing table on probe failure [ Upstream commit 8bf108d7161ffc6880ad13a0cc109de3cf631727 ] If complete = true in dsa_tree_setup(), it means that we are the last switch of the tree which is successfully probing, and we should be setting up all switches from our probe path. After "complete" becomes true, dsa_tree_setup_cpu_ports() or any subsequent function may fail. If that happens, the entire tree setup is in limbo: the first N-1 switches have successfully finished probing (doing nothing but having allocated persistent memory in the tree's dst->ports, and maybe dst->rtable), and switch N failed to probe, ending the tree setup process before anything is tangible from the user's PoV. If switch N fails to probe, its memory (ports) will be freed and removed from dst->ports. However, the dst->rtable elements pointing to its ports, as created by dsa_link_touch(), will remain there, and will lead to use-after-free if dereferenced. If dsa_tree_setup_switches() returns -EPROBE_DEFER, which is entirely possible because that is where ds->ops->setup() is, we get a kasan report like this: ================================================================== BUG: KASAN: slab-use-after-free in mv88e6xxx_setup_upstream_port+0x240/0x568 Read of size 8 at addr ffff000004f56020 by task kworker/u8:3/42 Call trace: __asan_report_load8_noabort+0x20/0x30 mv88e6xxx_setup_upstream_port+0x240/0x568 mv88e6xxx_setup+0xebc/0x1eb0 dsa_register_switch+0x1af4/0x2ae0 mv88e6xxx_register_switch+0x1b8/0x2a8 mv88e6xxx_probe+0xc4c/0xf60 mdio_probe+0x78/0xb8 really_probe+0x2b8/0x5a8 __driver_probe_device+0x164/0x298 driver_probe_device+0x78/0x258 __device_attach_driver+0x274/0x350 Allocated by task 42: __kasan_kmalloc+0x84/0xa0 __kmalloc_cache_noprof+0x298/0x490 dsa_switch_touch_ports+0x174/0x3d8 dsa_register_switch+0x800/0x2ae0 mv88e6xxx_register_switch+0x1b8/0x2a8 mv88e6xxx_probe+0xc4c/0xf60 mdio_probe+0x78/0xb8 really_probe+0x2b8/0x5a8 __driver_probe_device+0x164/0x298 driver_probe_device+0x78/0x258 __device_attach_driver+0x274/0x350 Freed by task 42: __kasan_slab_free+0x48/0x68 kfree+0x138/0x418 dsa_register_switch+0x2694/0x2ae0 mv88e6xxx_register_switch+0x1b8/0x2a8 mv88e6xxx_probe+0xc4c/0xf60 mdio_probe+0x78/0xb8 really_probe+0x2b8/0x5a8 __driver_probe_device+0x164/0x298 driver_probe_device+0x78/0x258 __device_attach_driver+0x274/0x350 The simplest way to fix the bug is to delete the routing table in its entirety. dsa_tree_setup_routing_table() has no problem in regenerating it even if we deleted links between ports other than those of switch N, because dsa_link_touch() first checks whether the port pair already exists in dst->rtable, allocating if not. The deletion of the routing table in its entirety already exists in dsa_tree_teardown(), so refactor that into a function that can also be called from the tree setup error path. In my analysis of the commit to blame, it is the one which added dsa_link elements to dst->rtable. Prior to that, each switch had its own ds->rtable which is freed when the switch fails to probe. But the tree is potentially persistent memory. Fixes: c5f51765a1f6 ("net: dsa: list DSA links in the fabric") Signed-off-by: Vladimir Oltean Link: https://patch.msgid.link/20250414213001.2957964-1-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- net/dsa/dsa.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 399675c5fcc7..07736edc8b6a 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -867,6 +867,16 @@ static void dsa_tree_teardown_lags(struct dsa_switch_tree *dst) kfree(dst->lags); } +static void dsa_tree_teardown_routing_table(struct dsa_switch_tree *dst) +{ + struct dsa_link *dl, *next; + + list_for_each_entry_safe(dl, next, &dst->rtable, list) { + list_del(&dl->list); + kfree(dl); + } +} + static int dsa_tree_setup(struct dsa_switch_tree *dst) { bool complete; @@ -884,7 +894,7 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst) err = dsa_tree_setup_cpu_ports(dst); if (err) - return err; + goto teardown_rtable; err = dsa_tree_setup_switches(dst); if (err) @@ -916,14 +926,14 @@ teardown_switches: dsa_tree_teardown_switches(dst); teardown_cpu_ports: dsa_tree_teardown_cpu_ports(dst); +teardown_rtable: + dsa_tree_teardown_routing_table(dst); return err; } static void dsa_tree_teardown(struct dsa_switch_tree *dst) { - struct dsa_link *dl, *next; - if (!dst->setup) return; @@ -937,10 +947,7 @@ static void dsa_tree_teardown(struct dsa_switch_tree *dst) dsa_tree_teardown_cpu_ports(dst); - list_for_each_entry_safe(dl, next, &dst->rtable, list) { - list_del(&dl->list); - kfree(dl); - } + dsa_tree_teardown_routing_table(dst); pr_info("DSA: tree %d torn down\n", dst->index); From c7ee467f29a8bf0bff8bc00a41ca6e217356b7a3 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 15 Apr 2025 00:30:20 +0300 Subject: [PATCH 283/606] net: dsa: avoid refcount warnings when ds->ops->tag_8021q_vlan_del() fails [ Upstream commit 514eff7b0aa1c5eb645ddbb8676ef3e2d88a8b99 ] This is very similar to the problem and solution from commit 232deb3f9567 ("net: dsa: avoid refcount warnings when ->port_{fdb,mdb}_del returns error"), except for the dsa_port_do_tag_8021q_vlan_del() operation. Fixes: c64b9c05045a ("net: dsa: tag_8021q: add proper cross-chip notifier support") Signed-off-by: Vladimir Oltean Link: https://patch.msgid.link/20250414213020.2959021-1-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- net/dsa/tag_8021q.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c index cbdfc392f7e0..a5420421e462 100644 --- a/net/dsa/tag_8021q.c +++ b/net/dsa/tag_8021q.c @@ -197,7 +197,7 @@ static int dsa_port_do_tag_8021q_vlan_del(struct dsa_port *dp, u16 vid) err = ds->ops->tag_8021q_vlan_del(ds, port, vid); if (err) { - refcount_inc(&v->refcount); + refcount_set(&v->refcount, 1); return err; } From 06ec3c18810fde67049d77bef785d940e8f05e28 Mon Sep 17 00:00:00 2001 From: Sagi Maimon Date: Tue, 15 Apr 2025 08:31:31 +0300 Subject: [PATCH 284/606] ptp: ocp: fix start time alignment in ptp_ocp_signal_set [ Upstream commit 2a5970d5aaff8f3e33ce3bfaa403ae88c40de40d ] In ptp_ocp_signal_set, the start time for periodic signals is not aligned to the next period boundary. The current code rounds up the start time and divides by the period but fails to multiply back by the period, causing misaligned signal starts. Fix this by multiplying the rounded-up value by the period to ensure the start time is the closest next period. Fixes: 4bd46bb037f8e ("ptp: ocp: Use DIV64_U64_ROUND_UP for rounding.") Signed-off-by: Sagi Maimon Reviewed-by: Vadim Fedorenko Link: https://patch.msgid.link/20250415053131.129413-1-maimon.sagi@gmail.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/ptp/ptp_ocp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c index 13343c319877..4899fdf9bdf7 100644 --- a/drivers/ptp/ptp_ocp.c +++ b/drivers/ptp/ptp_ocp.c @@ -1842,6 +1842,7 @@ ptp_ocp_signal_set(struct ptp_ocp *bp, int gen, struct ptp_ocp_signal *s) if (!s->start) { /* roundup() does not work on 32-bit systems */ s->start = DIV64_U64_ROUND_UP(start_ns, s->period); + s->start *= s->period; s->start = ktime_add(s->start, s->phase); } From d64a7166fd124db099c7ca51d1594a16c6492df3 Mon Sep 17 00:00:00 2001 From: Meghana Malladi Date: Tue, 4 Mar 2025 16:27:52 +0530 Subject: [PATCH 285/606] net: ti: icss-iep: Add pwidth configuration for perout signal [ Upstream commit e5b456a14215e3c0e84844c2926861b972e03632 ] icss_iep_perout_enable_hw() is a common function for generating both pps and perout signals. When enabling pps, the application needs to only pass enable/disable argument, whereas for perout it supports different flags to configure the signal. But icss_iep_perout_enable_hw() function is missing to hook the configuration params passed by the app, causing perout to behave same a pps (except being able to configure the period). As duty cycle is also one feature which can configured for perout, incorporate this in the function to get the expected signal. Signed-off-by: Meghana Malladi Reviewed-by: Jacob Keller Reviewed-by: Kory Maincent Link: https://patch.msgid.link/20250304105753.1552159-2-m-malladi@ti.com Signed-off-by: Jakub Kicinski Stable-dep-of: 7349c9e99793 ("net: ti: icss-iep: Fix possible NULL pointer dereference for perout request") Signed-off-by: Sasha Levin --- drivers/net/ethernet/ti/icssg/icss_iep.c | 47 ++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.c b/drivers/net/ethernet/ti/icssg/icss_iep.c index 3f9a030471fe..923ac58c9de5 100644 --- a/drivers/net/ethernet/ti/icssg/icss_iep.c +++ b/drivers/net/ethernet/ti/icssg/icss_iep.c @@ -476,9 +476,16 @@ static void icss_iep_update_to_next_boundary(struct icss_iep *iep, u64 start_ns) static int icss_iep_perout_enable_hw(struct icss_iep *iep, struct ptp_perout_request *req, int on) { + struct timespec64 ts; + u64 ns_width; int ret; u64 cmp; + /* Calculate width of the signal for PPS/PEROUT handling */ + ts.tv_sec = req->on.sec; + ts.tv_nsec = req->on.nsec; + ns_width = timespec64_to_ns(&ts); + if (iep->ops && iep->ops->perout_enable) { ret = iep->ops->perout_enable(iep->clockops_data, req, on, &cmp); if (ret) @@ -489,8 +496,9 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep, regmap_write(iep->map, ICSS_IEP_CMP1_REG0, lower_32_bits(cmp)); if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) regmap_write(iep->map, ICSS_IEP_CMP1_REG1, upper_32_bits(cmp)); - /* Configure SYNC, 1ms pulse width */ - regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, 1000000); + /* Configure SYNC, based on req on width */ + regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, + div_u64(ns_width, iep->def_inc)); regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0); regmap_write(iep->map, ICSS_IEP_SYNC_START_REG, 0); regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0); /* one-shot mode */ @@ -517,6 +525,8 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep, + req->period.nsec; icss_iep_update_to_next_boundary(iep, start_ns); + regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, + div_u64(ns_width, iep->def_inc)); /* Enable Sync in single shot mode */ regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, IEP_SYNC_CTRL_SYNC_N_EN(0) | IEP_SYNC_CTRL_SYNC_EN); @@ -544,7 +554,36 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep, static int icss_iep_perout_enable(struct icss_iep *iep, struct ptp_perout_request *req, int on) { - return -EOPNOTSUPP; + int ret = 0; + + /* Reject requests with unsupported flags */ + if (req->flags & ~PTP_PEROUT_DUTY_CYCLE) + return -EOPNOTSUPP; + + mutex_lock(&iep->ptp_clk_mutex); + + if (iep->pps_enabled) { + ret = -EBUSY; + goto exit; + } + + if (iep->perout_enabled == !!on) + goto exit; + + /* Set default "on" time (1ms) for the signal if not passed by the app */ + if (!(req->flags & PTP_PEROUT_DUTY_CYCLE)) { + req->on.sec = 0; + req->on.nsec = NSEC_PER_MSEC; + } + + ret = icss_iep_perout_enable_hw(iep, req, on); + if (!ret) + iep->perout_enabled = !!on; + +exit: + mutex_unlock(&iep->ptp_clk_mutex); + + return ret; } static int icss_iep_pps_enable(struct icss_iep *iep, int on) @@ -572,6 +611,8 @@ static int icss_iep_pps_enable(struct icss_iep *iep, int on) rq.perout.period.nsec = 0; rq.perout.start.sec = ts.tv_sec + 2; rq.perout.start.nsec = 0; + rq.perout.on.sec = 0; + rq.perout.on.nsec = NSEC_PER_MSEC; ret = icss_iep_perout_enable_hw(iep, &rq.perout, on); } else { ret = icss_iep_perout_enable_hw(iep, &rq.perout, on); From 8b9808b1f64e201eb2416d1794ad5157bc2db660 Mon Sep 17 00:00:00 2001 From: Meghana Malladi Date: Tue, 4 Mar 2025 16:27:53 +0530 Subject: [PATCH 286/606] net: ti: icss-iep: Add phase offset configuration for perout signal [ Upstream commit 220cb1be647a7ca4e60241405c66f8f612c9b046 ] icss_iep_perout_enable_hw() is a common function for generating both pps and perout signals. When enabling pps, the application needs to only pass enable/disable argument, whereas for perout it supports different flags to configure the signal. In case the app passes a valid phase offset value, the signal should start toggling after that phase offset, else start immediately or as soon as possible. ICSS_IEP_SYNC_START_REG register take number of clock cycles to wait before starting the signal after activation time. Set appropriate value to this register to support phase offset. Signed-off-by: Meghana Malladi Reviewed-by: Jacob Keller Reviewed-by: Kory Maincent Link: https://patch.msgid.link/20250304105753.1552159-3-m-malladi@ti.com Signed-off-by: Jakub Kicinski Stable-dep-of: 7349c9e99793 ("net: ti: icss-iep: Fix possible NULL pointer dereference for perout request") Signed-off-by: Sasha Levin --- drivers/net/ethernet/ti/icssg/icss_iep.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.c b/drivers/net/ethernet/ti/icssg/icss_iep.c index 923ac58c9de5..6006276ecce6 100644 --- a/drivers/net/ethernet/ti/icssg/icss_iep.c +++ b/drivers/net/ethernet/ti/icssg/icss_iep.c @@ -477,6 +477,7 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep, struct ptp_perout_request *req, int on) { struct timespec64 ts; + u64 ns_start; u64 ns_width; int ret; u64 cmp; @@ -486,6 +487,14 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep, ts.tv_nsec = req->on.nsec; ns_width = timespec64_to_ns(&ts); + if (req->flags & PTP_PEROUT_PHASE) { + ts.tv_sec = req->phase.sec; + ts.tv_nsec = req->phase.nsec; + ns_start = timespec64_to_ns(&ts); + } else { + ns_start = 0; + } + if (iep->ops && iep->ops->perout_enable) { ret = iep->ops->perout_enable(iep->clockops_data, req, on, &cmp); if (ret) @@ -500,7 +509,8 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep, regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, div_u64(ns_width, iep->def_inc)); regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0); - regmap_write(iep->map, ICSS_IEP_SYNC_START_REG, 0); + regmap_write(iep->map, ICSS_IEP_SYNC_START_REG, + div_u64(ns_start, iep->def_inc)); regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0); /* one-shot mode */ /* Enable CMP 1 */ regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, @@ -527,6 +537,8 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep, regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, div_u64(ns_width, iep->def_inc)); + regmap_write(iep->map, ICSS_IEP_SYNC_START_REG, + div_u64(ns_start, iep->def_inc)); /* Enable Sync in single shot mode */ regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, IEP_SYNC_CTRL_SYNC_N_EN(0) | IEP_SYNC_CTRL_SYNC_EN); @@ -557,7 +569,8 @@ static int icss_iep_perout_enable(struct icss_iep *iep, int ret = 0; /* Reject requests with unsupported flags */ - if (req->flags & ~PTP_PEROUT_DUTY_CYCLE) + if (req->flags & ~(PTP_PEROUT_DUTY_CYCLE | + PTP_PEROUT_PHASE)) return -EOPNOTSUPP; mutex_lock(&iep->ptp_clk_mutex); @@ -607,6 +620,7 @@ static int icss_iep_pps_enable(struct icss_iep *iep, int on) if (on) { ns = icss_iep_gettime(iep, NULL); ts = ns_to_timespec64(ns); + rq.perout.flags = 0; rq.perout.period.sec = 1; rq.perout.period.nsec = 0; rq.perout.start.sec = ts.tv_sec + 2; From 7891619d21f07a88e0275d6d43db74035aa74f69 Mon Sep 17 00:00:00 2001 From: Meghana Malladi Date: Tue, 15 Apr 2025 14:35:43 +0530 Subject: [PATCH 287/606] net: ti: icss-iep: Fix possible NULL pointer dereference for perout request [ Upstream commit 7349c9e9979333abfce42da5f9025598083b59c9 ] The ICSS IEP driver tracks perout and pps enable state with flags. Currently when disabling pps and perout signals during icss_iep_exit(), results in NULL pointer dereference for perout. To fix the null pointer dereference issue, the icss_iep_perout_enable_hw function can be modified to directly clear the IEP CMP registers when disabling PPS or PEROUT, without referencing the ptp_perout_request structure, as its contents are irrelevant in this case. Fixes: 9b115361248d ("net: ti: icssg-prueth: Fix clearing of IEP_CMP_CFG registers during iep_init") Reported-by: Dan Carpenter Closes: https://lore.kernel.org/all/7b1c7c36-363a-4085-b26c-4f210bee1df6@stanley.mountain/ Signed-off-by: Meghana Malladi Reviewed-by: Jacob Keller Link: https://patch.msgid.link/20250415090543.717991-4-m-malladi@ti.com Signed-off-by: Paolo Abeni Signed-off-by: Sasha Levin --- drivers/net/ethernet/ti/icssg/icss_iep.c | 117 +++++++++++------------ 1 file changed, 56 insertions(+), 61 deletions(-) diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.c b/drivers/net/ethernet/ti/icssg/icss_iep.c index 6006276ecce6..f3315c651515 100644 --- a/drivers/net/ethernet/ti/icssg/icss_iep.c +++ b/drivers/net/ethernet/ti/icssg/icss_iep.c @@ -482,6 +482,22 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep, int ret; u64 cmp; + if (!on) { + /* Disable CMP 1 */ + regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, + IEP_CMP_CFG_CMP_EN(1), 0); + + /* clear CMP regs */ + regmap_write(iep->map, ICSS_IEP_CMP1_REG0, 0); + if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) + regmap_write(iep->map, ICSS_IEP_CMP1_REG1, 0); + + /* Disable sync */ + regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0); + + return 0; + } + /* Calculate width of the signal for PPS/PEROUT handling */ ts.tv_sec = req->on.sec; ts.tv_nsec = req->on.nsec; @@ -500,64 +516,39 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep, if (ret) return ret; - if (on) { - /* Configure CMP */ - regmap_write(iep->map, ICSS_IEP_CMP1_REG0, lower_32_bits(cmp)); - if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) - regmap_write(iep->map, ICSS_IEP_CMP1_REG1, upper_32_bits(cmp)); - /* Configure SYNC, based on req on width */ - regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, - div_u64(ns_width, iep->def_inc)); - regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0); - regmap_write(iep->map, ICSS_IEP_SYNC_START_REG, - div_u64(ns_start, iep->def_inc)); - regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0); /* one-shot mode */ - /* Enable CMP 1 */ - regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, - IEP_CMP_CFG_CMP_EN(1), IEP_CMP_CFG_CMP_EN(1)); - } else { - /* Disable CMP 1 */ - regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, - IEP_CMP_CFG_CMP_EN(1), 0); - - /* clear regs */ - regmap_write(iep->map, ICSS_IEP_CMP1_REG0, 0); - if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) - regmap_write(iep->map, ICSS_IEP_CMP1_REG1, 0); - } + /* Configure CMP */ + regmap_write(iep->map, ICSS_IEP_CMP1_REG0, lower_32_bits(cmp)); + if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) + regmap_write(iep->map, ICSS_IEP_CMP1_REG1, upper_32_bits(cmp)); + /* Configure SYNC, based on req on width */ + regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, + div_u64(ns_width, iep->def_inc)); + regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0); + regmap_write(iep->map, ICSS_IEP_SYNC_START_REG, + div_u64(ns_start, iep->def_inc)); + regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0); /* one-shot mode */ + /* Enable CMP 1 */ + regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, + IEP_CMP_CFG_CMP_EN(1), IEP_CMP_CFG_CMP_EN(1)); } else { - if (on) { - u64 start_ns; + u64 start_ns; - iep->period = ((u64)req->period.sec * NSEC_PER_SEC) + - req->period.nsec; - start_ns = ((u64)req->period.sec * NSEC_PER_SEC) - + req->period.nsec; - icss_iep_update_to_next_boundary(iep, start_ns); + iep->period = ((u64)req->period.sec * NSEC_PER_SEC) + + req->period.nsec; + start_ns = ((u64)req->period.sec * NSEC_PER_SEC) + + req->period.nsec; + icss_iep_update_to_next_boundary(iep, start_ns); - regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, - div_u64(ns_width, iep->def_inc)); - regmap_write(iep->map, ICSS_IEP_SYNC_START_REG, - div_u64(ns_start, iep->def_inc)); - /* Enable Sync in single shot mode */ - regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, - IEP_SYNC_CTRL_SYNC_N_EN(0) | IEP_SYNC_CTRL_SYNC_EN); - /* Enable CMP 1 */ - regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, - IEP_CMP_CFG_CMP_EN(1), IEP_CMP_CFG_CMP_EN(1)); - } else { - /* Disable CMP 1 */ - regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, - IEP_CMP_CFG_CMP_EN(1), 0); - - /* clear CMP regs */ - regmap_write(iep->map, ICSS_IEP_CMP1_REG0, 0); - if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) - regmap_write(iep->map, ICSS_IEP_CMP1_REG1, 0); - - /* Disable sync */ - regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0); - } + regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, + div_u64(ns_width, iep->def_inc)); + regmap_write(iep->map, ICSS_IEP_SYNC_START_REG, + div_u64(ns_start, iep->def_inc)); + /* Enable Sync in single shot mode */ + regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, + IEP_SYNC_CTRL_SYNC_N_EN(0) | IEP_SYNC_CTRL_SYNC_EN); + /* Enable CMP 1 */ + regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, + IEP_CMP_CFG_CMP_EN(1), IEP_CMP_CFG_CMP_EN(1)); } return 0; @@ -568,11 +559,21 @@ static int icss_iep_perout_enable(struct icss_iep *iep, { int ret = 0; + if (!on) + goto disable; + /* Reject requests with unsupported flags */ if (req->flags & ~(PTP_PEROUT_DUTY_CYCLE | PTP_PEROUT_PHASE)) return -EOPNOTSUPP; + /* Set default "on" time (1ms) for the signal if not passed by the app */ + if (!(req->flags & PTP_PEROUT_DUTY_CYCLE)) { + req->on.sec = 0; + req->on.nsec = NSEC_PER_MSEC; + } + +disable: mutex_lock(&iep->ptp_clk_mutex); if (iep->pps_enabled) { @@ -583,12 +584,6 @@ static int icss_iep_perout_enable(struct icss_iep *iep, if (iep->perout_enabled == !!on) goto exit; - /* Set default "on" time (1ms) for the signal if not passed by the app */ - if (!(req->flags & PTP_PEROUT_DUTY_CYCLE)) { - req->on.sec = 0; - req->on.nsec = NSEC_PER_MSEC; - } - ret = icss_iep_perout_enable_hw(iep, req, on); if (!ret) iep->perout_enabled = !!on; From d853feb79d7e0846247cec25f2844d5825e21950 Mon Sep 17 00:00:00 2001 From: Bo-Cun Chen Date: Wed, 16 Apr 2025 01:51:07 +0100 Subject: [PATCH 288/606] net: ethernet: mtk_eth_soc: correct the max weight of the queue limit for 100Mbps [ Upstream commit 6b02eb372c6776c9abb8bc81cf63f96039c24664 ] Without this patch, the maximum weight of the queue limit will be incorrect when linked at 100Mbps due to an apparent typo. Fixes: f63959c7eec31 ("net: ethernet: mtk_eth_soc: implement multi-queue support for per-port queues") Signed-off-by: Bo-Cun Chen Signed-off-by: Daniel Golle Link: https://patch.msgid.link/74111ba0bdb13743313999ed467ce564e8189006.1744764277.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index bdc424123ee6..a22a5bdc7ce6 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -724,7 +724,7 @@ static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx, case SPEED_100: val |= MTK_QTX_SCH_MAX_RATE_EN | FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 103) | - FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 3); + FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 3) | FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1); break; case SPEED_1000: @@ -747,7 +747,7 @@ static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx, case SPEED_100: val |= MTK_QTX_SCH_MAX_RATE_EN | FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 1) | - FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5); + FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5) | FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 1); break; case SPEED_1000: From a2874f0dff63829d1f540003e2d83adb610ee64a Mon Sep 17 00:00:00 2001 From: Bo-Cun Chen Date: Wed, 16 Apr 2025 01:51:25 +0100 Subject: [PATCH 289/606] net: ethernet: mtk_eth_soc: revise QDMA packet scheduler settings [ Upstream commit 1b66124135f5f8640bd540fadda4b20cdd23114b ] The QDMA packet scheduler suffers from a performance issue. Fix this by picking up changes from MediaTek's SDK which change to use Token Bucket instead of Leaky Bucket and fix the SPEED_1000 configuration. Fixes: 160d3a9b1929 ("net: ethernet: mtk_eth_soc: introduce MTK_NETSYS_V2 support") Signed-off-by: Bo-Cun Chen Signed-off-by: Daniel Golle Link: https://patch.msgid.link/18040f60f9e2f5855036b75b28c4332a2d2ebdd8.1744764277.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index a22a5bdc7ce6..c201ea20e404 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -752,8 +752,8 @@ static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx, break; case SPEED_1000: val |= MTK_QTX_SCH_MAX_RATE_EN | - FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 10) | - FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 5) | + FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, 1) | + FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, 6) | FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, 10); break; default: @@ -3244,7 +3244,7 @@ static int mtk_start_dma(struct mtk_eth *eth) if (mtk_is_netsys_v2_or_greater(eth)) val |= MTK_MUTLI_CNT | MTK_RESV_BUF | MTK_WCOMP_EN | MTK_DMAD_WR_WDONE | - MTK_CHK_DDONE_EN | MTK_LEAKY_BUCKET_EN; + MTK_CHK_DDONE_EN; else val |= MTK_RX_BT_32DWORDS; mtk_w32(eth, val, reg_map->qdma.glo_cfg); From d7c65ecad9596c0e9c58cc26ee805031ba00df4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= Date: Wed, 9 Apr 2025 20:21:27 +0200 Subject: [PATCH 290/606] riscv: Properly export reserved regions in /proc/iomem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit e94eb7ea6f206e229791761a5fdf9389f8dbd183 ] The /proc/iomem represents the kernel's memory map. Regions marked with "Reserved" tells the user that the range should not be tampered with. Kexec-tools, when using the older kexec_load syscall relies on the "Reserved" regions to build the memory segments, that will be the target of the new kexec'd kernel. The RISC-V port tries to expose all reserved regions to userland, but some regions were not properly exposed: Regions that resided in both the "regular" and reserved memory block, e.g. the EFI Memory Map. A missing entry could result in reserved memory being overwritten. It turns out, that arm64, and loongarch had a similar issue a while back: commit d91680e687f4 ("arm64: Fix /proc/iomem for reserved but not memory regions") commit 50d7ba36b916 ("arm64: export memblock_reserve()d regions via /proc/iomem") Similar to the other ports, resolve the issue by splitting the regions in an arch initcall, since we need a working allocator. Fixes: ffe0e5261268 ("RISC-V: Improve init_resources()") Signed-off-by: Björn Töpel Reviewed-by: Alexandre Ghiti Link: https://lore.kernel.org/r/20250409182129.634415-1-bjorn@kernel.org Signed-off-by: Alexandre Ghiti Signed-off-by: Sasha Levin --- arch/riscv/kernel/setup.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c index 175184b05926..f598e0eb3b0a 100644 --- a/arch/riscv/kernel/setup.c +++ b/arch/riscv/kernel/setup.c @@ -73,6 +73,9 @@ static struct resource bss_res = { .name = "Kernel bss", }; static struct resource elfcorehdr_res = { .name = "ELF Core hdr", }; #endif +static int num_standard_resources; +static struct resource *standard_resources; + static int __init add_resource(struct resource *parent, struct resource *res) { @@ -146,7 +149,7 @@ static void __init init_resources(void) struct resource *res = NULL; struct resource *mem_res = NULL; size_t mem_res_sz = 0; - int num_resources = 0, res_idx = 0; + int num_resources = 0, res_idx = 0, non_resv_res = 0; int ret = 0; /* + 1 as memblock_alloc() might increase memblock.reserved.cnt */ @@ -215,6 +218,7 @@ static void __init init_resources(void) /* Add /memory regions to the resource tree */ for_each_mem_region(region) { res = &mem_res[res_idx--]; + non_resv_res++; if (unlikely(memblock_is_nomap(region))) { res->name = "Reserved"; @@ -232,6 +236,9 @@ static void __init init_resources(void) goto error; } + num_standard_resources = non_resv_res; + standard_resources = &mem_res[res_idx + 1]; + /* Clean-up any unused pre-allocated resources */ if (res_idx >= 0) memblock_free(mem_res, (res_idx + 1) * sizeof(*mem_res)); @@ -243,6 +250,33 @@ static void __init init_resources(void) memblock_free(mem_res, mem_res_sz); } +static int __init reserve_memblock_reserved_regions(void) +{ + u64 i, j; + + for (i = 0; i < num_standard_resources; i++) { + struct resource *mem = &standard_resources[i]; + phys_addr_t r_start, r_end, mem_size = resource_size(mem); + + if (!memblock_is_region_reserved(mem->start, mem_size)) + continue; + + for_each_reserved_mem_range(j, &r_start, &r_end) { + resource_size_t start, end; + + start = max(PFN_PHYS(PFN_DOWN(r_start)), mem->start); + end = min(PFN_PHYS(PFN_UP(r_end)) - 1, mem->end); + + if (start > mem->end || end < mem->start) + continue; + + reserve_region_with_split(mem, start, end, "Reserved"); + } + } + + return 0; +} +arch_initcall(reserve_memblock_reserved_regions); static void __init parse_dtb(void) { From ec95d0dfc672f6a282cfdcadd58471e96056b690 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Mon, 7 Apr 2025 10:58:03 +0200 Subject: [PATCH 291/606] kunit: qemu_configs: SH: Respect kunit cmdline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit b26c1a85f3fc3cc749380ff94199377fc2d0c203 ] The default SH kunit configuration sets CONFIG_CMDLINE_OVERWRITE which completely disregards the cmdline passed from the bootloader/QEMU in favor of the builtin CONFIG_CMDLINE. However the kunit tool needs to pass arguments to the in-kernel kunit core, for filters and other runtime parameters. Enable CONFIG_CMDLINE_EXTEND instead, so kunit arguments are respected. Link: https://lore.kernel.org/r/20250407-kunit-sh-v1-1-f5432a54cf2f@linutronix.de Fixes: 8110a3cab05e ("kunit: tool: Add support for SH under QEMU") Signed-off-by: Thomas Weißschuh Reviewed-by: David Gow Signed-off-by: Shuah Khan Signed-off-by: Sasha Levin --- tools/testing/kunit/qemu_configs/sh.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/testing/kunit/qemu_configs/sh.py b/tools/testing/kunit/qemu_configs/sh.py index 78a474a5b95f..f00cb89fdef6 100644 --- a/tools/testing/kunit/qemu_configs/sh.py +++ b/tools/testing/kunit/qemu_configs/sh.py @@ -7,7 +7,9 @@ CONFIG_CPU_SUBTYPE_SH7751R=y CONFIG_MEMORY_START=0x0c000000 CONFIG_SH_RTS7751R2D=y CONFIG_RTS7751R2D_PLUS=y -CONFIG_SERIAL_SH_SCI=y''', +CONFIG_SERIAL_SH_SCI=y +CONFIG_CMDLINE_EXTEND=y +''', qemu_arch='sh4', kernel_path='arch/sh/boot/zImage', kernel_command_line='console=ttySC1', From ba433e6c10027a5842a9e79ab5baab1a6537ecf6 Mon Sep 17 00:00:00 2001 From: WangYuli Date: Fri, 11 Apr 2025 15:32:21 +0800 Subject: [PATCH 292/606] riscv: KGDB: Do not inline arch_kgdb_breakpoint() [ Upstream commit 3af4bec9c1db3f003be4d5ae09b6a737e4be1612 ] The arch_kgdb_breakpoint() function defines the kgdb_compiled_break symbol using inline assembly. There's a potential issue where the compiler might inline arch_kgdb_breakpoint(), which would then define the kgdb_compiled_break symbol multiple times, leading to fail to link vmlinux.o. This isn't merely a potential compilation problem. The intent here is to determine the global symbol address of kgdb_compiled_break, and if this function is inlined multiple times, it would logically be a grave error. Link: https://lore.kernel.org/all/4b4187c1-77e5-44b7-885f-d6826723dd9a@sifive.com/ Link: https://lore.kernel.org/all/5b0adf9b-2b22-43fe-ab74-68df94115b9a@ghiti.fr/ Link: https://lore.kernel.org/all/23693e7f-4fff-40f3-a437-e06d827278a5@ghiti.fr/ Fixes: fe89bd2be866 ("riscv: Add KGDB support") Co-developed-by: Huacai Chen Signed-off-by: Huacai Chen Signed-off-by: WangYuli Link: https://lore.kernel.org/r/F22359AFB6FF9FD8+20250411073222.56820-1-wangyuli@uniontech.com Signed-off-by: Palmer Dabbelt Signed-off-by: Sasha Levin --- arch/riscv/include/asm/kgdb.h | 9 +-------- arch/riscv/kernel/kgdb.c | 8 ++++++++ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/arch/riscv/include/asm/kgdb.h b/arch/riscv/include/asm/kgdb.h index 46677daf708b..cc11c4544cff 100644 --- a/arch/riscv/include/asm/kgdb.h +++ b/arch/riscv/include/asm/kgdb.h @@ -19,16 +19,9 @@ #ifndef __ASSEMBLY__ +void arch_kgdb_breakpoint(void); extern unsigned long kgdb_compiled_break; -static inline void arch_kgdb_breakpoint(void) -{ - asm(".global kgdb_compiled_break\n" - ".option norvc\n" - "kgdb_compiled_break: ebreak\n" - ".option rvc\n"); -} - #endif /* !__ASSEMBLY__ */ #define DBG_REG_ZERO "zero" diff --git a/arch/riscv/kernel/kgdb.c b/arch/riscv/kernel/kgdb.c index 2e0266ae6bd7..5d1ce8dacaf5 100644 --- a/arch/riscv/kernel/kgdb.c +++ b/arch/riscv/kernel/kgdb.c @@ -254,6 +254,14 @@ void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) regs->epc = pc; } +noinline void arch_kgdb_breakpoint(void) +{ + asm(".global kgdb_compiled_break\n" + ".option norvc\n" + "kgdb_compiled_break: ebreak\n" + ".option rvc\n"); +} + void kgdb_arch_handle_qxfer_pkt(char *remcom_in_buffer, char *remcom_out_buffer) { From d217f7a822915f7fd91765ed8da2529506f5cba0 Mon Sep 17 00:00:00 2001 From: WangYuli Date: Fri, 11 Apr 2025 15:32:22 +0800 Subject: [PATCH 293/606] riscv: KGDB: Remove ".option norvc/.option rvc" for kgdb_compiled_break [ Upstream commit 550c2aa787d1b06efcb11de1877354502a1237f2 ] [ Quoting Samuel Holland: ] This is a separate issue, but using ".option rvc" here is a bug. It will unconditionally enable the C extension for the rest of the file, even if the kernel is being built with CONFIG_RISCV_ISA_C=n. [ Quoting Palmer Dabbelt: ] We're just looking at the address of kgdb_compiled_break, so it's fine if it ends up as a c.ebreak. [ Quoting Alexandre Ghiti: ] .option norvc is used to prevent the assembler from using compressed instructions, but it's generally used when we need to ensure the size of the instructions that are used, which is not the case here as noted by Palmer since we only care about the address. So yes it will work fine with C enabled :) So let's just remove them all. Link: https://lore.kernel.org/all/4b4187c1-77e5-44b7-885f-d6826723dd9a@sifive.com/ Link: https://lore.kernel.org/all/mhng-69513841-5068-441d-be8f-2aeebdc56a08@palmer-ri-x1c9a/ Link: https://lore.kernel.org/all/23693e7f-4fff-40f3-a437-e06d827278a5@ghiti.fr/ Fixes: fe89bd2be866 ("riscv: Add KGDB support") Cc: Samuel Holland Cc: Palmer Dabbelt Cc: Alexandre Ghiti Signed-off-by: WangYuli Link: https://lore.kernel.org/r/8B431C6A4626225C+20250411073222.56820-2-wangyuli@uniontech.com Signed-off-by: Palmer Dabbelt Signed-off-by: Sasha Levin --- arch/riscv/kernel/kgdb.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/riscv/kernel/kgdb.c b/arch/riscv/kernel/kgdb.c index 5d1ce8dacaf5..9f3db3503dab 100644 --- a/arch/riscv/kernel/kgdb.c +++ b/arch/riscv/kernel/kgdb.c @@ -257,9 +257,7 @@ void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) noinline void arch_kgdb_breakpoint(void) { asm(".global kgdb_compiled_break\n" - ".option norvc\n" - "kgdb_compiled_break: ebreak\n" - ".option rvc\n"); + "kgdb_compiled_break: ebreak\n"); } void kgdb_arch_handle_qxfer_pkt(char *remcom_in_buffer, From 404faab1dd6b613494aed73af5ab31a2ce624c8b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 15 Apr 2025 11:58:08 +0200 Subject: [PATCH 294/606] cpufreq/sched: Fix the usage of CPUFREQ_NEED_UPDATE_LIMITS [ Upstream commit cfde542df7dd51d26cf667f4af497878ddffd85a ] Commit 8e461a1cb43d ("cpufreq: schedutil: Fix superfluous updates caused by need_freq_update") modified sugov_should_update_freq() to set the need_freq_update flag only for drivers with CPUFREQ_NEED_UPDATE_LIMITS set, but that flag generally needs to be set when the policy limits change because the driver callback may need to be invoked for the new limits to take effect. However, if the return value of cpufreq_driver_resolve_freq() after applying the new limits is still equal to the previously selected frequency, the driver callback needs to be invoked only in the case when CPUFREQ_NEED_UPDATE_LIMITS is set (which means that the driver specifically wants its callback to be invoked every time the policy limits change). Update the code accordingly to avoid missing policy limits changes for drivers without CPUFREQ_NEED_UPDATE_LIMITS. Fixes: 8e461a1cb43d ("cpufreq: schedutil: Fix superfluous updates caused by need_freq_update") Closes: https://lore.kernel.org/lkml/Z_Tlc6Qs-tYpxWYb@linaro.org/ Reported-by: Stephan Gerhold Signed-off-by: Rafael J. Wysocki Reviewed-by: Christian Loehle Link: https://patch.msgid.link/3010358.e9J7NaK4W3@rjwysocki.net Signed-off-by: Sasha Levin --- kernel/sched/cpufreq_schedutil.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c index a49f136014ce..259521b179aa 100644 --- a/kernel/sched/cpufreq_schedutil.c +++ b/kernel/sched/cpufreq_schedutil.c @@ -83,7 +83,7 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time) if (unlikely(sg_policy->limits_changed)) { sg_policy->limits_changed = false; - sg_policy->need_freq_update = cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS); + sg_policy->need_freq_update = true; return true; } @@ -95,10 +95,22 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time) static bool sugov_update_next_freq(struct sugov_policy *sg_policy, u64 time, unsigned int next_freq) { - if (sg_policy->need_freq_update) + if (sg_policy->need_freq_update) { sg_policy->need_freq_update = false; - else if (sg_policy->next_freq == next_freq) + /* + * The policy limits have changed, but if the return value of + * cpufreq_driver_resolve_freq() after applying the new limits + * is still equal to the previously selected frequency, the + * driver callback need not be invoked unless the driver + * specifically wants that to happen on every update of the + * policy limits. + */ + if (sg_policy->next_freq == next_freq && + !cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS)) + return false; + } else if (sg_policy->next_freq == next_freq) { return false; + } sg_policy->next_freq = next_freq; sg_policy->last_freq_update_time = time; From 411b7005f4e8a2227b7c2fab3528d250b4e7123e Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Sat, 12 Apr 2025 18:39:12 +0200 Subject: [PATCH 295/606] writeback: fix false warning in inode_to_wb() commit 9e888998ea4d22257b07ce911576509486fa0667 upstream. inode_to_wb() is used also for filesystems that don't support cgroup writeback. For these filesystems inode->i_wb is stable during the lifetime of the inode (it points to bdi->wb) and there's no need to hold locks protecting the inode->i_wb dereference. Improve the warning in inode_to_wb() to not trigger for these filesystems. Link: https://lkml.kernel.org/r/20250412163914.3773459-3-agruenba@redhat.com Fixes: aaa2cacf8184 ("writeback: add lockdep annotation to inode_to_wb()") Signed-off-by: Jan Kara Signed-off-by: Andreas Gruenbacher Reviewed-by: Andreas Gruenbacher Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- include/linux/backing-dev.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index 1a97277f99b1..ae8c46ad9222 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h @@ -250,6 +250,7 @@ static inline struct bdi_writeback *inode_to_wb(const struct inode *inode) { #ifdef CONFIG_LOCKDEP WARN_ON_ONCE(debug_locks && + (inode->i_sb->s_iflags & SB_I_CGROUPWB) && (!lockdep_is_held(&inode->i_lock) && !lockdep_is_held(&inode->i_mapping->i_pages.xa_lock) && !lockdep_is_held(&inode->i_wb->list_lock))); From 3d6102ae330a4b1ba0f39a231343ca7c7ae15996 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 14 Apr 2025 15:18:23 -0600 Subject: [PATCH 296/606] Revert "PCI: Avoid reset when disabled via sysfs" commit bc0b828ef6e561081ebc4c758d0c4d166bb9829c upstream. This reverts commit 479380efe1625e251008d24b2810283db60d6fcd. The reset_method attribute on a PCI device is only intended to manage the availability of function scoped resets for a device. It was never intended to restrict resets targeting the bus or slot. In introducing a restriction that each device must support function level reset by testing pci_reset_supported(), we essentially create a catch-22, that a device must have a function scope reset in order to support bus/slot reset, when we use bus/slot reset to effect a reset of a device that does not support a function scoped reset, especially multi-function devices. This breaks the majority of uses cases where vfio-pci uses bus/slot resets to manage multifunction devices that do not support function scoped resets. Fixes: 479380efe162 ("PCI: Avoid reset when disabled via sysfs") Reported-by: Cal Peake Closes: https://lore.kernel.org/all/808e1111-27b7-f35b-6d5c-5b275e73677b@absolutedigital.net Reported-by: Athul Krishna Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220010 Signed-off-by: Alex Williamson Signed-off-by: Bjorn Helgaas Reviewed-by: Kevin Tian Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20250414211828.3530741-1-alex.williamson@redhat.com Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index bcce569a8339..095fa1910d36 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -5714,8 +5714,6 @@ static bool pci_bus_resettable(struct pci_bus *bus) return false; list_for_each_entry(dev, &bus->devices, bus_list) { - if (!pci_reset_supported(dev)) - return false; if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET || (dev->subordinate && !pci_bus_resettable(dev->subordinate))) return false; @@ -5792,8 +5790,6 @@ static bool pci_slot_resettable(struct pci_slot *slot) list_for_each_entry(dev, &slot->bus->devices, bus_list) { if (!dev->slot || dev->slot != slot) continue; - if (!pci_reset_supported(dev)) - return false; if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET || (dev->subordinate && !pci_bus_resettable(dev->subordinate))) return false; From 444139d6c43b673768fb2dbc0e7cb1247895928e Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 3 Apr 2025 17:02:08 +0100 Subject: [PATCH 297/606] ASoC: codecs:lpass-wsa-macro: Fix vi feedback rate commit d7bff1415e85b889dc8908be6aedba8807ae5e37 upstream. Currently the VI feedback rate is set to fixed 8K, fix this by getting the correct rate from params_rate. Without this patch incorrect rate will be set on the VI feedback recording resulting in rate miss match and audio artifacts. Fixes: 2c4066e5d428 ("ASoC: codecs: lpass-wsa-macro: add dapm widgets and route") Cc: stable@vger.kernel.org Signed-off-by: Srinivas Kandagatla Reviewed-by: Dmitry Baryshkov Link: https://patch.msgid.link/20250403160209.21613-2-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/lpass-wsa-macro.c | 39 +++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index 6ce309980cd1..ec9f0b5d6778 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -66,6 +66,10 @@ #define CDC_WSA_TX_SPKR_PROT_CLK_DISABLE 0 #define CDC_WSA_TX_SPKR_PROT_PCM_RATE_MASK GENMASK(3, 0) #define CDC_WSA_TX_SPKR_PROT_PCM_RATE_8K 0 +#define CDC_WSA_TX_SPKR_PROT_PCM_RATE_16K 1 +#define CDC_WSA_TX_SPKR_PROT_PCM_RATE_24K 2 +#define CDC_WSA_TX_SPKR_PROT_PCM_RATE_32K 3 +#define CDC_WSA_TX_SPKR_PROT_PCM_RATE_48K 4 #define CDC_WSA_TX0_SPKR_PROT_PATH_CFG0 (0x0248) #define CDC_WSA_TX1_SPKR_PROT_PATH_CTL (0x0264) #define CDC_WSA_TX1_SPKR_PROT_PATH_CFG0 (0x0268) @@ -347,6 +351,7 @@ struct wsa_macro { int ear_spkr_gain; int spkr_gain_offset; int spkr_mode; + u32 pcm_rate_vi; int is_softclip_on[WSA_MACRO_SOFTCLIP_MAX]; int softclip_clk_users[WSA_MACRO_SOFTCLIP_MAX]; struct regmap *regmap; @@ -974,6 +979,7 @@ static int wsa_macro_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_component *component = dai->component; + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); int ret; switch (substream->stream) { @@ -985,6 +991,11 @@ static int wsa_macro_hw_params(struct snd_pcm_substream *substream, __func__, params_rate(params)); return ret; } + break; + case SNDRV_PCM_STREAM_CAPTURE: + if (dai->id == WSA_MACRO_AIF_VI) + wsa->pcm_rate_vi = params_rate(params); + break; default: break; @@ -1159,6 +1170,28 @@ static int wsa_macro_enable_vi_feedback(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); u32 tx_reg0, tx_reg1; + u32 rate_val; + + switch (wsa->pcm_rate_vi) { + case 8000: + rate_val = CDC_WSA_TX_SPKR_PROT_PCM_RATE_8K; + break; + case 16000: + rate_val = CDC_WSA_TX_SPKR_PROT_PCM_RATE_16K; + break; + case 24000: + rate_val = CDC_WSA_TX_SPKR_PROT_PCM_RATE_24K; + break; + case 32000: + rate_val = CDC_WSA_TX_SPKR_PROT_PCM_RATE_32K; + break; + case 48000: + rate_val = CDC_WSA_TX_SPKR_PROT_PCM_RATE_48K; + break; + default: + rate_val = CDC_WSA_TX_SPKR_PROT_PCM_RATE_8K; + break; + } if (test_bit(WSA_MACRO_TX0, &wsa->active_ch_mask[WSA_MACRO_AIF_VI])) { tx_reg0 = CDC_WSA_TX0_SPKR_PROT_PATH_CTL; @@ -1170,7 +1203,7 @@ static int wsa_macro_enable_vi_feedback(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: - /* Enable V&I sensing */ + /* Enable V&I sensing */ snd_soc_component_update_bits(component, tx_reg0, CDC_WSA_TX_SPKR_PROT_RESET_MASK, CDC_WSA_TX_SPKR_PROT_RESET); @@ -1179,10 +1212,10 @@ static int wsa_macro_enable_vi_feedback(struct snd_soc_dapm_widget *w, CDC_WSA_TX_SPKR_PROT_RESET); snd_soc_component_update_bits(component, tx_reg0, CDC_WSA_TX_SPKR_PROT_PCM_RATE_MASK, - CDC_WSA_TX_SPKR_PROT_PCM_RATE_8K); + rate_val); snd_soc_component_update_bits(component, tx_reg1, CDC_WSA_TX_SPKR_PROT_PCM_RATE_MASK, - CDC_WSA_TX_SPKR_PROT_PCM_RATE_8K); + rate_val); snd_soc_component_update_bits(component, tx_reg0, CDC_WSA_TX_SPKR_PROT_CLK_EN_MASK, CDC_WSA_TX_SPKR_PROT_CLK_ENABLE); From bf39a185a6269e7b3ba25f8d223c51323abafad6 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 3 Apr 2025 17:02:09 +0100 Subject: [PATCH 298/606] ASoC: codecs:lpass-wsa-macro: Fix logic of enabling vi channels commit 7648beb65600220996ebb2da207610b1ff9b735e upstream. Existing code only configures one of WSA_MACRO_TX0 or WSA_MACRO_TX1 paths eventhough we enable both of them. Fix this bug by adding proper checks and rearranging some of the common code to able to allow setting both TX0 and TX1 paths Without this patch only one channel gets enabled in VI path instead of 2 channels. End result would be 1 channel recording instead of 2. Fixes: 2c4066e5d428 ("ASoC: codecs: lpass-wsa-macro: add dapm widgets and route") Cc: stable@vger.kernel.org Co-developed-by: Manikantan R Signed-off-by: Manikantan R Signed-off-by: Srinivas Kandagatla Reviewed-by: Dmitry Baryshkov Link: https://patch.msgid.link/20250403160209.21613-3-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/lpass-wsa-macro.c | 108 +++++++++++++++++------------ 1 file changed, 63 insertions(+), 45 deletions(-) diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index ec9f0b5d6778..e29815535929 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -1153,6 +1153,67 @@ static void wsa_macro_mclk_enable(struct wsa_macro *wsa, bool mclk_enable) } } +static void wsa_macro_enable_disable_vi_sense(struct snd_soc_component *component, bool enable, + u32 tx_reg0, u32 tx_reg1, u32 val) +{ + if (enable) { + /* Enable V&I sensing */ + snd_soc_component_update_bits(component, tx_reg0, + CDC_WSA_TX_SPKR_PROT_RESET_MASK, + CDC_WSA_TX_SPKR_PROT_RESET); + snd_soc_component_update_bits(component, tx_reg1, + CDC_WSA_TX_SPKR_PROT_RESET_MASK, + CDC_WSA_TX_SPKR_PROT_RESET); + snd_soc_component_update_bits(component, tx_reg0, + CDC_WSA_TX_SPKR_PROT_PCM_RATE_MASK, + val); + snd_soc_component_update_bits(component, tx_reg1, + CDC_WSA_TX_SPKR_PROT_PCM_RATE_MASK, + val); + snd_soc_component_update_bits(component, tx_reg0, + CDC_WSA_TX_SPKR_PROT_CLK_EN_MASK, + CDC_WSA_TX_SPKR_PROT_CLK_ENABLE); + snd_soc_component_update_bits(component, tx_reg1, + CDC_WSA_TX_SPKR_PROT_CLK_EN_MASK, + CDC_WSA_TX_SPKR_PROT_CLK_ENABLE); + snd_soc_component_update_bits(component, tx_reg0, + CDC_WSA_TX_SPKR_PROT_RESET_MASK, + CDC_WSA_TX_SPKR_PROT_NO_RESET); + snd_soc_component_update_bits(component, tx_reg1, + CDC_WSA_TX_SPKR_PROT_RESET_MASK, + CDC_WSA_TX_SPKR_PROT_NO_RESET); + } else { + snd_soc_component_update_bits(component, tx_reg0, + CDC_WSA_TX_SPKR_PROT_RESET_MASK, + CDC_WSA_TX_SPKR_PROT_RESET); + snd_soc_component_update_bits(component, tx_reg1, + CDC_WSA_TX_SPKR_PROT_RESET_MASK, + CDC_WSA_TX_SPKR_PROT_RESET); + snd_soc_component_update_bits(component, tx_reg0, + CDC_WSA_TX_SPKR_PROT_CLK_EN_MASK, + CDC_WSA_TX_SPKR_PROT_CLK_DISABLE); + snd_soc_component_update_bits(component, tx_reg1, + CDC_WSA_TX_SPKR_PROT_CLK_EN_MASK, + CDC_WSA_TX_SPKR_PROT_CLK_DISABLE); + } +} + +static void wsa_macro_enable_disable_vi_feedback(struct snd_soc_component *component, + bool enable, u32 rate) +{ + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); + + if (test_bit(WSA_MACRO_TX0, &wsa->active_ch_mask[WSA_MACRO_AIF_VI])) + wsa_macro_enable_disable_vi_sense(component, enable, + CDC_WSA_TX0_SPKR_PROT_PATH_CTL, + CDC_WSA_TX1_SPKR_PROT_PATH_CTL, rate); + + if (test_bit(WSA_MACRO_TX1, &wsa->active_ch_mask[WSA_MACRO_AIF_VI])) + wsa_macro_enable_disable_vi_sense(component, enable, + CDC_WSA_TX2_SPKR_PROT_PATH_CTL, + CDC_WSA_TX3_SPKR_PROT_PATH_CTL, rate); +} + static int wsa_macro_mclk_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -1169,7 +1230,6 @@ static int wsa_macro_enable_vi_feedback(struct snd_soc_dapm_widget *w, { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); - u32 tx_reg0, tx_reg1; u32 rate_val; switch (wsa->pcm_rate_vi) { @@ -1193,56 +1253,14 @@ static int wsa_macro_enable_vi_feedback(struct snd_soc_dapm_widget *w, break; } - if (test_bit(WSA_MACRO_TX0, &wsa->active_ch_mask[WSA_MACRO_AIF_VI])) { - tx_reg0 = CDC_WSA_TX0_SPKR_PROT_PATH_CTL; - tx_reg1 = CDC_WSA_TX1_SPKR_PROT_PATH_CTL; - } else if (test_bit(WSA_MACRO_TX1, &wsa->active_ch_mask[WSA_MACRO_AIF_VI])) { - tx_reg0 = CDC_WSA_TX2_SPKR_PROT_PATH_CTL; - tx_reg1 = CDC_WSA_TX3_SPKR_PROT_PATH_CTL; - } - switch (event) { case SND_SOC_DAPM_POST_PMU: /* Enable V&I sensing */ - snd_soc_component_update_bits(component, tx_reg0, - CDC_WSA_TX_SPKR_PROT_RESET_MASK, - CDC_WSA_TX_SPKR_PROT_RESET); - snd_soc_component_update_bits(component, tx_reg1, - CDC_WSA_TX_SPKR_PROT_RESET_MASK, - CDC_WSA_TX_SPKR_PROT_RESET); - snd_soc_component_update_bits(component, tx_reg0, - CDC_WSA_TX_SPKR_PROT_PCM_RATE_MASK, - rate_val); - snd_soc_component_update_bits(component, tx_reg1, - CDC_WSA_TX_SPKR_PROT_PCM_RATE_MASK, - rate_val); - snd_soc_component_update_bits(component, tx_reg0, - CDC_WSA_TX_SPKR_PROT_CLK_EN_MASK, - CDC_WSA_TX_SPKR_PROT_CLK_ENABLE); - snd_soc_component_update_bits(component, tx_reg1, - CDC_WSA_TX_SPKR_PROT_CLK_EN_MASK, - CDC_WSA_TX_SPKR_PROT_CLK_ENABLE); - snd_soc_component_update_bits(component, tx_reg0, - CDC_WSA_TX_SPKR_PROT_RESET_MASK, - CDC_WSA_TX_SPKR_PROT_NO_RESET); - snd_soc_component_update_bits(component, tx_reg1, - CDC_WSA_TX_SPKR_PROT_RESET_MASK, - CDC_WSA_TX_SPKR_PROT_NO_RESET); + wsa_macro_enable_disable_vi_feedback(component, true, rate_val); break; case SND_SOC_DAPM_POST_PMD: /* Disable V&I sensing */ - snd_soc_component_update_bits(component, tx_reg0, - CDC_WSA_TX_SPKR_PROT_RESET_MASK, - CDC_WSA_TX_SPKR_PROT_RESET); - snd_soc_component_update_bits(component, tx_reg1, - CDC_WSA_TX_SPKR_PROT_RESET_MASK, - CDC_WSA_TX_SPKR_PROT_RESET); - snd_soc_component_update_bits(component, tx_reg0, - CDC_WSA_TX_SPKR_PROT_CLK_EN_MASK, - CDC_WSA_TX_SPKR_PROT_CLK_DISABLE); - snd_soc_component_update_bits(component, tx_reg1, - CDC_WSA_TX_SPKR_PROT_CLK_EN_MASK, - CDC_WSA_TX_SPKR_PROT_CLK_DISABLE); + wsa_macro_enable_disable_vi_feedback(component, false, rate_val); break; } From a12c14577882b1f2b4cff0f86265682f16e97b0c Mon Sep 17 00:00:00 2001 From: Evgeny Pimenov Date: Tue, 1 Apr 2025 23:40:58 +0300 Subject: [PATCH 299/606] ASoC: qcom: Fix sc7280 lpass potential buffer overflow commit a31a4934b31faea76e735bab17e63d02fcd8e029 upstream. Case values introduced in commit 5f78e1fb7a3e ("ASoC: qcom: Add driver support for audioreach solution") cause out of bounds access in arrays of sc7280 driver data (e.g. in case of RX_CODEC_DMA_RX_0 in sc7280_snd_hw_params()). Redefine LPASS_MAX_PORTS to consider the maximum possible port id for q6dsp as sc7280 driver utilizes some of those values. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: 77d0ffef793d ("ASoC: qcom: Add macro for lpass DAI id's max limit") Cc: stable@vger.kernel.org # v6.0+ Suggested-by: Mikhail Kobuk Suggested-by: Alexey Khoroshilov Signed-off-by: Evgeny Pimenov Link: https://patch.msgid.link/20250401204058.32261-1-pimenoveu12@gmail.com Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/qcom/lpass.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index bdfe66ec3314..ea12f02eca55 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -13,10 +13,11 @@ #include #include #include +#include #include "lpass-hdmi.h" #define LPASS_AHBIX_CLOCK_FREQUENCY 131072000 -#define LPASS_MAX_PORTS (LPASS_CDC_DMA_VA_TX8 + 1) +#define LPASS_MAX_PORTS (DISPLAY_PORT_RX_7 + 1) #define LPASS_MAX_MI2S_PORTS (8) #define LPASS_MAX_DMA_CHANNELS (8) #define LPASS_MAX_HDMI_DMA_CHANNELS (4) From e446b60a2be1c6f3af4e9d6a20c472874e041618 Mon Sep 17 00:00:00 2001 From: Denis Arefev Date: Thu, 3 Apr 2025 15:26:01 +0300 Subject: [PATCH 300/606] asus-laptop: Fix an uninitialized variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 6c683c6887e4addcd6bd1ddce08cafccb0a21e32 upstream. The value returned by acpi_evaluate_integer() is not checked, but the result is not always successful, so it is necessary to add a check of the returned value. If the result remains negative during three iterations of the loop, then the uninitialized variable 'val' will be used in the clamp_val() macro, so it must be initialized with the current value of the 'curr' variable. In this case, the algorithm should be less noisy. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: b23910c2194e ("asus-laptop: Pegatron Lucid accelerometer") Cc: stable@vger.kernel.org Signed-off-by: Denis Arefev Link: https://lore.kernel.org/r/20250403122603.18172-1-arefev@swemel.ru Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen Signed-off-by: Greg Kroah-Hartman --- drivers/platform/x86/asus-laptop.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 761029f39314..c22346570510 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -427,11 +427,14 @@ static int asus_pega_lucid_set(struct asus_laptop *asus, int unit, bool enable) static int pega_acc_axis(struct asus_laptop *asus, int curr, char *method) { + unsigned long long val = (unsigned long long)curr; + acpi_status status; int i, delta; - unsigned long long val; - for (i = 0; i < PEGA_ACC_RETRIES; i++) { - acpi_evaluate_integer(asus->handle, method, NULL, &val); + for (i = 0; i < PEGA_ACC_RETRIES; i++) { + status = acpi_evaluate_integer(asus->handle, method, NULL, &val); + if (ACPI_FAILURE(status)) + continue; /* The output is noisy. From reading the ASL * dissassembly, timeout errors are returned with 1's * in the high word, and the lack of locking around From b699aeb91b1032bfd84c5062770fbb859267afbd Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Tue, 1 Apr 2025 15:02:21 -0700 Subject: [PATCH 301/606] nfs: add missing selections of CONFIG_CRC32 [ Upstream commit cd35b6cb46649750b7dbd0df0e2d767415d8917b ] nfs.ko, nfsd.ko, and lockd.ko all use crc32_le(), which is available only when CONFIG_CRC32 is enabled. But the only NFS kconfig option that selected CONFIG_CRC32 was CONFIG_NFS_DEBUG, which is client-specific and did not actually guard the use of crc32_le() even on the client. The code worked around this bug by only actually calling crc32_le() when CONFIG_CRC32 is built-in, instead hard-coding '0' in other cases. This avoided randconfig build errors, and in real kernels the fallback code was unlikely to be reached since CONFIG_CRC32 is 'default y'. But, this really needs to just be done properly, especially now that I'm planning to update CONFIG_CRC32 to not be 'default y'. Therefore, make CONFIG_NFS_FS, CONFIG_NFSD, and CONFIG_LOCKD select CONFIG_CRC32. Then remove the fallback code that becomes unnecessary, as well as the selection of CONFIG_CRC32 from CONFIG_NFS_DEBUG. Fixes: 1264a2f053a3 ("NFS: refactor code for calculating the crc32 hash of a filehandle") Signed-off-by: Eric Biggers Acked-by: Anna Schumaker Signed-off-by: Chuck Lever Signed-off-by: Sasha Levin --- fs/Kconfig | 1 + fs/nfs/Kconfig | 2 +- fs/nfs/internal.h | 7 ------- fs/nfs/nfs4session.h | 4 ---- fs/nfsd/Kconfig | 1 + fs/nfsd/nfsfh.h | 7 ------- include/linux/nfs.h | 7 ------- 7 files changed, 3 insertions(+), 26 deletions(-) diff --git a/fs/Kconfig b/fs/Kconfig index 02a9237807a7..85ae4953f2d7 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -365,6 +365,7 @@ config GRACE_PERIOD config LOCKD tristate depends on FILE_LOCKING + select CRC32 select GRACE_PERIOD config LOCKD_V4 diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index 7df2503cef6c..2d99f5e7a686 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig @@ -2,6 +2,7 @@ config NFS_FS tristate "NFS client support" depends on INET && FILE_LOCKING && MULTIUSER + select CRC32 select LOCKD select SUNRPC select NFS_ACL_SUPPORT if NFS_V3_ACL @@ -194,7 +195,6 @@ config NFS_USE_KERNEL_DNS config NFS_DEBUG bool depends on NFS_FS && SUNRPC_DEBUG - select CRC32 default y config NFS_DISABLE_UDP_SUPPORT diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index a92b234ae087..ca49d999159e 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -859,18 +859,11 @@ u64 nfs_timespec_to_change_attr(const struct timespec64 *ts) return ((u64)ts->tv_sec << 30) + ts->tv_nsec; } -#ifdef CONFIG_CRC32 static inline u32 nfs_stateid_hash(const nfs4_stateid *stateid) { return ~crc32_le(0xFFFFFFFF, &stateid->other[0], NFS4_STATEID_OTHER_SIZE); } -#else -static inline u32 nfs_stateid_hash(nfs4_stateid *stateid) -{ - return 0; -} -#endif static inline bool nfs_error_is_fatal(int err) { diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h index 351616c61df5..f9c291e2165c 100644 --- a/fs/nfs/nfs4session.h +++ b/fs/nfs/nfs4session.h @@ -148,16 +148,12 @@ static inline void nfs4_copy_sessionid(struct nfs4_sessionid *dst, memcpy(dst->data, src->data, NFS4_MAX_SESSIONID_LEN); } -#ifdef CONFIG_CRC32 /* * nfs_session_id_hash - calculate the crc32 hash for the session id * @session - pointer to session */ #define nfs_session_id_hash(sess_id) \ (~crc32_le(0xFFFFFFFF, &(sess_id)->data[0], sizeof((sess_id)->data))) -#else -#define nfs_session_id_hash(session) (0) -#endif #else /* defined(CONFIG_NFS_V4_1) */ static inline int nfs4_init_session(struct nfs_client *clp) diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig index 43b88eaf0673..05c10f70456c 100644 --- a/fs/nfsd/Kconfig +++ b/fs/nfsd/Kconfig @@ -4,6 +4,7 @@ config NFSD depends on INET depends on FILE_LOCKING depends on FSNOTIFY + select CRC32 select LOCKD select SUNRPC select EXPORTFS diff --git a/fs/nfsd/nfsfh.h b/fs/nfsd/nfsfh.h index 40426f899e76..f1420d3510d2 100644 --- a/fs/nfsd/nfsfh.h +++ b/fs/nfsd/nfsfh.h @@ -263,7 +263,6 @@ static inline bool fh_fsid_match(const struct knfsd_fh *fh1, return true; } -#ifdef CONFIG_CRC32 /** * knfsd_fh_hash - calculate the crc32 hash for the filehandle * @fh - pointer to filehandle @@ -275,12 +274,6 @@ static inline u32 knfsd_fh_hash(const struct knfsd_fh *fh) { return ~crc32_le(0xFFFFFFFF, fh->fh_raw, fh->fh_size); } -#else -static inline u32 knfsd_fh_hash(const struct knfsd_fh *fh) -{ - return 0; -} -#endif /** * fh_clear_pre_post_attrs - Reset pre/post attributes diff --git a/include/linux/nfs.h b/include/linux/nfs.h index ceb70a926b95..095a95c1fae8 100644 --- a/include/linux/nfs.h +++ b/include/linux/nfs.h @@ -46,7 +46,6 @@ enum nfs3_stable_how { NFS_INVALID_STABLE_HOW = -1 }; -#ifdef CONFIG_CRC32 /** * nfs_fhandle_hash - calculate the crc32 hash for the filehandle * @fh - pointer to filehandle @@ -58,10 +57,4 @@ static inline u32 nfs_fhandle_hash(const struct nfs_fh *fh) { return ~crc32_le(0xFFFFFFFF, &fh->data[0], fh->size); } -#else /* CONFIG_CRC32 */ -static inline u32 nfs_fhandle_hash(const struct nfs_fh *fh) -{ - return 0; -} -#endif /* CONFIG_CRC32 */ #endif /* _LINUX_NFS_H */ From 7d192e27a431026c58d60edf66dc6cd98d0c01fc Mon Sep 17 00:00:00 2001 From: Li Lingfeng Date: Thu, 10 Apr 2025 09:57:08 +0800 Subject: [PATCH 302/606] nfsd: decrease sc_count directly if fail to queue dl_recall [ Upstream commit a1d14d931bf700c1025db8c46d6731aa5cf440f9 ] A deadlock warning occurred when invoking nfs4_put_stid following a failed dl_recall queue operation: T1 T2 nfs4_laundromat nfs4_get_client_reaplist nfs4_anylock_blockers __break_lease spin_lock // ctx->flc_lock spin_lock // clp->cl_lock nfs4_lockowner_has_blockers locks_owner_has_blockers spin_lock // flctx->flc_lock nfsd_break_deleg_cb nfsd_break_one_deleg nfs4_put_stid refcount_dec_and_lock spin_lock // clp->cl_lock When a file is opened, an nfs4_delegation is allocated with sc_count initialized to 1, and the file_lease holds a reference to the delegation. The file_lease is then associated with the file through kernel_setlease. The disassociation is performed in nfsd4_delegreturn via the following call chain: nfsd4_delegreturn --> destroy_delegation --> destroy_unhashed_deleg --> nfs4_unlock_deleg_lease --> kernel_setlease --> generic_delete_lease The corresponding sc_count reference will be released after this disassociation. Since nfsd_break_one_deleg executes while holding the flc_lock, the disassociation process becomes blocked when attempting to acquire flc_lock in generic_delete_lease. This means: 1) sc_count in nfsd_break_one_deleg will not be decremented to 0; 2) The nfs4_put_stid called by nfsd_break_one_deleg will not attempt to acquire cl_lock; 3) Consequently, no deadlock condition is created. Given that sc_count in nfsd_break_one_deleg remains non-zero, we can safely perform refcount_dec on sc_count directly. This approach effectively avoids triggering deadlock warnings. Fixes: 230ca758453c ("nfsd: put dl_stid if fail to queue dl_recall") Signed-off-by: Li Lingfeng Reviewed-by: Jeff Layton Signed-off-by: Chuck Lever Signed-off-by: Sasha Levin --- fs/nfsd/nfs4state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 140784446ad2..e2875706e6bf 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -4938,7 +4938,7 @@ static void nfsd_break_one_deleg(struct nfs4_delegation *dp) queued = nfsd4_run_cb(&dp->dl_recall); WARN_ON_ONCE(!queued); if (!queued) - nfs4_put_stid(&dp->dl_stid); + refcount_dec(&dp->dl_stid.sc_count); } /* Called from break_lease() with flc_lock held. */ From 42203e004d8e2336d1dd6818ffbbd91956daedfb Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 31 Mar 2025 10:16:46 +0300 Subject: [PATCH 303/606] i2c: atr: Fix wrong include [ Upstream commit 75caec0c2aa3a7ec84348d438c74cb8a2eb4de97 ] The fwnode.h is not supposed to be used by the drivers as it has the definitions for the core parts for different device property provider implementations. Drop it. Note, that fwnode API for drivers is provided in property.h which is included here. Fixes: a076a860acae ("media: i2c: add I2C Address Translator (ATR) support") Signed-off-by: Andy Shevchenko Acked-by: Mukesh Kumar Savaliya Reviewed-by: Luca Ceresoli Reviewed-by: Tomi Valkeinen [wsa: reworded subject] Signed-off-by: Wolfram Sang Signed-off-by: Sasha Levin --- drivers/i2c/i2c-atr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/i2c-atr.c b/drivers/i2c/i2c-atr.c index c03196da1163..03caa4ef012f 100644 --- a/drivers/i2c/i2c-atr.c +++ b/drivers/i2c/i2c-atr.c @@ -8,12 +8,12 @@ * Originally based on i2c-mux.c */ -#include #include #include #include #include #include +#include #include #include From 0a6c0fc1f83f7166bfde85a07edf5915bfe413a3 Mon Sep 17 00:00:00 2001 From: Menglong Dong Date: Sun, 13 Apr 2025 09:44:44 +0800 Subject: [PATCH 304/606] ftrace: fix incorrect hash size in register_ftrace_direct() [ Upstream commit 92f1d3b40179b15630d72e2c6e4e25a899b67ba9 ] The maximum of the ftrace hash bits is made fls(32) in register_ftrace_direct(), which seems illogical. So, we fix it by making the max hash bits FTRACE_HASH_MAX_BITS instead. Link: https://lore.kernel.org/20250413014444.36724-1-dongml2@chinatelecom.cn Fixes: d05cb470663a ("ftrace: Fix modification of direct_function hash while in use") Signed-off-by: Menglong Dong Acked-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt (Google) Signed-off-by: Sasha Levin --- kernel/trace/ftrace.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 580ceb75f8c3..650493ed76cd 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -5420,9 +5420,10 @@ int register_ftrace_direct(struct ftrace_ops *ops, unsigned long addr) /* Make a copy hash to place the new and the old entries in */ size = hash->count + direct_functions->count; - if (size > 32) - size = 32; - new_hash = alloc_ftrace_hash(fls(size)); + size = fls(size); + if (size > FTRACE_HASH_MAX_BITS) + size = FTRACE_HASH_MAX_BITS; + new_hash = alloc_ftrace_hash(size); if (!new_hash) goto out_unlock; From 600a099bec16d287e11327ff8d1deec03487e30a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Danis?= Date: Mon, 14 Apr 2025 11:08:15 +0200 Subject: [PATCH 305/606] Bluetooth: l2cap: Process valid commands in too long frame MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit e2e49e214145a8f6ece6ecd52fec63ebc2b27ce9 upstream. This is required for passing PTS test cases: - L2CAP/COS/CED/BI-14-C Multiple Signaling Command in one PDU, Data Truncated, BR/EDR, Connection Request - L2CAP/COS/CED/BI-15-C Multiple Signaling Command in one PDU, Data Truncated, BR/EDR, Disconnection Request The test procedure defined in L2CAP.TS.p39 for both tests is: 1. The Lower Tester sends a C-frame to the IUT with PDU Length set to 8 and Channel ID set to the correct signaling channel for the logical link. The Information payload contains one L2CAP_ECHO_REQ packet with Data Length set to 0 with 0 octets of echo data and one command packet and Data Length set as specified in Table 4.6 and the correct command data. 2. The IUT sends an L2CAP_ECHO_RSP PDU to the Lower Tester. 3. Perform alternative 3A, 3B, 3C, or 3D depending on the IUT’s response. Alternative 3A (IUT terminates the link): 3A.1 The IUT terminates the link. 3A.2 The test ends with a Pass verdict. Alternative 3B (IUT discards the frame): 3B.1 The IUT does not send a reply to the Lower Tester. Alternative 3C (IUT rejects PDU): 3C.1 The IUT sends an L2CAP_COMMAND_REJECT_RSP PDU to the Lower Tester. Alternative 3D (Any other IUT response): 3D.1 The Upper Tester issues a warning and the test ends. 4. The Lower Tester sends a C-frame to the IUT with PDU Length set to 4 and Channel ID set to the correct signaling channel for the logical link. The Information payload contains Data Length set to 0 with an L2CAP_ECHO_REQ packet with 0 octets of echo data. 5. The IUT sends an L2CAP_ECHO_RSP PDU to the Lower Tester. With expected outcome: In Steps 2 and 5, the IUT responds with an L2CAP_ECHO_RSP. In Step 3A.1, the IUT terminates the link. In Step 3B.1, the IUT does not send a reply to the Lower Tester. In Step 3C.1, the IUT rejects the PDU. In Step 3D.1, the IUT sends any valid response. Currently PTS fails with the following logs: Failed to receive ECHO RESPONSE. And HCI logs: > ACL Data RX: Handle 11 flags 0x02 dlen 20 L2CAP: Information Response (0x0b) ident 2 len 12 Type: Fixed channels supported (0x0003) Result: Success (0x0000) Channels: 0x000000000000002e L2CAP Signaling (BR/EDR) Connectionless reception AMP Manager Protocol L2CAP Signaling (LE) > ACL Data RX: Handle 11 flags 0x02 dlen 13 frame too long 08 01 00 00 08 02 01 00 aa ......... Cc: stable@vger.kernel.org Signed-off-by: Frédéric Danis Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/l2cap_core.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 1258532228bb..d4dcdb2370cc 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -7510,8 +7510,24 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) if (skb->len > len) { BT_ERR("Frame is too long (len %u, expected len %d)", skb->len, len); + /* PTS test cases L2CAP/COS/CED/BI-14-C and BI-15-C + * (Multiple Signaling Command in one PDU, Data + * Truncated, BR/EDR) send a C-frame to the IUT with + * PDU Length set to 8 and Channel ID set to the + * correct signaling channel for the logical link. + * The Information payload contains one L2CAP_ECHO_REQ + * packet with Data Length set to 0 with 0 octets of + * echo data and one invalid command packet due to + * data truncated in PDU but present in HCI packet. + * + * Shorter the socket buffer to the PDU length to + * allow to process valid commands from the PDU before + * setting the socket unreliable. + */ + skb->len = len; + l2cap_recv_frame(conn, skb); l2cap_conn_unreliable(conn, ECOMM); - goto drop; + goto unlock; } /* Append fragment into frame (with header) */ From ab46314a4e90c61765c3282aad48dfbdef7d335e Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 15 Apr 2025 09:15:19 -0700 Subject: [PATCH 306/606] Bluetooth: vhci: Avoid needless snprintf() calls commit 875db86e1ec75fe633f1e85ed2f92c731cdbf760 upstream. Avoid double-copying of string literals. Use a "const char *" for each string instead of copying from .rodata into stack and then into the skb. We can go directly from .rodata to the skb. This also works around a Clang bug (that has since been fixed[1]). Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202401250927.1poZERd6-lkp@intel.com/ Fixes: ab4e4380d4e1 ("Bluetooth: Add vhci devcoredump support") Link: https://github.com/llvm/llvm-project/commit/ea2e66aa8b6e363b89df66dc44275a0d7ecd70ce [1] Cc: stable@vger.kernel.org Signed-off-by: Kees Cook Reviewed-by: Nathan Chancellor Reviewed-by: Josh Poimboeuf Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Greg Kroah-Hartman --- drivers/bluetooth/hci_vhci.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index 28750a40f0ed..4bfc78f9781e 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -289,18 +289,18 @@ static void vhci_coredump(struct hci_dev *hdev) static void vhci_coredump_hdr(struct hci_dev *hdev, struct sk_buff *skb) { - char buf[80]; + const char *buf; - snprintf(buf, sizeof(buf), "Controller Name: vhci_ctrl\n"); + buf = "Controller Name: vhci_ctrl\n"; skb_put_data(skb, buf, strlen(buf)); - snprintf(buf, sizeof(buf), "Firmware Version: vhci_fw\n"); + buf = "Firmware Version: vhci_fw\n"; skb_put_data(skb, buf, strlen(buf)); - snprintf(buf, sizeof(buf), "Driver: vhci_drv\n"); + buf = "Driver: vhci_drv\n"; skb_put_data(skb, buf, strlen(buf)); - snprintf(buf, sizeof(buf), "Vendor: vhci\n"); + buf = "Vendor: vhci\n"; skb_put_data(skb, buf, strlen(buf)); } From 78b1126ca42bce82a7d23d9b638ab3133617a904 Mon Sep 17 00:00:00 2001 From: Johannes Kimmel Date: Wed, 19 Mar 2025 22:49:00 +0100 Subject: [PATCH 307/606] btrfs: correctly escape subvol in btrfs_show_options() commit dc08c58696f8555e4a802f1f23c894a330d80ab7 upstream. Currently, displaying the btrfs subvol mount option doesn't escape ','. This makes parsing /proc/self/mounts and /proc/self/mountinfo ambiguous for subvolume names that contain commas. The text after the comma could be mistaken for another option (think "subvol=foo,ro", where ro is actually part of the subvolumes name). Replace the manual escape characters list with a call to seq_show_option(). Thanks to Calvin Walton for suggesting this approach. Fixes: c8d3fe028f64 ("Btrfs: show subvol= and subvolid= in /proc/mounts") CC: stable@vger.kernel.org # 5.4+ Suggested-by: Calvin Walton Signed-off-by: Johannes Kimmel Reviewed-by: David Sterba Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/super.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index fb4992570c2b..2045ac3d94c4 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -1336,8 +1336,7 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry) subvol_name = btrfs_get_subvol_name_from_objectid(info, BTRFS_I(d_inode(dentry))->root->root_key.objectid); if (!IS_ERR(subvol_name)) { - seq_puts(seq, ",subvol="); - seq_escape(seq, subvol_name, " \t\n\\"); + seq_show_option(seq, "subvol", subvol_name); kfree(subvol_name); } return 0; From 8a53d36ba10b352cb481c899321d594fc85faacc Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 8 Apr 2025 13:17:20 +0800 Subject: [PATCH 308/606] crypto: caam/qi - Fix drv_ctx refcount bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit b7b39df7e710b0068356e4c696af07aa10e2cd3d upstream. Ensure refcount is raised before request is enqueued since it could be dequeued before the call returns. Reported-by: Sean Anderson Cc: Fixes: 11144416a755 ("crypto: caam/qi - optimize frame queue cleanup") Signed-off-by: Herbert Xu Reviewed-by: Horia Geantă Tested-by: Sean Anderson Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/crypto/caam/qi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/caam/qi.c b/drivers/crypto/caam/qi.c index 7a3a104557f0..fa5bd64b7407 100644 --- a/drivers/crypto/caam/qi.c +++ b/drivers/crypto/caam/qi.c @@ -122,12 +122,12 @@ int caam_qi_enqueue(struct device *qidev, struct caam_drv_req *req) qm_fd_addr_set64(&fd, addr); do { + refcount_inc(&req->drv_ctx->refcnt); ret = qman_enqueue(req->drv_ctx->req_fq, &fd); - if (likely(!ret)) { - refcount_inc(&req->drv_ctx->refcnt); + if (likely(!ret)) return 0; - } + refcount_dec(&req->drv_ctx->refcnt); if (ret != -EBUSY) break; num_retries++; From 9f77aa584a659b21211a794e53522e6fb16d4a16 Mon Sep 17 00:00:00 2001 From: Vasiliy Kovalev Date: Sat, 19 Oct 2024 22:13:03 +0300 Subject: [PATCH 309/606] hfs/hfsplus: fix slab-out-of-bounds in hfs_bnode_read_key commit bb5e07cb927724e0b47be371fa081141cfb14414 upstream. Syzbot reported an issue in hfs subsystem: BUG: KASAN: slab-out-of-bounds in memcpy_from_page include/linux/highmem.h:423 [inline] BUG: KASAN: slab-out-of-bounds in hfs_bnode_read fs/hfs/bnode.c:35 [inline] BUG: KASAN: slab-out-of-bounds in hfs_bnode_read_key+0x314/0x450 fs/hfs/bnode.c:70 Write of size 94 at addr ffff8880123cd100 by task syz-executor237/5102 Call Trace: __dump_stack lib/dump_stack.c:94 [inline] dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120 print_address_description mm/kasan/report.c:377 [inline] print_report+0x169/0x550 mm/kasan/report.c:488 kasan_report+0x143/0x180 mm/kasan/report.c:601 kasan_check_range+0x282/0x290 mm/kasan/generic.c:189 __asan_memcpy+0x40/0x70 mm/kasan/shadow.c:106 memcpy_from_page include/linux/highmem.h:423 [inline] hfs_bnode_read fs/hfs/bnode.c:35 [inline] hfs_bnode_read_key+0x314/0x450 fs/hfs/bnode.c:70 hfs_brec_insert+0x7f3/0xbd0 fs/hfs/brec.c:159 hfs_cat_create+0x41d/0xa50 fs/hfs/catalog.c:118 hfs_mkdir+0x6c/0xe0 fs/hfs/dir.c:232 vfs_mkdir+0x2f9/0x4f0 fs/namei.c:4257 do_mkdirat+0x264/0x3a0 fs/namei.c:4280 __do_sys_mkdir fs/namei.c:4300 [inline] __se_sys_mkdir fs/namei.c:4298 [inline] __x64_sys_mkdir+0x6c/0x80 fs/namei.c:4298 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7fbdd6057a99 Add a check for key length in hfs_bnode_read_key to prevent out-of-bounds memory access. If the key length is invalid, the key buffer is cleared, improving stability and reliability. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reported-by: syzbot+5f3a973ed3dfb85a6683@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=5f3a973ed3dfb85a6683 Cc: stable@vger.kernel.org Signed-off-by: Vasiliy Kovalev Link: https://lore.kernel.org/20241019191303.24048-1-kovalev@altlinux.org Reviewed-by: Cengiz Can Signed-off-by: Christian Brauner Signed-off-by: Greg Kroah-Hartman --- fs/hfs/bnode.c | 6 ++++++ fs/hfsplus/bnode.c | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c index 6add6ebfef89..cb823a8a6ba9 100644 --- a/fs/hfs/bnode.c +++ b/fs/hfs/bnode.c @@ -67,6 +67,12 @@ void hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off) else key_len = tree->max_key_len + 1; + if (key_len > sizeof(hfs_btree_key) || key_len < 1) { + memset(key, 0, sizeof(hfs_btree_key)); + pr_err("hfs: Invalid key length: %d\n", key_len); + return; + } + hfs_bnode_read(node, key, off, key_len); } diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c index 87974d5e6791..079ea80534f7 100644 --- a/fs/hfsplus/bnode.c +++ b/fs/hfsplus/bnode.c @@ -67,6 +67,12 @@ void hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off) else key_len = tree->max_key_len + 2; + if (key_len > sizeof(hfsplus_btree_key) || key_len < 1) { + memset(key, 0, sizeof(hfsplus_btree_key)); + pr_err("hfsplus: Invalid key length: %d\n", key_len); + return; + } + hfs_bnode_read(node, key, off, key_len); } From e89bf1311d4497c6743f3021e9c481b16c3a41c9 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Mon, 7 Apr 2025 17:33:34 -0300 Subject: [PATCH 310/606] i2c: cros-ec-tunnel: defer probe if parent EC is not present commit 424eafe65647a8d6c690284536e711977153195a upstream. When i2c-cros-ec-tunnel and the EC driver are built-in, the EC parent device will not be found, leading to NULL pointer dereference. That can also be reproduced by unbinding the controller driver and then loading i2c-cros-ec-tunnel module (or binding the device). [ 271.991245] BUG: kernel NULL pointer dereference, address: 0000000000000058 [ 271.998215] #PF: supervisor read access in kernel mode [ 272.003351] #PF: error_code(0x0000) - not-present page [ 272.008485] PGD 0 P4D 0 [ 272.011022] Oops: Oops: 0000 [#1] SMP NOPTI [ 272.015207] CPU: 0 UID: 0 PID: 3859 Comm: insmod Tainted: G S 6.15.0-rc1-00004-g44722359ed83 #30 PREEMPT(full) 3c7fb39a552e7d949de2ad921a7d6588d3a4fdc5 [ 272.030312] Tainted: [S]=CPU_OUT_OF_SPEC [ 272.034233] Hardware name: HP Berknip/Berknip, BIOS Google_Berknip.13434.356.0 05/17/2021 [ 272.042400] RIP: 0010:ec_i2c_probe+0x2b/0x1c0 [i2c_cros_ec_tunnel] [ 272.048577] Code: 1f 44 00 00 41 57 41 56 41 55 41 54 53 48 83 ec 10 65 48 8b 05 06 a0 6c e7 48 89 44 24 08 4c 8d 7f 10 48 8b 47 50 4c 8b 60 78 <49> 83 7c 24 58 00 0f 84 2f 01 00 00 48 89 fb be 30 06 00 00 4c 9 [ 272.067317] RSP: 0018:ffffa32082a03940 EFLAGS: 00010282 [ 272.072541] RAX: ffff969580b6a810 RBX: ffff969580b68c10 RCX: 0000000000000000 [ 272.079672] RDX: 0000000000000000 RSI: 0000000000000282 RDI: ffff969580b68c00 [ 272.086804] RBP: 00000000fffffdfb R08: 0000000000000000 R09: 0000000000000000 [ 272.093936] R10: 0000000000000000 R11: ffffffffc0600000 R12: 0000000000000000 [ 272.101067] R13: ffffffffa666fbb8 R14: ffffffffc05b5528 R15: ffff969580b68c10 [ 272.108198] FS: 00007b930906fc40(0000) GS:ffff969603149000(0000) knlGS:0000000000000000 [ 272.116282] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 272.122024] CR2: 0000000000000058 CR3: 000000012631c000 CR4: 00000000003506f0 [ 272.129155] Call Trace: [ 272.131606] [ 272.133709] ? acpi_dev_pm_attach+0xdd/0x110 [ 272.137985] platform_probe+0x69/0xa0 [ 272.141652] really_probe+0x152/0x310 [ 272.145318] __driver_probe_device+0x77/0x110 [ 272.149678] driver_probe_device+0x1e/0x190 [ 272.153864] __driver_attach+0x10b/0x1e0 [ 272.157790] ? driver_attach+0x20/0x20 [ 272.161542] bus_for_each_dev+0x107/0x150 [ 272.165553] bus_add_driver+0x15d/0x270 [ 272.169392] driver_register+0x65/0x110 [ 272.173232] ? cleanup_module+0xa80/0xa80 [i2c_cros_ec_tunnel 3a00532f3f4af4a9eade753f86b0f8dd4e4e5698] [ 272.182617] do_one_initcall+0x110/0x350 [ 272.186543] ? security_kernfs_init_security+0x49/0xd0 [ 272.191682] ? __kernfs_new_node+0x1b9/0x240 [ 272.195954] ? security_kernfs_init_security+0x49/0xd0 [ 272.201093] ? __kernfs_new_node+0x1b9/0x240 [ 272.205365] ? kernfs_link_sibling+0x105/0x130 [ 272.209810] ? kernfs_next_descendant_post+0x1c/0xa0 [ 272.214773] ? kernfs_activate+0x57/0x70 [ 272.218699] ? kernfs_add_one+0x118/0x160 [ 272.222710] ? __kernfs_create_file+0x71/0xa0 [ 272.227069] ? sysfs_add_bin_file_mode_ns+0xd6/0x110 [ 272.232033] ? internal_create_group+0x453/0x4a0 [ 272.236651] ? __vunmap_range_noflush+0x214/0x2d0 [ 272.241355] ? __free_frozen_pages+0x1dc/0x420 [ 272.245799] ? free_vmap_area_noflush+0x10a/0x1c0 [ 272.250505] ? load_module+0x1509/0x16f0 [ 272.254431] do_init_module+0x60/0x230 [ 272.258181] __se_sys_finit_module+0x27a/0x370 [ 272.262627] do_syscall_64+0x6a/0xf0 [ 272.266206] ? do_syscall_64+0x76/0xf0 [ 272.269956] ? irqentry_exit_to_user_mode+0x79/0x90 [ 272.274836] entry_SYSCALL_64_after_hwframe+0x55/0x5d [ 272.279887] RIP: 0033:0x7b9309168d39 [ 272.283466] Code: 5b 41 5c 5d c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d af 40 0c 00 f7 d8 64 89 01 8 [ 272.302210] RSP: 002b:00007fff50f1a288 EFLAGS: 00000246 ORIG_RAX: 0000000000000139 [ 272.309774] RAX: ffffffffffffffda RBX: 000058bf9b50f6d0 RCX: 00007b9309168d39 [ 272.316905] RDX: 0000000000000000 RSI: 000058bf6c103a77 RDI: 0000000000000003 [ 272.324036] RBP: 00007fff50f1a2e0 R08: 00007fff50f19218 R09: 0000000021ec4150 [ 272.331166] R10: 000058bf9b50f7f0 R11: 0000000000000246 R12: 0000000000000000 [ 272.338296] R13: 00000000fffffffe R14: 0000000000000000 R15: 000058bf6c103a77 [ 272.345428] [ 272.347617] Modules linked in: i2c_cros_ec_tunnel(+) [ 272.364585] gsmi: Log Shutdown Reason 0x03 Returning -EPROBE_DEFER will allow the device to be bound once the controller is bound, in the case of built-in drivers. Fixes: 9d230c9e4f4e ("i2c: ChromeOS EC tunnel driver") Signed-off-by: Thadeu Lima de Souza Cascardo Cc: # v3.16+ Signed-off-by: Andi Shyti Link: https://lore.kernel.org/r/20250407-null-ec-parent-v1-1-f7dda62d3110@igalia.com Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-cros-ec-tunnel.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c index 2737fd8abd32..0cad18ae959e 100644 --- a/drivers/i2c/busses/i2c-cros-ec-tunnel.c +++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c @@ -247,6 +247,9 @@ static int ec_i2c_probe(struct platform_device *pdev) u32 remote_bus; int err; + if (!ec) + return dev_err_probe(dev, -EPROBE_DEFER, "couldn't find parent EC device\n"); + if (!ec->cmd_xfer) { dev_err(dev, "Missing sendrecv\n"); return -EINVAL; From 952e7a7e317f126d0a2b879fc531b716932d5ffa Mon Sep 17 00:00:00 2001 From: Edward Adam Davis Date: Fri, 4 Apr 2025 13:31:29 +0800 Subject: [PATCH 311/606] isofs: Prevent the use of too small fid commit 0405d4b63d082861f4eaff9d39c78ee9dc34f845 upstream. syzbot reported a slab-out-of-bounds Read in isofs_fh_to_parent. [1] The handle_bytes value passed in by the reproducing program is equal to 12. In handle_to_path(), only 12 bytes of memory are allocated for the structure file_handle->f_handle member, which causes an out-of-bounds access when accessing the member parent_block of the structure isofs_fid in isofs, because accessing parent_block requires at least 16 bytes of f_handle. Here, fh_len is used to indirectly confirm that the value of handle_bytes is greater than 3 before accessing parent_block. [1] BUG: KASAN: slab-out-of-bounds in isofs_fh_to_parent+0x1b8/0x210 fs/isofs/export.c:183 Read of size 4 at addr ffff0000cc030d94 by task syz-executor215/6466 CPU: 1 UID: 0 PID: 6466 Comm: syz-executor215 Not tainted 6.14.0-rc7-syzkaller-ga2392f333575 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 02/12/2025 Call trace: show_stack+0x2c/0x3c arch/arm64/kernel/stacktrace.c:466 (C) __dump_stack lib/dump_stack.c:94 [inline] dump_stack_lvl+0xe4/0x150 lib/dump_stack.c:120 print_address_description mm/kasan/report.c:408 [inline] print_report+0x198/0x550 mm/kasan/report.c:521 kasan_report+0xd8/0x138 mm/kasan/report.c:634 __asan_report_load4_noabort+0x20/0x2c mm/kasan/report_generic.c:380 isofs_fh_to_parent+0x1b8/0x210 fs/isofs/export.c:183 exportfs_decode_fh_raw+0x2dc/0x608 fs/exportfs/expfs.c:523 do_handle_to_path+0xa0/0x198 fs/fhandle.c:257 handle_to_path fs/fhandle.c:385 [inline] do_handle_open+0x8cc/0xb8c fs/fhandle.c:403 __do_sys_open_by_handle_at fs/fhandle.c:443 [inline] __se_sys_open_by_handle_at fs/fhandle.c:434 [inline] __arm64_sys_open_by_handle_at+0x80/0x94 fs/fhandle.c:434 __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline] invoke_syscall+0x98/0x2b8 arch/arm64/kernel/syscall.c:49 el0_svc_common+0x130/0x23c arch/arm64/kernel/syscall.c:132 do_el0_svc+0x48/0x58 arch/arm64/kernel/syscall.c:151 el0_svc+0x54/0x168 arch/arm64/kernel/entry-common.c:744 el0t_64_sync_handler+0x84/0x108 arch/arm64/kernel/entry-common.c:762 el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:600 Allocated by task 6466: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x40/0x78 mm/kasan/common.c:68 kasan_save_alloc_info+0x40/0x50 mm/kasan/generic.c:562 poison_kmalloc_redzone mm/kasan/common.c:377 [inline] __kasan_kmalloc+0xac/0xc4 mm/kasan/common.c:394 kasan_kmalloc include/linux/kasan.h:260 [inline] __do_kmalloc_node mm/slub.c:4294 [inline] __kmalloc_noprof+0x32c/0x54c mm/slub.c:4306 kmalloc_noprof include/linux/slab.h:905 [inline] handle_to_path fs/fhandle.c:357 [inline] do_handle_open+0x5a4/0xb8c fs/fhandle.c:403 __do_sys_open_by_handle_at fs/fhandle.c:443 [inline] __se_sys_open_by_handle_at fs/fhandle.c:434 [inline] __arm64_sys_open_by_handle_at+0x80/0x94 fs/fhandle.c:434 __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline] invoke_syscall+0x98/0x2b8 arch/arm64/kernel/syscall.c:49 el0_svc_common+0x130/0x23c arch/arm64/kernel/syscall.c:132 do_el0_svc+0x48/0x58 arch/arm64/kernel/syscall.c:151 el0_svc+0x54/0x168 arch/arm64/kernel/entry-common.c:744 el0t_64_sync_handler+0x84/0x108 arch/arm64/kernel/entry-common.c:762 el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:600 Reported-by: syzbot+4d7cd7dd0ce1aa8d5c65@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=4d7cd7dd0ce1aa8d5c65 Tested-by: syzbot+4d7cd7dd0ce1aa8d5c65@syzkaller.appspotmail.com CC: stable@vger.kernel.org Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Edward Adam Davis Signed-off-by: Jan Kara Link: https://patch.msgid.link/tencent_9C8CB8A7E7C6C512C7065DC98B6EDF6EC606@qq.com Signed-off-by: Greg Kroah-Hartman --- fs/isofs/export.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/isofs/export.c b/fs/isofs/export.c index 35768a63fb1d..421d247fae52 100644 --- a/fs/isofs/export.c +++ b/fs/isofs/export.c @@ -180,7 +180,7 @@ static struct dentry *isofs_fh_to_parent(struct super_block *sb, return NULL; return isofs_export_iget(sb, - fh_len > 2 ? ifid->parent_block : 0, + fh_len > 3 ? ifid->parent_block : 0, ifid->parent_offset, fh_len > 4 ? ifid->parent_generation : 0); } From f8530400f21c649298b71044b5222703dded898e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Tue, 15 Apr 2025 10:51:47 +0200 Subject: [PATCH 312/606] loop: properly send KOBJ_CHANGED uevent for disk device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit e7bc0010ceb403d025100698586c8e760921d471 upstream. The original commit message and the wording "uncork" in the code comment indicate that it is expected that the suppressed event instances are automatically sent after unsuppressing. This is not the case, instead they are discarded. In effect this means that no "changed" events are emitted on the device itself by default. While each discovered partition does trigger a changed event on the device, devices without partitions don't have any event emitted. This makes udev miss the device creation and prompted workarounds in userspace. See the linked util-linux/losetup bug. Explicitly emit the events and drop the confusingly worded comments. Link: https://github.com/util-linux/util-linux/issues/2434 Fixes: 498ef5c777d9 ("loop: suppress uevents while reconfiguring the device") Cc: stable@vger.kernel.org Signed-off-by: Thomas Weißschuh Link: https://lore.kernel.org/r/20250415-loop-uevent-changed-v2-1-0c4e6a923b2a@linutronix.de Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/block/loop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 886c63599037..6ea448511ff1 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -629,8 +629,8 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, error = 0; done: - /* enable and uncork uevent now that we are done */ dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0); + kobject_uevent(&disk_to_dev(lo->lo_disk)->kobj, KOBJ_CHANGE); return error; out_err: @@ -1104,8 +1104,8 @@ static int loop_configure(struct loop_device *lo, blk_mode_t mode, if (partscan) clear_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state); - /* enable and uncork uevent now that we are done */ dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0); + kobject_uevent(&disk_to_dev(lo->lo_disk)->kobj, KOBJ_CHANGE); loop_global_unlock(lo, is_loop); if (partscan) From 2912683a104e9b4902b5c0015a27bad39361fe56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Tue, 15 Apr 2025 16:55:06 +0200 Subject: [PATCH 313/606] loop: LOOP_SET_FD: send uevents for partitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 0dba7a05b9e47d8b546399117b0ddf2426dc6042 upstream. Remove the suppression of the uevents before scanning for partitions. The partitions inherit their suppression settings from their parent device, which lead to the uevents being dropped. This is similar to the same changes for LOOP_CONFIGURE done in commit bb430b694226 ("loop: LOOP_CONFIGURE: send uevents for partitions"). Fixes: 498ef5c777d9 ("loop: suppress uevents while reconfiguring the device") Cc: stable@vger.kernel.org Signed-off-by: Thomas Weißschuh Reviewed-by: Jan Kara Link: https://lore.kernel.org/r/20250415-loop-uevent-changed-v3-1-60ff69ac6088@linutronix.de Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- drivers/block/loop.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 6ea448511ff1..8a6c1146df00 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -624,12 +624,12 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, * dependency. */ fput(old_file); + dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0); if (partscan) loop_reread_partitions(lo); error = 0; done: - dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0); kobject_uevent(&disk_to_dev(lo->lo_disk)->kobj, KOBJ_CHANGE); return error; @@ -637,6 +637,7 @@ out_err: loop_global_unlock(lo, is_loop); out_putf: fput(file); + dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0); goto done; } From 006b67ac61312fe2be05f33acb3f9473df6a7416 Mon Sep 17 00:00:00 2001 From: Baoquan He Date: Thu, 10 Apr 2025 11:57:14 +0800 Subject: [PATCH 314/606] mm/gup: fix wrongly calculated returned value in fault_in_safe_writeable() commit 8c03ebd7cdc06bd0d2fecb4d1a609ef1dbb7d0aa upstream. Not like fault_in_readable() or fault_in_writeable(), in fault_in_safe_writeable() local variable 'start' is increased page by page to loop till the whole address range is handled. However, it mistakenly calculates the size of the handled range with 'uaddr - start'. Fix it here. Andreas said: : In gfs2, fault_in_iov_iter_writeable() is used in : gfs2_file_direct_read() and gfs2_file_read_iter(), so this potentially : affects buffered as well as direct reads. This bug could cause those : gfs2 functions to spin in a loop. Link: https://lkml.kernel.org/r/20250410035717.473207-1-bhe@redhat.com Link: https://lkml.kernel.org/r/20250410035717.473207-2-bhe@redhat.com Signed-off-by: Baoquan He Fixes: fe673d3f5bf1 ("mm: gup: make fault_in_safe_writeable() use fixup_user_fault()") Reviewed-by: Oscar Salvador Acked-by: David Hildenbrand Cc: Andreas Gruenbacher Cc: Yanjun.Zhu Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- mm/gup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/gup.c b/mm/gup.c index 69d259f7bf37..29c719b3ab31 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -1871,8 +1871,8 @@ size_t fault_in_safe_writeable(const char __user *uaddr, size_t size) } while (start != end); mmap_read_unlock(mm); - if (size > (unsigned long)uaddr - start) - return size - ((unsigned long)uaddr - start); + if (size > start - (unsigned long)uaddr) + return size - (start - (unsigned long)uaddr); return 0; } EXPORT_SYMBOL(fault_in_safe_writeable); From c3b3987bae52a17b0cf7d17ed664cfece68dd3e1 Mon Sep 17 00:00:00 2001 From: "Vishal Moola (Oracle)" Date: Thu, 3 Apr 2025 16:54:17 -0700 Subject: [PATCH 315/606] mm: fix filemap_get_folios_contig returning batches of identical folios commit 8ab1b16023961dc640023b10436d282f905835ad upstream. filemap_get_folios_contig() is supposed to return distinct folios found within [start, end]. Large folios in the Xarray become multi-index entries. xas_next() can iterate through the sub-indexes before finding a sibling entry and breaking out of the loop. This can result in a returned folio_batch containing an indeterminate number of duplicate folios, which forces the callers to skeptically handle the returned batch. This is inefficient and incurs a large maintenance overhead. We can fix this by calling xas_advance() after we have successfully adding a folio to the batch to ensure our Xarray is positioned such that it will correctly find the next folio - similar to filemap_get_read_batch(). Link: https://lkml.kernel.org/r/Z-8s1-kiIDkzgRbc@fedora Fixes: 35b471467f88 ("filemap: add filemap_get_folios_contig()") Signed-off-by: Vishal Moola (Oracle) Reported-by: Qu Wenruo Closes: https://lkml.kernel.org/r/b714e4de-2583-4035-b829-72cfb5eb6fc6@gmx.com Tested-by: Qu Wenruo Cc: Matthew Wilcox (Oracle) Cc: Vivek Kasireddy Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- mm/filemap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/filemap.c b/mm/filemap.c index d7c79a69afc8..05eb77623a10 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2256,6 +2256,7 @@ unsigned filemap_get_folios_contig(struct address_space *mapping, *start = folio->index + nr; goto out; } + xas_advance(&xas, folio_next_index(folio) - 1); continue; put_folio: folio_put(folio); From 23385f567b0300a2cbcc6a5eac42f6b41d513b7a Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Wed, 9 Apr 2025 12:40:43 +0300 Subject: [PATCH 316/606] mm: fix apply_to_existing_page_range() commit a995199384347261bb3f21b2e171fa7f988bd2f8 upstream. In the case of apply_to_existing_page_range(), apply_to_pte_range() is reached with 'create' set to false. When !create, the loop over the PTE page table is broken. apply_to_pte_range() will only move to the next PTE entry if 'create' is true or if the current entry is not pte_none(). This means that the user of apply_to_existing_page_range() will not have 'fn' called for any entries after the first pte_none() in the PTE page table. Fix the loop logic in apply_to_pte_range(). There are no known runtime issues from this, but the fix is trivial enough for stable@ even without a known buggy user. Link: https://lkml.kernel.org/r/20250409094043.1629234-1-kirill.shutemov@linux.intel.com Signed-off-by: Kirill A. Shutemov Fixes: be1db4753ee6 ("mm/memory.c: add apply_to_existing_page_range() helper") Cc: Daniel Axtens Cc: David Hildenbrand Cc: Vlastimil Babka Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- mm/memory.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index d04faa09eaf6..8b80db7115e5 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2600,11 +2600,11 @@ static int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd, if (fn) { do { if (create || !pte_none(ptep_get(pte))) { - err = fn(pte++, addr, data); + err = fn(pte, addr, data); if (err) break; } - } while (addr += PAGE_SIZE, addr != end); + } while (pte++, addr += PAGE_SIZE, addr != end); } *mask |= PGTBL_PTE_MODIFIED; From 0874b629f65320778e7e3e206177770666d9db18 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 10 Feb 2025 15:11:22 +0100 Subject: [PATCH 317/606] ovl: don't allow datadir only commit eb3a04a8516ee9b5174379306f94279fc90424c4 upstream. In theory overlayfs could support upper layer directly referring to a data layer, but there's no current use case for this. Originally, when data-only layers were introduced, this wasn't allowed, only introduced by the "datadir+" feature, but without actually handling this case, resulting in an Oops. Fix by disallowing datadir without lowerdir. Reported-by: Giuseppe Scrivano Fixes: 24e16e385f22 ("ovl: add support for appending lowerdirs one by one") Cc: # v6.7 Reviewed-by: Amir Goldstein Reviewed-by: Alexander Larsson Reviewed-by: Christian Brauner Signed-off-by: Miklos Szeredi Signed-off-by: Greg Kroah-Hartman --- fs/overlayfs/super.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 2c056d737c27..93ee57bc82ad 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -1180,6 +1180,11 @@ static struct ovl_entry *ovl_get_lowerstack(struct super_block *sb, return ERR_PTR(-EINVAL); } + if (ctx->nr == ctx->nr_data) { + pr_err("at least one non-data lowerdir is required\n"); + return ERR_PTR(-EINVAL); + } + err = -EINVAL; for (i = 0; i < ctx->nr; i++) { l = &ctx->lower[i]; From 1db2451de23e98bc864c6a6e52aa0d82c91cb325 Mon Sep 17 00:00:00 2001 From: Sean Heelan Date: Mon, 7 Apr 2025 11:26:50 +0000 Subject: [PATCH 318/606] ksmbd: Fix dangling pointer in krb_authenticate commit 1e440d5b25b7efccb3defe542a73c51005799a5f upstream. krb_authenticate frees sess->user and does not set the pointer to NULL. It calls ksmbd_krb5_authenticate to reinitialise sess->user but that function may return without doing so. If that happens then smb2_sess_setup, which calls krb_authenticate, will be accessing free'd memory when it later uses sess->user. Cc: stable@vger.kernel.org Signed-off-by: Sean Heelan Acked-by: Namjae Jeon Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/smb/server/smb2pdu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index 8877f9e900b2..d41d67ec5ee5 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c @@ -1599,8 +1599,10 @@ static int krb5_authenticate(struct ksmbd_work *work, if (prev_sess_id && prev_sess_id != sess->id) destroy_previous_session(conn, sess->user, prev_sess_id); - if (sess->state == SMB2_SESSION_VALID) + if (sess->state == SMB2_SESSION_VALID) { ksmbd_free_user(sess->user); + sess->user = NULL; + } retval = ksmbd_krb5_authenticate(sess, in_blob, in_len, out_blob, &out_len); From 296cb5457cc6f4a754c4ae29855f8a253d52bcc6 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Tue, 15 Apr 2025 09:30:21 +0900 Subject: [PATCH 319/606] ksmbd: fix use-after-free in smb_break_all_levII_oplock() commit 18b4fac5ef17f77fed9417d22210ceafd6525fc7 upstream. There is a room in smb_break_all_levII_oplock that can cause racy issues when unlocking in the middle of the loop. This patch use read lock to protect whole loop. Cc: stable@vger.kernel.org Reported-by: Norbert Szetei Tested-by: Norbert Szetei Signed-off-by: Namjae Jeon Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/smb/server/oplock.c | 29 +++++++++-------------------- fs/smb/server/oplock.h | 1 - 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c index 371a5ead8663..5a5277b4b53b 100644 --- a/fs/smb/server/oplock.c +++ b/fs/smb/server/oplock.c @@ -129,14 +129,6 @@ static void free_opinfo(struct oplock_info *opinfo) kfree(opinfo); } -static inline void opinfo_free_rcu(struct rcu_head *rcu_head) -{ - struct oplock_info *opinfo; - - opinfo = container_of(rcu_head, struct oplock_info, rcu_head); - free_opinfo(opinfo); -} - struct oplock_info *opinfo_get(struct ksmbd_file *fp) { struct oplock_info *opinfo; @@ -157,8 +149,8 @@ static struct oplock_info *opinfo_get_list(struct ksmbd_inode *ci) if (list_empty(&ci->m_op_list)) return NULL; - rcu_read_lock(); - opinfo = list_first_or_null_rcu(&ci->m_op_list, struct oplock_info, + down_read(&ci->m_lock); + opinfo = list_first_entry(&ci->m_op_list, struct oplock_info, op_entry); if (opinfo) { if (opinfo->conn == NULL || @@ -171,8 +163,7 @@ static struct oplock_info *opinfo_get_list(struct ksmbd_inode *ci) } } } - - rcu_read_unlock(); + up_read(&ci->m_lock); return opinfo; } @@ -185,7 +176,7 @@ void opinfo_put(struct oplock_info *opinfo) if (!atomic_dec_and_test(&opinfo->refcount)) return; - call_rcu(&opinfo->rcu_head, opinfo_free_rcu); + free_opinfo(opinfo); } static void opinfo_add(struct oplock_info *opinfo) @@ -193,7 +184,7 @@ static void opinfo_add(struct oplock_info *opinfo) struct ksmbd_inode *ci = opinfo->o_fp->f_ci; down_write(&ci->m_lock); - list_add_rcu(&opinfo->op_entry, &ci->m_op_list); + list_add(&opinfo->op_entry, &ci->m_op_list); up_write(&ci->m_lock); } @@ -207,7 +198,7 @@ static void opinfo_del(struct oplock_info *opinfo) write_unlock(&lease_list_lock); } down_write(&ci->m_lock); - list_del_rcu(&opinfo->op_entry); + list_del(&opinfo->op_entry); up_write(&ci->m_lock); } @@ -1347,8 +1338,8 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp, ci = fp->f_ci; op = opinfo_get(fp); - rcu_read_lock(); - list_for_each_entry_rcu(brk_op, &ci->m_op_list, op_entry) { + down_read(&ci->m_lock); + list_for_each_entry(brk_op, &ci->m_op_list, op_entry) { if (brk_op->conn == NULL) continue; @@ -1358,7 +1349,6 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp, if (ksmbd_conn_releasing(brk_op->conn)) continue; - rcu_read_unlock(); if (brk_op->is_lease && (brk_op->o_lease->state & (~(SMB2_LEASE_READ_CACHING_LE | SMB2_LEASE_HANDLE_CACHING_LE)))) { @@ -1388,9 +1378,8 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp, oplock_break(brk_op, SMB2_OPLOCK_LEVEL_NONE, NULL); next: opinfo_put(brk_op); - rcu_read_lock(); } - rcu_read_unlock(); + up_read(&ci->m_lock); if (op) opinfo_put(op); diff --git a/fs/smb/server/oplock.h b/fs/smb/server/oplock.h index 59554b73f60c..0fe931485465 100644 --- a/fs/smb/server/oplock.h +++ b/fs/smb/server/oplock.h @@ -78,7 +78,6 @@ struct oplock_info { struct list_head lease_entry; wait_queue_head_t oplock_q; /* Other server threads */ wait_queue_head_t oplock_brk; /* oplock breaking wait */ - struct rcu_head rcu_head; }; struct lease_break_info { From 160935d81f2c577984cb684af8decb5090f73b28 Mon Sep 17 00:00:00 2001 From: Denis Arefev Date: Wed, 9 Apr 2025 12:04:49 +0300 Subject: [PATCH 320/606] ksmbd: Prevent integer overflow in calculation of deadtime commit a93ff742820f75bf8bb3fcf21d9f25ca6eb3d4c6 upstream. The user can set any value for 'deadtime'. This affects the arithmetic expression 'req->deadtime * SMB_ECHO_INTERVAL', which is subject to overflow. The added check makes the server behavior more predictable. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: 0626e6641f6b ("cifsd: add server handler for central processing and tranport layers") Cc: stable@vger.kernel.org Signed-off-by: Denis Arefev Acked-by: Namjae Jeon Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/smb/server/transport_ipc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/smb/server/transport_ipc.c b/fs/smb/server/transport_ipc.c index 2d7cd7f42f27..281101fd1f76 100644 --- a/fs/smb/server/transport_ipc.c +++ b/fs/smb/server/transport_ipc.c @@ -296,7 +296,11 @@ static int ipc_server_config_on_startup(struct ksmbd_startup_request *req) server_conf.signing = req->signing; server_conf.tcp_port = req->tcp_port; server_conf.ipc_timeout = req->ipc_timeout * HZ; - server_conf.deadtime = req->deadtime * SMB_ECHO_INTERVAL; + if (check_mul_overflow(req->deadtime, SMB_ECHO_INTERVAL, + &server_conf.deadtime)) { + ret = -EINVAL; + goto out; + } server_conf.share_fake_fscaps = req->share_fake_fscaps; ksmbd_init_domain(req->sub_auth); @@ -322,6 +326,7 @@ static int ipc_server_config_on_startup(struct ksmbd_startup_request *req) ret |= ksmbd_set_work_group(req->work_group); ret |= ksmbd_tcp_set_interfaces(KSMBD_STARTUP_CONFIG_INTERFACES(req), req->ifc_list_sz); +out: if (ret) { pr_err("Server configuration error: %s %s %s\n", req->netbios_name, req->server_string, From b7ce8db490286c2e009758fa1416d66aeb333614 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Tue, 15 Apr 2025 09:31:08 +0900 Subject: [PATCH 321/606] ksmbd: fix the warning from __kernel_write_iter commit b37f2f332b40ad1c27f18682a495850f2f04db0a upstream. [ 2110.972290] ------------[ cut here ]------------ [ 2110.972301] WARNING: CPU: 3 PID: 735 at fs/read_write.c:599 __kernel_write_iter+0x21b/0x280 This patch doesn't allow writing to directory. Cc: stable@vger.kernel.org Reported-by: Norbert Szetei Tested-by: Norbert Szetei Signed-off-by: Namjae Jeon Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/smb/server/vfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c index d0c19ad9d014..fa5b7e63eb83 100644 --- a/fs/smb/server/vfs.c +++ b/fs/smb/server/vfs.c @@ -496,7 +496,8 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp, int err = 0; if (work->conn->connection_type) { - if (!(fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE))) { + if (!(fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE)) || + S_ISDIR(file_inode(fp->filp)->i_mode)) { pr_err("no right to write(%pD)\n", fp->filp); err = -EACCES; goto out; From fd8973b625b67ae8e93176ac04f1deba0ae72ae6 Mon Sep 17 00:00:00 2001 From: Kuniyuki Iwashima Date: Wed, 2 Apr 2025 13:26:47 -0700 Subject: [PATCH 322/606] Revert "smb: client: Fix netns refcount imbalance causing leaks and use-after-free" commit c707193a17128fae2802d10cbad7239cc57f0c95 upstream. This reverts commit 4e7f1644f2ac6d01dc584f6301c3b1d5aac4eaef. The commit e9f2517a3e18 ("smb: client: fix TCP timers deadlock after rmmod") is not only a bogus fix for LOCKDEP null-ptr-deref but also introduces a real issue, TCP sockets leak, which will be explained in detail in the next revert. Also, CNA assigned CVE-2024-54680 to it but is rejecting it. [0] Thus, we are reverting the commit and its follow-up commit 4e7f1644f2ac ("smb: client: Fix netns refcount imbalance causing leaks and use-after-free"). Link: https://lore.kernel.org/all/2025040248-tummy-smilingly-4240@gregkh/ #[0] Fixes: 4e7f1644f2ac ("smb: client: Fix netns refcount imbalance causing leaks and use-after-free") Signed-off-by: Kuniyuki Iwashima Cc: stable@vger.kernel.org Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/smb/client/connect.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 108e4881d6a2..bc8ecfb59ddd 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -316,7 +316,6 @@ cifs_abort_connection(struct TCP_Server_Info *server) server->ssocket->flags); sock_release(server->ssocket); server->ssocket = NULL; - put_net(cifs_net_ns(server)); } server->sequence_number = 0; server->session_estab = false; @@ -3150,12 +3149,8 @@ generic_ip_connect(struct TCP_Server_Info *server) /* * Grab netns reference for the socket. * - * This reference will be released in several situations: - * - In the failure path before the cifsd thread is started. - * - In the all place where server->socket is released, it is - * also set to NULL. - * - Ultimately in clean_demultiplex_info(), during the final - * teardown. + * It'll be released here, on error, or in clean_demultiplex_info() upon server + * teardown. */ get_net(net); @@ -3171,8 +3166,10 @@ generic_ip_connect(struct TCP_Server_Info *server) } rc = bind_socket(server); - if (rc < 0) + if (rc < 0) { + put_net(cifs_net_ns(server)); return rc; + } /* * Eventually check for other socket options to change from @@ -3218,6 +3215,9 @@ generic_ip_connect(struct TCP_Server_Info *server) if (sport == htons(RFC1001_PORT)) rc = ip_rfc1001_connect(server); + if (rc < 0) + put_net(cifs_net_ns(server)); + return rc; } From 8dbf060480236877703bff0106fc984576184d11 Mon Sep 17 00:00:00 2001 From: Kuniyuki Iwashima Date: Wed, 2 Apr 2025 13:26:48 -0700 Subject: [PATCH 323/606] Revert "smb: client: fix TCP timers deadlock after rmmod" commit 95d2b9f693ff2a1180a23d7d59acc0c4e72f4c41 upstream. This reverts commit e9f2517a3e18a54a3943c098d2226b245d488801. Commit e9f2517a3e18 ("smb: client: fix TCP timers deadlock after rmmod") is intended to fix a null-ptr-deref in LOCKDEP, which is mentioned as CVE-2024-54680, but is actually did not fix anything; The issue can be reproduced on top of it. [0] Also, it reverted the change by commit ef7134c7fc48 ("smb: client: Fix use-after-free of network namespace.") and introduced a real issue by reviving the kernel TCP socket. When a reconnect happens for a CIFS connection, the socket state transitions to FIN_WAIT_1. Then, inet_csk_clear_xmit_timers_sync() in tcp_close() stops all timers for the socket. If an incoming FIN packet is lost, the socket will stay at FIN_WAIT_1 forever, and such sockets could be leaked up to net.ipv4.tcp_max_orphans. Usually, FIN can be retransmitted by the peer, but if the peer aborts the connection, the issue comes into reality. I warned about this privately by pointing out the exact report [1], but the bogus fix was finally merged. So, we should not stop the timers to finally kill the connection on our side in that case, meaning we must not use a kernel socket for TCP whose sk->sk_net_refcnt is 0. The kernel socket does not have a reference to its netns to make it possible to tear down netns without cleaning up every resource in it. For example, tunnel devices use a UDP socket internally, but we can destroy netns without removing such devices and let it complete during exit. Otherwise, netns would be leaked when the last application died. However, this is problematic for TCP sockets because TCP has timers to close the connection gracefully even after the socket is close()d. The lifetime of the socket and its netns is different from the lifetime of the underlying connection. If the socket user does not maintain the netns lifetime, the timer could be fired after the socket is close()d and its netns is freed up, resulting in use-after-free. Actually, we have seen so many similar issues and converted such sockets to have a reference to netns. That's why I converted the CIFS client socket to have a reference to netns (sk->sk_net_refcnt == 1), which is somehow mentioned as out-of-scope of CIFS and technically wrong in e9f2517a3e18, but **is in-scope and right fix**. Regarding the LOCKDEP issue, we can prevent the module unload by bumping the module refcount when switching the LOCKDDEP key in sock_lock_init_class_and_name(). [2] For a while, let's revert the bogus fix. Note that now we can use sk_net_refcnt_upgrade() for the socket conversion, but I'll do so later separately to make backport easy. Link: https://lore.kernel.org/all/20250402020807.28583-1-kuniyu@amazon.com/ #[0] Link: https://lore.kernel.org/netdev/c08bd5378da647a2a4c16698125d180a@huawei.com/ #[1] Link: https://lore.kernel.org/lkml/20250402005841.19846-1-kuniyu@amazon.com/ #[2] Fixes: e9f2517a3e18 ("smb: client: fix TCP timers deadlock after rmmod") Signed-off-by: Kuniyuki Iwashima Cc: stable@vger.kernel.org Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/smb/client/connect.c | 36 ++++++++++-------------------------- 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index bc8ecfb59ddd..54aba8d642ee 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -1003,13 +1003,9 @@ clean_demultiplex_info(struct TCP_Server_Info *server) msleep(125); if (cifs_rdma_enabled(server)) smbd_destroy(server); - if (server->ssocket) { sock_release(server->ssocket); server->ssocket = NULL; - - /* Release netns reference for the socket. */ - put_net(cifs_net_ns(server)); } if (!list_empty(&server->pending_mid_q)) { @@ -1058,7 +1054,6 @@ clean_demultiplex_info(struct TCP_Server_Info *server) */ } - /* Release netns reference for this server. */ put_net(cifs_net_ns(server)); kfree(server->leaf_fullpath); kfree(server->hostname); @@ -1730,8 +1725,6 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx, tcp_ses->ops = ctx->ops; tcp_ses->vals = ctx->vals; - - /* Grab netns reference for this server. */ cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns)); tcp_ses->conn_id = atomic_inc_return(&tcpSesNextId); @@ -1863,7 +1856,6 @@ smbd_connected: out_err_crypto_release: cifs_crypto_secmech_release(tcp_ses); - /* Release netns reference for this server. */ put_net(cifs_net_ns(tcp_ses)); out_err: @@ -1872,10 +1864,8 @@ out_err: cifs_put_tcp_session(tcp_ses->primary_server, false); kfree(tcp_ses->hostname); kfree(tcp_ses->leaf_fullpath); - if (tcp_ses->ssocket) { + if (tcp_ses->ssocket) sock_release(tcp_ses->ssocket); - put_net(cifs_net_ns(tcp_ses)); - } kfree(tcp_ses); } return ERR_PTR(rc); @@ -3139,20 +3129,20 @@ generic_ip_connect(struct TCP_Server_Info *server) socket = server->ssocket; } else { struct net *net = cifs_net_ns(server); + struct sock *sk; - rc = sock_create_kern(net, sfamily, SOCK_STREAM, IPPROTO_TCP, &server->ssocket); + rc = __sock_create(net, sfamily, SOCK_STREAM, + IPPROTO_TCP, &server->ssocket, 1); if (rc < 0) { cifs_server_dbg(VFS, "Error %d creating socket\n", rc); return rc; } - /* - * Grab netns reference for the socket. - * - * It'll be released here, on error, or in clean_demultiplex_info() upon server - * teardown. - */ - get_net(net); + sk = server->ssocket->sk; + __netns_tracker_free(net, &sk->ns_tracker, false); + sk->sk_net_refcnt = 1; + get_net_track(net, &sk->ns_tracker, GFP_KERNEL); + sock_inuse_add(net, 1); /* BB other socket options to set KEEPALIVE, NODELAY? */ cifs_dbg(FYI, "Socket created\n"); @@ -3166,10 +3156,8 @@ generic_ip_connect(struct TCP_Server_Info *server) } rc = bind_socket(server); - if (rc < 0) { - put_net(cifs_net_ns(server)); + if (rc < 0) return rc; - } /* * Eventually check for other socket options to change from @@ -3206,7 +3194,6 @@ generic_ip_connect(struct TCP_Server_Info *server) if (rc < 0) { cifs_dbg(FYI, "Error %d connecting to server\n", rc); trace_smb3_connect_err(server->hostname, server->conn_id, &server->dstaddr, rc); - put_net(cifs_net_ns(server)); sock_release(socket); server->ssocket = NULL; return rc; @@ -3215,9 +3202,6 @@ generic_ip_connect(struct TCP_Server_Info *server) if (sport == htons(RFC1001_PORT)) rc = ip_rfc1001_connect(server); - if (rc < 0) - put_net(cifs_net_ns(server)); - return rc; } From e0e1b00208ecbad8debbdc6bd5a203475a7a0d68 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Wed, 9 Apr 2025 14:24:46 -0700 Subject: [PATCH 324/606] riscv: Avoid fortify warning in syscall_get_arguments() commit adf53771a3123df99ca26e38818760fbcf5c05d0 upstream. When building with CONFIG_FORTIFY_SOURCE=y and W=1, there is a warning because of the memcpy() in syscall_get_arguments(): In file included from include/linux/string.h:392, from include/linux/bitmap.h:13, from include/linux/cpumask.h:12, from arch/riscv/include/asm/processor.h:55, from include/linux/sched.h:13, from kernel/ptrace.c:13: In function 'fortify_memcpy_chk', inlined from 'syscall_get_arguments.isra' at arch/riscv/include/asm/syscall.h:66:2: include/linux/fortify-string.h:580:25: error: call to '__read_overflow2_field' declared with attribute warning: detected read beyond size of field (2nd parameter); maybe use struct_group()? [-Werror=attribute-warning] 580 | __read_overflow2_field(q_size_field, size); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors The fortified memcpy() routine enforces that the source is not overread and the destination is not overwritten if the size of either field and the size of the copy are known at compile time. The memcpy() in syscall_get_arguments() intentionally overreads from a1 to a5 in 'struct pt_regs' but this is bigger than the size of a1. Normally, this could be solved by wrapping a1 through a5 with struct_group() but there was already a struct_group() applied to these members in commit bba547810c66 ("riscv: tracing: Fix __write_overflow_field in ftrace_partial_regs()"). Just avoid memcpy() altogether and write the copying of args from regs manually, which clears up the warning at the expense of three extra lines of code. Signed-off-by: Nathan Chancellor Reviewed-by: Dmitry V. Levin Fixes: e2c0cdfba7f6 ("RISC-V: User-facing API") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250409-riscv-avoid-fortify-warning-syscall_get_arguments-v1-1-7853436d4755@kernel.org Signed-off-by: Palmer Dabbelt Signed-off-by: Greg Kroah-Hartman --- arch/riscv/include/asm/syscall.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/riscv/include/asm/syscall.h b/arch/riscv/include/asm/syscall.h index 121fff429dce..eceabf59ae48 100644 --- a/arch/riscv/include/asm/syscall.h +++ b/arch/riscv/include/asm/syscall.h @@ -62,8 +62,11 @@ static inline void syscall_get_arguments(struct task_struct *task, unsigned long *args) { args[0] = regs->orig_a0; - args++; - memcpy(args, ®s->a1, 5 * sizeof(args[0])); + args[1] = regs->a1; + args[2] = regs->a2; + args[3] = regs->a3; + args[4] = regs->a4; + args[5] = regs->a5; } static inline int syscall_get_arch(struct task_struct *task) From 607723b13a0cdfb9ea4da6edb819f0b496e0d133 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 4 Apr 2025 17:42:32 +0100 Subject: [PATCH 325/606] selftests/mm: generate a temporary mountpoint for cgroup filesystem commit 9c02223e2d9df5cb37c51aedb78f3960294e09b5 upstream. Currently if the filesystem for the cgroups version it wants to use is not mounted charge_reserved_hugetlb.sh and hugetlb_reparenting_test.sh tests will attempt to mount it on the hard coded path /dev/cgroup/memory, deleting that directory when the test finishes. This will fail if there is not a preexisting directory at that path, and since the directory is deleted subsequent runs of the test will fail. Instead of relying on this hard coded directory name use mktemp to generate a temporary directory to use as a mountpoint, fixing both the assumption and the disruption caused by deleting a preexisting directory. This means that if the relevant cgroup filesystem is not already mounted then we rely on having coreutils (which provides mktemp) installed. I suspect that many current users are relying on having things automounted by default, and given that the script relies on bash it's probably not an unreasonable requirement. Link: https://lkml.kernel.org/r/20250404-kselftest-mm-cgroup2-detection-v1-1-3dba6d32ba8c@kernel.org Fixes: 209376ed2a84 ("selftests/vm: make charge_reserved_hugetlb.sh work with existing cgroup setting") Signed-off-by: Mark Brown Cc: Aishwarya TCV Cc: Mark Brown Cc: Mina Almasry Cc: Shuah Khan Cc: Waiman Long Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- tools/testing/selftests/mm/charge_reserved_hugetlb.sh | 4 ++-- tools/testing/selftests/mm/hugetlb_reparenting_test.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/mm/charge_reserved_hugetlb.sh b/tools/testing/selftests/mm/charge_reserved_hugetlb.sh index 8e00276b4e69..dc3fc438b3d9 100755 --- a/tools/testing/selftests/mm/charge_reserved_hugetlb.sh +++ b/tools/testing/selftests/mm/charge_reserved_hugetlb.sh @@ -27,7 +27,7 @@ fi if [[ $cgroup2 ]]; then cgroup_path=$(mount -t cgroup2 | head -1 | awk '{print $3}') if [[ -z "$cgroup_path" ]]; then - cgroup_path=/dev/cgroup/memory + cgroup_path=$(mktemp -d) mount -t cgroup2 none $cgroup_path do_umount=1 fi @@ -35,7 +35,7 @@ if [[ $cgroup2 ]]; then else cgroup_path=$(mount -t cgroup | grep ",hugetlb" | awk '{print $3}') if [[ -z "$cgroup_path" ]]; then - cgroup_path=/dev/cgroup/memory + cgroup_path=$(mktemp -d) mount -t cgroup memory,hugetlb $cgroup_path do_umount=1 fi diff --git a/tools/testing/selftests/mm/hugetlb_reparenting_test.sh b/tools/testing/selftests/mm/hugetlb_reparenting_test.sh index 14d26075c863..302f2c7003f0 100755 --- a/tools/testing/selftests/mm/hugetlb_reparenting_test.sh +++ b/tools/testing/selftests/mm/hugetlb_reparenting_test.sh @@ -22,7 +22,7 @@ fi if [[ $cgroup2 ]]; then CGROUP_ROOT=$(mount -t cgroup2 | head -1 | awk '{print $3}') if [[ -z "$CGROUP_ROOT" ]]; then - CGROUP_ROOT=/dev/cgroup/memory + CGROUP_ROOT=$(mktemp -d) mount -t cgroup2 none $CGROUP_ROOT do_umount=1 fi From d5421baa0e156a68e812cae9ce6e3e1951107ee1 Mon Sep 17 00:00:00 2001 From: Chunjie Zhu Date: Sat, 12 Apr 2025 21:15:55 -0500 Subject: [PATCH 326/606] smb3 client: fix open hardlink on deferred close file error commit 262b73ef442e68e53220b9d6fc5a0d08b557fa42 upstream. The following Python script results in unexpected behaviour when run on a CIFS filesystem against a Windows Server: # Create file fd = os.open('test', os.O_WRONLY|os.O_CREAT) os.write(fd, b'foo') os.close(fd) # Open and close the file to leave a pending deferred close fd = os.open('test', os.O_RDONLY|os.O_DIRECT) os.close(fd) # Try to open the file via a hard link os.link('test', 'new') newfd = os.open('new', os.O_RDONLY|os.O_DIRECT) The final open returns EINVAL due to the server returning STATUS_INVALID_PARAMETER. The root cause of this is that the client caches lease keys per inode, but the spec requires them to be related to the filename which causes problems when hard links are involved: From MS-SMB2 section 3.3.5.9.11: "The server MUST attempt to locate a Lease by performing a lookup in the LeaseTable.LeaseList using the LeaseKey in the SMB2_CREATE_REQUEST_LEASE_V2 as the lookup key. If a lease is found, Lease.FileDeleteOnClose is FALSE, and Lease.Filename does not match the file name for the incoming request, the request MUST be failed with STATUS_INVALID_PARAMETER" On client side, we first check the context of file open, if it hits above conditions, we first close all opening files which are belong to the same inode, then we do open the hard link file. Cc: stable@vger.kernel.org Signed-off-by: Chunjie Zhu Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/smb/client/cifsproto.h | 2 ++ fs/smb/client/file.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index 85b0a30493a6..7f97e5468652 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -158,6 +158,8 @@ extern int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); extern int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, struct cifsFileInfo **ret_file); +extern int cifs_get_hardlink_path(struct cifs_tcon *tcon, struct inode *inode, + struct file *file); extern unsigned int smbCalcSize(void *buf); extern int decode_negTokenInit(unsigned char *security_blob, int length, struct TCP_Server_Info *server); diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c index cb75b95efb70..d883ed75022c 100644 --- a/fs/smb/client/file.c +++ b/fs/smb/client/file.c @@ -816,6 +816,11 @@ int cifs_open(struct inode *inode, struct file *file) } else { _cifsFileInfo_put(cfile, true, false); } + } else { + /* hard link on the defeered close file */ + rc = cifs_get_hardlink_path(tcon, inode, file); + if (rc) + cifs_close_deferred_file(CIFS_I(inode)); } if (server->oplocks) @@ -1878,6 +1883,29 @@ cifs_move_llist(struct list_head *source, struct list_head *dest) list_move(li, dest); } +int +cifs_get_hardlink_path(struct cifs_tcon *tcon, struct inode *inode, + struct file *file) +{ + struct cifsFileInfo *open_file = NULL; + struct cifsInodeInfo *cinode = CIFS_I(inode); + int rc = 0; + + spin_lock(&tcon->open_file_lock); + spin_lock(&cinode->open_file_lock); + + list_for_each_entry(open_file, &cinode->openFileList, flist) { + if (file->f_flags == open_file->f_flags) { + rc = -EINVAL; + break; + } + } + + spin_unlock(&cinode->open_file_lock); + spin_unlock(&tcon->open_file_lock); + return rc; +} + void cifs_free_llist(struct list_head *llist) { From 596cbe6320681801bd6386564a84244ef30b3c1a Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 2 Apr 2025 17:06:59 -0700 Subject: [PATCH 327/606] string: Add load_unaligned_zeropad() code path to sized_strscpy() commit d94c12bd97d567de342fd32599e7cd9e50bfa140 upstream. The call to read_word_at_a_time() in sized_strscpy() is problematic with MTE because it may trigger a tag check fault when reading across a tag granule (16 bytes) boundary. To make this code MTE compatible, let's start using load_unaligned_zeropad() on architectures where it is available (i.e. architectures that define CONFIG_DCACHE_WORD_ACCESS). Because load_unaligned_zeropad() takes care of page boundaries as well as tag granule boundaries, also disable the code preventing crossing page boundaries when using load_unaligned_zeropad(). Signed-off-by: Peter Collingbourne Link: https://linux-review.googlesource.com/id/If4b22e43b5a4ca49726b4bf98ada827fdf755548 Fixes: 94ab5b61ee16 ("kasan, arm64: enable CONFIG_KASAN_HW_TAGS") Cc: stable@vger.kernel.org Reviewed-by: Catalin Marinas Link: https://lore.kernel.org/r/20250403000703.2584581-2-pcc@google.com Signed-off-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- lib/string.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/string.c b/lib/string.c index be26623953d2..d49243af5bf2 100644 --- a/lib/string.c +++ b/lib/string.c @@ -128,6 +128,7 @@ ssize_t strscpy(char *dest, const char *src, size_t count) if (count == 0 || WARN_ON_ONCE(count > INT_MAX)) return -E2BIG; +#ifndef CONFIG_DCACHE_WORD_ACCESS #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS /* * If src is unaligned, don't cross a page boundary, @@ -142,12 +143,14 @@ ssize_t strscpy(char *dest, const char *src, size_t count) /* If src or dest is unaligned, don't do word-at-a-time. */ if (((long) dest | (long) src) & (sizeof(long) - 1)) max = 0; +#endif #endif /* - * read_word_at_a_time() below may read uninitialized bytes after the - * trailing zero and use them in comparisons. Disable this optimization - * under KMSAN to prevent false positive reports. + * load_unaligned_zeropad() or read_word_at_a_time() below may read + * uninitialized bytes after the trailing zero and use them in + * comparisons. Disable this optimization under KMSAN to prevent + * false positive reports. */ if (IS_ENABLED(CONFIG_KMSAN)) max = 0; @@ -155,7 +158,11 @@ ssize_t strscpy(char *dest, const char *src, size_t count) while (max >= sizeof(unsigned long)) { unsigned long c, data; +#ifdef CONFIG_DCACHE_WORD_ACCESS + c = load_unaligned_zeropad(src+res); +#else c = read_word_at_a_time(src+res); +#endif if (has_zero(c, &data, &constants)) { data = prep_zero_mask(c, data, &constants); data = create_zero_mask(data); From 89baf6bbe6b68981f06766965519ac265e707862 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Thu, 17 Apr 2025 18:30:03 -0400 Subject: [PATCH 328/606] tracing: Fix filter string testing commit a8c5b0ed89a3f2c81c6ae0b041394e6eea0e7024 upstream. The filter string testing uses strncpy_from_kernel/user_nofault() to retrieve the string to test the filter against. The if() statement was incorrect as it considered 0 as a fault, when it is only negative that it faulted. Running the following commands: # cd /sys/kernel/tracing # echo "filename.ustring ~ \"/proc*\"" > events/syscalls/sys_enter_openat/filter # echo 1 > events/syscalls/sys_enter_openat/enable # ls /proc/$$/maps # cat trace Would produce nothing, but with the fix it will produce something like: ls-1192 [007] ..... 8169.828333: sys_openat(dfd: ffffffffffffff9c, filename: 7efc18359904, flags: 80000, mode: 0) Link: https://lore.kernel.org/all/CAEf4BzbVPQ=BjWztmEwBPRKHUwNfKBkS3kce-Rzka6zvbQeVpg@mail.gmail.com/ Cc: stable@vger.kernel.org Cc: Masami Hiramatsu Cc: Mathieu Desnoyers Cc: Andrew Morton Link: https://lore.kernel.org/20250417183003.505835fb@gandalf.local.home Fixes: 77360f9bbc7e5 ("tracing: Add test for user space strings when filtering on string pointers") Reported-by: Andrii Nakryiko Reported-by: Mykyta Yatsenko Signed-off-by: Steven Rostedt (Google) Signed-off-by: Greg Kroah-Hartman --- kernel/trace/trace_events_filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 0c611b281a5b..f50c2ad43f3d 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c @@ -808,7 +808,7 @@ static __always_inline char *test_string(char *str) kstr = ubuf->buffer; /* For safety, do not trust the string pointer */ - if (!strncpy_from_kernel_nofault(kstr, str, USTRING_BUF_SIZE)) + if (strncpy_from_kernel_nofault(kstr, str, USTRING_BUF_SIZE) < 0) return NULL; return kstr; } @@ -827,7 +827,7 @@ static __always_inline char *test_ustring(char *str) /* user space address? */ ustr = (char __user *)str; - if (!strncpy_from_user_nofault(kstr, ustr, USTRING_BUF_SIZE)) + if (strncpy_from_user_nofault(kstr, ustr, USTRING_BUF_SIZE) < 0) return NULL; return kstr; From f6ec52710dc5e156b774cbef5d0f5c99b1c53a80 Mon Sep 17 00:00:00 2001 From: Xiangsheng Hou Date: Mon, 7 Apr 2025 19:50:49 +0800 Subject: [PATCH 329/606] virtiofs: add filesystem context source name check commit a94fd938df2b1628da66b498aa0eeb89593bc7a2 upstream. In certain scenarios, for example, during fuzz testing, the source name may be NULL, which could lead to a kernel panic. Therefore, an extra check for the source name should be added. Fixes: a62a8ef9d97d ("virtio-fs: add virtiofs filesystem") Cc: # all LTS kernels Signed-off-by: Xiangsheng Hou Link: https://lore.kernel.org/20250407115111.25535-1-xiangsheng.hou@mediatek.com Signed-off-by: Christian Brauner Signed-off-by: Greg Kroah-Hartman --- fs/fuse/virtio_fs.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c index d84dacbdce2c..a6814bea0e0a 100644 --- a/fs/fuse/virtio_fs.c +++ b/fs/fuse/virtio_fs.c @@ -1430,6 +1430,9 @@ static int virtio_fs_get_tree(struct fs_context *fsc) unsigned int virtqueue_size; int err = -EIO; + if (!fsc->source) + return invalf(fsc, "No source specified"); + /* This gets a reference on virtio_fs object. This ptr gets installed * in fc->iq->priv. Once fuse_conn is going away, it calls ->put() * to drop the reference to this object. From 971ba6a64c53fbe3378d11d7295a9fc81c3695ee Mon Sep 17 00:00:00 2001 From: "Borislav Petkov (AMD)" Date: Thu, 10 Apr 2025 13:42:22 +0200 Subject: [PATCH 330/606] x86/microcode/AMD: Extend the SHA check to Zen5, block loading of any unreleased standalone Zen5 microcode patches commit 805b743fc163f1abef7ce1bea8eca8dfab5b685b upstream. All Zen5 machines out there should get BIOS updates which update to the correct microcode patches addressing the microcode signature issue. However, silly people carve out random microcode blobs from BIOS packages and think are doing other people a service this way... Block loading of any unreleased standalone Zen5 microcode patches. Signed-off-by: Borislav Petkov (AMD) Signed-off-by: Ingo Molnar Cc: Cc: Andrew Cooper Cc: Boris Ostrovsky Cc: Linus Torvalds Cc: Maciej S. Szmigiero Cc: Nikolay Borisov Cc: Tom Lendacky Link: https://lore.kernel.org/r/20250410114222.32523-1-bp@kernel.org Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/microcode/amd.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index 0ee172ce2d21..ce78e39004e0 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -201,6 +201,12 @@ static bool need_sha_check(u32 cur_rev) case 0xa70c0: return cur_rev <= 0xa70C009; break; case 0xaa001: return cur_rev <= 0xaa00116; break; case 0xaa002: return cur_rev <= 0xaa00218; break; + case 0xb0021: return cur_rev <= 0xb002146; break; + case 0xb1010: return cur_rev <= 0xb101046; break; + case 0xb2040: return cur_rev <= 0xb204031; break; + case 0xb4040: return cur_rev <= 0xb404031; break; + case 0xb6000: return cur_rev <= 0xb600031; break; + case 0xb7000: return cur_rev <= 0xb700031; break; default: break; } @@ -216,8 +222,7 @@ static bool verify_sha256_digest(u32 patch_id, u32 cur_rev, const u8 *data, unsi struct sha256_state s; int i; - if (x86_family(bsp_cpuid_1_eax) < 0x17 || - x86_family(bsp_cpuid_1_eax) > 0x19) + if (x86_family(bsp_cpuid_1_eax) < 0x17) return true; if (!need_sha_check(cur_rev)) From 5e036349bb0106e22d5bffb0de4727b0c9aa1a5e Mon Sep 17 00:00:00 2001 From: Sandipan Das Date: Fri, 18 Apr 2025 11:49:40 +0530 Subject: [PATCH 331/606] x86/cpu/amd: Fix workaround for erratum 1054 commit 263e55949d8902a6a09bdb92a1ab6a3f67231abe upstream. Erratum 1054 affects AMD Zen processors that are a part of Family 17h Models 00-2Fh and the workaround is to not set HWCR[IRPerfEn]. However, when X86_FEATURE_ZEN1 was introduced, the condition to detect unaffected processors was incorrectly changed in a way that the IRPerfEn bit gets set only for unaffected Zen 1 processors. Ensure that HWCR[IRPerfEn] is set for all unaffected processors. This includes a subset of Zen 1 (Family 17h Models 30h and above) and all later processors. Also clear X86_FEATURE_IRPERF on affected processors so that the IRPerfCount register is not used by other entities like the MSR PMU driver. Fixes: 232afb557835 ("x86/CPU/AMD: Add X86_FEATURE_ZEN1") Signed-off-by: Sandipan Das Signed-off-by: Ingo Molnar Acked-by: Borislav Petkov Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/caa057a9d6f8ad579e2f1abaa71efbd5bd4eaf6d.1744956467.git.sandipan.das@amd.com Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/amd.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index be378b44ca35..498f27537772 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -1039,6 +1039,16 @@ static void init_amd_zen1(struct cpuinfo_x86 *c) pr_notice_once("AMD Zen1 DIV0 bug detected. Disable SMT for full protection.\n"); setup_force_cpu_bug(X86_BUG_DIV0); + + /* + * Turn off the Instructions Retired free counter on machines that are + * susceptible to erratum #1054 "Instructions Retired Performance + * Counter May Be Inaccurate". + */ + if (c->x86_model < 0x30) { + msr_clear_bit(MSR_K7_HWCR, MSR_K7_HWCR_IRPERF_EN_BIT); + clear_cpu_cap(c, X86_FEATURE_IRPERF); + } } static bool cpu_has_zenbleed_microcode(void) @@ -1185,13 +1195,8 @@ static void init_amd(struct cpuinfo_x86 *c) if (!cpu_feature_enabled(X86_FEATURE_XENPV)) set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS); - /* - * Turn on the Instructions Retired free counter on machines not - * susceptible to erratum #1054 "Instructions Retired Performance - * Counter May Be Inaccurate". - */ - if (cpu_has(c, X86_FEATURE_IRPERF) && - (boot_cpu_has(X86_FEATURE_ZEN1) && c->x86_model > 0x2f)) + /* Enable the Instructions Retired free counter */ + if (cpu_has(c, X86_FEATURE_IRPERF)) msr_set_bit(MSR_K7_HWCR, MSR_K7_HWCR_IRPERF_EN_BIT); check_null_seg_clears_base(c); From bbb6b149c33963672eca56af6220cbd3ef467595 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 17 Apr 2025 22:21:21 +0200 Subject: [PATCH 332/606] x86/boot/sev: Avoid shared GHCB page for early memory acceptance commit d54d610243a4508183978871e5faff5502786cd4 upstream. Communicating with the hypervisor using the shared GHCB page requires clearing the C bit in the mapping of that page. When executing in the context of the EFI boot services, the page tables are owned by the firmware, and this manipulation is not possible. So switch to a different API for accepting memory in SEV-SNP guests, one which is actually supported at the point during boot where the EFI stub may need to accept memory, but the SEV-SNP init code has not executed yet. For simplicity, also switch the memory acceptance carried out by the decompressor when not booting via EFI - this only involves the allocation for the decompressed kernel, and is generally only called after kexec, as normal boot will jump straight into the kernel from the EFI stub. Fixes: 6c3211796326 ("x86/sev: Add SNP-specific unaccepted memory support") Tested-by: Tom Lendacky Co-developed-by: Tom Lendacky Signed-off-by: Tom Lendacky Signed-off-by: Ard Biesheuvel Signed-off-by: Ingo Molnar Cc: Cc: Dionna Amalie Glaze Cc: Kevin Loughlin Cc: Kirill A. Shutemov Cc: Linus Torvalds Cc: linux-efi@vger.kernel.org Link: https://lore.kernel.org/r/20250404082921.2767593-8-ardb+git@google.com # discussion thread #1 Link: https://lore.kernel.org/r/20250410132850.3708703-2-ardb+git@google.com # discussion thread #2 Link: https://lore.kernel.org/r/20250417202120.1002102-2-ardb+git@google.com # final submission Signed-off-by: Greg Kroah-Hartman --- arch/x86/boot/compressed/mem.c | 5 ++- arch/x86/boot/compressed/sev.c | 67 ++++++++-------------------------- arch/x86/boot/compressed/sev.h | 2 + 3 files changed, 21 insertions(+), 53 deletions(-) diff --git a/arch/x86/boot/compressed/mem.c b/arch/x86/boot/compressed/mem.c index b3c3a4be7471..18bb201e4354 100644 --- a/arch/x86/boot/compressed/mem.c +++ b/arch/x86/boot/compressed/mem.c @@ -34,11 +34,14 @@ static bool early_is_tdx_guest(void) void arch_accept_memory(phys_addr_t start, phys_addr_t end) { + static bool sevsnp; + /* Platform-specific memory-acceptance call goes here */ if (early_is_tdx_guest()) { if (!tdx_accept_memory(start, end)) panic("TDX: Failed to accept memory\n"); - } else if (sev_snp_enabled()) { + } else if (sevsnp || (sev_get_status() & MSR_AMD64_SEV_SNP_ENABLED)) { + sevsnp = true; snp_accept_memory(start, end); } else { error("Cannot accept memory: unknown platform\n"); diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c index 01d61f0609ab..5616c3b25806 100644 --- a/arch/x86/boot/compressed/sev.c +++ b/arch/x86/boot/compressed/sev.c @@ -135,10 +135,7 @@ bool sev_snp_enabled(void) static void __page_state_change(unsigned long paddr, enum psc_op op) { - u64 val; - - if (!sev_snp_enabled()) - return; + u64 val, msr; /* * If private -> shared then invalidate the page before requesting the @@ -147,6 +144,9 @@ static void __page_state_change(unsigned long paddr, enum psc_op op) if (op == SNP_PAGE_STATE_SHARED && pvalidate(paddr, RMP_PG_SIZE_4K, 0)) sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PVALIDATE); + /* Save the current GHCB MSR value */ + msr = sev_es_rd_ghcb_msr(); + /* Issue VMGEXIT to change the page state in RMP table. */ sev_es_wr_ghcb_msr(GHCB_MSR_PSC_REQ_GFN(paddr >> PAGE_SHIFT, op)); VMGEXIT(); @@ -156,6 +156,9 @@ static void __page_state_change(unsigned long paddr, enum psc_op op) if ((GHCB_RESP_CODE(val) != GHCB_MSR_PSC_RESP) || GHCB_MSR_PSC_RESP_VAL(val)) sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PSC); + /* Restore the GHCB MSR value */ + sev_es_wr_ghcb_msr(msr); + /* * Now that page state is changed in the RMP table, validate it so that it is * consistent with the RMP entry. @@ -166,11 +169,17 @@ static void __page_state_change(unsigned long paddr, enum psc_op op) void snp_set_page_private(unsigned long paddr) { + if (!sev_snp_enabled()) + return; + __page_state_change(paddr, SNP_PAGE_STATE_PRIVATE); } void snp_set_page_shared(unsigned long paddr) { + if (!sev_snp_enabled()) + return; + __page_state_change(paddr, SNP_PAGE_STATE_SHARED); } @@ -194,56 +203,10 @@ static bool early_setup_ghcb(void) return true; } -static phys_addr_t __snp_accept_memory(struct snp_psc_desc *desc, - phys_addr_t pa, phys_addr_t pa_end) -{ - struct psc_hdr *hdr; - struct psc_entry *e; - unsigned int i; - - hdr = &desc->hdr; - memset(hdr, 0, sizeof(*hdr)); - - e = desc->entries; - - i = 0; - while (pa < pa_end && i < VMGEXIT_PSC_MAX_ENTRY) { - hdr->end_entry = i; - - e->gfn = pa >> PAGE_SHIFT; - e->operation = SNP_PAGE_STATE_PRIVATE; - if (IS_ALIGNED(pa, PMD_SIZE) && (pa_end - pa) >= PMD_SIZE) { - e->pagesize = RMP_PG_SIZE_2M; - pa += PMD_SIZE; - } else { - e->pagesize = RMP_PG_SIZE_4K; - pa += PAGE_SIZE; - } - - e++; - i++; - } - - if (vmgexit_psc(boot_ghcb, desc)) - sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PSC); - - pvalidate_pages(desc); - - return pa; -} - void snp_accept_memory(phys_addr_t start, phys_addr_t end) { - struct snp_psc_desc desc = {}; - unsigned int i; - phys_addr_t pa; - - if (!boot_ghcb && !early_setup_ghcb()) - sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PSC); - - pa = start; - while (pa < end) - pa = __snp_accept_memory(&desc, pa, end); + for (phys_addr_t pa = start; pa < end; pa += PAGE_SIZE) + __page_state_change(pa, SNP_PAGE_STATE_PRIVATE); } void sev_es_shutdown_ghcb(void) diff --git a/arch/x86/boot/compressed/sev.h b/arch/x86/boot/compressed/sev.h index fc725a981b09..4e463f33186d 100644 --- a/arch/x86/boot/compressed/sev.h +++ b/arch/x86/boot/compressed/sev.h @@ -12,11 +12,13 @@ bool sev_snp_enabled(void); void snp_accept_memory(phys_addr_t start, phys_addr_t end); +u64 sev_get_status(void); #else static inline bool sev_snp_enabled(void) { return false; } static inline void snp_accept_memory(phys_addr_t start, phys_addr_t end) { } +static inline u64 sev_get_status(void) { return 0; } #endif From 92d8a4e6217e596d8d74922d9c2b898362633588 Mon Sep 17 00:00:00 2001 From: Chandrakanth Patil Date: Thu, 3 Apr 2025 01:07:34 +0530 Subject: [PATCH 333/606] scsi: megaraid_sas: Block zero-length ATA VPD inquiry commit aad9945623ab4029ae7789609fb6166c97976c62 upstream. A firmware bug was observed where ATA VPD inquiry commands with a zero-length data payload were not handled and failed with a non-standard status code of 0xf0. Avoid sending ATA VPD inquiry commands without data payload by setting the device no_vpd_size flag to 1. In addition, if the firmware returns a status code of 0xf0, set scsi_cmnd->result to CHECK_CONDITION to facilitate proper error handling. Suggested-by: Martin K. Petersen Signed-off-by: Chandrakanth Patil Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250402193735.5098-1-chandrakanth.patil@broadcom.com Tested-by: Ryan Lahfa Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/megaraid/megaraid_sas_base.c | 9 +++++++-- drivers/scsi/megaraid/megaraid_sas_fusion.c | 5 ++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 4cc93cb79b8b..dd3630b09aa2 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -2101,6 +2101,9 @@ static int megasas_slave_configure(struct scsi_device *sdev) /* This sdev property may change post OCR */ megasas_set_dynamic_target_properties(sdev, is_target_prop); + if (!MEGASAS_IS_LOGICAL(sdev)) + sdev->no_vpd_size = 1; + mutex_unlock(&instance->reset_mutex); return 0; @@ -3660,8 +3663,10 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, case MFI_STAT_SCSI_IO_FAILED: case MFI_STAT_LD_INIT_IN_PROGRESS: - cmd->scmd->result = - (DID_ERROR << 16) | hdr->scsi_status; + if (hdr->scsi_status == 0xf0) + cmd->scmd->result = (DID_ERROR << 16) | SAM_STAT_CHECK_CONDITION; + else + cmd->scmd->result = (DID_ERROR << 16) | hdr->scsi_status; break; case MFI_STAT_SCSI_DONE_WITH_ERROR: diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 8a83f3fc2b86..5ebcb582cf0c 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -2043,7 +2043,10 @@ map_cmd_status(struct fusion_context *fusion, case MFI_STAT_SCSI_IO_FAILED: case MFI_STAT_LD_INIT_IN_PROGRESS: - scmd->result = (DID_ERROR << 16) | ext_status; + if (ext_status == 0xf0) + scmd->result = (DID_ERROR << 16) | SAM_STAT_CHECK_CONDITION; + else + scmd->result = (DID_ERROR << 16) | ext_status; break; case MFI_STAT_SCSI_DONE_WITH_ERROR: From 064dc7a70cec0a2e79d66b60b935555750af9528 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Wed, 19 Mar 2025 15:30:21 +0000 Subject: [PATCH 334/606] scsi: ufs: exynos: Ensure consistent phy reference counts commit 7f05fd9a3b6fb3a9abc5a748307d11831c03175f upstream. ufshcd_link_startup() can call ufshcd_vops_link_startup_notify() multiple times when retrying. This causes the phy reference count to keep increasing and the phy to not properly re-initialize. If the phy has already been previously powered on, first issue a phy_power_off() and phy_exit(), before re-initializing and powering on again. Signed-off-by: Peter Griffin Link: https://lore.kernel.org/r/20250319-exynos-ufs-stability-fixes-v2-4-96722cc2ba1b@linaro.org Fixes: 3d73b200f989 ("scsi: ufs: ufs-exynos: Change ufs phy control sequence") Cc: stable@vger.kernel.org Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/ufs/host/ufs-exynos.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c index 268189f01e15..d138b66d5e35 100644 --- a/drivers/ufs/host/ufs-exynos.c +++ b/drivers/ufs/host/ufs-exynos.c @@ -901,6 +901,12 @@ static int exynos_ufs_phy_init(struct exynos_ufs *ufs) } phy_set_bus_width(generic_phy, ufs->avail_ln_rx); + + if (generic_phy->power_count) { + phy_power_off(generic_phy); + phy_exit(generic_phy); + } + ret = phy_init(generic_phy); if (ret) { dev_err(hba->dev, "%s: phy init failed, ret = %d\n", From c2b169fc7a12665d8a675c1ff14bca1b9c63fb9a Mon Sep 17 00:00:00 2001 From: Sharath Srinivasan Date: Wed, 26 Mar 2025 14:05:32 -0700 Subject: [PATCH 335/606] RDMA/cma: Fix workqueue crash in cma_netevent_work_handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 45f5dcdd049719fb999393b30679605f16ebce14 upstream. struct rdma_cm_id has member "struct work_struct net_work" that is reused for enqueuing cma_netevent_work_handler()s onto cma_wq. Below crash[1] can occur if more than one call to cma_netevent_callback() occurs in quick succession, which further enqueues cma_netevent_work_handler()s for the same rdma_cm_id, overwriting any previously queued work-item(s) that was just scheduled to run i.e. there is no guarantee the queued work item may run between two successive calls to cma_netevent_callback() and the 2nd INIT_WORK would overwrite the 1st work item (for the same rdma_cm_id), despite grabbing id_table_lock during enqueue. Also drgn analysis [2] indicates the work item was likely overwritten. Fix this by moving the INIT_WORK() to __rdma_create_id(), so that it doesn't race with any existing queue_work() or its worker thread. [1] Trimmed crash stack: ============================================= BUG: kernel NULL pointer dereference, address: 0000000000000008 kworker/u256:6 ... 6.12.0-0... Workqueue: cma_netevent_work_handler [rdma_cm] (rdma_cm) RIP: 0010:process_one_work+0xba/0x31a Call Trace: worker_thread+0x266/0x3a0 kthread+0xcf/0x100 ret_from_fork+0x31/0x50 ret_from_fork_asm+0x1a/0x30 ============================================= [2] drgn crash analysis: >>> trace = prog.crashed_thread().stack_trace() >>> trace (0) crash_setup_regs (./arch/x86/include/asm/kexec.h:111:15) (1) __crash_kexec (kernel/crash_core.c:122:4) (2) panic (kernel/panic.c:399:3) (3) oops_end (arch/x86/kernel/dumpstack.c:382:3) ... (8) process_one_work (kernel/workqueue.c:3168:2) (9) process_scheduled_works (kernel/workqueue.c:3310:3) (10) worker_thread (kernel/workqueue.c:3391:4) (11) kthread (kernel/kthread.c:389:9) Line workqueue.c:3168 for this kernel version is in process_one_work(): 3168 strscpy(worker->desc, pwq->wq->name, WORKER_DESC_LEN); >>> trace[8]["work"] *(struct work_struct *)0xffff92577d0a21d8 = { .data = (atomic_long_t){ .counter = (s64)536870912, <=== Note }, .entry = (struct list_head){ .next = (struct list_head *)0xffff924d075924c0, .prev = (struct list_head *)0xffff924d075924c0, }, .func = (work_func_t)cma_netevent_work_handler+0x0 = 0xffffffffc2cec280, } Suspicion is that pwq is NULL: >>> trace[8]["pwq"] (struct pool_workqueue *) In process_one_work(), pwq is assigned from: struct pool_workqueue *pwq = get_work_pwq(work); and get_work_pwq() is: static struct pool_workqueue *get_work_pwq(struct work_struct *work) { unsigned long data = atomic_long_read(&work->data); if (data & WORK_STRUCT_PWQ) return work_struct_pwq(data); else return NULL; } WORK_STRUCT_PWQ is 0x4: >>> print(repr(prog['WORK_STRUCT_PWQ'])) Object(prog, 'enum work_flags', value=4) But work->data is 536870912 which is 0x20000000. So, get_work_pwq() returns NULL and we crash in process_one_work(): 3168 strscpy(worker->desc, pwq->wq->name, WORKER_DESC_LEN); ============================================= Fixes: 925d046e7e52 ("RDMA/core: Add a netevent notifier to cma") Cc: stable@vger.kernel.org Co-developed-by: Håkon Bugge Signed-off-by: Håkon Bugge Signed-off-by: Sharath Srinivasan Reviewed-by: Patrisious Haddad Link: https://patch.msgid.link/bf0082f9-5b25-4593-92c6-d130aa8ba439@oracle.com Signed-off-by: Leon Romanovsky Signed-off-by: Greg Kroah-Hartman --- drivers/infiniband/core/cma.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 64ace0b968f0..348527cf1e7b 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -72,6 +72,8 @@ static const char * const cma_events[] = { static void cma_iboe_set_mgid(struct sockaddr *addr, union ib_gid *mgid, enum ib_gid_type gid_type); +static void cma_netevent_work_handler(struct work_struct *_work); + const char *__attribute_const__ rdma_event_msg(enum rdma_cm_event_type event) { size_t index = event; @@ -1017,6 +1019,7 @@ __rdma_create_id(struct net *net, rdma_cm_event_handler event_handler, get_random_bytes(&id_priv->seq_num, sizeof id_priv->seq_num); id_priv->id.route.addr.dev_addr.net = get_net(net); id_priv->seq_num &= 0x00ffffff; + INIT_WORK(&id_priv->id.net_work, cma_netevent_work_handler); rdma_restrack_new(&id_priv->res, RDMA_RESTRACK_CM_ID); if (parent) @@ -5211,7 +5214,6 @@ static int cma_netevent_callback(struct notifier_block *self, if (!memcmp(current_id->id.route.addr.dev_addr.dst_dev_addr, neigh->ha, ETH_ALEN)) continue; - INIT_WORK(¤t_id->id.net_work, cma_netevent_work_handler); cma_id_get(current_id); queue_work(cma_wq, ¤t_id->id.net_work); } From 196a4eecb87b94145243c8c0847d41eb1fa84527 Mon Sep 17 00:00:00 2001 From: Dapeng Mi Date: Tue, 15 Apr 2025 10:41:35 +0000 Subject: [PATCH 336/606] perf/x86/intel: Allow to update user space GPRs from PEBS records commit 71dcc11c2cd9e434c34a63154ecadca21c135ddd upstream. Currently when a user samples user space GPRs (--user-regs option) with PEBS, the user space GPRs actually always come from software PMI instead of from PEBS hardware. This leads to the sampled GPRs to possibly be inaccurate for single PEBS record case because of the skid between counter overflow and GPRs sampling on PMI. For the large PEBS case, it is even worse. If user sets the exclude_kernel attribute, large PEBS would be used to sample user space GPRs, but since PEBS GPRs group is not really enabled, it leads to all samples in the large PEBS record to share the same piece of user space GPRs, like this reproducer shows: $ perf record -e branches:pu --user-regs=ip,ax -c 100000 ./foo $ perf report -D | grep "AX" .... AX 0x000000003a0d4ead .... AX 0x000000003a0d4ead .... AX 0x000000003a0d4ead .... AX 0x000000003a0d4ead .... AX 0x000000003a0d4ead .... AX 0x000000003a0d4ead .... AX 0x000000003a0d4ead .... AX 0x000000003a0d4ead .... AX 0x000000003a0d4ead .... AX 0x000000003a0d4ead .... AX 0x000000003a0d4ead So enable GPRs group for user space GPRs sampling and prioritize reading GPRs from PEBS. If the PEBS sampled GPRs is not user space GPRs (single PEBS record case), perf_sample_regs_user() modifies them to user space GPRs. [ mingo: Clarified the changelog. ] Fixes: c22497f5838c ("perf/x86/intel: Support adaptive PEBS v4") Signed-off-by: Dapeng Mi Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Ingo Molnar Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250415104135.318169-2-dapeng1.mi@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- arch/x86/events/intel/ds.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c index dcb1e9b8d866..7dcf5305d695 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c @@ -1203,8 +1203,10 @@ static u64 pebs_update_adaptive_cfg(struct perf_event *event) * + precise_ip < 2 for the non event IP * + For RTM TSX weight we need GPRs for the abort code. */ - gprs = (sample_type & PERF_SAMPLE_REGS_INTR) && - (attr->sample_regs_intr & PEBS_GP_REGS); + gprs = ((sample_type & PERF_SAMPLE_REGS_INTR) && + (attr->sample_regs_intr & PEBS_GP_REGS)) || + ((sample_type & PERF_SAMPLE_REGS_USER) && + (attr->sample_regs_user & PEBS_GP_REGS)); tsx_weight = (sample_type & PERF_SAMPLE_WEIGHT_TYPE) && ((attr->config & INTEL_ARCH_EVENT_MASK) == @@ -1856,7 +1858,7 @@ static void setup_pebs_adaptive_sample_data(struct perf_event *event, regs->flags &= ~PERF_EFLAGS_EXACT; } - if (sample_type & PERF_SAMPLE_REGS_INTR) + if (sample_type & (PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER)) adaptive_pebs_save_regs(regs, gprs); } From aea923afeae483eb520278346456fa2c0bdcafff Mon Sep 17 00:00:00 2001 From: Kan Liang Date: Wed, 16 Apr 2025 07:24:24 -0700 Subject: [PATCH 337/606] perf/x86/intel/uncore: Fix the scale of IIO free running counters on SNR commit 96a720db59ab330c8562b2437153faa45dac705f upstream. There was a mistake in the SNR uncore spec. The counter increments for every 32 bytes of data sent from the IO agent to the SOC, not 4 bytes which was documented in the spec. The event list has been updated: "EventName": "UNC_IIO_BANDWIDTH_IN.PART0_FREERUN", "BriefDescription": "Free running counter that increments for every 32 bytes of data sent from the IO agent to the SOC", Update the scale of the IIO bandwidth in free running counters as well. Fixes: 210cc5f9db7a ("perf/x86/intel/uncore: Add uncore support for Snow Ridge server") Signed-off-by: Kan Liang Signed-off-by: Ingo Molnar Acked-by: Peter Zijlstra Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250416142426.3933977-1-kan.liang@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- arch/x86/events/intel/uncore_snbep.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c index a8f11e60b987..5d7e15cb8535 100644 --- a/arch/x86/events/intel/uncore_snbep.c +++ b/arch/x86/events/intel/uncore_snbep.c @@ -4882,28 +4882,28 @@ static struct uncore_event_desc snr_uncore_iio_freerunning_events[] = { INTEL_UNCORE_EVENT_DESC(ioclk, "event=0xff,umask=0x10"), /* Free-Running IIO BANDWIDTH IN Counters */ INTEL_UNCORE_EVENT_DESC(bw_in_port0, "event=0xff,umask=0x20"), - INTEL_UNCORE_EVENT_DESC(bw_in_port0.scale, "3.814697266e-6"), + INTEL_UNCORE_EVENT_DESC(bw_in_port0.scale, "3.0517578125e-5"), INTEL_UNCORE_EVENT_DESC(bw_in_port0.unit, "MiB"), INTEL_UNCORE_EVENT_DESC(bw_in_port1, "event=0xff,umask=0x21"), - INTEL_UNCORE_EVENT_DESC(bw_in_port1.scale, "3.814697266e-6"), + INTEL_UNCORE_EVENT_DESC(bw_in_port1.scale, "3.0517578125e-5"), INTEL_UNCORE_EVENT_DESC(bw_in_port1.unit, "MiB"), INTEL_UNCORE_EVENT_DESC(bw_in_port2, "event=0xff,umask=0x22"), - INTEL_UNCORE_EVENT_DESC(bw_in_port2.scale, "3.814697266e-6"), + INTEL_UNCORE_EVENT_DESC(bw_in_port2.scale, "3.0517578125e-5"), INTEL_UNCORE_EVENT_DESC(bw_in_port2.unit, "MiB"), INTEL_UNCORE_EVENT_DESC(bw_in_port3, "event=0xff,umask=0x23"), - INTEL_UNCORE_EVENT_DESC(bw_in_port3.scale, "3.814697266e-6"), + INTEL_UNCORE_EVENT_DESC(bw_in_port3.scale, "3.0517578125e-5"), INTEL_UNCORE_EVENT_DESC(bw_in_port3.unit, "MiB"), INTEL_UNCORE_EVENT_DESC(bw_in_port4, "event=0xff,umask=0x24"), - INTEL_UNCORE_EVENT_DESC(bw_in_port4.scale, "3.814697266e-6"), + INTEL_UNCORE_EVENT_DESC(bw_in_port4.scale, "3.0517578125e-5"), INTEL_UNCORE_EVENT_DESC(bw_in_port4.unit, "MiB"), INTEL_UNCORE_EVENT_DESC(bw_in_port5, "event=0xff,umask=0x25"), - INTEL_UNCORE_EVENT_DESC(bw_in_port5.scale, "3.814697266e-6"), + INTEL_UNCORE_EVENT_DESC(bw_in_port5.scale, "3.0517578125e-5"), INTEL_UNCORE_EVENT_DESC(bw_in_port5.unit, "MiB"), INTEL_UNCORE_EVENT_DESC(bw_in_port6, "event=0xff,umask=0x26"), - INTEL_UNCORE_EVENT_DESC(bw_in_port6.scale, "3.814697266e-6"), + INTEL_UNCORE_EVENT_DESC(bw_in_port6.scale, "3.0517578125e-5"), INTEL_UNCORE_EVENT_DESC(bw_in_port6.unit, "MiB"), INTEL_UNCORE_EVENT_DESC(bw_in_port7, "event=0xff,umask=0x27"), - INTEL_UNCORE_EVENT_DESC(bw_in_port7.scale, "3.814697266e-6"), + INTEL_UNCORE_EVENT_DESC(bw_in_port7.scale, "3.0517578125e-5"), INTEL_UNCORE_EVENT_DESC(bw_in_port7.unit, "MiB"), { /* end: all zeroes */ }, }; From 9686a16c35ef149b6d9958cd1dd8a8fb356589f3 Mon Sep 17 00:00:00 2001 From: Kan Liang Date: Wed, 16 Apr 2025 07:24:25 -0700 Subject: [PATCH 338/606] perf/x86/intel/uncore: Fix the scale of IIO free running counters on ICX commit 32c7f1150225694d95a51110a93be25db03bb5db upstream. There was a mistake in the ICX uncore spec too. The counter increments for every 32 bytes rather than 4 bytes. The same as SNR, there are 1 ioclk and 8 IIO bandwidth in free running counters. Reuse the snr_uncore_iio_freerunning_events(). Fixes: 2b3b76b5ec67 ("perf/x86/intel/uncore: Add Ice Lake server uncore support") Reported-by: Tang Jun Signed-off-by: Kan Liang Signed-off-by: Ingo Molnar Acked-by: Peter Zijlstra Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250416142426.3933977-2-kan.liang@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- arch/x86/events/intel/uncore_snbep.c | 33 +--------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c index 5d7e15cb8535..989c1f7dbab5 100644 --- a/arch/x86/events/intel/uncore_snbep.c +++ b/arch/x86/events/intel/uncore_snbep.c @@ -5476,37 +5476,6 @@ static struct freerunning_counters icx_iio_freerunning[] = { [ICX_IIO_MSR_BW_IN] = { 0xaa0, 0x1, 0x10, 8, 48, icx_iio_bw_freerunning_box_offsets }, }; -static struct uncore_event_desc icx_uncore_iio_freerunning_events[] = { - /* Free-Running IIO CLOCKS Counter */ - INTEL_UNCORE_EVENT_DESC(ioclk, "event=0xff,umask=0x10"), - /* Free-Running IIO BANDWIDTH IN Counters */ - INTEL_UNCORE_EVENT_DESC(bw_in_port0, "event=0xff,umask=0x20"), - INTEL_UNCORE_EVENT_DESC(bw_in_port0.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_in_port0.unit, "MiB"), - INTEL_UNCORE_EVENT_DESC(bw_in_port1, "event=0xff,umask=0x21"), - INTEL_UNCORE_EVENT_DESC(bw_in_port1.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_in_port1.unit, "MiB"), - INTEL_UNCORE_EVENT_DESC(bw_in_port2, "event=0xff,umask=0x22"), - INTEL_UNCORE_EVENT_DESC(bw_in_port2.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_in_port2.unit, "MiB"), - INTEL_UNCORE_EVENT_DESC(bw_in_port3, "event=0xff,umask=0x23"), - INTEL_UNCORE_EVENT_DESC(bw_in_port3.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_in_port3.unit, "MiB"), - INTEL_UNCORE_EVENT_DESC(bw_in_port4, "event=0xff,umask=0x24"), - INTEL_UNCORE_EVENT_DESC(bw_in_port4.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_in_port4.unit, "MiB"), - INTEL_UNCORE_EVENT_DESC(bw_in_port5, "event=0xff,umask=0x25"), - INTEL_UNCORE_EVENT_DESC(bw_in_port5.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_in_port5.unit, "MiB"), - INTEL_UNCORE_EVENT_DESC(bw_in_port6, "event=0xff,umask=0x26"), - INTEL_UNCORE_EVENT_DESC(bw_in_port6.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_in_port6.unit, "MiB"), - INTEL_UNCORE_EVENT_DESC(bw_in_port7, "event=0xff,umask=0x27"), - INTEL_UNCORE_EVENT_DESC(bw_in_port7.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_in_port7.unit, "MiB"), - { /* end: all zeroes */ }, -}; - static struct intel_uncore_type icx_uncore_iio_free_running = { .name = "iio_free_running", .num_counters = 9, @@ -5514,7 +5483,7 @@ static struct intel_uncore_type icx_uncore_iio_free_running = { .num_freerunning_types = ICX_IIO_FREERUNNING_TYPE_MAX, .freerunning = icx_iio_freerunning, .ops = &skx_uncore_iio_freerunning_ops, - .event_descs = icx_uncore_iio_freerunning_events, + .event_descs = snr_uncore_iio_freerunning_events, .format_group = &skx_uncore_iio_freerunning_format_group, }; From 0df68b586020fdde51c24062ef3abf7e31572815 Mon Sep 17 00:00:00 2001 From: Kan Liang Date: Wed, 16 Apr 2025 07:24:26 -0700 Subject: [PATCH 339/606] perf/x86/intel/uncore: Fix the scale of IIO free running counters on SPR commit 506f981ab40f0b03a11a640cfd77f48b09aff330 upstream. The scale of IIO bandwidth in free running counters is inherited from the ICX. The counter increments for every 32 bytes rather than 4 bytes. The IIO bandwidth out free running counters don't increment with a consistent size. The increment depends on the requested size. It's impossible to find a fixed increment. Remove it from the event_descs. Fixes: 0378c93a92e2 ("perf/x86/intel/uncore: Support IIO free-running counters on Sapphire Rapids server") Reported-by: Tang Jun Signed-off-by: Kan Liang Signed-off-by: Ingo Molnar Acked-by: Peter Zijlstra Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250416142426.3933977-3-kan.liang@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- arch/x86/events/intel/uncore_snbep.c | 58 +--------------------------- 1 file changed, 1 insertion(+), 57 deletions(-) diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c index 989c1f7dbab5..091ed4651471 100644 --- a/arch/x86/events/intel/uncore_snbep.c +++ b/arch/x86/events/intel/uncore_snbep.c @@ -6210,69 +6210,13 @@ static struct freerunning_counters spr_iio_freerunning[] = { [SPR_IIO_MSR_BW_OUT] = { 0x3808, 0x1, 0x10, 8, 48 }, }; -static struct uncore_event_desc spr_uncore_iio_freerunning_events[] = { - /* Free-Running IIO CLOCKS Counter */ - INTEL_UNCORE_EVENT_DESC(ioclk, "event=0xff,umask=0x10"), - /* Free-Running IIO BANDWIDTH IN Counters */ - INTEL_UNCORE_EVENT_DESC(bw_in_port0, "event=0xff,umask=0x20"), - INTEL_UNCORE_EVENT_DESC(bw_in_port0.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_in_port0.unit, "MiB"), - INTEL_UNCORE_EVENT_DESC(bw_in_port1, "event=0xff,umask=0x21"), - INTEL_UNCORE_EVENT_DESC(bw_in_port1.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_in_port1.unit, "MiB"), - INTEL_UNCORE_EVENT_DESC(bw_in_port2, "event=0xff,umask=0x22"), - INTEL_UNCORE_EVENT_DESC(bw_in_port2.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_in_port2.unit, "MiB"), - INTEL_UNCORE_EVENT_DESC(bw_in_port3, "event=0xff,umask=0x23"), - INTEL_UNCORE_EVENT_DESC(bw_in_port3.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_in_port3.unit, "MiB"), - INTEL_UNCORE_EVENT_DESC(bw_in_port4, "event=0xff,umask=0x24"), - INTEL_UNCORE_EVENT_DESC(bw_in_port4.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_in_port4.unit, "MiB"), - INTEL_UNCORE_EVENT_DESC(bw_in_port5, "event=0xff,umask=0x25"), - INTEL_UNCORE_EVENT_DESC(bw_in_port5.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_in_port5.unit, "MiB"), - INTEL_UNCORE_EVENT_DESC(bw_in_port6, "event=0xff,umask=0x26"), - INTEL_UNCORE_EVENT_DESC(bw_in_port6.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_in_port6.unit, "MiB"), - INTEL_UNCORE_EVENT_DESC(bw_in_port7, "event=0xff,umask=0x27"), - INTEL_UNCORE_EVENT_DESC(bw_in_port7.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_in_port7.unit, "MiB"), - /* Free-Running IIO BANDWIDTH OUT Counters */ - INTEL_UNCORE_EVENT_DESC(bw_out_port0, "event=0xff,umask=0x30"), - INTEL_UNCORE_EVENT_DESC(bw_out_port0.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_out_port0.unit, "MiB"), - INTEL_UNCORE_EVENT_DESC(bw_out_port1, "event=0xff,umask=0x31"), - INTEL_UNCORE_EVENT_DESC(bw_out_port1.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_out_port1.unit, "MiB"), - INTEL_UNCORE_EVENT_DESC(bw_out_port2, "event=0xff,umask=0x32"), - INTEL_UNCORE_EVENT_DESC(bw_out_port2.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_out_port2.unit, "MiB"), - INTEL_UNCORE_EVENT_DESC(bw_out_port3, "event=0xff,umask=0x33"), - INTEL_UNCORE_EVENT_DESC(bw_out_port3.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_out_port3.unit, "MiB"), - INTEL_UNCORE_EVENT_DESC(bw_out_port4, "event=0xff,umask=0x34"), - INTEL_UNCORE_EVENT_DESC(bw_out_port4.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_out_port4.unit, "MiB"), - INTEL_UNCORE_EVENT_DESC(bw_out_port5, "event=0xff,umask=0x35"), - INTEL_UNCORE_EVENT_DESC(bw_out_port5.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_out_port5.unit, "MiB"), - INTEL_UNCORE_EVENT_DESC(bw_out_port6, "event=0xff,umask=0x36"), - INTEL_UNCORE_EVENT_DESC(bw_out_port6.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_out_port6.unit, "MiB"), - INTEL_UNCORE_EVENT_DESC(bw_out_port7, "event=0xff,umask=0x37"), - INTEL_UNCORE_EVENT_DESC(bw_out_port7.scale, "3.814697266e-6"), - INTEL_UNCORE_EVENT_DESC(bw_out_port7.unit, "MiB"), - { /* end: all zeroes */ }, -}; - static struct intel_uncore_type spr_uncore_iio_free_running = { .name = "iio_free_running", .num_counters = 17, .num_freerunning_types = SPR_IIO_FREERUNNING_TYPE_MAX, .freerunning = spr_iio_freerunning, .ops = &skx_uncore_iio_freerunning_ops, - .event_descs = spr_uncore_iio_freerunning_events, + .event_descs = snr_uncore_iio_freerunning_events, .format_group = &skx_uncore_iio_freerunning_format_group, }; From 31330248abad7c4b42afc7a29ac1bd5789f296a9 Mon Sep 17 00:00:00 2001 From: Nikita Zhandarovich Date: Thu, 16 Jan 2025 05:48:01 -0800 Subject: [PATCH 340/606] drm/repaper: fix integer overflows in repeat functions commit 4d098000ac193f359e6b8ca4801dbdbd6a27b41f upstream. There are conditions, albeit somewhat unlikely, under which right hand expressions, calculating the end of time period in functions like repaper_frame_fixed_repeat(), may overflow. For instance, if 'factor10x' in repaper_get_temperature() is high enough (170), as is 'epd->stage_time' in repaper_probe(), then the resulting value of 'end' will not fit in unsigned int expression. Mitigate this by casting 'epd->factored_stage_time' to wider type before any multiplication is done. Found by Linux Verification Center (linuxtesting.org) with static analysis tool SVACE. Fixes: 3589211e9b03 ("drm/tinydrm: Add RePaper e-ink driver") Cc: stable@vger.kernel.org Signed-off-by: Nikita Zhandarovich Signed-off-by: Alex Lanzano Link: https://patchwork.freedesktop.org/patch/msgid/20250116134801.22067-1-n.zhandarovich@fintech.ru Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/tiny/repaper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c index 13ae148f59b9..7796ca579cbd 100644 --- a/drivers/gpu/drm/tiny/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -455,7 +455,7 @@ static void repaper_frame_fixed_repeat(struct repaper_epd *epd, u8 fixed_value, enum repaper_stage stage) { u64 start = local_clock(); - u64 end = start + (epd->factored_stage_time * 1000 * 1000); + u64 end = start + ((u64)epd->factored_stage_time * 1000 * 1000); do { repaper_frame_fixed(epd, fixed_value, stage); @@ -466,7 +466,7 @@ static void repaper_frame_data_repeat(struct repaper_epd *epd, const u8 *image, const u8 *mask, enum repaper_stage stage) { u64 start = local_clock(); - u64 end = start + (epd->factored_stage_time * 1000 * 1000); + u64 end = start + ((u64)epd->factored_stage_time * 1000 * 1000); do { repaper_frame_data(epd, image, mask, stage); From 42c2525bc0a81a63a6a7ec656b67ef641049efe7 Mon Sep 17 00:00:00 2001 From: Akhil P Oommen Date: Wed, 26 Feb 2025 01:22:14 +0530 Subject: [PATCH 341/606] drm/msm/a6xx: Fix stale rpmh votes from GPU commit f561db72a663f8a73c2250bf3244ce1ce221bed7 upstream. It was observed on sc7180 (A618 gpu) that GPU votes for GX rail and CNOC BCM nodes were not removed after GPU suspend. This was because we skipped sending 'prepare-slumber' request to gmu during suspend sequence in some cases. So, make sure we always call prepare-slumber hfi during suspend. Also, calling prepare-slumber without a prior oob-gpu handshake messes up gmu firmware's internal state. So, do that when required. Fixes: 4b565ca5a2cb ("drm/msm: Add A6XX device support") Cc: stable@vger.kernel.org Signed-off-by: Akhil P Oommen Patchwork: https://patchwork.freedesktop.org/patch/639569/ Signed-off-by: Rob Clark Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 82 ++++++++++++++------------- 1 file changed, 44 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 9009442b543d..e7136b7759cb 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -1042,50 +1042,51 @@ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu) struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; u32 val; + int ret; /* - * The GMU may still be in slumber unless the GPU started so check and - * skip putting it back into slumber if so + * GMU firmware's internal power state gets messed up if we send "prepare_slumber" hfi when + * oob_gpu handshake wasn't done after the last wake up. So do a dummy handshake here when + * required */ - val = gmu_read(gmu, REG_A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE); + if (adreno_gpu->base.needs_hw_init) { + if (a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET)) + goto force_off; - if (val != 0xf) { - int ret = a6xx_gmu_wait_for_idle(gmu); - - /* If the GMU isn't responding assume it is hung */ - if (ret) { - a6xx_gmu_force_off(gmu); - return; - } - - a6xx_bus_clear_pending_transactions(adreno_gpu, a6xx_gpu->hung); - - /* tell the GMU we want to slumber */ - ret = a6xx_gmu_notify_slumber(gmu); - if (ret) { - a6xx_gmu_force_off(gmu); - return; - } - - ret = gmu_poll_timeout(gmu, - REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, val, - !(val & A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS_GPUBUSYIGNAHB), - 100, 10000); - - /* - * Let the user know we failed to slumber but don't worry too - * much because we are powering down anyway - */ - - if (ret) - DRM_DEV_ERROR(gmu->dev, - "Unable to slumber GMU: status = 0%x/0%x\n", - gmu_read(gmu, - REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS), - gmu_read(gmu, - REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS2)); + a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET); } + ret = a6xx_gmu_wait_for_idle(gmu); + + /* If the GMU isn't responding assume it is hung */ + if (ret) + goto force_off; + + a6xx_bus_clear_pending_transactions(adreno_gpu, a6xx_gpu->hung); + + /* tell the GMU we want to slumber */ + ret = a6xx_gmu_notify_slumber(gmu); + if (ret) + goto force_off; + + ret = gmu_poll_timeout(gmu, + REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, val, + !(val & A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS_GPUBUSYIGNAHB), + 100, 10000); + + /* + * Let the user know we failed to slumber but don't worry too + * much because we are powering down anyway + */ + + if (ret) + DRM_DEV_ERROR(gmu->dev, + "Unable to slumber GMU: status = 0%x/0%x\n", + gmu_read(gmu, + REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS), + gmu_read(gmu, + REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS2)); + /* Turn off HFI */ a6xx_hfi_stop(gmu); @@ -1094,6 +1095,11 @@ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu) /* Tell RPMh to power off the GPU */ a6xx_rpmh_stop(gmu); + + return; + +force_off: + a6xx_gmu_force_off(gmu); } From d189b32f9dd801dd6fd09e80b1f2c5f808b5dec7 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 19 Mar 2025 11:58:31 -0500 Subject: [PATCH 342/606] drm/amd: Handle being compiled without SI or CIK support better commit 5f054ddead33c1622ea9c0c0aaf07c6843fc7ab0 upstream. If compiled without SI or CIK support but amdgpu tries to load it will run into failures with uninitialized callbacks. Show a nicer message in this case and fail probe instead. Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4050 Signed-off-by: Mario Limonciello Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 44 ++++++++++++++----------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index a51ceebb8054..bacf2e5de2ab 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1651,7 +1651,6 @@ static const u16 amdgpu_unsupported_pciidlist[] = { }; static const struct pci_device_id pciidlist[] = { -#ifdef CONFIG_DRM_AMDGPU_SI {0x1002, 0x6780, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, {0x1002, 0x6784, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, {0x1002, 0x6788, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, @@ -1724,8 +1723,6 @@ static const struct pci_device_id pciidlist[] = { {0x1002, 0x6665, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|AMD_IS_MOBILITY}, {0x1002, 0x6667, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|AMD_IS_MOBILITY}, {0x1002, 0x666F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|AMD_IS_MOBILITY}, -#endif -#ifdef CONFIG_DRM_AMDGPU_CIK /* Kaveri */ {0x1002, 0x1304, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU}, {0x1002, 0x1305, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_APU}, @@ -1808,7 +1805,6 @@ static const struct pci_device_id pciidlist[] = { {0x1002, 0x985D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU}, {0x1002, 0x985E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU}, {0x1002, 0x985F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU}, -#endif /* topaz */ {0x1002, 0x6900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, {0x1002, 0x6901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ}, @@ -2090,14 +2086,14 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, return -ENOTSUPP; } + switch (flags & AMD_ASIC_MASK) { + case CHIP_TAHITI: + case CHIP_PITCAIRN: + case CHIP_VERDE: + case CHIP_OLAND: + case CHIP_HAINAN: #ifdef CONFIG_DRM_AMDGPU_SI - if (!amdgpu_si_support) { - switch (flags & AMD_ASIC_MASK) { - case CHIP_TAHITI: - case CHIP_PITCAIRN: - case CHIP_VERDE: - case CHIP_OLAND: - case CHIP_HAINAN: + if (!amdgpu_si_support) { dev_info(&pdev->dev, "SI support provided by radeon.\n"); dev_info(&pdev->dev, @@ -2105,16 +2101,18 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, ); return -ENODEV; } - } + break; +#else + dev_info(&pdev->dev, "amdgpu is built without SI support.\n"); + return -ENODEV; #endif + case CHIP_KAVERI: + case CHIP_BONAIRE: + case CHIP_HAWAII: + case CHIP_KABINI: + case CHIP_MULLINS: #ifdef CONFIG_DRM_AMDGPU_CIK - if (!amdgpu_cik_support) { - switch (flags & AMD_ASIC_MASK) { - case CHIP_KAVERI: - case CHIP_BONAIRE: - case CHIP_HAWAII: - case CHIP_KABINI: - case CHIP_MULLINS: + if (!amdgpu_cik_support) { dev_info(&pdev->dev, "CIK support provided by radeon.\n"); dev_info(&pdev->dev, @@ -2122,8 +2120,14 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, ); return -ENODEV; } - } + break; +#else + dev_info(&pdev->dev, "amdgpu is built without CIK support.\n"); + return -ENODEV; #endif + default: + break; + } adev = devm_drm_dev_alloc(&pdev->dev, &amdgpu_kms_driver, typeof(*adev), ddev); if (IS_ERR(adev)) From 5096174074114f83c700a27869c54362cbb10f3e Mon Sep 17 00:00:00 2001 From: Denis Arefev Date: Fri, 21 Mar 2025 13:52:32 +0300 Subject: [PATCH 343/606] drm/amd/pm: Prevent division by zero commit 7d641c2b83275d3b0424127b2e0d2d0f7dd82aef upstream. The user can set any speed value. If speed is greater than UINT_MAX/8, division by zero is possible. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: b64625a303de ("drm/amd/pm: correct the address of Arcturus fan related registers") Signed-off-by: Denis Arefev Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 4c58c2cd26d8..0cdf3257b19b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -1274,6 +1274,9 @@ static int arcturus_set_fan_speed_rpm(struct smu_context *smu, uint32_t crystal_clock_freq = 2500; uint32_t tach_period; + if (!speed || speed > UINT_MAX/8) + return -EINVAL; + tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed); WREG32_SOC15(THM, 0, mmCG_TACH_CTRL_ARCT, REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL_ARCT), From 587de3ca7875c06fe3c3aa4073a85c4eff46591f Mon Sep 17 00:00:00 2001 From: Denis Arefev Date: Fri, 21 Mar 2025 14:08:15 +0300 Subject: [PATCH 344/606] drm/amd/pm/powerplay: Prevent division by zero commit 4b8c3c0d17c07f301011e2908fecd2ebdcfe3d1c upstream. The user can set any speed value. If speed is greater than UINT_MAX/8, division by zero is possible. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: c52dcf49195d ("drm/amd/pp: Avoid divide-by-zero in fan_ctrl_set_fan_speed_rpm") Signed-off-by: Denis Arefev Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c index 190af79f3236..e93b7c4aa8c9 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c @@ -307,10 +307,10 @@ int vega10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) int result = 0; if (hwmgr->thermal_controller.fanInfo.bNoFan || - speed == 0 || + (!speed || speed > UINT_MAX/8) || (speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) || (speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM)) - return -1; + return -EINVAL; if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) result = vega10_fan_ctrl_stop_smc_fan_control(hwmgr); From de2cba068c9c648503973b57696d035cfe58a9f6 Mon Sep 17 00:00:00 2001 From: Denis Arefev Date: Thu, 20 Mar 2025 12:35:02 +0300 Subject: [PATCH 345/606] drm/amd/pm/smu11: Prevent division by zero commit 7ba88b5cccc1a99c1afb96e31e7eedac9907704c upstream. The user can set any speed value. If speed is greater than UINT_MAX/8, division by zero is possible. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: 1e866f1fe528 ("drm/amd/pm: Prevent divide by zero") Signed-off-by: Denis Arefev Signed-off-by: Alex Deucher (cherry picked from commit da7dc714a8f8e1c9fc33c57cd63583779a3bef71) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index 123c19bb6228..1b726489d86a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -1202,7 +1202,7 @@ int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu, uint32_t crystal_clock_freq = 2500; uint32_t tach_period; - if (speed == 0) + if (!speed || speed > UINT_MAX/8) return -EINVAL; /* * To prevent from possible overheat, some ASICs may have requirement From b0742a709be7979c7a480772046a1f36d09dab00 Mon Sep 17 00:00:00 2001 From: Denis Arefev Date: Fri, 21 Mar 2025 14:08:16 +0300 Subject: [PATCH 346/606] drm/amd/pm/powerplay/hwmgr/smu7_thermal: Prevent division by zero commit 7c246a05df51c52fe0852ce56ba10c41e6ed1f39 upstream. The user can set any speed value. If speed is greater than UINT_MAX/8, division by zero is possible. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: c52dcf49195d ("drm/amd/pp: Avoid divide-by-zero in fan_ctrl_set_fan_speed_rpm") Signed-off-by: Denis Arefev Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c index a6c3610db23e..7209e965dc52 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c @@ -267,10 +267,10 @@ int smu7_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) if (hwmgr->thermal_controller.fanInfo.bNoFan || (hwmgr->thermal_controller.fanInfo. ucTachometerPulsesPerRevolution == 0) || - speed == 0 || + (!speed || speed > UINT_MAX/8) || (speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) || (speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM)) - return 0; + return -EINVAL; if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) smu7_fan_ctrl_stop_smc_fan_control(hwmgr); From c3ff73e3bddf1a6c30d7effe4018d12ba0cadd2e Mon Sep 17 00:00:00 2001 From: Denis Arefev Date: Fri, 21 Mar 2025 13:52:31 +0300 Subject: [PATCH 347/606] drm/amd/pm/swsmu/smu13/smu_v13_0: Prevent division by zero commit f23e9116ebb71b63fe9cec0dcac792aa9af30b0c upstream. The user can set any speed value. If speed is greater than UINT_MAX/8, division by zero is possible. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: c05d1c401572 ("drm/amd/swsmu: add aldebaran smu13 ip support (v3)") Signed-off-by: Denis Arefev Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index c0adfa46ac78..8504692be47f 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -1227,7 +1227,7 @@ int smu_v13_0_set_fan_speed_rpm(struct smu_context *smu, uint32_t tach_period; int ret; - if (!speed) + if (!speed || speed > UINT_MAX/8) return -EINVAL; ret = smu_v13_0_auto_fan_control(smu, 0); From 068091b796480819bf70b159f17e222ad8bea900 Mon Sep 17 00:00:00 2001 From: Denis Arefev Date: Fri, 21 Mar 2025 13:52:33 +0300 Subject: [PATCH 348/606] drm/amd/pm/powerplay/hwmgr/vega20_thermal: Prevent division by zero commit 4e3d9508c056d7e0a56b58d5c81253e2a0d22b6c upstream. The user can set any speed value. If speed is greater than UINT_MAX/8, division by zero is possible. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: 031db09017da ("drm/amd/powerplay/vega20: enable fan RPM and pwm settings V2") Signed-off-by: Denis Arefev Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c index e9737ca8418a..a1b1c985ca9a 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c @@ -191,7 +191,7 @@ int vega20_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) uint32_t tach_period, crystal_clock_freq; int result = 0; - if (!speed) + if (!speed || speed > UINT_MAX/8) return -EINVAL; if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) { From ae73db71a2a1a7ee9bb8eb3e3a76eb56bf4e96cb Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Mon, 7 Apr 2025 15:18:25 +0100 Subject: [PATCH 349/606] drm/amdgpu/dma_buf: fix page_link check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit c0dd8a9253fadfb8e5357217d085f1989da4ef0a upstream. The page_link lower bits of the first sg could contain something like SG_END, if we are mapping a single VRAM page or contiguous blob which fits into one sg entry. Rather pull out the struct page, and use that in our check to know if we mapped struct pages vs VRAM. Fixes: f44ffd677fb3 ("drm/amdgpu: add support for exporting VRAM using DMA-buf v3") Signed-off-by: Matthew Auld Cc: Christian König Cc: amd-gfx@lists.freedesktop.org Cc: # v5.8+ Reviewed-by: Christian König Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index ba3a87cb88cc..be4cc4868a74 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -211,7 +211,7 @@ static void amdgpu_dma_buf_unmap(struct dma_buf_attachment *attach, struct sg_table *sgt, enum dma_data_direction dir) { - if (sgt->sgl->page_link) { + if (sg_page(sgt->sgl)) { dma_unmap_sgtable(attach->dev, sgt, dir, 0); sg_free_table(sgt); kfree(sgt); From 31e94c7989572f96926673614a3b958915a13ca9 Mon Sep 17 00:00:00 2001 From: Chris Bainbridge Date: Wed, 26 Mar 2025 12:52:10 +0000 Subject: [PATCH 350/606] drm/nouveau: prime: fix ttm_bo_delayed_delete oops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 8ec0fbb28d049273bfd4f1e7a5ae4c74884beed3 upstream. Fix an oops in ttm_bo_delayed_delete which results from dererencing a dangling pointer: Oops: general protection fault, probably for non-canonical address 0x6b6b6b6b6b6b6b7b: 0000 [#1] PREEMPT SMP CPU: 4 UID: 0 PID: 1082 Comm: kworker/u65:2 Not tainted 6.14.0-rc4-00267-g505460b44513-dirty #216 Hardware name: LENOVO 82N6/LNVNB161216, BIOS GKCN65WW 01/16/2024 Workqueue: ttm ttm_bo_delayed_delete [ttm] RIP: 0010:dma_resv_iter_first_unlocked+0x55/0x290 Code: 31 f6 48 c7 c7 00 2b fa aa e8 97 bd 52 ff e8 a2 c1 53 00 5a 85 c0 74 48 e9 88 01 00 00 4c 89 63 20 4d 85 e4 0f 84 30 01 00 00 <41> 8b 44 24 10 c6 43 2c 01 48 89 df 89 43 28 e8 97 fd ff ff 4c 8b RSP: 0018:ffffbf9383473d60 EFLAGS: 00010202 RAX: 0000000000000001 RBX: ffffbf9383473d88 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 RBP: ffffbf9383473d78 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000000 R12: 6b6b6b6b6b6b6b6b R13: ffffa003bbf78580 R14: ffffa003a6728040 R15: 00000000000383cc FS: 0000000000000000(0000) GS:ffffa00991c00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000758348024dd0 CR3: 000000012c259000 CR4: 0000000000f50ef0 PKRU: 55555554 Call Trace: ? __die_body.cold+0x19/0x26 ? die_addr+0x3d/0x70 ? exc_general_protection+0x159/0x460 ? asm_exc_general_protection+0x27/0x30 ? dma_resv_iter_first_unlocked+0x55/0x290 dma_resv_wait_timeout+0x56/0x100 ttm_bo_delayed_delete+0x69/0xb0 [ttm] process_one_work+0x217/0x5c0 worker_thread+0x1c8/0x3d0 ? apply_wqattrs_cleanup.part.0+0xc0/0xc0 kthread+0x10b/0x240 ? kthreads_online_cpu+0x140/0x140 ret_from_fork+0x40/0x70 ? kthreads_online_cpu+0x140/0x140 ret_from_fork_asm+0x11/0x20 The cause of this is: - drm_prime_gem_destroy calls dma_buf_put(dma_buf) which releases the reference to the shared dma_buf. The reference count is 0, so the dma_buf is destroyed, which in turn decrements the corresponding amdgpu_bo reference count to 0, and the amdgpu_bo is destroyed - calling drm_gem_object_release then dma_resv_fini (which destroys the reservation object), then finally freeing the amdgpu_bo. - nouveau_bo obj->bo.base.resv is now a dangling pointer to the memory formerly allocated to the amdgpu_bo. - nouveau_gem_object_del calls ttm_bo_put(&nvbo->bo) which calls ttm_bo_release, which schedules ttm_bo_delayed_delete. - ttm_bo_delayed_delete runs and dereferences the dangling resv pointer, resulting in a general protection fault. Fix this by moving the drm_prime_gem_destroy call from nouveau_gem_object_del to nouveau_bo_del_ttm. This ensures that it will be run after ttm_bo_delayed_delete. Signed-off-by: Chris Bainbridge Suggested-by: Christian König Fixes: 22b33e8ed0e3 ("nouveau: add PRIME support") Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3937 Cc: Stable@vger.kernel.org Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/Z-P4epVK8k7tFZ7C@debian.local Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/nouveau/nouveau_bo.c | 3 +++ drivers/gpu/drm/nouveau/nouveau_gem.c | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 5d398a422459..036ee0343972 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -144,6 +144,9 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo) nouveau_bo_del_io_reserve_lru(bo); nv10_bo_put_tile_region(dev, nvbo->tile, NULL); + if (bo->base.import_attach) + drm_prime_gem_destroy(&bo->base, bo->sg); + /* * If nouveau_bo_new() allocated this buffer, the GEM object was never * initialized, so don't attempt to release it. diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 7b69e6df5748..cd97df690335 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -87,9 +87,6 @@ nouveau_gem_object_del(struct drm_gem_object *gem) return; } - if (gem->import_attach) - drm_prime_gem_destroy(gem, nvbo->bo.sg); - ttm_bo_put(&nvbo->bo); pm_runtime_mark_last_busy(dev); From 3309feab2b26ffc56e335f82550cd873fb5a4a3b Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Wed, 15 Jan 2025 09:58:59 +0100 Subject: [PATCH 351/606] drm/sti: remove duplicate object names commit 7fb6afa9125fc111478615e24231943c4f76cc2e upstream. When merging 2 drivers common object files were not deduplicated. Fixes: dcec16efd677 ("drm/sti: Build monolithic driver") Cc: stable@kernel.org Signed-off-by: Rolf Eike Beer Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/1920148.tdWV9SEqCh@devpool47.emlix.com Signed-off-by: Raphael Gallais-Pou Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/sti/Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/sti/Makefile b/drivers/gpu/drm/sti/Makefile index f203ac5514ae..f778a4eee7c9 100644 --- a/drivers/gpu/drm/sti/Makefile +++ b/drivers/gpu/drm/sti/Makefile @@ -7,8 +7,6 @@ sti-drm-y := \ sti_compositor.o \ sti_crtc.o \ sti_plane.o \ - sti_crtc.o \ - sti_plane.o \ sti_hdmi.o \ sti_hdmi_tx3g4c28phy.o \ sti_dvo.o \ From 3184297d6ff0d4ed7053a8c33d4667430e6fbe3c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 27 Mar 2025 14:47:39 +0200 Subject: [PATCH 352/606] drm/i915/gvt: fix unterminated-string-initialization warning commit 2e43ae7dd71cd9bb0d1bce1d3306bf77523feb81 upstream. Initializing const char opregion_signature[16] = OPREGION_SIGNATURE (which is "IntelGraphicsMem") drops the NUL termination of the string. This is intentional, but the compiler doesn't know this. Switch to initializing header->signature directly from the string litaral, with sizeof destination rather than source. We don't treat the signature as a string other than for initialization; it's really just a blob of binary data. Add a static assert for good measure to cross-check the sizes. Reported-by: Kees Cook Closes: https://lore.kernel.org/r/20250310222355.work.417-kees@kernel.org Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13934 Tested-by: Nicolas Chauvet Tested-by: Damian Tometzki Cc: stable@vger.kernel.org Reviewed-by: Zhenyu Wang Link: https://lore.kernel.org/r/20250327124739.2609656-1-jani.nikula@intel.com Signed-off-by: Jani Nikula (cherry picked from commit 4f8207469094bd04aad952258ceb9ff4c77b6bfa) Signed-off-by: Jani Nikula Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/gvt/opregion.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/opregion.c b/drivers/gpu/drm/i915/gvt/opregion.c index d2bed466540a..3da476dec1da 100644 --- a/drivers/gpu/drm/i915/gvt/opregion.c +++ b/drivers/gpu/drm/i915/gvt/opregion.c @@ -222,7 +222,6 @@ int intel_vgpu_init_opregion(struct intel_vgpu *vgpu) u8 *buf; struct opregion_header *header; struct vbt v; - const char opregion_signature[16] = OPREGION_SIGNATURE; gvt_dbg_core("init vgpu%d opregion\n", vgpu->id); vgpu_opregion(vgpu)->va = (void *)__get_free_pages(GFP_KERNEL | @@ -236,8 +235,10 @@ int intel_vgpu_init_opregion(struct intel_vgpu *vgpu) /* emulated opregion with VBT mailbox only */ buf = (u8 *)vgpu_opregion(vgpu)->va; header = (struct opregion_header *)buf; - memcpy(header->signature, opregion_signature, - sizeof(opregion_signature)); + + static_assert(sizeof(header->signature) == sizeof(OPREGION_SIGNATURE) - 1); + memcpy(header->signature, OPREGION_SIGNATURE, sizeof(header->signature)); + header->size = 0x8; header->opregion_ver = 0x02000000; header->mboxes = MBOX_VBT; From 7e2449ee66936d9feb0e48b3da66f5e6d860cd0c Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sun, 23 Feb 2025 17:22:29 +0000 Subject: [PATCH 353/606] io_uring/net: fix accept multishot handling Commit f6a89bf5278d6e15016a736db67043560d1b50d5 upstream. REQ_F_APOLL_MULTISHOT doesn't guarantee it's executed from the multishot context, so a multishot accept may get executed inline, fail io_req_post_cqe(), and ask the core code to kill the request with -ECANCELED by returning IOU_STOP_MULTISHOT even when a socket has been accepted and installed. Cc: stable@vger.kernel.org Fixes: 390ed29b5e425 ("io_uring: add IORING_ACCEPT_MULTISHOT for accept") Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/51c6deb01feaa78b08565ca8f24843c017f5bc80.1740331076.git.asml.silence@gmail.com Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- io_uring/net.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/io_uring/net.c b/io_uring/net.c index 1a0e98e19dc0..4948a67bbac4 100644 --- a/io_uring/net.c +++ b/io_uring/net.c @@ -1438,6 +1438,8 @@ retry: goto retry; io_req_set_res(req, ret, 0); + if (!(issue_flags & IO_URING_F_MULTISHOT)) + return IOU_OK; return IOU_STOP_MULTISHOT; } From 8c8d0e800044360485e5d960fb634906c9b30728 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 28 Mar 2025 21:39:08 +0100 Subject: [PATCH 354/606] cpufreq: Reference count policy in cpufreq_update_limits() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 9e4e249018d208678888bdf22f6b652728106528 upstream. Since acpi_processor_notify() can be called before registering a cpufreq driver or even in cases when a cpufreq driver is not registered at all, cpufreq_update_limits() needs to check if a cpufreq driver is present and prevent it from being unregistered. For this purpose, make it call cpufreq_cpu_get() to obtain a cpufreq policy pointer for the given CPU and reference count the corresponding policy object, if present. Fixes: 5a25e3f7cc53 ("cpufreq: intel_pstate: Driver-specific handling of _PPC updates") Closes: https://lore.kernel.org/linux-acpi/Z-ShAR59cTow0KcR@mail-itl Reported-by: Marek Marczykowski-Górecki Cc: All applicable Signed-off-by: Rafael J. Wysocki Acked-by: Viresh Kumar Link: https://patch.msgid.link/1928789.tdWV9SEqCh@rjwysocki.net [do not use __free(cpufreq_cpu_put) in a backport] Signed-off-by: Marek Marczykowski-Górecki Signed-off-by: Greg Kroah-Hartman --- drivers/cpufreq/cpufreq.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index df445b44e9ec..0ac0998152ce 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -2725,10 +2725,18 @@ EXPORT_SYMBOL(cpufreq_update_policy); */ void cpufreq_update_limits(unsigned int cpu) { + struct cpufreq_policy *policy; + + policy = cpufreq_cpu_get(cpu); + if (!policy) + return; + if (cpufreq_driver->update_limits) cpufreq_driver->update_limits(cpu); else cpufreq_update_policy(cpu); + + cpufreq_cpu_put(policy); } EXPORT_SYMBOL_GPL(cpufreq_update_limits); From 9b1f50da6054b300c5044109c8ce464da43bec45 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Mon, 7 Apr 2025 16:22:12 -0700 Subject: [PATCH 355/606] kbuild: Add '-fno-builtin-wcslen' commit 84ffc79bfbf70c779e60218563f2f3ad45288671 upstream. A recent optimization change in LLVM [1] aims to transform certain loop idioms into calls to strlen() or wcslen(). This change transforms the first while loop in UniStrcat() into a call to wcslen(), breaking the build when UniStrcat() gets inlined into alloc_path_with_tree_prefix(): ld.lld: error: undefined symbol: wcslen >>> referenced by nls_ucs2_utils.h:54 (fs/smb/client/../../nls/nls_ucs2_utils.h:54) >>> vmlinux.o:(alloc_path_with_tree_prefix) >>> referenced by nls_ucs2_utils.h:54 (fs/smb/client/../../nls/nls_ucs2_utils.h:54) >>> vmlinux.o:(alloc_path_with_tree_prefix) Disable this optimization with '-fno-builtin-wcslen', which prevents the compiler from assuming that wcslen() is available in the kernel's C library. [ More to the point - it's not that we couldn't implement wcslen(), it's that this isn't an optimization at all in the context of the kernel. Replacing a simple inlined loop with a function call to the same loop is just stupid and pointless if you don't have long strings and fancy libraries with vectorization support etc. For the regular 'strlen()' cases, we want the compiler to do this in order to handle the trivial case of constant strings. And we do have optimized versions of 'strlen()' on some architectures. But for wcslen? Just no. - Linus ] Cc: stable@vger.kernel.org Link: https://github.com/llvm/llvm-project/commit/9694844d7e36fd5e01011ab56b64f27b867aa72d [1] Signed-off-by: Nathan Chancellor Signed-off-by: Linus Torvalds [nathan: Resolve small conflict in older trees] Signed-off-by: Nathan Chancellor Signed-off-by: Greg Kroah-Hartman --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 45f6b7d3d51e..18ca8d458fa4 100644 --- a/Makefile +++ b/Makefile @@ -1004,6 +1004,9 @@ ifdef CONFIG_CC_IS_GCC KBUILD_CFLAGS += -fconserve-stack endif +# Ensure compilers do not transform certain loops into calls to wcslen() +KBUILD_CFLAGS += -fno-builtin-wcslen + # change __FILE__ to the relative path from the srctree KBUILD_CPPFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=) From d69a23d8e925f8052d657652a6875ec2712c7e33 Mon Sep 17 00:00:00 2001 From: Yu Kuai Date: Thu, 20 Feb 2025 20:43:48 +0800 Subject: [PATCH 356/606] md: fix mddev uaf while iterating all_mddevs list commit 8542870237c3a48ff049b6c5df5f50c8728284fa upstream. While iterating all_mddevs list from md_notify_reboot() and md_exit(), list_for_each_entry_safe is used, and this can race with deletint the next mddev, causing UAF: t1: spin_lock //list_for_each_entry_safe(mddev, n, ...) mddev_get(mddev1) // assume mddev2 is the next entry spin_unlock t2: //remove mddev2 ... mddev_free spin_lock list_del spin_unlock kfree(mddev2) mddev_put(mddev1) spin_lock //continue dereference mddev2->all_mddevs The old helper for_each_mddev() actually grab the reference of mddev2 while holding the lock, to prevent from being freed. This problem can be fixed the same way, however, the code will be complex. Hence switch to use list_for_each_entry, in this case mddev_put() can free the mddev1 and it's not safe as well. Refer to md_seq_show(), also factor out a helper mddev_put_locked() to fix this problem. Cc: Christoph Hellwig Link: https://lore.kernel.org/linux-raid/20250220124348.845222-1-yukuai1@huaweicloud.com Fixes: f26514342255 ("md: stop using for_each_mddev in md_notify_reboot") Fixes: 16648bac862f ("md: stop using for_each_mddev in md_exit") Reported-and-tested-by: Guillaume Morin Closes: https://lore.kernel.org/all/Z7Y0SURoA8xwg7vn@bender.morinfr.org/ Signed-off-by: Yu Kuai Reviewed-by: Christoph Hellwig Cc: Salvatore Bonaccorso Signed-off-by: Greg Kroah-Hartman --- drivers/md/md.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index a8ac4afc51d9..ca7ae3aad265 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -649,6 +649,12 @@ static void __mddev_put(struct mddev *mddev) queue_work(md_misc_wq, &mddev->del_work); } +static void mddev_put_locked(struct mddev *mddev) +{ + if (atomic_dec_and_test(&mddev->active)) + __mddev_put(mddev); +} + void mddev_put(struct mddev *mddev) { if (!atomic_dec_and_lock(&mddev->active, &all_mddevs_lock)) @@ -8417,9 +8423,7 @@ static int md_seq_show(struct seq_file *seq, void *v) if (mddev == list_last_entry(&all_mddevs, struct mddev, all_mddevs)) status_unused(seq); - if (atomic_dec_and_test(&mddev->active)) - __mddev_put(mddev); - + mddev_put_locked(mddev); return 0; } @@ -9699,11 +9703,11 @@ EXPORT_SYMBOL_GPL(rdev_clear_badblocks); static int md_notify_reboot(struct notifier_block *this, unsigned long code, void *x) { - struct mddev *mddev, *n; + struct mddev *mddev; int need_delay = 0; spin_lock(&all_mddevs_lock); - list_for_each_entry_safe(mddev, n, &all_mddevs, all_mddevs) { + list_for_each_entry(mddev, &all_mddevs, all_mddevs) { if (!mddev_get(mddev)) continue; spin_unlock(&all_mddevs_lock); @@ -9715,8 +9719,8 @@ static int md_notify_reboot(struct notifier_block *this, mddev_unlock(mddev); } need_delay = 1; - mddev_put(mddev); spin_lock(&all_mddevs_lock); + mddev_put_locked(mddev); } spin_unlock(&all_mddevs_lock); @@ -10039,7 +10043,7 @@ void md_autostart_arrays(int part) static __exit void md_exit(void) { - struct mddev *mddev, *n; + struct mddev *mddev; int delay = 1; unregister_blkdev(MD_MAJOR,"md"); @@ -10060,7 +10064,7 @@ static __exit void md_exit(void) remove_proc_entry("mdstat", NULL); spin_lock(&all_mddevs_lock); - list_for_each_entry_safe(mddev, n, &all_mddevs, all_mddevs) { + list_for_each_entry(mddev, &all_mddevs, all_mddevs) { if (!mddev_get(mddev)) continue; spin_unlock(&all_mddevs_lock); @@ -10072,8 +10076,8 @@ static __exit void md_exit(void) * the mddev for destruction by a workqueue, and the * destroy_workqueue() below will wait for that to complete. */ - mddev_put(mddev); spin_lock(&all_mddevs_lock); + mddev_put_locked(mddev); } spin_unlock(&all_mddevs_lock); From 392dfed4af7244ace265a565e2823970d327b495 Mon Sep 17 00:00:00 2001 From: "Matthieu Baerts (NGI0)" Date: Fri, 14 Mar 2025 21:11:33 +0100 Subject: [PATCH 357/606] mptcp: sockopt: fix getting freebind & transparent commit e2f4ac7bab2205d3c4dd9464e6ffd82502177c51 upstream. When adding a socket option support in MPTCP, both the get and set parts are supposed to be implemented. IP(V6)_FREEBIND and IP(V6)_TRANSPARENT support for the setsockopt part has been added a while ago, but it looks like the get part got forgotten. It should have been present as a way to verify a setting has been set as expected, and not to act differently from TCP or any other socket types. Everything was in place to expose it, just the last step was missing. Only new code is added to cover these specific getsockopt(), that seems safe. Fixes: c9406a23c116 ("mptcp: sockopt: add SOL_IP freebind & transparent options") Cc: stable@vger.kernel.org Reviewed-by: Mat Martineau Signed-off-by: Matthieu Baerts (NGI0) Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250314-net-mptcp-fix-data-stream-corr-sockopt-v1-3-122dbb249db3@kernel.org Signed-off-by: Paolo Abeni [ Conflict in sockopt.c due to commit e08d0b3d1723 ("inet: implement lockless IP_TOS") not being in this version. The conflict is in the context and the modification can still be applied in mptcp_getsockopt_v4() after the IP_TOS case. ] Signed-off-by: Matthieu Baerts (NGI0) Signed-off-by: Greg Kroah-Hartman --- net/mptcp/sockopt.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c index 8c9fd9c1dbce..31f6899ef71a 100644 --- a/net/mptcp/sockopt.c +++ b/net/mptcp/sockopt.c @@ -1388,6 +1388,12 @@ static int mptcp_getsockopt_v4(struct mptcp_sock *msk, int optname, switch (optname) { case IP_TOS: return mptcp_put_int_option(msk, optval, optlen, inet_sk(sk)->tos); + case IP_FREEBIND: + return mptcp_put_int_option(msk, optval, optlen, + inet_test_bit(FREEBIND, sk)); + case IP_TRANSPARENT: + return mptcp_put_int_option(msk, optval, optlen, + inet_test_bit(TRANSPARENT, sk)); } return -EOPNOTSUPP; @@ -1402,6 +1408,12 @@ static int mptcp_getsockopt_v6(struct mptcp_sock *msk, int optname, case IPV6_V6ONLY: return mptcp_put_int_option(msk, optval, optlen, sk->sk_ipv6only); + case IPV6_TRANSPARENT: + return mptcp_put_int_option(msk, optval, optlen, + inet_test_bit(TRANSPARENT, sk)); + case IPV6_FREEBIND: + return mptcp_put_int_option(msk, optval, optlen, + inet_test_bit(FREEBIND, sk)); } return -EOPNOTSUPP; From 11a2f91f1844d5b6b24a1fdd038c99463ed0e017 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Tue, 28 Nov 2023 15:18:59 -0800 Subject: [PATCH 358/606] selftests: mptcp: add mptcp_lib_wait_local_port_listen commit 9369777c29395730cec967e7d0f48aed872b7110 upstream. To avoid duplicated code in different MPTCP selftests, we can add and use helpers defined in mptcp_lib.sh. wait_local_port_listen() helper is defined in diag.sh, mptcp_connect.sh, mptcp_join.sh and simult_flows.sh, export it into mptcp_lib.sh and rename it with mptcp_lib_ prefix. Use this new helper in all these scripts. Note: We only have IPv4 connections in this helper, not looking at IPv6 (tcp6) but that's OK because we only have IPv4 connections here in diag.sh. Reviewed-by: Matthieu Baerts Signed-off-by: Geliang Tang Signed-off-by: Mat Martineau Link: https://lore.kernel.org/r/20231128-send-net-next-2023107-v4-15-8d6b94150f6b@kernel.org Signed-off-by: Jakub Kicinski Stable-dep-of: 5afca7e996c4 ("selftests: mptcp: join: test for prohibited MPC to port-based endp") [ Conflict in diag.sh, because commit 1f24ba67ba49 ("selftests: mptcp: diag: check CURRESTAB counters") that is more recent that the one here, has been backported in this kernel version before, introducing chk_msk_cestab() helper in the same context. wait_local_port_listen() was still the same as in the original, and can then be simply removed from diag.sh. ] Signed-off-by: Matthieu Baerts (NGI0) Signed-off-by: Greg Kroah-Hartman --- tools/testing/selftests/net/mptcp/diag.sh | 23 +++---------------- .../selftests/net/mptcp/mptcp_connect.sh | 19 +-------------- .../testing/selftests/net/mptcp/mptcp_join.sh | 20 +--------------- .../testing/selftests/net/mptcp/mptcp_lib.sh | 18 +++++++++++++++ .../selftests/net/mptcp/simult_flows.sh | 19 +-------------- 5 files changed, 24 insertions(+), 75 deletions(-) diff --git a/tools/testing/selftests/net/mptcp/diag.sh b/tools/testing/selftests/net/mptcp/diag.sh index 7f89623f1080..f00c97b2a6b5 100755 --- a/tools/testing/selftests/net/mptcp/diag.sh +++ b/tools/testing/selftests/net/mptcp/diag.sh @@ -186,23 +186,6 @@ chk_msk_inuse() __chk_nr get_msk_inuse $expected "${msg}" 0 } -# $1: ns, $2: port -wait_local_port_listen() -{ - local listener_ns="${1}" - local port="${2}" - - local port_hex i - - port_hex="$(printf "%04X" "${port}")" - for i in $(seq 10); do - ip netns exec "${listener_ns}" cat /proc/net/tcp | \ - awk "BEGIN {rc=1} {if (\$2 ~ /:${port_hex}\$/ && \$4 ~ /0A/) {rc=0; exit}} END {exit rc}" && - break - sleep 0.1 - done -} - # $1: cestab nr chk_msk_cestab() { @@ -240,7 +223,7 @@ echo "a" | \ ip netns exec $ns \ ./mptcp_connect -p 10000 -l -t ${timeout_poll} -w 20 \ 0.0.0.0 >/dev/null & -wait_local_port_listen $ns 10000 +mptcp_lib_wait_local_port_listen $ns 10000 chk_msk_nr 0 "no msk on netns creation" chk_msk_listen 10000 @@ -265,7 +248,7 @@ echo "a" | \ ip netns exec $ns \ ./mptcp_connect -p 10001 -l -s TCP -t ${timeout_poll} -w 20 \ 0.0.0.0 >/dev/null & -wait_local_port_listen $ns 10001 +mptcp_lib_wait_local_port_listen $ns 10001 echo "b" | \ timeout ${timeout_test} \ ip netns exec $ns \ @@ -288,7 +271,7 @@ for I in `seq 1 $NR_CLIENTS`; do ./mptcp_connect -p $((I+10001)) -l -w 20 \ -t ${timeout_poll} 0.0.0.0 >/dev/null & done -wait_local_port_listen $ns $((NR_CLIENTS + 10001)) +mptcp_lib_wait_local_port_listen $ns $((NR_CLIENTS + 10001)) for I in `seq 1 $NR_CLIENTS`; do echo "b" | \ diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.sh b/tools/testing/selftests/net/mptcp/mptcp_connect.sh index d203d314b7b2..3763ffa214d5 100755 --- a/tools/testing/selftests/net/mptcp/mptcp_connect.sh +++ b/tools/testing/selftests/net/mptcp/mptcp_connect.sh @@ -342,23 +342,6 @@ do_ping() return 0 } -# $1: ns, $2: port -wait_local_port_listen() -{ - local listener_ns="${1}" - local port="${2}" - - local port_hex i - - port_hex="$(printf "%04X" "${port}")" - for i in $(seq 10); do - ip netns exec "${listener_ns}" cat /proc/net/tcp* | \ - awk "BEGIN {rc=1} {if (\$2 ~ /:${port_hex}\$/ && \$4 ~ /0A/) {rc=0; exit}} END {exit rc}" && - break - sleep 0.1 - done -} - do_transfer() { local listener_ns="$1" @@ -448,7 +431,7 @@ do_transfer() $extra_args $local_addr < "$sin" > "$sout" & local spid=$! - wait_local_port_listen "${listener_ns}" "${port}" + mptcp_lib_wait_local_port_listen "${listener_ns}" "${port}" local start start=$(date +%s%3N) diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh index 497dc187387f..442b7220468a 100755 --- a/tools/testing/selftests/net/mptcp/mptcp_join.sh +++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh @@ -598,24 +598,6 @@ link_failure() done } -# $1: ns, $2: port -wait_local_port_listen() -{ - local listener_ns="${1}" - local port="${2}" - - local port_hex - port_hex="$(printf "%04X" "${port}")" - - local i - for i in $(seq 10); do - ip netns exec "${listener_ns}" cat /proc/net/tcp* | \ - awk "BEGIN {rc=1} {if (\$2 ~ /:${port_hex}\$/ && \$4 ~ /0A/) {rc=0; exit}} END {exit rc}" && - break - sleep 0.1 - done -} - rm_addr_count() { mptcp_lib_get_counter "${1}" "MPTcpExtRmAddr" @@ -1117,7 +1099,7 @@ do_transfer() fi local spid=$! - wait_local_port_listen "${listener_ns}" "${port}" + mptcp_lib_wait_local_port_listen "${listener_ns}" "${port}" extra_cl_args="$extra_args $extra_cl_args" if [ "$test_linkfail" -eq 0 ];then diff --git a/tools/testing/selftests/net/mptcp/mptcp_lib.sh b/tools/testing/selftests/net/mptcp/mptcp_lib.sh index d98c89f31afe..919f4f1018eb 100644 --- a/tools/testing/selftests/net/mptcp/mptcp_lib.sh +++ b/tools/testing/selftests/net/mptcp/mptcp_lib.sh @@ -274,3 +274,21 @@ mptcp_lib_events() { ip netns exec "${ns}" ./pm_nl_ctl events >> "${evts}" 2>&1 & pid=$! } + +# $1: ns, $2: port +mptcp_lib_wait_local_port_listen() { + local listener_ns="${1}" + local port="${2}" + + local port_hex + port_hex="$(printf "%04X" "${port}")" + + local _ + for _ in $(seq 10); do + ip netns exec "${listener_ns}" cat /proc/net/tcp* | \ + awk "BEGIN {rc=1} {if (\$2 ~ /:${port_hex}\$/ && \$4 ~ /0A/) \ + {rc=0; exit}} END {exit rc}" && + break + sleep 0.1 + done +} diff --git a/tools/testing/selftests/net/mptcp/simult_flows.sh b/tools/testing/selftests/net/mptcp/simult_flows.sh index f24bd2bf0831..214a89fce8b8 100755 --- a/tools/testing/selftests/net/mptcp/simult_flows.sh +++ b/tools/testing/selftests/net/mptcp/simult_flows.sh @@ -123,23 +123,6 @@ setup() grep -q ' kmemleak_init$\| lockdep_init$\| kasan_init$\| prove_locking$' /proc/kallsyms && slack=$((slack+550)) } -# $1: ns, $2: port -wait_local_port_listen() -{ - local listener_ns="${1}" - local port="${2}" - - local port_hex i - - port_hex="$(printf "%04X" "${port}")" - for i in $(seq 10); do - ip netns exec "${listener_ns}" cat /proc/net/tcp* | \ - awk "BEGIN {rc=1} {if (\$2 ~ /:${port_hex}\$/ && \$4 ~ /0A/) {rc=0; exit}} END {exit rc}" && - break - sleep 0.1 - done -} - do_transfer() { local cin=$1 @@ -179,7 +162,7 @@ do_transfer() 0.0.0.0 < "$sin" > "$sout" & local spid=$! - wait_local_port_listen "${ns3}" "${port}" + mptcp_lib_wait_local_port_listen "${ns3}" "${port}" timeout ${timeout_test} \ ip netns exec ${ns1} \ From 5a4b7181213268c9b07bef8800905528435db44a Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Tue, 25 Feb 2025 20:02:48 +0900 Subject: [PATCH 359/606] misc: pci_endpoint_test: Avoid issue of interrupts remaining after request_irq error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f6cb7828c8e17520d4f5afb416515d3fae1af9a9 upstream. After devm_request_irq() fails with error in pci_endpoint_test_request_irq(), the pci_endpoint_test_free_irq_vectors() is called assuming that all IRQs have been released. However, some requested IRQs remain unreleased, so there are still /proc/irq/* entries remaining, and this results in WARN() with the following message: remove_proc_entry: removing non-empty directory 'irq/30', leaking at least 'pci-endpoint-test.0' WARNING: CPU: 0 PID: 202 at fs/proc/generic.c:719 remove_proc_entry +0x190/0x19c To solve this issue, set the number of remaining IRQs to test->num_irqs, and release IRQs in advance by calling pci_endpoint_test_release_irq(). Cc: stable@vger.kernel.org Fixes: e03327122e2c ("pci_endpoint_test: Add 2 ioctl commands") Reviewed-by: Manivannan Sadhasivam Signed-off-by: Kunihiko Hayashi Link: https://lore.kernel.org/r/20250225110252.28866-3-hayashi.kunihiko@socionext.com [kwilczynski: commit log] Signed-off-by: Krzysztof Wilczyński Signed-off-by: Kunihiko Hayashi Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pci_endpoint_test.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index af519088732d..cd5af3e55f28 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -260,6 +260,9 @@ fail: break; } + test->num_irqs = i; + pci_endpoint_test_release_irq(test); + return false; } From 9d8d2899c5b99028a53bd6b32f2a313bed00270a Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Tue, 25 Feb 2025 20:02:49 +0900 Subject: [PATCH 360/606] misc: pci_endpoint_test: Fix displaying 'irq_type' after 'request_irq' error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 919d14603dab6a9cf03ebbeb2cfa556df48737c8 upstream. There are two variables that indicate the interrupt type to be used in the next test execution, global "irq_type" and "test->irq_type". The former is referenced from pci_endpoint_test_get_irq() to preserve the current type for ioctl(PCITEST_GET_IRQTYPE). In the pci_endpoint_test_request_irq(), since this global variable is referenced when an error occurs, the unintended error message is displayed. For example, after running "pcitest -i 2", the following message shows "MSI 3" even if the current IRQ type becomes "MSI-X": pci-endpoint-test 0000:01:00.0: Failed to request IRQ 30 for MSI 3 SET IRQ TYPE TO MSI-X: NOT OKAY Fix this issue by using "test->irq_type" instead of global "irq_type". Cc: stable@vger.kernel.org Fixes: b2ba9225e031 ("misc: pci_endpoint_test: Avoid using module parameter to determine irqtype") Reviewed-by: Manivannan Sadhasivam Signed-off-by: Kunihiko Hayashi Link: https://lore.kernel.org/r/20250225110252.28866-4-hayashi.kunihiko@socionext.com [kwilczynski: commit log] Signed-off-by: Krzysztof Wilczyński Signed-off-by: Kunihiko Hayashi Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pci_endpoint_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index cd5af3e55f28..a5d13da45789 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -243,7 +243,7 @@ static bool pci_endpoint_test_request_irq(struct pci_endpoint_test *test) return true; fail: - switch (irq_type) { + switch (test->irq_type) { case IRQ_TYPE_LEGACY: dev_err(dev, "Failed to request IRQ %d for Legacy\n", pci_irq_vector(pdev, i)); From da210d4f884fea3c6da9645898904ce21ba7e6fe Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Tue, 25 Feb 2025 20:02:50 +0900 Subject: [PATCH 361/606] misc: pci_endpoint_test: Fix 'irq_type' to convey the correct type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit baaef0a274cfb75f9b50eab3ef93205e604f662c upstream. There are two variables that indicate the interrupt type to be used in the next test execution, "irq_type" as global and "test->irq_type". The global is referenced from pci_endpoint_test_get_irq() to preserve the current type for ioctl(PCITEST_GET_IRQTYPE). The type set in this function isn't reflected in the global "irq_type", so ioctl(PCITEST_GET_IRQTYPE) returns the previous type. As a result, the wrong type is displayed in old version of "pcitest" as follows: - Result of running "pcitest -i 0" SET IRQ TYPE TO LEGACY: OKAY - Result of running "pcitest -I" GET IRQ TYPE: MSI Whereas running the new version of "pcitest" in kselftest results in an error as follows: # RUN pci_ep_basic.LEGACY_IRQ_TEST ... # pci_endpoint_test.c:104:LEGACY_IRQ_TEST:Expected 0 (0) == ret (1) # pci_endpoint_test.c:104:LEGACY_IRQ_TEST:Can't get Legacy IRQ type Fix this issue by propagating the current type to the global "irq_type". Fixes: b2ba9225e031 ("misc: pci_endpoint_test: Avoid using module parameter to determine irqtype") Signed-off-by: Kunihiko Hayashi [kwilczynski: commit log] Signed-off-by: Krzysztof Wilczyński Reviewed-by: Niklas Cassel Reviewed-by: Manivannan Sadhasivam Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250225110252.28866-5-hayashi.kunihiko@socionext.com Signed-off-by: Kunihiko Hayashi Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pci_endpoint_test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index a5d13da45789..c95a2b0b9012 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -711,6 +711,7 @@ static bool pci_endpoint_test_set_irq(struct pci_endpoint_test *test, if (!pci_endpoint_test_request_irq(test)) goto err; + irq_type = test->irq_type; return true; err: From 4f687721a981a657aef002ffb8aa7329e1950974 Mon Sep 17 00:00:00 2001 From: Piotr Jaroszynski Date: Tue, 4 Mar 2025 00:51:27 -0800 Subject: [PATCH 362/606] Fix mmu notifiers for range-based invalidates commit f7edb07ad7c66eab3dce57384f33b9799d579133 upstream. Update the __flush_tlb_range_op macro not to modify its parameters as these are unexepcted semantics. In practice, this fixes the call to mmu_notifier_arch_invalidate_secondary_tlbs() in __flush_tlb_range_nosync() to use the correct range instead of an empty range with start=end. The empty range was (un)lucky as it results in taking the invalidate-all path that doesn't cause correctness issues, but can certainly result in suboptimal perf. This has been broken since commit 6bbd42e2df8f ("mmu_notifiers: call invalidate_range() when invalidating TLBs") when the call to the notifiers was added to __flush_tlb_range(). It predates the addition of the __flush_tlb_range_op() macro from commit 360839027a6e ("arm64: tlb: Refactor the core flush algorithm of __flush_tlb_range") that made the bug hard to spot. Fixes: 6bbd42e2df8f ("mmu_notifiers: call invalidate_range() when invalidating TLBs") Signed-off-by: Piotr Jaroszynski Cc: Catalin Marinas Cc: Will Deacon Cc: Robin Murphy Cc: Alistair Popple Cc: Raghavendra Rao Ananta Cc: SeongJae Park Cc: Jason Gunthorpe Cc: John Hubbard Cc: Nicolin Chen Cc: linux-arm-kernel@lists.infradead.org Cc: iommu@lists.linux.dev Cc: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org Cc: stable@vger.kernel.org Reviewed-by: Catalin Marinas Reviewed-by: Alistair Popple Link: https://lore.kernel.org/r/20250304085127.2238030-1-pjaroszynski@nvidia.com Signed-off-by: Will Deacon [will: Resolve conflicts due to lack of LPA2 support] Signed-off-by: Will Deacon Signed-off-by: Greg Kroah-Hartman --- arch/arm64/include/asm/tlbflush.h | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h index b73baaf8ae47..d37db2f7a54c 100644 --- a/arch/arm64/include/asm/tlbflush.h +++ b/arch/arm64/include/asm/tlbflush.h @@ -369,31 +369,33 @@ static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch) #define __flush_tlb_range_op(op, start, pages, stride, \ asid, tlb_level, tlbi_user) \ do { \ + typeof(start) __flush_start = start; \ + typeof(pages) __flush_pages = pages; \ int num = 0; \ int scale = 3; \ unsigned long addr; \ \ - while (pages > 0) { \ + while (__flush_pages > 0) { \ if (!system_supports_tlb_range() || \ - pages == 1) { \ - addr = __TLBI_VADDR(start, asid); \ + __flush_pages == 1) { \ + addr = __TLBI_VADDR(__flush_start, asid); \ __tlbi_level(op, addr, tlb_level); \ if (tlbi_user) \ __tlbi_user_level(op, addr, tlb_level); \ - start += stride; \ - pages -= stride >> PAGE_SHIFT; \ + __flush_start += stride; \ + __flush_pages -= stride >> PAGE_SHIFT; \ continue; \ } \ \ - num = __TLBI_RANGE_NUM(pages, scale); \ + num = __TLBI_RANGE_NUM(__flush_pages, scale); \ if (num >= 0) { \ - addr = __TLBI_VADDR_RANGE(start, asid, scale, \ - num, tlb_level); \ + addr = __TLBI_VADDR_RANGE(__flush_start, asid, \ + scale, num, tlb_level); \ __tlbi(r##op, addr); \ if (tlbi_user) \ __tlbi_user(r##op, addr); \ - start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \ - pages -= __TLBI_RANGE_PAGES(num, scale); \ + __flush_start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \ + __flush_pages -= __TLBI_RANGE_PAGES(num, scale);\ } \ scale--; \ } \ From dafbcfb8ffe6c6e4021f1d784d0a9cf62a894697 Mon Sep 17 00:00:00 2001 From: Hamza Mahfooz Date: Mon, 9 Dec 2024 13:20:39 -0500 Subject: [PATCH 363/606] efi/libstub: Bump up EFI_MMAP_NR_SLACK_SLOTS to 32 commit ec4696925da6b9baec38345184403ce9e29a2e48 upstream. Recent platforms require more slack slots than the current value of EFI_MMAP_NR_SLACK_SLOTS, otherwise they fail to boot. The current workaround is to append `efi=disable_early_pci_dma` to the kernel's cmdline. So, bump up EFI_MMAP_NR_SLACK_SLOTS to 32 to allow those platforms to boot with the aforementioned workaround. Signed-off-by: Hamza Mahfooz Acked-by: Ard Biesheuvel Reviewed-by: Allen Pais Signed-off-by: Ard Biesheuvel Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/efi/libstub/efistub.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index fc18fd649ed7..5ecb9d3f3e9f 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -171,7 +171,7 @@ void efi_set_u64_split(u64 data, u32 *lo, u32 *hi) * the EFI memory map. Other related structures, e.g. x86 e820ext, need * to factor in this headroom requirement as well. */ -#define EFI_MMAP_NR_SLACK_SLOTS 8 +#define EFI_MMAP_NR_SLACK_SLOTS 32 typedef struct efi_generic_dev_path efi_device_path_protocol_t; From fa1103f21b7ad0e907b1c3e618c1a8e10a22d160 Mon Sep 17 00:00:00 2001 From: Roger Pau Monne Date: Thu, 25 Jul 2024 09:31:14 +0200 Subject: [PATCH 364/606] x86/xen: move xen_reserve_extra_memory() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit fc05ea89c9ab45e70cb73e70bc0b9cdd403e0ee1 upstream. In preparation for making the function static. No functional change. Signed-off-by: Roger Pau Monné Reviewed-by: Juergen Gross Message-ID: <20240725073116.14626-2-roger.pau@citrix.com> Signed-off-by: Juergen Gross [ Stable backport - move the code as it exists ] Signed-off-by: Jason Andryuk Signed-off-by: Greg Kroah-Hartman --- arch/x86/xen/enlighten_pvh.c | 82 ++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/arch/x86/xen/enlighten_pvh.c b/arch/x86/xen/enlighten_pvh.c index 60b358c2f434..89984018141c 100644 --- a/arch/x86/xen/enlighten_pvh.c +++ b/arch/x86/xen/enlighten_pvh.c @@ -26,47 +26,6 @@ bool __ro_after_init xen_pvh; EXPORT_SYMBOL_GPL(xen_pvh); -void __init xen_pvh_init(struct boot_params *boot_params) -{ - xen_pvh = 1; - xen_domain_type = XEN_HVM_DOMAIN; - xen_start_flags = pvh_start_info.flags; - - if (xen_initial_domain()) - x86_init.oem.arch_setup = xen_add_preferred_consoles; - x86_init.oem.banner = xen_banner; - - xen_efi_init(boot_params); - - if (xen_initial_domain()) { - struct xen_platform_op op = { - .cmd = XENPF_get_dom0_console, - }; - int ret = HYPERVISOR_platform_op(&op); - - if (ret > 0) - xen_init_vga(&op.u.dom0_console, - min(ret * sizeof(char), - sizeof(op.u.dom0_console)), - &boot_params->screen_info); - } -} - -void __init mem_map_via_hcall(struct boot_params *boot_params_p) -{ - struct xen_memory_map memmap; - int rc; - - memmap.nr_entries = ARRAY_SIZE(boot_params_p->e820_table); - set_xen_guest_handle(memmap.buffer, boot_params_p->e820_table); - rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap); - if (rc) { - xen_raw_printk("XENMEM_memory_map failed (%d)\n", rc); - BUG(); - } - boot_params_p->e820_entries = memmap.nr_entries; -} - /* * Reserve e820 UNUSABLE regions to inflate the memory balloon. * @@ -133,3 +92,44 @@ void __init xen_reserve_extra_memory(struct boot_params *bootp) xen_add_extra_mem(PFN_UP(e->addr), pages); } } + +void __init xen_pvh_init(struct boot_params *boot_params) +{ + xen_pvh = 1; + xen_domain_type = XEN_HVM_DOMAIN; + xen_start_flags = pvh_start_info.flags; + + if (xen_initial_domain()) + x86_init.oem.arch_setup = xen_add_preferred_consoles; + x86_init.oem.banner = xen_banner; + + xen_efi_init(boot_params); + + if (xen_initial_domain()) { + struct xen_platform_op op = { + .cmd = XENPF_get_dom0_console, + }; + int ret = HYPERVISOR_platform_op(&op); + + if (ret > 0) + xen_init_vga(&op.u.dom0_console, + min(ret * sizeof(char), + sizeof(op.u.dom0_console)), + &boot_params->screen_info); + } +} + +void __init mem_map_via_hcall(struct boot_params *boot_params_p) +{ + struct xen_memory_map memmap; + int rc; + + memmap.nr_entries = ARRAY_SIZE(boot_params_p->e820_table); + set_xen_guest_handle(memmap.buffer, boot_params_p->e820_table); + rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap); + if (rc) { + xen_raw_printk("XENMEM_memory_map failed (%d)\n", rc); + BUG(); + } + boot_params_p->e820_entries = memmap.nr_entries; +} From e5f0581ecb2ab22c8118204a9d5ca5dbd05f606e Mon Sep 17 00:00:00 2001 From: Roger Pau Monne Date: Thu, 25 Jul 2024 09:31:15 +0200 Subject: [PATCH 365/606] x86/xen: fix memblock_reserve() usage on PVH MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 4c006734898a113a64a528027274a571b04af95a upstream. The current usage of memblock_reserve() in init_pvh_bootparams() is done before the .bss is zeroed, and that used to be fine when memblock_reserved_init_regions implicitly ended up in the .meminit.data section. However after commit 73db3abdca58c memblock_reserved_init_regions ends up in the .bss section, thus breaking it's usage before the .bss is cleared. Move and rename the call to xen_reserve_extra_memory() so it's done in the x86_init.oem.arch_setup hook, which gets executed after the .bss has been zeroed, but before calling e820__memory_setup(). Fixes: 73db3abdca58c ("init/modpost: conditionally check section mismatch to __meminit*") Signed-off-by: Roger Pau Monné Reviewed-by: Juergen Gross Message-ID: <20240725073116.14626-3-roger.pau@citrix.com> Signed-off-by: Juergen Gross [ Context fixup for hypercall_page removal ] Signed-off-by: Jason Andryuk Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/xen/hypervisor.h | 5 ----- arch/x86/platform/pvh/enlighten.c | 3 --- arch/x86/xen/enlighten_pvh.c | 15 ++++++++++++--- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/xen/hypervisor.h index 64fbd2dbc5b7..a9088250770f 100644 --- a/arch/x86/include/asm/xen/hypervisor.h +++ b/arch/x86/include/asm/xen/hypervisor.h @@ -62,11 +62,6 @@ void xen_arch_unregister_cpu(int num); #ifdef CONFIG_PVH void __init xen_pvh_init(struct boot_params *boot_params); void __init mem_map_via_hcall(struct boot_params *boot_params_p); -#ifdef CONFIG_XEN_PVH -void __init xen_reserve_extra_memory(struct boot_params *bootp); -#else -static inline void xen_reserve_extra_memory(struct boot_params *bootp) { } -#endif #endif /* Lazy mode for batching updates / context switch */ diff --git a/arch/x86/platform/pvh/enlighten.c b/arch/x86/platform/pvh/enlighten.c index a12117f3d4de..00a92cb2c814 100644 --- a/arch/x86/platform/pvh/enlighten.c +++ b/arch/x86/platform/pvh/enlighten.c @@ -74,9 +74,6 @@ static void __init init_pvh_bootparams(bool xen_guest) } else xen_raw_printk("Warning: Can fit ISA range into e820\n"); - if (xen_guest) - xen_reserve_extra_memory(&pvh_bootparams); - pvh_bootparams.hdr.cmd_line_ptr = pvh_start_info.cmdline_paddr; diff --git a/arch/x86/xen/enlighten_pvh.c b/arch/x86/xen/enlighten_pvh.c index 89984018141c..ac0a8adb2c50 100644 --- a/arch/x86/xen/enlighten_pvh.c +++ b/arch/x86/xen/enlighten_pvh.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -40,8 +41,9 @@ EXPORT_SYMBOL_GPL(xen_pvh); * hypervisor should notify us which memory ranges are suitable for creating * foreign mappings, but that's not yet implemented. */ -void __init xen_reserve_extra_memory(struct boot_params *bootp) +static void __init pvh_reserve_extra_memory(void) { + struct boot_params *bootp = &boot_params; unsigned int i, ram_pages = 0, extra_pages; for (i = 0; i < bootp->e820_entries; i++) { @@ -93,14 +95,21 @@ void __init xen_reserve_extra_memory(struct boot_params *bootp) } } +static void __init pvh_arch_setup(void) +{ + pvh_reserve_extra_memory(); + + if (xen_initial_domain()) + xen_add_preferred_consoles(); +} + void __init xen_pvh_init(struct boot_params *boot_params) { xen_pvh = 1; xen_domain_type = XEN_HVM_DOMAIN; xen_start_flags = pvh_start_info.flags; - if (xen_initial_domain()) - x86_init.oem.arch_setup = xen_add_preferred_consoles; + x86_init.oem.arch_setup = pvh_arch_setup; x86_init.oem.banner = xen_banner; xen_efi_init(boot_params); From 29f040d4efb08497165a695f40d7049bd35f846b Mon Sep 17 00:00:00 2001 From: Vishal Annapurve Date: Fri, 28 Feb 2025 01:44:15 +0000 Subject: [PATCH 366/606] x86/tdx: Fix arch_safe_halt() execution for TDX VMs commit 9f98a4f4e7216dbe366010b4cdcab6b220f229c4 upstream. Direct HLT instruction execution causes #VEs for TDX VMs which is routed to hypervisor via TDCALL. If HLT is executed in STI-shadow, resulting #VE handler will enable interrupts before TDCALL is routed to hypervisor leading to missed wakeup events, as current TDX spec doesn't expose interruptibility state information to allow #VE handler to selectively enable interrupts. Commit bfe6ed0c6727 ("x86/tdx: Add HLT support for TDX guests") prevented the idle routines from executing HLT instruction in STI-shadow. But it missed the paravirt routine which can be reached via this path as an example: kvm_wait() => safe_halt() => raw_safe_halt() => arch_safe_halt() => irq.safe_halt() => pv_native_safe_halt() To reliably handle arch_safe_halt() for TDX VMs, introduce explicit dependency on CONFIG_PARAVIRT and override paravirt halt()/safe_halt() routines with TDX-safe versions that execute direct TDCALL and needed interrupt flag updates. Executing direct TDCALL brings in additional benefit of avoiding HLT related #VEs altogether. As tested by Ryan Afranji: "Tested with the specjbb2015 benchmark. It has heavy lock contention which leads to many halt calls. TDX VMs suffered a poor score before this patchset. Verified the major performance improvement with this patchset applied." Fixes: bfe6ed0c6727 ("x86/tdx: Add HLT support for TDX guests") Signed-off-by: Vishal Annapurve Signed-off-by: Ingo Molnar Reviewed-by: Kirill A. Shutemov Tested-by: Ryan Afranji Cc: Andy Lutomirski Cc: Brian Gerst Cc: Juergen Gross Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Josh Poimboeuf Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250228014416.3925664-3-vannapurve@google.com Signed-off-by: Greg Kroah-Hartman --- arch/x86/Kconfig | 1 + arch/x86/coco/tdx/tdx.c | 26 +++++++++++++++++++++++++- arch/x86/include/asm/tdx.h | 4 ++-- arch/x86/kernel/process.c | 2 +- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index a0af6e8d584b..d874ea22512b 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -881,6 +881,7 @@ config INTEL_TDX_GUEST depends on X86_64 && CPU_SUP_INTEL depends on X86_X2APIC depends on EFI_STUB + depends on PARAVIRT select ARCH_HAS_CC_PLATFORM select X86_MEM_ENCRYPT select X86_MCE diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c index 2f67e196a2ea..98d0ee9600eb 100644 --- a/arch/x86/coco/tdx/tdx.c +++ b/arch/x86/coco/tdx/tdx.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -334,7 +335,7 @@ static int handle_halt(struct ve_info *ve) return ve_instr_len(ve); } -void __cpuidle tdx_safe_halt(void) +void __cpuidle tdx_halt(void) { const bool irq_disabled = false; @@ -345,6 +346,16 @@ void __cpuidle tdx_safe_halt(void) WARN_ONCE(1, "HLT instruction emulation failed\n"); } +static void __cpuidle tdx_safe_halt(void) +{ + tdx_halt(); + /* + * "__cpuidle" section doesn't support instrumentation, so stick + * with raw_* variant that avoids tracing hooks. + */ + raw_local_irq_enable(); +} + static int read_msr(struct pt_regs *regs, struct ve_info *ve) { struct tdx_hypercall_args args = { @@ -888,6 +899,19 @@ void __init tdx_early_init(void) x86_platform.guest.enc_cache_flush_required = tdx_cache_flush_required; x86_platform.guest.enc_tlb_flush_required = tdx_tlb_flush_required; + /* + * Avoid "sti;hlt" execution in TDX guests as HLT induces a #VE that + * will enable interrupts before HLT TDCALL invocation if executed + * in STI-shadow, possibly resulting in missed wakeup events. + * + * Modify all possible HLT execution paths to use TDX specific routines + * that directly execute TDCALL and toggle the interrupt state as + * needed after TDCALL completion. This also reduces HLT related #VEs + * in addition to having a reliable halt logic execution. + */ + pv_ops.irq.safe_halt = tdx_safe_halt; + pv_ops.irq.halt = tdx_halt; + /* * TDX intercepts the RDMSR to read the X2APIC ID in the parallel * bringup low level code. That raises #VE which cannot be handled diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 603e6d1e9d4a..c632f09f0c97 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -46,7 +46,7 @@ void tdx_get_ve_info(struct ve_info *ve); bool tdx_handle_virt_exception(struct pt_regs *regs, struct ve_info *ve); -void tdx_safe_halt(void); +void tdx_halt(void); bool tdx_early_handle_ve(struct pt_regs *regs); @@ -55,7 +55,7 @@ int tdx_mcall_get_report0(u8 *reportdata, u8 *tdreport); #else static inline void tdx_early_init(void) { }; -static inline void tdx_safe_halt(void) { }; +static inline void tdx_halt(void) { }; static inline bool tdx_early_handle_ve(struct pt_regs *regs) { return false; } diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index bbe11363550b..419353904173 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -955,7 +955,7 @@ void select_idle_routine(const struct cpuinfo_x86 *c) static_call_update(x86_idle, mwait_idle); } else if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) { pr_info("using TDX aware idle routine\n"); - static_call_update(x86_idle, tdx_safe_halt); + static_call_update(x86_idle, tdx_halt); } else static_call_update(x86_idle, default_idle); } From 6f8d51051d8039c3a565e0843fbdfd009f8a1d42 Mon Sep 17 00:00:00 2001 From: Maksim Davydov Date: Wed, 15 Jan 2025 16:17:04 +0300 Subject: [PATCH 367/606] x86/split_lock: Fix the delayed detection logic commit c929d08df8bee855528b9d15b853c892c54e1eee upstream. If the warning mode with disabled mitigation mode is used, then on each CPU where the split lock occurred detection will be disabled in order to make progress and delayed work will be scheduled, which then will enable detection back. Now it turns out that all CPUs use one global delayed work structure. This leads to the fact that if a split lock occurs on several CPUs at the same time (within 2 jiffies), only one CPU will schedule delayed work, but the rest will not. The return value of schedule_delayed_work_on() would have shown this, but it is not checked in the code. A diagram that can help to understand the bug reproduction: - sld_update_msr() enables/disables SLD on both CPUs on the same core - schedule_delayed_work_on() internally checks WORK_STRUCT_PENDING_BIT. If a work has the 'pending' status, then schedule_delayed_work_on() will return an error code and, most importantly, the work will not be placed in the workqueue. Let's say we have a multicore system on which split_lock_mitigate=0 and a multithreaded application is running that calls splitlock in multiple threads. Due to the fact that sld_update_msr() affects the entire core (both CPUs), we will consider 2 CPUs from different cores. Let the 2 threads of this application schedule to CPU0 (core 0) and to CPU 2 (core 1), then: | || | | CPU 0 (core 0) || CPU 2 (core 1) | |_________________________________||___________________________________| | || | | 1) SPLIT LOCK occured || | | || | | 2) split_lock_warn() || | | || | | 3) sysctl_sld_mitigate == 0 || | | (work = &sl_reenable) || | | || | | 4) schedule_delayed_work_on() || | | (reenable will be called || | | after 2 jiffies on CPU 0) || | | || | | 5) disable SLD for core 0 || | | || | | ------------------------- || | | || | | || 6) SPLIT LOCK occured | | || | | || 7) split_lock_warn() | | || | | || 8) sysctl_sld_mitigate == 0 | | || (work = &sl_reenable, | | || the same address as in 3) ) | | || | | 2 jiffies || 9) schedule_delayed_work_on() | | || fials because the work is in | | || the pending state since 4). | | || The work wasn't placed to the | | || workqueue. reenable won't be | | || called on CPU 2 | | || | | || 10) disable SLD for core 0 | | || | | || From now on SLD will | | || never be reenabled on core 1 | | || | | ------------------------- || | | || | | 11) enable SLD for core 0 by || | | __split_lock_reenable || | | || | If the application threads can be scheduled to all processor cores, then over time there will be only one core left, on which SLD will be enabled and split lock will be able to be detected; and on all other cores SLD will be disabled all the time. Most likely, this bug has not been noticed for so long because sysctl_sld_mitigate default value is 1, and in this case a semaphore is used that does not allow 2 different cores to have SLD disabled at the same time, that is, strictly only one work is placed in the workqueue. In order to fix the warning mode with disabled mitigation mode, delayed work has to be per-CPU. Implement it. Fixes: 727209376f49 ("x86/split_lock: Add sysctl to control the misery mode") Signed-off-by: Maksim Davydov Signed-off-by: Ingo Molnar Tested-by: Guilherme G. Piccoli Cc: Thomas Gleixner Cc: Ravi Bangoria Cc: Tom Lendacky Link: https://lore.kernel.org/r/20250115131704.132609-1-davydov-max@yandex-team.ru Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/intel.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 38eeff91109f..6c0e0619e6d3 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -1168,7 +1168,13 @@ static void __split_lock_reenable(struct work_struct *work) { sld_update_msr(true); } -static DECLARE_DELAYED_WORK(sl_reenable, __split_lock_reenable); +/* + * In order for each CPU to schedule its delayed work independently of the + * others, delayed work struct must be per-CPU. This is not required when + * sysctl_sld_mitigate is enabled because of the semaphore that limits + * the number of simultaneously scheduled delayed works to 1. + */ +static DEFINE_PER_CPU(struct delayed_work, sl_reenable); /* * If a CPU goes offline with pending delayed work to re-enable split lock @@ -1189,7 +1195,7 @@ static int splitlock_cpu_offline(unsigned int cpu) static void split_lock_warn(unsigned long ip) { - struct delayed_work *work; + struct delayed_work *work = NULL; int cpu; if (!current->reported_split_lock) @@ -1211,11 +1217,17 @@ static void split_lock_warn(unsigned long ip) if (down_interruptible(&buslock_sem) == -EINTR) return; work = &sl_reenable_unlock; - } else { - work = &sl_reenable; } cpu = get_cpu(); + + if (!work) { + work = this_cpu_ptr(&sl_reenable); + /* Deferred initialization of per-CPU struct */ + if (!work->work.func) + INIT_DELAYED_WORK(work, __split_lock_reenable); + } + schedule_delayed_work_on(cpu, work, 2); /* Disable split lock detection on this CPU to make progress */ From 427036030f4d796533dcadba9b845896cb6c10a7 Mon Sep 17 00:00:00 2001 From: "Chunguang.xu" Date: Tue, 3 Dec 2024 11:34:41 +0800 Subject: [PATCH 368/606] nvme-rdma: unquiesce admin_q before destroy it commit 5858b687559809f05393af745cbadf06dee61295 upstream. Kernel will hang on destroy admin_q while we create ctrl failed, such as following calltrace: PID: 23644 TASK: ff2d52b40f439fc0 CPU: 2 COMMAND: "nvme" #0 [ff61d23de260fb78] __schedule at ffffffff8323bc15 #1 [ff61d23de260fc08] schedule at ffffffff8323c014 #2 [ff61d23de260fc28] blk_mq_freeze_queue_wait at ffffffff82a3dba1 #3 [ff61d23de260fc78] blk_freeze_queue at ffffffff82a4113a #4 [ff61d23de260fc90] blk_cleanup_queue at ffffffff82a33006 #5 [ff61d23de260fcb0] nvme_rdma_destroy_admin_queue at ffffffffc12686ce #6 [ff61d23de260fcc8] nvme_rdma_setup_ctrl at ffffffffc1268ced #7 [ff61d23de260fd28] nvme_rdma_create_ctrl at ffffffffc126919b #8 [ff61d23de260fd68] nvmf_dev_write at ffffffffc024f362 #9 [ff61d23de260fe38] vfs_write at ffffffff827d5f25 RIP: 00007fda7891d574 RSP: 00007ffe2ef06958 RFLAGS: 00000202 RAX: ffffffffffffffda RBX: 000055e8122a4d90 RCX: 00007fda7891d574 RDX: 000000000000012b RSI: 000055e8122a4d90 RDI: 0000000000000004 RBP: 00007ffe2ef079c0 R8: 000000000000012b R9: 000055e8122a4d90 R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000004 R13: 000055e8122923c0 R14: 000000000000012b R15: 00007fda78a54500 ORIG_RAX: 0000000000000001 CS: 0033 SS: 002b This due to we have quiesced admi_q before cancel requests, but forgot to unquiesce before destroy it, as a result we fail to drain the pending requests, and hang on blk_mq_freeze_queue_wait() forever. Here try to reuse nvme_rdma_teardown_admin_queue() to fix this issue and simplify the code. Fixes: 958dc1d32c80 ("nvme-rdma: add clean action for failed reconnection") Reported-by: Yingfu.zhou Signed-off-by: Chunguang.xu Signed-off-by: Yue.zhao Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke Signed-off-by: Keith Busch [Minor context change fixed] Signed-off-by: Feng Liu Signed-off-by: He Zhe Signed-off-by: Greg Kroah-Hartman --- drivers/nvme/host/rdma.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index c04317a966b3..055b95d2ce93 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -1083,13 +1083,7 @@ destroy_io: nvme_rdma_free_io_queues(ctrl); } destroy_admin: - nvme_quiesce_admin_queue(&ctrl->ctrl); - blk_sync_queue(ctrl->ctrl.admin_q); - nvme_rdma_stop_queue(&ctrl->queues[0]); - nvme_cancel_admin_tagset(&ctrl->ctrl); - if (new) - nvme_remove_admin_tag_set(&ctrl->ctrl); - nvme_rdma_destroy_admin_queue(ctrl); + nvme_rdma_teardown_admin_queue(ctrl, new); return ret; } From 1f1feff02e9da0dd0cdb195c428c42b5f9b6c771 Mon Sep 17 00:00:00 2001 From: Nathan Lynch Date: Thu, 30 May 2024 19:44:12 -0500 Subject: [PATCH 369/606] powerpc/rtas: Prevent Spectre v1 gadget construction in sys_rtas() commit 0974d03eb479384466d828d65637814bee6b26d7 upstream. Smatch warns: arch/powerpc/kernel/rtas.c:1932 __do_sys_rtas() warn: potential spectre issue 'args.args' [r] (local cap) The 'nargs' and 'nret' locals come directly from a user-supplied buffer and are used as indexes into a small stack-based array and as inputs to copy_to_user() after they are subject to bounds checks. Use array_index_nospec() after the bounds checks to clamp these values for speculative execution. Signed-off-by: Nathan Lynch Reported-by: Breno Leitao Reviewed-by: Breno Leitao Signed-off-by: Michael Ellerman Link: https://msgid.link/20240530-sys_rtas-nargs-nret-v1-1-129acddd4d89@linux.ibm.com [Minor context change fixed] Signed-off-by: Cliff Liu Signed-off-by: He Zhe Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/rtas.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 46b9476d7582..dc294c95da21 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -1839,6 +1840,9 @@ SYSCALL_DEFINE1(rtas, struct rtas_args __user *, uargs) || nargs + nret > ARRAY_SIZE(args.args)) return -EINVAL; + nargs = array_index_nospec(nargs, ARRAY_SIZE(args.args)); + nret = array_index_nospec(nret, ARRAY_SIZE(args.args) - nargs); + /* Copy in args. */ if (copy_from_user(args.args, uargs->args, nargs * sizeof(rtas_arg_t)) != 0) From 37491e1dbb50fa3d37c0a4e33965d053ed47da0c Mon Sep 17 00:00:00 2001 From: Yuli Wang Date: Sat, 8 Mar 2025 13:51:32 +0800 Subject: [PATCH 370/606] LoongArch: Eliminate superfluous get_numa_distances_cnt() commit a0d3c8bcb9206ac207c7ad3182027c6b0a1319bb upstream. In LoongArch, get_numa_distances_cnt() isn't in use, resulting in a compiler warning. Fix follow errors with clang-18 when W=1e: arch/loongarch/kernel/acpi.c:259:28: error: unused function 'get_numa_distances_cnt' [-Werror,-Wunused-function] 259 | static inline unsigned int get_numa_distances_cnt(struct acpi_table_slit *slit) | ^~~~~~~~~~~~~~~~~~~~~~ 1 error generated. Link: https://lore.kernel.org/all/Z7bHPVUH4lAezk0E@kernel.org/ Signed-off-by: Yuli Wang Signed-off-by: Huacai Chen Signed-off-by: Greg Kroah-Hartman --- arch/loongarch/kernel/acpi.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/arch/loongarch/kernel/acpi.c b/arch/loongarch/kernel/acpi.c index 55d6a48c76a8..1f529b13490b 100644 --- a/arch/loongarch/kernel/acpi.c +++ b/arch/loongarch/kernel/acpi.c @@ -216,18 +216,6 @@ static __init int setup_node(int pxm) return acpi_map_pxm_to_node(pxm); } -/* - * Callback for SLIT parsing. pxm_to_node() returns NUMA_NO_NODE for - * I/O localities since SRAT does not list them. I/O localities are - * not supported at this point. - */ -unsigned int numa_distance_cnt; - -static inline unsigned int get_numa_distances_cnt(struct acpi_table_slit *slit) -{ - return slit->locality_count; -} - void __init numa_set_distance(int from, int to, int distance) { if ((u8)distance != distance || (from == to && distance != LOCAL_DISTANCE)) { From 0e66fd8e5a2e45c7dacfc9178ba702153f4a61a8 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 11 Nov 2024 14:08:06 +0300 Subject: [PATCH 371/606] usb: typec: fix potential array underflow in ucsi_ccg_sync_control() commit e56aac6e5a25630645607b6856d4b2a17b2311a5 upstream. The "command" variable can be controlled by the user via debugfs. The worry is that if con_index is zero then "&uc->ucsi->connector[con_index - 1]" would be an array underflow. Fixes: 170a6726d0e2 ("usb: typec: ucsi: add support for separate DP altmode devices") Signed-off-by: Dan Carpenter Reviewed-by: Heikki Krogerus Link: https://lore.kernel.org/r/c69ef0b3-61b0-4dde-98dd-97b97f81d912@stanley.mountain Signed-off-by: Greg Kroah-Hartman [Minor context change fixed. 13f2ec3115c8 ("usb: typec: ucsi: simplify command sending API") rename ucsi_ccg_sync_write to ucsi_ccg_sync_control in v6.11, so this patch is applied in ucsi_ccg_sync_write in v6.6.] Signed-off-by: Bin Lan Signed-off-by: He Zhe Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/ucsi/ucsi_ccg.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c index 7c7f388aac96..3ef02d35bfbe 100644 --- a/drivers/usb/typec/ucsi/ucsi_ccg.c +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c @@ -585,6 +585,10 @@ static int ucsi_ccg_sync_write(struct ucsi *ucsi, unsigned int offset, uc->has_multiple_dp) { con_index = (uc->last_cmd_sent >> 16) & UCSI_CMD_CONNECTOR_MASK; + if (con_index == 0) { + ret = -EINVAL; + goto unlock; + } con = &uc->ucsi->connector[con_index - 1]; ucsi_ccg_update_set_new_cam_cmd(uc, con, (u64 *)val); } @@ -600,6 +604,7 @@ static int ucsi_ccg_sync_write(struct ucsi *ucsi, unsigned int offset, err_clear_bit: clear_bit(DEV_CMD_PENDING, &uc->flags); pm_runtime_put_sync(uc->dev); +unlock: mutex_unlock(&uc->lock); return ret; From e8336d3c9ab7477e5852573ce49a7700d315f240 Mon Sep 17 00:00:00 2001 From: GONG Ruiqi Date: Tue, 7 Jan 2025 09:57:50 +0800 Subject: [PATCH 372/606] usb: typec: fix pm usage counter imbalance in ucsi_ccg_sync_control() commit b0e525d7a22ea350e75e2aec22e47fcfafa4cacd upstream. The error handling for the case `con_index == 0` should involve dropping the pm usage counter, as ucsi_ccg_sync_control() gets it at the beginning. Fix it. Cc: stable Fixes: e56aac6e5a25 ("usb: typec: fix potential array underflow in ucsi_ccg_sync_control()") Signed-off-by: GONG Ruiqi Reviewed-by: Dan Carpenter Reviewed-by: Heikki Krogerus Link: https://lore.kernel.org/r/20250107015750.2778646-1-gongruiqi1@huawei.com Signed-off-by: Greg Kroah-Hartman [Minor context change fixed] Signed-off-by: Bin Lan Signed-off-by: He Zhe Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/ucsi/ucsi_ccg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c index 3ef02d35bfbe..35f4c4482fca 100644 --- a/drivers/usb/typec/ucsi/ucsi_ccg.c +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c @@ -587,7 +587,7 @@ static int ucsi_ccg_sync_write(struct ucsi *ucsi, unsigned int offset, UCSI_CMD_CONNECTOR_MASK; if (con_index == 0) { ret = -EINVAL; - goto unlock; + goto err_put; } con = &uc->ucsi->connector[con_index - 1]; ucsi_ccg_update_set_new_cam_cmd(uc, con, (u64 *)val); @@ -603,8 +603,8 @@ static int ucsi_ccg_sync_write(struct ucsi *ucsi, unsigned int offset, err_clear_bit: clear_bit(DEV_CMD_PENDING, &uc->flags); +err_put: pm_runtime_put_sync(uc->dev); -unlock: mutex_unlock(&uc->lock); return ret; From 84464db2ec2a55b9313d5f264da196a37ec80994 Mon Sep 17 00:00:00 2001 From: Boris Burkov Date: Fri, 19 Jul 2024 16:49:08 -0700 Subject: [PATCH 373/606] btrfs: fix qgroup reserve leaks in cow_file_range commit 30479f31d44d47ed00ae0c7453d9b253537005b2 upstream. In the buffered write path, the dirty page owns the qgroup reserve until it creates an ordered_extent. Therefore, any errors that occur before the ordered_extent is created must free that reservation, or else the space is leaked. The fstest generic/475 exercises various IO error paths, and is able to trigger errors in cow_file_range where we fail to get to allocating the ordered extent. Note that because we *do* clear delalloc, we are likely to remove the inode from the delalloc list, so the inodes/pages to not have invalidate/launder called on them in the commit abort path. This results in failures at the unmount stage of the test that look like: BTRFS: error (device dm-8 state EA) in cleanup_transaction:2018: errno=-5 IO failure BTRFS: error (device dm-8 state EA) in btrfs_replace_file_extents:2416: errno=-5 IO failure BTRFS warning (device dm-8 state EA): qgroup 0/5 has unreleased space, type 0 rsv 28672 ------------[ cut here ]------------ WARNING: CPU: 3 PID: 22588 at fs/btrfs/disk-io.c:4333 close_ctree+0x222/0x4d0 [btrfs] Modules linked in: btrfs blake2b_generic libcrc32c xor zstd_compress raid6_pq CPU: 3 PID: 22588 Comm: umount Kdump: loaded Tainted: G W 6.10.0-rc7-gab56fde445b8 #21 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Arch Linux 1.16.3-1-1 04/01/2014 RIP: 0010:close_ctree+0x222/0x4d0 [btrfs] RSP: 0018:ffffb4465283be00 EFLAGS: 00010202 RAX: 0000000000000001 RBX: ffffa1a1818e1000 RCX: 0000000000000001 RDX: 0000000000000000 RSI: ffffb4465283bbe0 RDI: ffffa1a19374fcb8 RBP: ffffa1a1818e13c0 R08: 0000000100028b16 R09: 0000000000000000 R10: 0000000000000003 R11: 0000000000000003 R12: ffffa1a18ad7972c R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 FS: 00007f9168312b80(0000) GS:ffffa1a4afcc0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f91683c9140 CR3: 000000010acaa000 CR4: 00000000000006f0 Call Trace: ? close_ctree+0x222/0x4d0 [btrfs] ? __warn.cold+0x8e/0xea ? close_ctree+0x222/0x4d0 [btrfs] ? report_bug+0xff/0x140 ? handle_bug+0x3b/0x70 ? exc_invalid_op+0x17/0x70 ? asm_exc_invalid_op+0x1a/0x20 ? close_ctree+0x222/0x4d0 [btrfs] generic_shutdown_super+0x70/0x160 kill_anon_super+0x11/0x40 btrfs_kill_super+0x11/0x20 [btrfs] deactivate_locked_super+0x2e/0xa0 cleanup_mnt+0xb5/0x150 task_work_run+0x57/0x80 syscall_exit_to_user_mode+0x121/0x130 do_syscall_64+0xab/0x1a0 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f916847a887 ---[ end trace 0000000000000000 ]--- BTRFS error (device dm-8 state EA): qgroup reserved space leaked Cases 2 and 3 in the out_reserve path both pertain to this type of leak and must free the reserved qgroup data. Because it is already an error path, I opted not to handle the possible errors in btrfs_free_qgroup_data. Reviewed-by: Qu Wenruo Signed-off-by: Boris Burkov Signed-off-by: David Sterba [Minor conflict resolved due to code context change.] Signed-off-by: Jianqi Ren Signed-off-by: He Zhe Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/inode.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index cedffa567a75..fc127182067b 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1546,6 +1546,7 @@ out_unlock: locked_page, clear_bits, page_ops); + btrfs_qgroup_free_data(inode, NULL, start, cur_alloc_size, NULL); start += cur_alloc_size; } @@ -1559,6 +1560,7 @@ out_unlock: clear_bits |= EXTENT_CLEAR_DATA_RESV; extent_clear_unlock_delalloc(inode, start, end, locked_page, clear_bits, page_ops); + btrfs_qgroup_free_data(inode, NULL, start, cur_alloc_size, NULL); } return ret; } @@ -2222,13 +2224,15 @@ error: */ if (cow_start != (u64)-1) cur_offset = cow_start; - if (cur_offset < end) + if (cur_offset < end) { extent_clear_unlock_delalloc(inode, cur_offset, end, locked_page, EXTENT_LOCKED | EXTENT_DELALLOC | EXTENT_DEFRAG | EXTENT_DO_ACCOUNTING, PAGE_UNLOCK | PAGE_START_WRITEBACK | PAGE_END_WRITEBACK); + btrfs_qgroup_free_data(inode, NULL, cur_offset, end - cur_offset + 1, NULL); + } btrfs_free_path(path); return ret; } From 48128f54f57293d552cd3ba247cb720df02cf03e Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Fri, 10 Nov 2023 09:23:15 +0800 Subject: [PATCH 374/606] wifi: rtw89: pci: add pre_deinit to be called after probe complete commit 9e1aff437a560cd72cb6a60ee33fe162b0afdaf1 upstream. At probe stage, we only do partial initialization to enable ability to download firmware and read capabilities. After that, we use this pre_deinit to disable HCI to save power. Signed-off-by: Ping-Ke Shih Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20231110012319.12727-4-pkshih@realtek.com [ Zenm: The rtw89 driver in recent kernel versions supports both Wi-Fi 6/6E and Wi-Fi 7, however the rtw89 driver in kernel 6.6 supports Wi-Fi 6/6E only, so remove the unnecessary code for Wi-Fi 7 from the upstream patch to make it apply on 6.6.y. ] Signed-off-by: Zenm Chen Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/realtek/rtw89/core.c | 2 ++ drivers/net/wireless/realtek/rtw89/core.h | 6 ++++++ drivers/net/wireless/realtek/rtw89/pci.c | 8 ++++++++ 3 files changed, 16 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 535393eca564..d1d8fd812cbf 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -3807,6 +3807,8 @@ static int rtw89_chip_efuse_info_setup(struct rtw89_dev *rtwdev) rtw89_core_setup_phycap(rtwdev); rtw89_core_setup_rfe_parms(rtwdev); + rtw89_hci_mac_pre_deinit(rtwdev); + rtw89_mac_pwr_off(rtwdev); return 0; diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index ee6ae2a0c798..16aad0f8393a 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -2989,6 +2989,7 @@ struct rtw89_hci_ops { void (*write32)(struct rtw89_dev *rtwdev, u32 addr, u32 data); int (*mac_pre_init)(struct rtw89_dev *rtwdev); + int (*mac_pre_deinit)(struct rtw89_dev *rtwdev); int (*mac_post_init)(struct rtw89_dev *rtwdev); int (*deinit)(struct rtw89_dev *rtwdev); @@ -4515,6 +4516,11 @@ static inline void rtw89_hci_tx_kick_off(struct rtw89_dev *rtwdev, u8 txch) return rtwdev->hci.ops->tx_kick_off(rtwdev, txch); } +static inline int rtw89_hci_mac_pre_deinit(struct rtw89_dev *rtwdev) +{ + return rtwdev->hci.ops->mac_pre_deinit(rtwdev); +} + static inline void rtw89_hci_flush_queues(struct rtw89_dev *rtwdev, u32 queues, bool drop) { diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c index 98af64444d3e..7787159dd26f 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.c +++ b/drivers/net/wireless/realtek/rtw89/pci.c @@ -2568,6 +2568,13 @@ static int rtw89_pci_ops_mac_pre_init(struct rtw89_dev *rtwdev) return 0; } +static int rtw89_pci_ops_mac_pre_deinit(struct rtw89_dev *rtwdev) +{ + rtw89_pci_power_wake(rtwdev, false); + + return 0; +} + int rtw89_pci_ltr_set(struct rtw89_dev *rtwdev, bool en) { u32 val; @@ -3812,6 +3819,7 @@ static const struct rtw89_hci_ops rtw89_pci_ops = { .write32 = rtw89_pci_ops_write32, .mac_pre_init = rtw89_pci_ops_mac_pre_init, + .mac_pre_deinit = rtw89_pci_ops_mac_pre_deinit, .mac_post_init = rtw89_pci_ops_mac_post_init, .deinit = rtw89_pci_ops_deinit, From 31ff06b4a8a835c97a07dc8f572517412b222d0e Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Mon, 11 Nov 2024 14:38:35 +0800 Subject: [PATCH 375/606] wifi: rtw89: pci: disable PCIE wake bit when PCIE deinit commit 9c1df813e08832c3836c254bc8a2f83ff22dbc06 upstream. The PCIE wake bit is to control PCIE wake signal to host. When PCIE is going down, clear this bit to prevent waking up host unexpectedly. Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20241111063835.15454-1-pkshih@realtek.com [ Zenm: The rtw89 driver in recent kernel versions supports both Wi-Fi 6/6E and Wi-Fi 7, however the rtw89 driver in kernel 6.6 supports Wi-Fi 6/6E only, so remove the unnecessary code for Wi-Fi 7 from the upstream patch to make it apply on 6.6.y. ] Signed-off-by: Zenm Chen Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/realtek/rtw89/pci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c index 7787159dd26f..30cc6e03c355 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.c +++ b/drivers/net/wireless/realtek/rtw89/pci.c @@ -2482,6 +2482,8 @@ static int rtw89_pci_ops_deinit(struct rtw89_dev *rtwdev) { const struct rtw89_pci_info *info = rtwdev->pci_info; + rtw89_pci_power_wake(rtwdev, false); + if (rtwdev->chip->chip_id == RTL8852A) { /* ltr sw trigger */ rtw89_write32_set(rtwdev, R_AX_LTR_CTRL_0, B_AX_APP_LTR_IDLE); From c84632096722fd31251f0957fafc9e90d9a247fd Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Wed, 24 Apr 2024 16:15:15 -0400 Subject: [PATCH 376/606] drm/amd/display: Stop amdgpu_dm initialize when link nums greater than max_links commit cf8b16857db702ceb8d52f9219a4613363e2b1cf upstream. [Why] Coverity report OVERRUN warning. There are only max_links elements within dc->links. link count could up to AMDGPU_DM_MAX_DISPLAY_INDEX 31. [How] Make sure link count less than max_links. Reviewed-by: Harry Wentland Acked-by: Tom Chung Signed-off-by: Hersen Wu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher [Minor conflict resolved due to code context change. And the macro MAX_LINKS is introduced by Commit 60df5628144b ("drm/amd/display: handle invalid connector indices") after 6.10. So here we still use the original array length MAX_PIPES * 2] Signed-off-by: Jianqi Ren Signed-off-by: He Zhe Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 3696b9112c74..28f2b4022d34 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4484,17 +4484,17 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) } } + if (link_cnt > (MAX_PIPES * 2)) { + DRM_ERROR( + "KMS: Cannot support more than %d display indexes\n", + MAX_PIPES * 2); + goto fail; + } + /* loops over all connectors on the board */ for (i = 0; i < link_cnt; i++) { struct dc_link *link = NULL; - if (i > AMDGPU_DM_MAX_DISPLAY_INDEX) { - DRM_ERROR( - "KMS: Cannot support more than %d display indexes\n", - AMDGPU_DM_MAX_DISPLAY_INDEX); - continue; - } - aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL); if (!aconnector) goto fail; From efde4462b3217e777f385c8d2ade960de3d9666e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= Date: Tue, 18 Mar 2025 17:14:37 +0100 Subject: [PATCH 377/606] landlock: Add the errata interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 15383a0d63dbcd63dc7e8d9ec1bf3a0f7ebf64ac upstream. Some fixes may require user space to check if they are applied on the running kernel before using a specific feature. For instance, this applies when a restriction was previously too restrictive and is now getting relaxed (e.g. for compatibility reasons). However, non-visible changes for legitimate use (e.g. security fixes) do not require an erratum. Because fixes are backported down to a specific Landlock ABI, we need a way to avoid cherry-pick conflicts. The solution is to only update a file related to the lower ABI impacted by this issue. All the ABI files are then used to create a bitmask of fixes. The new errata interface is similar to the one used to get the supported Landlock ABI version, but it returns a bitmask instead because the order of fixes may not match the order of versions, and not all fixes may apply to all versions. The actual errata will come with dedicated commits. The description is not actually used in the code but serves as documentation. Create the landlock_abi_version symbol and use its value to check errata consistency. Update test_base's create_ruleset_checks_ordering tests and add errata tests. This commit is backportable down to the first version of Landlock. Fixes: 3532b0b4352c ("landlock: Enable user space to infer supported features") Cc: Günther Noack Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250318161443.279194-3-mic@digikod.net Signed-off-by: Mickaël Salaün Signed-off-by: Greg Kroah-Hartman --- include/uapi/linux/landlock.h | 2 + security/landlock/errata.h | 87 ++++++++++++++++++++ security/landlock/setup.c | 30 +++++++ security/landlock/setup.h | 3 + security/landlock/syscalls.c | 22 ++++- tools/testing/selftests/landlock/base_test.c | 46 ++++++++++- 6 files changed, 185 insertions(+), 5 deletions(-) create mode 100644 security/landlock/errata.h diff --git a/include/uapi/linux/landlock.h b/include/uapi/linux/landlock.h index 81d09ef9aa50..f82a66361a1e 100644 --- a/include/uapi/linux/landlock.h +++ b/include/uapi/linux/landlock.h @@ -38,9 +38,11 @@ struct landlock_ruleset_attr { * * - %LANDLOCK_CREATE_RULESET_VERSION: Get the highest supported Landlock ABI * version. + * - %LANDLOCK_CREATE_RULESET_ERRATA: Get a bitmask of fixed issues. */ /* clang-format off */ #define LANDLOCK_CREATE_RULESET_VERSION (1U << 0) +#define LANDLOCK_CREATE_RULESET_ERRATA (1U << 1) /* clang-format on */ /** diff --git a/security/landlock/errata.h b/security/landlock/errata.h new file mode 100644 index 000000000000..fe91ef0e6f72 --- /dev/null +++ b/security/landlock/errata.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Landlock - Errata information + * + * Copyright © 2025 Microsoft Corporation + */ + +#ifndef _SECURITY_LANDLOCK_ERRATA_H +#define _SECURITY_LANDLOCK_ERRATA_H + +#include + +struct landlock_erratum { + const int abi; + const u8 number; +}; + +/* clang-format off */ +#define LANDLOCK_ERRATUM(NUMBER) \ + { \ + .abi = LANDLOCK_ERRATA_ABI, \ + .number = NUMBER, \ + }, +/* clang-format on */ + +/* + * Some fixes may require user space to check if they are applied on the running + * kernel before using a specific feature. For instance, this applies when a + * restriction was previously too restrictive and is now getting relaxed (for + * compatibility or semantic reasons). However, non-visible changes for + * legitimate use (e.g. security fixes) do not require an erratum. + */ +static const struct landlock_erratum landlock_errata_init[] __initconst = { + +/* + * Only Sparse may not implement __has_include. If a compiler does not + * implement __has_include, a warning will be printed at boot time (see + * setup.c). + */ +#ifdef __has_include + +#define LANDLOCK_ERRATA_ABI 1 +#if __has_include("errata/abi-1.h") +#include "errata/abi-1.h" +#endif +#undef LANDLOCK_ERRATA_ABI + +#define LANDLOCK_ERRATA_ABI 2 +#if __has_include("errata/abi-2.h") +#include "errata/abi-2.h" +#endif +#undef LANDLOCK_ERRATA_ABI + +#define LANDLOCK_ERRATA_ABI 3 +#if __has_include("errata/abi-3.h") +#include "errata/abi-3.h" +#endif +#undef LANDLOCK_ERRATA_ABI + +#define LANDLOCK_ERRATA_ABI 4 +#if __has_include("errata/abi-4.h") +#include "errata/abi-4.h" +#endif +#undef LANDLOCK_ERRATA_ABI + +/* + * For each new erratum, we need to include all the ABI files up to the impacted + * ABI to make all potential future intermediate errata easy to backport. + * + * If such change involves more than one ABI addition, then it must be in a + * dedicated commit with the same Fixes tag as used for the actual fix. + * + * Each commit creating a new security/landlock/errata/abi-*.h file must have a + * Depends-on tag to reference the commit that previously added the line to + * include this new file, except if the original Fixes tag is enough. + * + * Each erratum must be documented in its related ABI file, and a dedicated + * commit must update Documentation/userspace-api/landlock.rst to include this + * erratum. This commit will not be backported. + */ + +#endif + + {} +}; + +#endif /* _SECURITY_LANDLOCK_ERRATA_H */ diff --git a/security/landlock/setup.c b/security/landlock/setup.c index 0f6113528fa4..8b46e8748b8a 100644 --- a/security/landlock/setup.c +++ b/security/landlock/setup.c @@ -6,11 +6,13 @@ * Copyright © 2018-2020 ANSSI */ +#include #include #include #include "common.h" #include "cred.h" +#include "errata.h" #include "fs.h" #include "ptrace.h" #include "setup.h" @@ -24,8 +26,36 @@ struct lsm_blob_sizes landlock_blob_sizes __ro_after_init = { .lbs_superblock = sizeof(struct landlock_superblock_security), }; +int landlock_errata __ro_after_init; + +static void __init compute_errata(void) +{ + size_t i; + +#ifndef __has_include + /* + * This is a safeguard to make sure the compiler implements + * __has_include (see errata.h). + */ + WARN_ON_ONCE(1); + return; +#endif + + for (i = 0; landlock_errata_init[i].number; i++) { + const int prev_errata = landlock_errata; + + if (WARN_ON_ONCE(landlock_errata_init[i].abi > + landlock_abi_version)) + continue; + + landlock_errata |= BIT(landlock_errata_init[i].number - 1); + WARN_ON_ONCE(prev_errata == landlock_errata); + } +} + static int __init landlock_init(void) { + compute_errata(); landlock_add_cred_hooks(); landlock_add_ptrace_hooks(); landlock_add_fs_hooks(); diff --git a/security/landlock/setup.h b/security/landlock/setup.h index 1daffab1ab4b..420dceca35d2 100644 --- a/security/landlock/setup.h +++ b/security/landlock/setup.h @@ -11,7 +11,10 @@ #include +extern const int landlock_abi_version; + extern bool landlock_initialized; +extern int landlock_errata; extern struct lsm_blob_sizes landlock_blob_sizes; diff --git a/security/landlock/syscalls.c b/security/landlock/syscalls.c index 336bedaa3af6..eb23df4e836c 100644 --- a/security/landlock/syscalls.c +++ b/security/landlock/syscalls.c @@ -150,7 +150,9 @@ static const struct file_operations ruleset_fops = { * the new ruleset. * @size: Size of the pointed &struct landlock_ruleset_attr (needed for * backward and forward compatibility). - * @flags: Supported value: %LANDLOCK_CREATE_RULESET_VERSION. + * @flags: Supported value: + * - %LANDLOCK_CREATE_RULESET_VERSION + * - %LANDLOCK_CREATE_RULESET_ERRATA * * This system call enables to create a new Landlock ruleset, and returns the * related file descriptor on success. @@ -159,6 +161,10 @@ static const struct file_operations ruleset_fops = { * 0, then the returned value is the highest supported Landlock ABI version * (starting at 1). * + * If @flags is %LANDLOCK_CREATE_RULESET_ERRATA and @attr is NULL and @size is + * 0, then the returned value is a bitmask of fixed issues for the current + * Landlock ABI version. + * * Possible returned errors are: * * - %EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time; @@ -181,9 +187,15 @@ SYSCALL_DEFINE3(landlock_create_ruleset, return -EOPNOTSUPP; if (flags) { - if ((flags == LANDLOCK_CREATE_RULESET_VERSION) && !attr && - !size) - return LANDLOCK_ABI_VERSION; + if (attr || size) + return -EINVAL; + + if (flags == LANDLOCK_CREATE_RULESET_VERSION) + return landlock_abi_version; + + if (flags == LANDLOCK_CREATE_RULESET_ERRATA) + return landlock_errata; + return -EINVAL; } @@ -213,6 +225,8 @@ SYSCALL_DEFINE3(landlock_create_ruleset, return ruleset_fd; } +const int landlock_abi_version = LANDLOCK_ABI_VERSION; + /* * Returns an owned ruleset from a FD. It is thus needed to call * landlock_put_ruleset() on the return value. diff --git a/tools/testing/selftests/landlock/base_test.c b/tools/testing/selftests/landlock/base_test.c index 5aa7d2feab10..b06410bd1aa1 100644 --- a/tools/testing/selftests/landlock/base_test.c +++ b/tools/testing/selftests/landlock/base_test.c @@ -98,10 +98,54 @@ TEST(abi_version) ASSERT_EQ(EINVAL, errno); } +/* + * Old source trees might not have the set of Kselftest fixes related to kernel + * UAPI headers. + */ +#ifndef LANDLOCK_CREATE_RULESET_ERRATA +#define LANDLOCK_CREATE_RULESET_ERRATA (1U << 1) +#endif + +TEST(errata) +{ + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE, + }; + int errata; + + errata = landlock_create_ruleset(NULL, 0, + LANDLOCK_CREATE_RULESET_ERRATA); + /* The errata bitmask will not be backported to tests. */ + ASSERT_LE(0, errata); + TH_LOG("errata: 0x%x", errata); + + ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0, + LANDLOCK_CREATE_RULESET_ERRATA)); + ASSERT_EQ(EINVAL, errno); + + ASSERT_EQ(-1, landlock_create_ruleset(NULL, sizeof(ruleset_attr), + LANDLOCK_CREATE_RULESET_ERRATA)); + ASSERT_EQ(EINVAL, errno); + + ASSERT_EQ(-1, + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), + LANDLOCK_CREATE_RULESET_ERRATA)); + ASSERT_EQ(EINVAL, errno); + + ASSERT_EQ(-1, landlock_create_ruleset( + NULL, 0, + LANDLOCK_CREATE_RULESET_VERSION | + LANDLOCK_CREATE_RULESET_ERRATA)); + ASSERT_EQ(-1, landlock_create_ruleset(NULL, 0, + LANDLOCK_CREATE_RULESET_ERRATA | + 1 << 31)); + ASSERT_EQ(EINVAL, errno); +} + /* Tests ordering of syscall argument checks. */ TEST(create_ruleset_checks_ordering) { - const int last_flag = LANDLOCK_CREATE_RULESET_VERSION; + const int last_flag = LANDLOCK_CREATE_RULESET_ERRATA; const int invalid_flag = last_flag << 1; int ruleset_fd; const struct landlock_ruleset_attr ruleset_attr = { From 0a721f240a68b4f81e1dfedbf5c68319ca51e7ff Mon Sep 17 00:00:00 2001 From: WangYuli Date: Wed, 12 Mar 2025 13:06:50 +0800 Subject: [PATCH 378/606] nvmet-fc: Remove unused functions commit 1b304c006b0fb4f0517a8c4ba8c46e88f48a069c upstream. The functions nvmet_fc_iodnum() and nvmet_fc_fodnum() are currently unutilized. Following commit c53432030d86 ("nvme-fabrics: Add target support for FC transport"), which introduced these two functions, they have not been used at all in practice. Remove them to resolve the compiler warnings. Fix follow errors with clang-19 when W=1e: drivers/nvme/target/fc.c:177:1: error: unused function 'nvmet_fc_iodnum' [-Werror,-Wunused-function] 177 | nvmet_fc_iodnum(struct nvmet_fc_ls_iod *iodptr) | ^~~~~~~~~~~~~~~ drivers/nvme/target/fc.c:183:1: error: unused function 'nvmet_fc_fodnum' [-Werror,-Wunused-function] 183 | nvmet_fc_fodnum(struct nvmet_fc_fcp_iod *fodptr) | ^~~~~~~~~~~~~~~ 2 errors generated. make[8]: *** [scripts/Makefile.build:207: drivers/nvme/target/fc.o] Error 1 make[7]: *** [scripts/Makefile.build:465: drivers/nvme/target] Error 2 make[6]: *** [scripts/Makefile.build:465: drivers/nvme] Error 2 make[6]: *** Waiting for unfinished jobs.... Fixes: c53432030d86 ("nvme-fabrics: Add target support for FC transport") Signed-off-by: WangYuli Reviewed-by: Chaitanya Kulkarni Reviewed-by: Christoph Hellwig Signed-off-by: Keith Busch Signed-off-by: Greg Kroah-Hartman --- drivers/nvme/target/fc.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/nvme/target/fc.c b/drivers/nvme/target/fc.c index 8a02ed63b156..d40d5a4ea932 100644 --- a/drivers/nvme/target/fc.c +++ b/drivers/nvme/target/fc.c @@ -173,20 +173,6 @@ struct nvmet_fc_tgt_assoc { struct rcu_head rcu; }; - -static inline int -nvmet_fc_iodnum(struct nvmet_fc_ls_iod *iodptr) -{ - return (iodptr - iodptr->tgtport->iod); -} - -static inline int -nvmet_fc_fodnum(struct nvmet_fc_fcp_iod *fodptr) -{ - return (fodptr - fodptr->queue->fod); -} - - /* * Association and Connection IDs: * From 1e2d849efc3225398cfb18fb5d9232fa6ab4851c Mon Sep 17 00:00:00 2001 From: Jan Stancek Date: Fri, 12 Jul 2024 09:11:14 +0200 Subject: [PATCH 379/606] sign-file,extract-cert: move common SSL helper functions to a header commit 300e6d4116f956b035281ec94297dc4dc8d4e1d3 upstream. Couple error handling helpers are repeated in both tools, so move them to a common header. Signed-off-by: Jan Stancek Reviewed-by: Jarkko Sakkinen Tested-by: R Nageswara Sastry Reviewed-by: Neal Gompa Signed-off-by: Jarkko Sakkinen Signed-off-by: Huacai Chen Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 1 + certs/Makefile | 2 +- certs/extract-cert.c | 37 ++----------------------------------- scripts/sign-file.c | 37 ++----------------------------------- scripts/ssl-common.h | 39 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 45 insertions(+), 71 deletions(-) create mode 100644 scripts/ssl-common.h diff --git a/MAINTAINERS b/MAINTAINERS index ae4c0cec5073..294d2ce29b73 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4784,6 +4784,7 @@ S: Maintained F: Documentation/admin-guide/module-signing.rst F: certs/ F: scripts/sign-file.c +F: scripts/ssl-common.h F: tools/certs/ CFAG12864B LCD DRIVER diff --git a/certs/Makefile b/certs/Makefile index 799ad7b9e68a..67e1f2707c2f 100644 --- a/certs/Makefile +++ b/certs/Makefile @@ -84,5 +84,5 @@ targets += x509_revocation_list hostprogs := extract-cert -HOSTCFLAGS_extract-cert.o = $(shell $(HOSTPKG_CONFIG) --cflags libcrypto 2> /dev/null) +HOSTCFLAGS_extract-cert.o = $(shell $(HOSTPKG_CONFIG) --cflags libcrypto 2> /dev/null) -I$(srctree)/scripts HOSTLDLIBS_extract-cert = $(shell $(HOSTPKG_CONFIG) --libs libcrypto 2> /dev/null || echo -lcrypto) diff --git a/certs/extract-cert.c b/certs/extract-cert.c index 70e9ec89d87d..8e7ba9974a1f 100644 --- a/certs/extract-cert.c +++ b/certs/extract-cert.c @@ -23,6 +23,8 @@ #include #include +#include "ssl-common.h" + /* * OpenSSL 3.0 deprecates the OpenSSL's ENGINE API. * @@ -40,41 +42,6 @@ void format(void) exit(2); } -static void display_openssl_errors(int l) -{ - const char *file; - char buf[120]; - int e, line; - - if (ERR_peek_error() == 0) - return; - fprintf(stderr, "At main.c:%d:\n", l); - - while ((e = ERR_get_error_line(&file, &line))) { - ERR_error_string(e, buf); - fprintf(stderr, "- SSL %s: %s:%d\n", buf, file, line); - } -} - -static void drain_openssl_errors(void) -{ - const char *file; - int line; - - if (ERR_peek_error() == 0) - return; - while (ERR_get_error_line(&file, &line)) {} -} - -#define ERR(cond, fmt, ...) \ - do { \ - bool __cond = (cond); \ - display_openssl_errors(__LINE__); \ - if (__cond) { \ - err(1, fmt, ## __VA_ARGS__); \ - } \ - } while(0) - static const char *key_pass; static BIO *wb; static char *cert_dst; diff --git a/scripts/sign-file.c b/scripts/sign-file.c index 3edb156ae52c..39ba58db5d4e 100644 --- a/scripts/sign-file.c +++ b/scripts/sign-file.c @@ -29,6 +29,8 @@ #include #include +#include "ssl-common.h" + /* * OpenSSL 3.0 deprecates the OpenSSL's ENGINE API. * @@ -83,41 +85,6 @@ void format(void) exit(2); } -static void display_openssl_errors(int l) -{ - const char *file; - char buf[120]; - int e, line; - - if (ERR_peek_error() == 0) - return; - fprintf(stderr, "At main.c:%d:\n", l); - - while ((e = ERR_get_error_line(&file, &line))) { - ERR_error_string(e, buf); - fprintf(stderr, "- SSL %s: %s:%d\n", buf, file, line); - } -} - -static void drain_openssl_errors(void) -{ - const char *file; - int line; - - if (ERR_peek_error() == 0) - return; - while (ERR_get_error_line(&file, &line)) {} -} - -#define ERR(cond, fmt, ...) \ - do { \ - bool __cond = (cond); \ - display_openssl_errors(__LINE__); \ - if (__cond) { \ - errx(1, fmt, ## __VA_ARGS__); \ - } \ - } while(0) - static const char *key_pass; static int pem_pw_cb(char *buf, int len, int w, void *v) diff --git a/scripts/ssl-common.h b/scripts/ssl-common.h new file mode 100644 index 000000000000..e6711c75ed91 --- /dev/null +++ b/scripts/ssl-common.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/* + * SSL helper functions shared by sign-file and extract-cert. + */ + +static void display_openssl_errors(int l) +{ + const char *file; + char buf[120]; + int e, line; + + if (ERR_peek_error() == 0) + return; + fprintf(stderr, "At main.c:%d:\n", l); + + while ((e = ERR_get_error_line(&file, &line))) { + ERR_error_string(e, buf); + fprintf(stderr, "- SSL %s: %s:%d\n", buf, file, line); + } +} + +static void drain_openssl_errors(void) +{ + const char *file; + int line; + + if (ERR_peek_error() == 0) + return; + while (ERR_get_error_line(&file, &line)) {} +} + +#define ERR(cond, fmt, ...) \ + do { \ + bool __cond = (cond); \ + display_openssl_errors(__LINE__); \ + if (__cond) { \ + errx(1, fmt, ## __VA_ARGS__); \ + } \ + } while (0) From 202bca49b7f9ed3c5f5f7bb00adabea6339efe2d Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 17 Mar 2025 14:38:13 +0100 Subject: [PATCH 380/606] xdp: Reset bpf_redirect_info before running a xdp's BPF prog. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ricardo reported a KASAN discovered use after free in v6.6-stable. The syzbot starts a BPF program via xdp_test_run_batch() which assigns ri->tgt_value via dev_hash_map_redirect() and the return code isn't XDP_REDIRECT it looks like nonsense. So the output in bpf_warn_invalid_xdp_action() appears once. Then the TUN driver runs another BPF program (on the same CPU) which returns XDP_REDIRECT without setting ri->tgt_value first. It invokes bpf_trace_printk() to print four characters and obtain the required return value. This is enough to get xdp_do_redirect() invoked which then accesses the pointer in tgt_value which might have been already deallocated. This problem does not affect upstream because since commit 401cb7dae8130 ("net: Reference bpf_redirect_info via task_struct on PREEMPT_RT.") the per-CPU variable is referenced via task's task_struct and exists on the stack during NAPI callback. Therefore it is cleared once before the first invocation and remains valid within the RCU section of the NAPI callback. Instead of performing the huge backport of the commit (plus its fix ups) here is an alternative version which only resets the variable in question prior invoking the BPF program. Acked-by: Toke Høiland-Jørgensen Reported-by: Ricardo Cañuelo Navarro Closes: https://lore.kernel.org/all/20250226-20250204-kasan-slab-use-after-free-read-in-dev_map_enqueue__submit-v3-0-360efec441ba@igalia.com/ Fixes: 97f91a7cf04ff ("bpf: add bpf_redirect_map helper routine") Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman --- include/net/xdp.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/net/xdp.h b/include/net/xdp.h index de08c8e0d134..b39ac83618a5 100644 --- a/include/net/xdp.h +++ b/include/net/xdp.h @@ -486,7 +486,14 @@ static __always_inline u32 bpf_prog_run_xdp(const struct bpf_prog *prog, * under local_bh_disable(), which provides the needed RCU protection * for accessing map entries. */ - u32 act = __bpf_prog_run(prog, xdp, BPF_DISPATCHER_FUNC(xdp)); + struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info); + u32 act; + + if (ri->map_id || ri->map_type) { + ri->map_id = 0; + ri->map_type = BPF_MAP_TYPE_UNSPEC; + } + act = __bpf_prog_run(prog, xdp, BPF_DISPATCHER_FUNC(xdp)); if (static_branch_unlikely(&bpf_master_redirect_enabled_key)) { if (act == XDP_TX && netif_is_bond_slave(xdp->rxq->dev)) From 9cac3ed9ca51d6e37bac71b571e9e8491c0d66e8 Mon Sep 17 00:00:00 2001 From: WangYuli Date: Tue, 18 Feb 2025 20:54:31 +0800 Subject: [PATCH 381/606] MIPS: dec: Declare which_prom() as static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 55fa5868519bc48a7344a4c070efa2f4468f2167 upstream. Declare which_prom() as static to suppress gcc compiler warning that 'missing-prototypes'. This function is not intended to be called from other parts. Fix follow error with gcc-14 when -Werror: arch/mips/dec/prom/init.c:45:13: error: no previous prototype for ‘which_prom’ [-Werror=missing-prototypes] 45 | void __init which_prom(s32 magic, s32 *prom_vec) | ^~~~~~~~~~ cc1: all warnings being treated as errors make[6]: *** [scripts/Makefile.build:207: arch/mips/dec/prom/init.o] Error 1 make[5]: *** [scripts/Makefile.build:465: arch/mips/dec/prom] Error 2 make[5]: *** Waiting for unfinished jobs.... Signed-off-by: WangYuli Signed-off-by: Thomas Bogendoerfer Signed-off-by: Greg Kroah-Hartman --- arch/mips/dec/prom/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/dec/prom/init.c b/arch/mips/dec/prom/init.c index cb12eb211a49..8d74d7d6c05b 100644 --- a/arch/mips/dec/prom/init.c +++ b/arch/mips/dec/prom/init.c @@ -42,7 +42,7 @@ int (*__pmax_close)(int); * Detect which PROM the DECSTATION has, and set the callback vectors * appropriately. */ -void __init which_prom(s32 magic, s32 *prom_vec) +static void __init which_prom(s32 magic, s32 *prom_vec) { /* * No sign of the REX PROM's magic number means we assume a non-REX From 1dab036557e68d03878c92fb9a1f6bb362c50752 Mon Sep 17 00:00:00 2001 From: WangYuli Date: Tue, 18 Feb 2025 20:57:23 +0800 Subject: [PATCH 382/606] MIPS: cevt-ds1287: Add missing ds1287.h include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f3be225f338a578851a7b607a409f476354a8deb upstream. Address the issue of cevt-ds1287.c not including the ds1287.h header file. Fix follow errors with gcc-14 when -Werror: arch/mips/kernel/cevt-ds1287.c:15:5: error: no previous prototype for ‘ds1287_timer_state’ [-Werror=missing-prototypes] 15 | int ds1287_timer_state(void) | ^~~~~~~~~~~~~~~~~~ arch/mips/kernel/cevt-ds1287.c:20:5: error: no previous prototype for ‘ds1287_set_base_clock’ [-Werror=missing-prototypes] 20 | int ds1287_set_base_clock(unsigned int hz) | ^~~~~~~~~~~~~~~~~~~~~ arch/mips/kernel/cevt-ds1287.c:103:12: error: no previous prototype for ‘ds1287_clockevent_init’ [-Werror=missing-prototypes] 103 | int __init ds1287_clockevent_init(int irq) | ^~~~~~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors make[7]: *** [scripts/Makefile.build:207: arch/mips/kernel/cevt-ds1287.o] Error 1 make[7]: *** Waiting for unfinished jobs.... make[6]: *** [scripts/Makefile.build:465: arch/mips/kernel] Error 2 make[6]: *** Waiting for unfinished jobs.... Signed-off-by: WangYuli Signed-off-by: Thomas Bogendoerfer Signed-off-by: Greg Kroah-Hartman --- arch/mips/kernel/cevt-ds1287.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/mips/kernel/cevt-ds1287.c b/arch/mips/kernel/cevt-ds1287.c index 9a47fbcd4638..de64d6bb7ba3 100644 --- a/arch/mips/kernel/cevt-ds1287.c +++ b/arch/mips/kernel/cevt-ds1287.c @@ -10,6 +10,7 @@ #include #include +#include #include int ds1287_timer_state(void) From 81faa5bfba73f35539b6ebabfd700373322f6dfa Mon Sep 17 00:00:00 2001 From: WangYuli Date: Tue, 18 Feb 2025 20:57:55 +0800 Subject: [PATCH 383/606] MIPS: ds1287: Match ds1287_set_base_clock() function types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit a759109b234385b74d2f5f4c86b5f59b3201ec12 upstream. Synchronize the declaration of ds1287_set_base_clock() between cevt-ds1287.c and ds1287.h. Fix follow error with gcc-14 when -Werror: arch/mips/kernel/cevt-ds1287.c:21:5: error: conflicting types for ‘ds1287_set_base_clock’; have ‘int(unsigned int)’ 21 | int ds1287_set_base_clock(unsigned int hz) | ^~~~~~~~~~~~~~~~~~~~~ In file included from arch/mips/kernel/cevt-ds1287.c:13: ./arch/mips/include/asm/ds1287.h:11:13: note: previous declaration of ‘ds1287_set_base_clock’ with type ‘void(unsigned int)’ 11 | extern void ds1287_set_base_clock(unsigned int clock); | ^~~~~~~~~~~~~~~~~~~~~ make[7]: *** [scripts/Makefile.build:207: arch/mips/kernel/cevt-ds1287.o] Error 1 make[6]: *** [scripts/Makefile.build:465: arch/mips/kernel] Error 2 make[6]: *** Waiting for unfinished jobs.... Signed-off-by: WangYuli Signed-off-by: Thomas Bogendoerfer Signed-off-by: Greg Kroah-Hartman --- arch/mips/include/asm/ds1287.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/include/asm/ds1287.h b/arch/mips/include/asm/ds1287.h index 46cfb01f9a14..51cb61fd4c03 100644 --- a/arch/mips/include/asm/ds1287.h +++ b/arch/mips/include/asm/ds1287.h @@ -8,7 +8,7 @@ #define __ASM_DS1287_H extern int ds1287_timer_state(void); -extern void ds1287_set_base_clock(unsigned int clock); +extern int ds1287_set_base_clock(unsigned int hz); extern int ds1287_clockevent_init(int irq); #endif From b6b77ca4c980da785e8622c28b923584a9d6a892 Mon Sep 17 00:00:00 2001 From: Haisu Wang Date: Fri, 25 Oct 2024 14:54:40 +0800 Subject: [PATCH 384/606] btrfs: fix the length of reserved qgroup to free commit 2b084d8205949dd804e279df8e68531da78be1e8 upstream. The dealloc flag may be cleared and the extent won't reach the disk in cow_file_range when errors path. The reserved qgroup space is freed in commit 30479f31d44d ("btrfs: fix qgroup reserve leaks in cow_file_range"). However, the length of untouched region to free needs to be adjusted with the correct remaining region size. Fixes: 30479f31d44d ("btrfs: fix qgroup reserve leaks in cow_file_range") CC: stable@vger.kernel.org # 6.11+ Reviewed-by: Qu Wenruo Reviewed-by: Boris Burkov Signed-off-by: Haisu Wang Reviewed-by: David Sterba Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index fc127182067b..11c4d69177f0 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1560,7 +1560,7 @@ out_unlock: clear_bits |= EXTENT_CLEAR_DATA_RESV; extent_clear_unlock_delalloc(inode, start, end, locked_page, clear_bits, page_ops); - btrfs_qgroup_free_data(inode, NULL, start, cur_alloc_size, NULL); + btrfs_qgroup_free_data(inode, NULL, start, end - start + 1, NULL); } return ret; } From f8dafdafddcf5ebf58658e89f8c003217e961e8c Mon Sep 17 00:00:00 2001 From: Jan Stancek Date: Fri, 12 Jul 2024 09:11:15 +0200 Subject: [PATCH 385/606] sign-file,extract-cert: avoid using deprecated ERR_get_error_line() commit 467d60eddf55588add232feda325da7215ddaf30 upstream. ERR_get_error_line() is deprecated since OpenSSL 3.0. Use ERR_peek_error_line() instead, and combine display_openssl_errors() and drain_openssl_errors() to a single function where parameter decides if it should consume errors silently. Signed-off-by: Jan Stancek Reviewed-by: Jarkko Sakkinen Tested-by: R Nageswara Sastry Reviewed-by: Neal Gompa Signed-off-by: Jarkko Sakkinen Signed-off-by: Huacai Chen Signed-off-by: Greg Kroah-Hartman --- certs/extract-cert.c | 4 ++-- scripts/sign-file.c | 6 +++--- scripts/ssl-common.h | 23 ++++++++--------------- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/certs/extract-cert.c b/certs/extract-cert.c index 8e7ba9974a1f..61bbe0085671 100644 --- a/certs/extract-cert.c +++ b/certs/extract-cert.c @@ -99,11 +99,11 @@ int main(int argc, char **argv) parms.cert = NULL; ENGINE_load_builtin_engines(); - drain_openssl_errors(); + drain_openssl_errors(__LINE__, 1); e = ENGINE_by_id("pkcs11"); ERR(!e, "Load PKCS#11 ENGINE"); if (ENGINE_init(e)) - drain_openssl_errors(); + drain_openssl_errors(__LINE__, 1); else ERR(1, "ENGINE_init"); if (key_pass) diff --git a/scripts/sign-file.c b/scripts/sign-file.c index 39ba58db5d4e..bb3fdf1a617c 100644 --- a/scripts/sign-file.c +++ b/scripts/sign-file.c @@ -114,11 +114,11 @@ static EVP_PKEY *read_private_key(const char *private_key_name) ENGINE *e; ENGINE_load_builtin_engines(); - drain_openssl_errors(); + drain_openssl_errors(__LINE__, 1); e = ENGINE_by_id("pkcs11"); ERR(!e, "Load PKCS#11 ENGINE"); if (ENGINE_init(e)) - drain_openssl_errors(); + drain_openssl_errors(__LINE__, 1); else ERR(1, "ENGINE_init"); if (key_pass) @@ -273,7 +273,7 @@ int main(int argc, char **argv) /* Digest the module data. */ OpenSSL_add_all_digests(); - display_openssl_errors(__LINE__); + drain_openssl_errors(__LINE__, 0); digest_algo = EVP_get_digestbyname(hash_algo); ERR(!digest_algo, "EVP_get_digestbyname"); diff --git a/scripts/ssl-common.h b/scripts/ssl-common.h index e6711c75ed91..2db0e181143c 100644 --- a/scripts/ssl-common.h +++ b/scripts/ssl-common.h @@ -3,7 +3,7 @@ * SSL helper functions shared by sign-file and extract-cert. */ -static void display_openssl_errors(int l) +static void drain_openssl_errors(int l, int silent) { const char *file; char buf[120]; @@ -11,28 +11,21 @@ static void display_openssl_errors(int l) if (ERR_peek_error() == 0) return; - fprintf(stderr, "At main.c:%d:\n", l); + if (!silent) + fprintf(stderr, "At main.c:%d:\n", l); - while ((e = ERR_get_error_line(&file, &line))) { + while ((e = ERR_peek_error_line(&file, &line))) { ERR_error_string(e, buf); - fprintf(stderr, "- SSL %s: %s:%d\n", buf, file, line); + if (!silent) + fprintf(stderr, "- SSL %s: %s:%d\n", buf, file, line); + ERR_get_error(); } } -static void drain_openssl_errors(void) -{ - const char *file; - int line; - - if (ERR_peek_error() == 0) - return; - while (ERR_get_error_line(&file, &line)) {} -} - #define ERR(cond, fmt, ...) \ do { \ bool __cond = (cond); \ - display_openssl_errors(__LINE__); \ + drain_openssl_errors(__LINE__, 0); \ if (__cond) { \ errx(1, fmt, ## __VA_ARGS__); \ } \ From 03af77aa9c03ecb731944a91c243ae9749bca5ee Mon Sep 17 00:00:00 2001 From: Karolina Stolarek Date: Wed, 13 Mar 2024 15:21:42 +0100 Subject: [PATCH 386/606] drm/tests: Build KMS helpers when DRM_KUNIT_TEST_HELPERS is enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f1a785101d50f5844ed29341142e7224b87f705d upstream. Commit 66671944e176 ("drm/tests: helpers: Add atomic helpers") introduced a dependency on CRTC helpers in KUnit test helpers. Select the former when building KUnit test helpers to avoid linker errors. Fixes: 66671944e176 ("drm/tests: helpers: Add atomic helpers") Cc: Maxime Ripard Cc: Maíra Canal Signed-off-by: Karolina Stolarek Link: https://lore.kernel.org/r/20240313142142.1318718-1-karolina.stolarek@intel.com Signed-off-by: Maxime Ripard Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index ec4abf9ff47b..a2b4c97bcb31 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -69,6 +69,7 @@ config DRM_USE_DYNAMIC_DEBUG config DRM_KUNIT_TEST_HELPERS tristate depends on DRM && KUNIT + select DRM_KMS_HELPER help KUnit Helpers for KMS drivers. @@ -79,7 +80,6 @@ config DRM_KUNIT_TEST select DRM_DISPLAY_DP_HELPER select DRM_DISPLAY_HELPER select DRM_LIB_RANDOM - select DRM_KMS_HELPER select DRM_BUDDY select DRM_EXPORT_FOR_TESTS if m select DRM_KUNIT_TEST_HELPERS From 2eb70f54ad8634b63402bd9bcea8e4ee5af85add Mon Sep 17 00:00:00 2001 From: Jan Stancek Date: Fri, 20 Sep 2024 19:52:48 +0300 Subject: [PATCH 387/606] sign-file,extract-cert: use pkcs11 provider for OPENSSL MAJOR >= 3 commit 558bdc45dfb2669e1741384a0c80be9c82fa052c upstream. ENGINE API has been deprecated since OpenSSL version 3.0 [1]. Distros have started dropping support from headers and in future it will likely disappear also from library. It has been superseded by the PROVIDER API, so use it instead for OPENSSL MAJOR >= 3. [1] https://github.com/openssl/openssl/blob/master/README-ENGINES.md [jarkko: fixed up alignment issues reported by checkpatch.pl --strict] Signed-off-by: Jan Stancek Reviewed-by: Jarkko Sakkinen Tested-by: R Nageswara Sastry Reviewed-by: Neal Gompa Signed-off-by: Jarkko Sakkinen Signed-off-by: Huacai Chen Signed-off-by: Greg Kroah-Hartman --- certs/extract-cert.c | 103 ++++++++++++++++++++++++++++++------------- scripts/sign-file.c | 95 +++++++++++++++++++++++++++------------ 2 files changed, 139 insertions(+), 59 deletions(-) diff --git a/certs/extract-cert.c b/certs/extract-cert.c index 61bbe0085671..7d6d468ed612 100644 --- a/certs/extract-cert.c +++ b/certs/extract-cert.c @@ -21,17 +21,18 @@ #include #include #include -#include - +#if OPENSSL_VERSION_MAJOR >= 3 +# define USE_PKCS11_PROVIDER +# include +# include +#else +# if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_DEPRECATED_3_0) +# define USE_PKCS11_ENGINE +# include +# endif +#endif #include "ssl-common.h" -/* - * OpenSSL 3.0 deprecates the OpenSSL's ENGINE API. - * - * Remove this if/when that API is no longer used - */ -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - #define PKEY_ID_PKCS7 2 static __attribute__((noreturn)) @@ -61,6 +62,66 @@ static void write_cert(X509 *x509) fprintf(stderr, "Extracted cert: %s\n", buf); } +static X509 *load_cert_pkcs11(const char *cert_src) +{ + X509 *cert = NULL; +#ifdef USE_PKCS11_PROVIDER + OSSL_STORE_CTX *store; + + if (!OSSL_PROVIDER_try_load(NULL, "pkcs11", true)) + ERR(1, "OSSL_PROVIDER_try_load(pkcs11)"); + if (!OSSL_PROVIDER_try_load(NULL, "default", true)) + ERR(1, "OSSL_PROVIDER_try_load(default)"); + + store = OSSL_STORE_open(cert_src, NULL, NULL, NULL, NULL); + ERR(!store, "OSSL_STORE_open"); + + while (!OSSL_STORE_eof(store)) { + OSSL_STORE_INFO *info = OSSL_STORE_load(store); + + if (!info) { + drain_openssl_errors(__LINE__, 0); + continue; + } + if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_CERT) { + cert = OSSL_STORE_INFO_get1_CERT(info); + ERR(!cert, "OSSL_STORE_INFO_get1_CERT"); + } + OSSL_STORE_INFO_free(info); + if (cert) + break; + } + OSSL_STORE_close(store); +#elif defined(USE_PKCS11_ENGINE) + ENGINE *e; + struct { + const char *cert_id; + X509 *cert; + } parms; + + parms.cert_id = cert_src; + parms.cert = NULL; + + ENGINE_load_builtin_engines(); + drain_openssl_errors(__LINE__, 1); + e = ENGINE_by_id("pkcs11"); + ERR(!e, "Load PKCS#11 ENGINE"); + if (ENGINE_init(e)) + drain_openssl_errors(__LINE__, 1); + else + ERR(1, "ENGINE_init"); + if (key_pass) + ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0), "Set PKCS#11 PIN"); + ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, &parms, NULL, 1); + ERR(!parms.cert, "Get X.509 from PKCS#11"); + cert = parms.cert; +#else + fprintf(stderr, "no pkcs11 engine/provider available\n"); + exit(1); +#endif + return cert; +} + int main(int argc, char **argv) { char *cert_src; @@ -89,28 +150,10 @@ int main(int argc, char **argv) fclose(f); exit(0); } else if (!strncmp(cert_src, "pkcs11:", 7)) { - ENGINE *e; - struct { - const char *cert_id; - X509 *cert; - } parms; + X509 *cert = load_cert_pkcs11(cert_src); - parms.cert_id = cert_src; - parms.cert = NULL; - - ENGINE_load_builtin_engines(); - drain_openssl_errors(__LINE__, 1); - e = ENGINE_by_id("pkcs11"); - ERR(!e, "Load PKCS#11 ENGINE"); - if (ENGINE_init(e)) - drain_openssl_errors(__LINE__, 1); - else - ERR(1, "ENGINE_init"); - if (key_pass) - ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0), "Set PKCS#11 PIN"); - ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, &parms, NULL, 1); - ERR(!parms.cert, "Get X.509 from PKCS#11"); - write_cert(parms.cert); + ERR(!cert, "load_cert_pkcs11 failed"); + write_cert(cert); } else { BIO *b; X509 *x509; diff --git a/scripts/sign-file.c b/scripts/sign-file.c index bb3fdf1a617c..7070245edfc1 100644 --- a/scripts/sign-file.c +++ b/scripts/sign-file.c @@ -27,17 +27,18 @@ #include #include #include -#include - +#if OPENSSL_VERSION_MAJOR >= 3 +# define USE_PKCS11_PROVIDER +# include +# include +#else +# if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_DEPRECATED_3_0) +# define USE_PKCS11_ENGINE +# include +# endif +#endif #include "ssl-common.h" -/* - * OpenSSL 3.0 deprecates the OpenSSL's ENGINE API. - * - * Remove this if/when that API is no longer used - */ -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - /* * Use CMS if we have openssl-1.0.0 or newer available - otherwise we have to * assume that it's not available and its header file is missing and that we @@ -106,28 +107,64 @@ static int pem_pw_cb(char *buf, int len, int w, void *v) return pwlen; } +static EVP_PKEY *read_private_key_pkcs11(const char *private_key_name) +{ + EVP_PKEY *private_key = NULL; +#ifdef USE_PKCS11_PROVIDER + OSSL_STORE_CTX *store; + + if (!OSSL_PROVIDER_try_load(NULL, "pkcs11", true)) + ERR(1, "OSSL_PROVIDER_try_load(pkcs11)"); + if (!OSSL_PROVIDER_try_load(NULL, "default", true)) + ERR(1, "OSSL_PROVIDER_try_load(default)"); + + store = OSSL_STORE_open(private_key_name, NULL, NULL, NULL, NULL); + ERR(!store, "OSSL_STORE_open"); + + while (!OSSL_STORE_eof(store)) { + OSSL_STORE_INFO *info = OSSL_STORE_load(store); + + if (!info) { + drain_openssl_errors(__LINE__, 0); + continue; + } + if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PKEY) { + private_key = OSSL_STORE_INFO_get1_PKEY(info); + ERR(!private_key, "OSSL_STORE_INFO_get1_PKEY"); + } + OSSL_STORE_INFO_free(info); + if (private_key) + break; + } + OSSL_STORE_close(store); +#elif defined(USE_PKCS11_ENGINE) + ENGINE *e; + + ENGINE_load_builtin_engines(); + drain_openssl_errors(__LINE__, 1); + e = ENGINE_by_id("pkcs11"); + ERR(!e, "Load PKCS#11 ENGINE"); + if (ENGINE_init(e)) + drain_openssl_errors(__LINE__, 1); + else + ERR(1, "ENGINE_init"); + if (key_pass) + ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0), "Set PKCS#11 PIN"); + private_key = ENGINE_load_private_key(e, private_key_name, NULL, NULL); + ERR(!private_key, "%s", private_key_name); +#else + fprintf(stderr, "no pkcs11 engine/provider available\n"); + exit(1); +#endif + return private_key; +} + static EVP_PKEY *read_private_key(const char *private_key_name) { - EVP_PKEY *private_key; - if (!strncmp(private_key_name, "pkcs11:", 7)) { - ENGINE *e; - - ENGINE_load_builtin_engines(); - drain_openssl_errors(__LINE__, 1); - e = ENGINE_by_id("pkcs11"); - ERR(!e, "Load PKCS#11 ENGINE"); - if (ENGINE_init(e)) - drain_openssl_errors(__LINE__, 1); - else - ERR(1, "ENGINE_init"); - if (key_pass) - ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0), - "Set PKCS#11 PIN"); - private_key = ENGINE_load_private_key(e, private_key_name, - NULL, NULL); - ERR(!private_key, "%s", private_key_name); + return read_private_key_pkcs11(private_key_name); } else { + EVP_PKEY *private_key; BIO *b; b = BIO_new_file(private_key_name, "rb"); @@ -136,9 +173,9 @@ static EVP_PKEY *read_private_key(const char *private_key_name) NULL); ERR(!private_key, "%s", private_key_name); BIO_free(b); - } - return private_key; + return private_key; + } } static X509 *read_x509(const char *x509_name) From e7144dae6bba4d2dc4317ab54af927eff6f86422 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 2 Apr 2025 09:42:07 +0200 Subject: [PATCH 388/606] ALSA: hda/realtek: Fix built-in mic on another ASUS VivoBook model commit 8983dc1b66c0e1928a263b8af0bb06f6cb9229c4 upstream. There is another VivoBook model which built-in mic got broken recently by the fix of the pin sort. Apply the correct quirk ALC256_FIXUP_ASUS_MIC_NO_PRESENCE to this model for addressing the regression, too. Fixes: 3b4309546b48 ("ALSA: hda: Fix headset detection failure due to unstable sort") Closes: https://lore.kernel.org/Z95s5T6OXFPjRnKf@eldamar.lan Link: https://patch.msgid.link/20250402074208.7347-1-tiwai@suse.de Signed-off-by: Takashi Iwai [ Salvatore Bonaccorso: Update for context change due to missing other quirk entries in the struct snd_pci_quirk alc269_fixup_tbl ] Signed-off-by: Salvatore Bonaccorso Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 5179061f57b5..2f3f295f2b0c 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -10238,6 +10238,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1c33, "ASUS UX5304MA", ALC245_FIXUP_CS35L41_SPI_2), SND_PCI_QUIRK(0x1043, 0x1c43, "ASUS UX8406MA", ALC245_FIXUP_CS35L41_SPI_2), SND_PCI_QUIRK(0x1043, 0x1c62, "ASUS GU603", ALC289_FIXUP_ASUS_GA401), + SND_PCI_QUIRK(0x1043, 0x1c80, "ASUS VivoBook TP401", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x1c92, "ASUS ROG Strix G15", ALC285_FIXUP_ASUS_G533Z_PINS), SND_PCI_QUIRK(0x1043, 0x1c9f, "ASUS G614JU/JV/JI", ALC285_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x1caf, "ASUS G634JY/JZ/JI/JG", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS), From 23ec0b4057294d86cdefafe373b1f03568f75aff Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 25 Apr 2025 10:45:59 +0200 Subject: [PATCH 389/606] Linux 6.6.88 Link: https://lore.kernel.org/r/20250423142643.246005366@linuxfoundation.org Tested-by: Peter Schneider Tested-by: Shuah Khan Tested-by: Ron Economos Tested-by: Jon Hunter Tested-by: Mark Brown Tested-by: Florian Fainelli Tested-by: Miguel Ojeda Tested-by: Linux Kernel Functional Testing Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 18ca8d458fa4..b1dfe3df7dfc 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 6 PATCHLEVEL = 6 -SUBLEVEL = 87 +SUBLEVEL = 88 EXTRAVERSION = NAME = Pinguïn Aangedreven From 96e027296cdc9b188df5af99661f1ed718c378f4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 30 Apr 2025 16:47:45 +0000 Subject: [PATCH 390/606] Revert "arm64: errata: Add newer ARM cores to the spectre_bhb_loop_affected() lists" This reverts commit 4117975672c4743cffaf32b6fd018cfacd1b420e which is commit a5951389e58d2e816eed3dbec5877de9327fd881 upstream. It breaks the Pixel 9 boot tests, so it needs to be reverted. It can come back later if someone figures out what's going wrong here... Bug: 414805007 Change-Id: I7a7dad01bc9ec0eb5a5eb29912226e0c1ef84985 Signed-off-by: Greg Kroah-Hartman --- arch/arm64/kernel/proton-pack.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c index ecfbff6991bb..36a1f9a16a73 100644 --- a/arch/arm64/kernel/proton-pack.c +++ b/arch/arm64/kernel/proton-pack.c @@ -876,14 +876,6 @@ static u8 spectre_bhb_loop_affected(void) { u8 k = 0; - static const struct midr_range spectre_bhb_k132_list[] = { - MIDR_ALL_VERSIONS(MIDR_CORTEX_X3), - MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V2), - }; - static const struct midr_range spectre_bhb_k38_list[] = { - MIDR_ALL_VERSIONS(MIDR_CORTEX_A715), - MIDR_ALL_VERSIONS(MIDR_CORTEX_A720), - }; static const struct midr_range spectre_bhb_k32_list[] = { MIDR_ALL_VERSIONS(MIDR_CORTEX_A78), MIDR_ALL_VERSIONS(MIDR_CORTEX_A78AE), @@ -897,7 +889,6 @@ static u8 spectre_bhb_loop_affected(void) }; static const struct midr_range spectre_bhb_k24_list[] = { MIDR_ALL_VERSIONS(MIDR_CORTEX_A76), - MIDR_ALL_VERSIONS(MIDR_CORTEX_A76AE), MIDR_ALL_VERSIONS(MIDR_CORTEX_A77), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_GOLD), @@ -913,11 +904,7 @@ static u8 spectre_bhb_loop_affected(void) {}, }; - if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k132_list)) - k = 132; - else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k38_list)) - k = 38; - else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k32_list)) + if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k32_list)) k = 32; else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k24_list)) k = 24; From f8bfb03c957e5b80d68c31ebf5cce62e8d594251 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 30 Apr 2025 07:06:29 +0000 Subject: [PATCH 391/606] ANDROID: GKI: Add bpf_redirect_info to virtual_device symbol list. In commit 202bca49b7f9 ("xdp: Reset bpf_redirect_info before running a xdp's BPF prog."), the bpf_redirect_info symbol is added to the virtio_net module, but that symbol is not currently exported by the GKI symbol lists. Fix this up by adding it to the symbol tables. Fixes: 202bca49b7f9 ("xdp: Reset bpf_redirect_info before running a xdp's BPF prog.") Change-Id: Ia5751e5c09127d875d8e5e44c71fa1c13f251054 Signed-off-by: Greg Kroah-Hartman --- android/abi_gki_aarch64.stg | 106 +++++++++++++++++++++++++ android/abi_gki_aarch64_virtual_device | 1 + 2 files changed, 107 insertions(+) diff --git a/android/abi_gki_aarch64.stg b/android/abi_gki_aarch64.stg index 3c34edd57c66..9f9a4eb216c3 100644 --- a/android/abi_gki_aarch64.stg +++ b/android/abi_gki_aarch64.stg @@ -43671,6 +43671,11 @@ member { type_id: 0x69fa9768 offset: 256 } +member { + id: 0x39d6d358 + type_id: 0x6875099c + offset: 32 +} member { id: 0x39e9b87f type_id: 0x6888b6e5 @@ -116525,6 +116530,11 @@ member { type_id: 0x34544a3f offset: 1216 } +member { + id: 0xfa946861 + name: "ipv4_nh" + type_id: 0xc9082b19 +} member { id: 0x3b9e102b name: "ipv6" @@ -116594,6 +116604,11 @@ member { type_id: 0x12e0cbae offset: 704 } +member { + id: 0xab39140b + name: "ipv6_nh" + type_id: 0x6d25e07f +} member { id: 0x9cf559e0 name: "ipv6_pinfo_offset" @@ -119164,6 +119179,12 @@ member { type_id: 0x340dea21 offset: 384 } +member { + id: 0x632a482d + name: "kern_flags" + type_id: 0xc9082b19 + offset: 224 +} member { id: 0x3afd0e3e name: "kern_hyp_va" @@ -127557,6 +127578,12 @@ member { name: "map" type_id: 0x04b193cc } +member { + id: 0x8df2c9e6 + name: "map" + type_id: 0x04b193cc + offset: 128 +} member { id: 0x8df87907 name: "map" @@ -127792,6 +127819,12 @@ member { name: "map_id" type_id: 0xe62ebf07 } +member { + id: 0x86e8b50e + name: "map_id" + type_id: 0xc9082b19 + offset: 256 +} member { id: 0xa32be5db name: "map_ifindex" @@ -128088,6 +128121,12 @@ member { type_id: 0x6e73208e offset: 192 } +member { + id: 0x2a09386d + name: "map_type" + type_id: 0x6e73208e + offset: 288 +} member { id: 0x2a261544 name: "map_type" @@ -141594,6 +141633,12 @@ member { name: "nh" type_id: 0x1f9da9a8 } +member { + id: 0x713b4511 + name: "nh" + type_id: 0x1e9c55da + offset: 320 +} member { id: 0xdb1c1db1 name: "nh_all" @@ -141622,6 +141667,11 @@ member { name: "nh_entry" type_id: 0x17b2105b } +member { + id: 0xd51ec347 + name: "nh_family" + type_id: 0xc9082b19 +} member { id: 0x9fb787a3 name: "nh_flags" @@ -199512,6 +199562,11 @@ member { name: "tgt" type_id: 0x3df0a7d3 } +member { + id: 0x073a3a88 + name: "tgt_index" + type_id: 0x92233392 +} member { id: 0xe9c20711 name: "tgt_qps" @@ -199524,6 +199579,12 @@ member { type_id: 0x28b9ec9a offset: 192 } +member { + id: 0xc9d6516c + name: "tgt_value" + type_id: 0x18bd6530 + offset: 64 +} member { id: 0x141d2755 name: "thaw" @@ -226777,6 +226838,15 @@ struct_union { member_id: 0x12f2249e } } +struct_union { + id: 0x6875099c + kind: UNION + definition { + bytesize: 16 + member_id: 0xfa946861 + member_id: 0xab39140b + } +} struct_union { id: 0x6888b6e5 kind: UNION @@ -231444,6 +231514,16 @@ struct_union { member_id: 0x982b4630 } } +struct_union { + id: 0x1e9c55da + kind: STRUCT + name: "bpf_nh_params" + definition { + bytesize: 20 + member_id: 0xd51ec347 + member_id: 0x39d6d358 + } +} struct_union { id: 0x3b3bbe3f kind: STRUCT @@ -231640,6 +231720,22 @@ struct_union { member_id: 0x0082372e } } +struct_union { + id: 0x212d37a1 + kind: STRUCT + name: "bpf_redirect_info" + definition { + bytesize: 64 + member_id: 0x073a3a88 + member_id: 0xc9d6516c + member_id: 0x8df2c9e6 + member_id: 0x2da184bc + member_id: 0x632a482d + member_id: 0x86e8b50e + member_id: 0x2a09386d + member_id: 0x713b4511 + } +} struct_union { id: 0x3a354a67 kind: STRUCT @@ -376131,6 +376227,15 @@ elf_symbol { type_id: 0x1de47b51 full_name: "bpf_prog_sub" } +elf_symbol { + id: 0x56b332ad + name: "bpf_redirect_info" + is_defined: true + symbol_type: OBJECT + crc: 0x678abaea + type_id: 0x212d37a1 + full_name: "bpf_redirect_info" +} elf_symbol { id: 0x6a712ee1 name: "bpf_stats_enabled_key" @@ -437615,6 +437720,7 @@ interface { symbol_id: 0x6ad917a1 symbol_id: 0xdeb1861d symbol_id: 0x7661d150 + symbol_id: 0x56b332ad symbol_id: 0x6a712ee1 symbol_id: 0xe594a242 symbol_id: 0x3afeb397 diff --git a/android/abi_gki_aarch64_virtual_device b/android/abi_gki_aarch64_virtual_device index db28f9c6be75..b13482c21b31 100644 --- a/android/abi_gki_aarch64_virtual_device +++ b/android/abi_gki_aarch64_virtual_device @@ -12,6 +12,7 @@ __arch_copy_to_user arm64_use_ng_mappings bcmp + bpf_redirect_info bpf_trace_run1 bpf_trace_run2 bpf_trace_run3 From 247395cbec421935d7b3ef1a006e7076587b7af1 Mon Sep 17 00:00:00 2001 From: Thorsten Leemhuis Date: Wed, 16 Oct 2024 16:18:41 +0200 Subject: [PATCH 392/606] module: sign with sha512 instead of sha1 by default commit f3b93547b91ad849b58eb5ab2dd070950ad7beb3 upstream. Switch away from using sha1 for module signing by default and use the more modern sha512 instead, which is what among others Arch, Fedora, RHEL, and Ubuntu are currently using for their kernels. Sha1 has not been considered secure against well-funded opponents since 2005[1]; since 2011 the NIST and other organizations furthermore recommended its replacement[2]. This is why OpenSSL on RHEL9, Fedora Linux 41+[3], and likely some other current and future distributions reject the creation of sha1 signatures, which leads to a build error of allmodconfig configurations: 80A20474797F0000:error:03000098:digital envelope routines:do_sigver_init:invalid digest:crypto/evp/m_sigver.c:342: make[4]: *** [.../certs/Makefile:53: certs/signing_key.pem] Error 1 make[4]: *** Deleting file 'certs/signing_key.pem' make[4]: *** Waiting for unfinished jobs.... make[3]: *** [.../scripts/Makefile.build:478: certs] Error 2 make[2]: *** [.../Makefile:1936: .] Error 2 make[1]: *** [.../Makefile:224: __sub-make] Error 2 make[1]: Leaving directory '...' make: *** [Makefile:224: __sub-make] Error 2 This change makes allmodconfig work again and sets a default that is more appropriate for current and future users, too. Link: https://www.schneier.com/blog/archives/2005/02/cryptanalysis_o.html [1] Link: https://csrc.nist.gov/projects/hash-functions [2] Link: https://fedoraproject.org/wiki/Changes/OpenSSLDistrustsha1SigVer [3] Signed-off-by: Thorsten Leemhuis Reviewed-by: Sami Tolvanen Tested-by: kdevops [0] Link: https://github.com/linux-kdevops/linux-modules-kpd/actions/runs/11420092929/job/31775404330 [0] Link: https://lore.kernel.org/r/52ee32c0c92afc4d3263cea1f8a1cdc809728aff.1729088288.git.linux@leemhuis.info Signed-off-by: Petr Pavlu Signed-off-by: Greg Kroah-Hartman --- kernel/module/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/module/Kconfig b/kernel/module/Kconfig index 33a2e991f608..b411315ecd3c 100644 --- a/kernel/module/Kconfig +++ b/kernel/module/Kconfig @@ -229,6 +229,7 @@ comment "Do not forget to sign required modules with scripts/sign-file" choice prompt "Which hash algorithm should modules be signed with?" depends on MODULE_SIG || IMA_APPRAISE_MODSIG + default MODULE_SIG_SHA512 help This determines which sort of hashing algorithm will be used during signature generation. This algorithm _must_ be built into the kernel From 415620362062e8992ed556a5e75a6b1e8aa3a513 Mon Sep 17 00:00:00 2001 From: Tong Tiangen Date: Sun, 4 Feb 2024 16:26:25 +0800 Subject: [PATCH 393/606] x86/extable: Remove unused fixup type EX_TYPE_COPY [ Upstream commit cb517619f96718a4c3c2534a3124177633f8998d ] After 034ff37d3407 ("x86: rewrite '__copy_user_nocache' function") rewrote __copy_user_nocache() to use EX_TYPE_UACCESS instead of the EX_TYPE_COPY exception type, there are no more EX_TYPE_COPY users, so remove it. [ bp: Massage commit message. ] Signed-off-by: Tong Tiangen Signed-off-by: Borislav Petkov (AMD) Link: https://lore.kernel.org/r/20240204082627.3892816-2-tongtiangen@huawei.com Stable-dep-of: 1a15bb8303b6 ("x86/mce: use is_copy_from_user() to determine copy-from-user context") Signed-off-by: Sasha Levin --- arch/x86/include/asm/asm.h | 3 --- arch/x86/include/asm/extable_fixup_types.h | 2 +- arch/x86/kernel/cpu/mce/severity.c | 1 - arch/x86/mm/extable.c | 9 --------- 4 files changed, 1 insertion(+), 14 deletions(-) diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h index ca8eed1d496a..2bec0c89a95c 100644 --- a/arch/x86/include/asm/asm.h +++ b/arch/x86/include/asm/asm.h @@ -229,9 +229,6 @@ register unsigned long current_stack_pointer asm(_ASM_SP); #define _ASM_EXTABLE_UA(from, to) \ _ASM_EXTABLE_TYPE(from, to, EX_TYPE_UACCESS) -#define _ASM_EXTABLE_CPY(from, to) \ - _ASM_EXTABLE_TYPE(from, to, EX_TYPE_COPY) - #define _ASM_EXTABLE_FAULT(from, to) \ _ASM_EXTABLE_TYPE(from, to, EX_TYPE_FAULT) diff --git a/arch/x86/include/asm/extable_fixup_types.h b/arch/x86/include/asm/extable_fixup_types.h index 991e31cfde94..afad9c0b07e0 100644 --- a/arch/x86/include/asm/extable_fixup_types.h +++ b/arch/x86/include/asm/extable_fixup_types.h @@ -36,7 +36,7 @@ #define EX_TYPE_DEFAULT 1 #define EX_TYPE_FAULT 2 #define EX_TYPE_UACCESS 3 -#define EX_TYPE_COPY 4 +/* unused, was: #define EX_TYPE_COPY 4 */ #define EX_TYPE_CLEAR_FS 5 #define EX_TYPE_FPU_RESTORE 6 #define EX_TYPE_BPF 7 diff --git a/arch/x86/kernel/cpu/mce/severity.c b/arch/x86/kernel/cpu/mce/severity.c index c4477162c07d..bca780fa5e57 100644 --- a/arch/x86/kernel/cpu/mce/severity.c +++ b/arch/x86/kernel/cpu/mce/severity.c @@ -290,7 +290,6 @@ static noinstr int error_context(struct mce *m, struct pt_regs *regs) switch (fixup_type) { case EX_TYPE_UACCESS: - case EX_TYPE_COPY: if (!copy_user) return IN_KERNEL; m->kflags |= MCE_IN_KERNEL_COPYIN; diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c index 271dcb2deabc..2354c0156e51 100644 --- a/arch/x86/mm/extable.c +++ b/arch/x86/mm/extable.c @@ -163,13 +163,6 @@ static bool ex_handler_uaccess(const struct exception_table_entry *fixup, return ex_handler_default(fixup, regs); } -static bool ex_handler_copy(const struct exception_table_entry *fixup, - struct pt_regs *regs, int trapnr) -{ - WARN_ONCE(trapnr == X86_TRAP_GP, "General protection fault in user access. Non-canonical address?"); - return ex_handler_fault(fixup, regs, trapnr); -} - static bool ex_handler_msr(const struct exception_table_entry *fixup, struct pt_regs *regs, bool wrmsr, bool safe, int reg) { @@ -267,8 +260,6 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code, return ex_handler_fault(e, regs, trapnr); case EX_TYPE_UACCESS: return ex_handler_uaccess(e, regs, trapnr, fault_addr); - case EX_TYPE_COPY: - return ex_handler_copy(e, regs, trapnr); case EX_TYPE_CLEAR_FS: return ex_handler_clear_fs(e, regs); case EX_TYPE_FPU_RESTORE: From 5724654a084f701dc64b08d34a0e800f22f0e6e4 Mon Sep 17 00:00:00 2001 From: Shuai Xue Date: Wed, 12 Mar 2025 19:28:50 +0800 Subject: [PATCH 394/606] x86/mce: use is_copy_from_user() to determine copy-from-user context [ Upstream commit 1a15bb8303b6b104e78028b6c68f76a0d4562134 ] Patch series "mm/hwpoison: Fix regressions in memory failure handling", v4. ## 1. What am I trying to do: This patchset resolves two critical regressions related to memory failure handling that have appeared in the upstream kernel since version 5.17, as compared to 5.10 LTS. - copyin case: poison found in user page while kernel copying from user space - instr case: poison found while instruction fetching in user space ## 2. What is the expected outcome and why - For copyin case: Kernel can recover from poison found where kernel is doing get_user() or copy_from_user() if those places get an error return and the kernel return -EFAULT to the process instead of crashing. More specifily, MCE handler checks the fixup handler type to decide whether an in kernel #MC can be recovered. When EX_TYPE_UACCESS is found, the PC jumps to recovery code specified in _ASM_EXTABLE_FAULT() and return a -EFAULT to user space. - For instr case: If a poison found while instruction fetching in user space, full recovery is possible. User process takes #PF, Linux allocates a new page and fills by reading from storage. ## 3. What actually happens and why - For copyin case: kernel panic since v5.17 Commit 4c132d1d844a ("x86/futex: Remove .fixup usage") introduced a new extable fixup type, EX_TYPE_EFAULT_REG, and later patches updated the extable fixup type for copy-from-user operations, changing it from EX_TYPE_UACCESS to EX_TYPE_EFAULT_REG. It breaks previous EX_TYPE_UACCESS handling when posion found in get_user() or copy_from_user(). - For instr case: user process is killed by a SIGBUS signal due to #CMCI and #MCE race When an uncorrected memory error is consumed there is a race between the CMCI from the memory controller reporting an uncorrected error with a UCNA signature, and the core reporting and SRAR signature machine check when the data is about to be consumed. ### Background: why *UN*corrected errors tied to *C*MCI in Intel platform [1] Prior to Icelake memory controllers reported patrol scrub events that detected a previously unseen uncorrected error in memory by signaling a broadcast machine check with an SRAO (Software Recoverable Action Optional) signature in the machine check bank. This was overkill because it's not an urgent problem that no core is on the verge of consuming that bad data. It's also found that multi SRAO UCE may cause nested MCE interrupts and finally become an IERR. Hence, Intel downgrades the machine check bank signature of patrol scrub from SRAO to UCNA (Uncorrected, No Action required), and signal changed to #CMCI. Just to add to the confusion, Linux does take an action (in uc_decode_notifier()) to try to offline the page despite the UC*NA* signature name. ### Background: why #CMCI and #MCE race when poison is consuming in Intel platform [1] Having decided that CMCI/UCNA is the best action for patrol scrub errors, the memory controller uses it for reads too. But the memory controller is executing asynchronously from the core, and can't tell the difference between a "real" read and a speculative read. So it will do CMCI/UCNA if an error is found in any read. Thus: 1) Core is clever and thinks address A is needed soon, issues a speculative read. 2) Core finds it is going to use address A soon after sending the read request 3) The CMCI from the memory controller is in a race with MCE from the core that will soon try to retire the load from address A. Quite often (because speculation has got better) the CMCI from the memory controller is delivered before the core is committed to the instruction reading address A, so the interrupt is taken, and Linux offlines the page (marking it as poison). ## Why user process is killed for instr case Commit 046545a661af ("mm/hwpoison: fix error page recovered but reported "not recovered"") tries to fix noise message "Memory error not recovered" and skips duplicate SIGBUSs due to the race. But it also introduced a bug that kill_accessing_process() return -EHWPOISON for instr case, as result, kill_me_maybe() send a SIGBUS to user process. # 4. The fix, in my opinion, should be: - For copyin case: The key point is whether the error context is in a read from user memory. We do not care about the ex-type if we know its a MOV reading from userspace. is_copy_from_user() return true when both of the following two checks are true: - the current instruction is copy - source address is user memory If copy_user is true, we set m->kflags |= MCE_IN_KERNEL_COPYIN | MCE_IN_KERNEL_RECOV; Then do_machine_check() will try fixup_exception() first. - For instr case: let kill_accessing_process() return 0 to prevent a SIGBUS. - For patch 3: The return value of memory_failure() is quite important while discussed instr case regression with Tony and Miaohe for patch 2, so add comment about the return value. This patch (of 3): Commit 4c132d1d844a ("x86/futex: Remove .fixup usage") introduced a new extable fixup type, EX_TYPE_EFAULT_REG, and commit 4c132d1d844a ("x86/futex: Remove .fixup usage") updated the extable fixup type for copy-from-user operations, changing it from EX_TYPE_UACCESS to EX_TYPE_EFAULT_REG. The error context for copy-from-user operations no longer functions as an in-kernel recovery context. Consequently, the error context for copy-from-user operations no longer functions as an in-kernel recovery context, resulting in kernel panics with the message: "Machine check: Data load in unrecoverable area of kernel." To address this, it is crucial to identify if an error context involves a read operation from user memory. The function is_copy_from_user() can be utilized to determine: - the current operation is copy - when reading user memory When these conditions are met, is_copy_from_user() will return true, confirming that it is indeed a direct copy from user memory. This check is essential for correctly handling the context of errors in these operations without relying on the extable fixup types that previously allowed for in-kernel recovery. So, use is_copy_from_user() to determine if a context is copy user directly. Link: https://lkml.kernel.org/r/20250312112852.82415-1-xueshuai@linux.alibaba.com Link: https://lkml.kernel.org/r/20250312112852.82415-2-xueshuai@linux.alibaba.com Fixes: 4c132d1d844a ("x86/futex: Remove .fixup usage") Signed-off-by: Shuai Xue Suggested-by: Peter Zijlstra Acked-by: Borislav Petkov (AMD) Tested-by: Tony Luck Cc: Baolin Wang Cc: Borislav Betkov Cc: Catalin Marinas Cc: Dave Hansen Cc: "H. Peter Anvin" Cc: Ingo Molnar Cc: Josh Poimboeuf Cc: Miaohe Lin Cc: Naoya Horiguchi Cc: Ruidong Tian Cc: Thomas Gleinxer Cc: Yazen Ghannam Cc: Jane Chu Cc: Jarkko Sakkinen Cc: Jonathan Cameron Cc: Signed-off-by: Andrew Morton Signed-off-by: Sasha Levin --- arch/x86/kernel/cpu/mce/severity.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/cpu/mce/severity.c b/arch/x86/kernel/cpu/mce/severity.c index bca780fa5e57..9c5754229d6e 100644 --- a/arch/x86/kernel/cpu/mce/severity.c +++ b/arch/x86/kernel/cpu/mce/severity.c @@ -288,13 +288,12 @@ static noinstr int error_context(struct mce *m, struct pt_regs *regs) copy_user = is_copy_from_user(regs); instrumentation_end(); - switch (fixup_type) { - case EX_TYPE_UACCESS: - if (!copy_user) - return IN_KERNEL; - m->kflags |= MCE_IN_KERNEL_COPYIN; - fallthrough; + if (copy_user) { + m->kflags |= MCE_IN_KERNEL_COPYIN | MCE_IN_KERNEL_RECOV; + return IN_KERNEL_RECOV; + } + switch (fixup_type) { case EX_TYPE_FAULT_MCE_SAFE: case EX_TYPE_DEFAULT_MCE_SAFE: m->kflags |= MCE_IN_KERNEL_RECOV; From 896e30f76840c9cc196927ee69109745fb23d499 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Google)" Date: Fri, 23 Feb 2024 15:28:27 -0500 Subject: [PATCH 395/606] tracing: Add __string_len() example [ Upstream commit dd6ae6d90a84d4bec49887c7aa2b22aa1c8b2897 ] There's no example code that uses __string_len(), and since the sample code is used for testing the event logic, add a use case. Link: https://lore.kernel.org/linux-trace-kernel/20240223152827.5f9f78e2@gandalf.local.home Cc: Masami Hiramatsu Cc: Mathieu Desnoyers Signed-off-by: Steven Rostedt (Google) Stable-dep-of: ea8d7647f9dd ("tracing: Verify event formats that have "%*p.."") Signed-off-by: Sasha Levin --- samples/trace_events/trace-events-sample.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/samples/trace_events/trace-events-sample.h b/samples/trace_events/trace-events-sample.h index 1c6b843b8c4e..04541dfbd44c 100644 --- a/samples/trace_events/trace-events-sample.h +++ b/samples/trace_events/trace-events-sample.h @@ -302,6 +302,7 @@ TRACE_EVENT(foo_bar, __bitmask( cpus, num_possible_cpus() ) __cpumask( cpum ) __vstring( vstr, fmt, va ) + __string_len( lstr, foo, bar / 2 < strlen(foo) ? bar / 2 : strlen(foo) ) ), TP_fast_assign( @@ -310,12 +311,13 @@ TRACE_EVENT(foo_bar, memcpy(__get_dynamic_array(list), lst, __length_of(lst) * sizeof(int)); __assign_str(str, string); + __assign_str(lstr, foo); __assign_vstr(vstr, fmt, va); __assign_bitmask(cpus, cpumask_bits(mask), num_possible_cpus()); __assign_cpumask(cpum, cpumask_bits(mask)); ), - TP_printk("foo %s %d %s %s %s %s (%s) (%s) %s", __entry->foo, __entry->bar, + TP_printk("foo %s %d %s %s %s %s %s (%s) (%s) %s", __entry->foo, __entry->bar, /* * Notice here the use of some helper functions. This includes: @@ -359,7 +361,8 @@ TRACE_EVENT(foo_bar, __print_array(__get_dynamic_array(list), __get_dynamic_array_len(list) / sizeof(int), sizeof(int)), - __get_str(str), __get_bitmask(cpus), __get_cpumask(cpum), + __get_str(str), __get_str(lstr), + __get_bitmask(cpus), __get_cpumask(cpum), __get_str(vstr)) ); From e13358c4884d9e824462232f86655bbb8c06cb30 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 22 Oct 2024 19:36:28 +0000 Subject: [PATCH 396/606] tracing: Add __print_dynamic_array() helper [ Upstream commit e52750fb1458ae9ea5860a08ed7a149185bc5b97 ] When printing a dynamic array in a trace event, the method is rather ugly. It has the format of: __print_array(__get_dynamic_array(array), __get_dynmaic_array_len(array) / el_size, el_size) Since dynamic arrays are known to the tracing infrastructure, create a helper macro that does the above for you. __print_dynamic_array(array, el_size) Which would expand to the same output. Signed-off-by: Steven Rostedt (Google) Signed-off-by: Avadhut Naik Signed-off-by: Borislav Petkov (AMD) Reviewed-by: Qiuxu Zhuo Link: https://lore.kernel.org/r/20241022194158.110073-3-avadhut.naik@amd.com Stable-dep-of: ea8d7647f9dd ("tracing: Verify event formats that have "%*p.."") Signed-off-by: Sasha Levin --- include/trace/stages/stage3_trace_output.h | 8 ++++++++ include/trace/stages/stage7_class_define.h | 1 + samples/trace_events/trace-events-sample.h | 7 ++++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/include/trace/stages/stage3_trace_output.h b/include/trace/stages/stage3_trace_output.h index c1fb1355d309..1e7b0bef95f5 100644 --- a/include/trace/stages/stage3_trace_output.h +++ b/include/trace/stages/stage3_trace_output.h @@ -119,6 +119,14 @@ trace_print_array_seq(p, array, count, el_size); \ }) +#undef __print_dynamic_array +#define __print_dynamic_array(array, el_size) \ + ({ \ + __print_array(__get_dynamic_array(array), \ + __get_dynamic_array_len(array) / (el_size), \ + (el_size)); \ + }) + #undef __print_hex_dump #define __print_hex_dump(prefix_str, prefix_type, \ rowsize, groupsize, buf, len, ascii) \ diff --git a/include/trace/stages/stage7_class_define.h b/include/trace/stages/stage7_class_define.h index bcb960d16fc0..fcd564a590f4 100644 --- a/include/trace/stages/stage7_class_define.h +++ b/include/trace/stages/stage7_class_define.h @@ -22,6 +22,7 @@ #undef __get_rel_cpumask #undef __get_rel_sockaddr #undef __print_array +#undef __print_dynamic_array #undef __print_hex_dump #undef __get_buf diff --git a/samples/trace_events/trace-events-sample.h b/samples/trace_events/trace-events-sample.h index 04541dfbd44c..24ec968d481f 100644 --- a/samples/trace_events/trace-events-sample.h +++ b/samples/trace_events/trace-events-sample.h @@ -317,7 +317,7 @@ TRACE_EVENT(foo_bar, __assign_cpumask(cpum, cpumask_bits(mask)); ), - TP_printk("foo %s %d %s %s %s %s %s (%s) (%s) %s", __entry->foo, __entry->bar, + TP_printk("foo %s %d %s %s %s %s %s %s (%s) (%s) %s", __entry->foo, __entry->bar, /* * Notice here the use of some helper functions. This includes: @@ -361,6 +361,11 @@ TRACE_EVENT(foo_bar, __print_array(__get_dynamic_array(list), __get_dynamic_array_len(list) / sizeof(int), sizeof(int)), + +/* A shortcut is to use __print_dynamic_array for dynamic arrays */ + + __print_dynamic_array(list, sizeof(int)), + __get_str(str), __get_str(lstr), __get_bitmask(cpus), __get_cpumask(cpum), __get_str(vstr)) From 4d11fac941d83509be4e6a21038281d6d96da50c Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Thu, 27 Mar 2025 19:53:11 -0400 Subject: [PATCH 397/606] tracing: Verify event formats that have "%*p.." [ Upstream commit ea8d7647f9ddf1f81e2027ed305299797299aa03 ] The trace event verifier checks the formats of trace events to make sure that they do not point at memory that is not in the trace event itself or in data that will never be freed. If an event references data that was allocated when the event triggered and that same data is freed before the event is read, then the kernel can crash by reading freed memory. The verifier runs at boot up (or module load) and scans the print formats of the events and checks their arguments to make sure that dereferenced pointers are safe. If the format uses "%*p.." the verifier will ignore it, and that could be dangerous. Cover this case as well. Also add to the sample code a use case of "%*pbl". Link: https://lore.kernel.org/all/bcba4d76-2c3f-4d11-baf0-02905db953dd@oracle.com/ Cc: stable@vger.kernel.org Cc: Masami Hiramatsu Cc: Mathieu Desnoyers Fixes: 5013f454a352c ("tracing: Add check of trace event print fmts for dereferencing pointers") Link: https://lore.kernel.org/20250327195311.2d89ec66@gandalf.local.home Reported-by: Libo Chen Reviewed-by: Libo Chen Tested-by: Libo Chen Signed-off-by: Steven Rostedt (Google) Signed-off-by: Sasha Levin --- kernel/trace/trace_events.c | 7 +++++++ samples/trace_events/trace-events-sample.h | 8 ++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 1a936978c2b1..5f74e9f9c8a7 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -470,6 +470,7 @@ static void test_event_printk(struct trace_event_call *call) case '%': continue; case 'p': + do_pointer: /* Find dereferencing fields */ switch (fmt[i + 1]) { case 'B': case 'R': case 'r': @@ -498,6 +499,12 @@ static void test_event_printk(struct trace_event_call *call) continue; if (fmt[i + j] == '*') { star = true; + /* Handle %*pbl case */ + if (!j && fmt[i + 1] == 'p') { + arg++; + i++; + goto do_pointer; + } continue; } if ((fmt[i + j] == 's')) { diff --git a/samples/trace_events/trace-events-sample.h b/samples/trace_events/trace-events-sample.h index 24ec968d481f..06be777b3b14 100644 --- a/samples/trace_events/trace-events-sample.h +++ b/samples/trace_events/trace-events-sample.h @@ -317,7 +317,8 @@ TRACE_EVENT(foo_bar, __assign_cpumask(cpum, cpumask_bits(mask)); ), - TP_printk("foo %s %d %s %s %s %s %s %s (%s) (%s) %s", __entry->foo, __entry->bar, + TP_printk("foo %s %d %s %s %s %s %s %s (%s) (%s) %s [%d] %*pbl", + __entry->foo, __entry->bar, /* * Notice here the use of some helper functions. This includes: @@ -368,7 +369,10 @@ TRACE_EVENT(foo_bar, __get_str(str), __get_str(lstr), __get_bitmask(cpus), __get_cpumask(cpum), - __get_str(vstr)) + __get_str(vstr), + __get_dynamic_array_len(cpus), + __get_dynamic_array_len(cpus), + __get_dynamic_array(cpus)) ); /* From beeeea11ee2a09230b3fd4863563d99b7b23c8f0 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 24 Apr 2024 18:39:07 +0300 Subject: [PATCH 398/606] media: subdev: Fix use of sd->enabled_streams in call_s_stream() [ Upstream commit 1d7804281df3f09f0a109d00406e859a00bae7ae ] call_s_stream() uses sd->enabled_streams to track whether streaming has already been enabled. However, v4l2_subdev_enable/disable_streams_fallback(), which was the original user of this field, already uses it, and v4l2_subdev_enable/disable_streams_fallback() will call call_s_stream(). This leads to a conflict as both functions set the field. Afaics, both functions set the field to the same value, so it won't cause a runtime bug, but it's still wrong and if we, e.g., change how v4l2_subdev_enable/disable_streams_fallback() operates we might easily cause bugs. Fix this by adding a new field, 's_stream_enabled', for call_s_stream(). Reviewed-by: Umang Jain Reviewed-by: Laurent Pinchart Tested-by: Umang Jain Signed-off-by: Tomi Valkeinen Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil Stable-dep-of: 36cef585e2a3 ("media: vimc: skip .s_stream() for stopped entities") Signed-off-by: Sasha Levin --- drivers/media/v4l2-core/v4l2-subdev.c | 8 ++------ include/media/v4l2-subdev.h | 3 +++ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index a32ef739eb44..8bfbe9d5fe3c 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -363,12 +363,8 @@ static int call_s_stream(struct v4l2_subdev *sd, int enable) * The .s_stream() operation must never be called to start or stop an * already started or stopped subdev. Catch offenders but don't return * an error yet to avoid regressions. - * - * As .s_stream() is mutually exclusive with the .enable_streams() and - * .disable_streams() operation, we can use the enabled_streams field - * to store the subdev streaming state. */ - if (WARN_ON(!!sd->enabled_streams == !!enable)) + if (WARN_ON(sd->s_stream_enabled == !!enable)) return 0; ret = sd->ops->video->s_stream(sd, enable); @@ -379,7 +375,7 @@ static int call_s_stream(struct v4l2_subdev *sd, int enable) } if (!ret) { - sd->enabled_streams = enable ? BIT(0) : 0; + sd->s_stream_enabled = enable; #if IS_REACHABLE(CONFIG_LEDS_CLASS) if (!IS_ERR_OR_NULL(sd->privacy_led)) { diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index ab2a7ef61d42..ee570dfbd791 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -1042,6 +1042,8 @@ struct v4l2_subdev_platform_data { * v4l2_subdev_enable_streams() and * v4l2_subdev_disable_streams() helper functions for fallback * cases. + * @s_stream_enabled: Tracks whether streaming has been enabled with s_stream. + * This is only for call_s_stream() internal use. * * Each instance of a subdev driver should create this struct, either * stand-alone or embedded in a larger struct. @@ -1090,6 +1092,7 @@ struct v4l2_subdev { */ struct v4l2_subdev_state *active_state; u64 enabled_streams; + bool s_stream_enabled; }; From 2b3dc697a46580b050e9bc00373a2860a77d67c2 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 24 Apr 2024 18:39:08 +0300 Subject: [PATCH 399/606] media: subdev: Improve v4l2_subdev_enable/disable_streams_fallback [ Upstream commit 61d6c8c896c1ccde350c281817847a32b0c6b83b ] v4l2_subdev_enable/disable_streams_fallback() supports falling back to .s_stream() for subdevs with a single source pad. It also tracks the enabled streams for that one pad in the sd->enabled_streams field. Tracking the enabled streams with sd->enabled_streams does not make sense, as with .s_stream() there can only be a single stream per pad. Thus, as the v4l2_subdev_enable/disable_streams_fallback() only supports a single source pad, all we really need is a boolean which tells whether streaming has been enabled on this pad or not. However, as we only need a true/false state for a pad (instead of tracking which streams have been enabled for a pad), we can easily extend the fallback mechanism to support multiple source pads as we only need to keep track of which pads have been enabled. Change the sd->enabled_streams field to sd->enabled_pads, which is a 64-bit bitmask tracking the enabled source pads. With this change we can remove the restriction that v4l2_subdev_enable/disable_streams_fallback() only supports a single source pad. Reviewed-by: Laurent Pinchart Tested-by: Umang Jain Signed-off-by: Tomi Valkeinen Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil Stable-dep-of: 36cef585e2a3 ("media: vimc: skip .s_stream() for stopped entities") Signed-off-by: Sasha Levin --- drivers/media/v4l2-core/v4l2-subdev.c | 68 ++++++++++++++++----------- include/media/v4l2-subdev.h | 9 ++-- 2 files changed, 44 insertions(+), 33 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 8bfbe9d5fe3c..f555fd3c4b76 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -1925,37 +1925,43 @@ static int v4l2_subdev_enable_streams_fallback(struct v4l2_subdev *sd, u32 pad, u64 streams_mask) { struct device *dev = sd->entity.graph_obj.mdev->dev; - unsigned int i; int ret; /* * The subdev doesn't implement pad-based stream enable, fall back - * on the .s_stream() operation. This can only be done for subdevs that - * have a single source pad, as sd->enabled_streams is global to the - * subdev. + * to the .s_stream() operation. */ if (!(sd->entity.pads[pad].flags & MEDIA_PAD_FL_SOURCE)) return -EOPNOTSUPP; - for (i = 0; i < sd->entity.num_pads; ++i) { - if (i != pad && sd->entity.pads[i].flags & MEDIA_PAD_FL_SOURCE) - return -EOPNOTSUPP; - } + /* + * .s_stream() means there is no streams support, so the only allowed + * stream is the implicit stream 0. + */ + if (streams_mask != BIT_ULL(0)) + return -EOPNOTSUPP; - if (sd->enabled_streams & streams_mask) { - dev_dbg(dev, "set of streams %#llx already enabled on %s:%u\n", - streams_mask, sd->entity.name, pad); + /* + * We use a 64-bit bitmask for tracking enabled pads, so only subdevices + * with 64 pads or less can be supported. + */ + if (pad >= sizeof(sd->enabled_pads) * BITS_PER_BYTE) + return -EOPNOTSUPP; + + if (sd->enabled_pads & BIT_ULL(pad)) { + dev_dbg(dev, "pad %u already enabled on %s\n", + pad, sd->entity.name); return -EALREADY; } - /* Start streaming when the first streams are enabled. */ - if (!sd->enabled_streams) { + /* Start streaming when the first pad is enabled. */ + if (!sd->enabled_pads) { ret = v4l2_subdev_call(sd, video, s_stream, 1); if (ret) return ret; } - sd->enabled_streams |= streams_mask; + sd->enabled_pads |= BIT_ULL(pad); return 0; } @@ -2042,37 +2048,43 @@ static int v4l2_subdev_disable_streams_fallback(struct v4l2_subdev *sd, u32 pad, u64 streams_mask) { struct device *dev = sd->entity.graph_obj.mdev->dev; - unsigned int i; int ret; /* - * If the subdev doesn't implement pad-based stream enable, fall back - * on the .s_stream() operation. This can only be done for subdevs that - * have a single source pad, as sd->enabled_streams is global to the - * subdev. + * If the subdev doesn't implement pad-based stream enable, fall back + * to the .s_stream() operation. */ if (!(sd->entity.pads[pad].flags & MEDIA_PAD_FL_SOURCE)) return -EOPNOTSUPP; - for (i = 0; i < sd->entity.num_pads; ++i) { - if (i != pad && sd->entity.pads[i].flags & MEDIA_PAD_FL_SOURCE) - return -EOPNOTSUPP; - } + /* + * .s_stream() means there is no streams support, so the only allowed + * stream is the implicit stream 0. + */ + if (streams_mask != BIT_ULL(0)) + return -EOPNOTSUPP; - if ((sd->enabled_streams & streams_mask) != streams_mask) { - dev_dbg(dev, "set of streams %#llx already disabled on %s:%u\n", - streams_mask, sd->entity.name, pad); + /* + * We use a 64-bit bitmask for tracking enabled pads, so only subdevices + * with 64 pads or less can be supported. + */ + if (pad >= sizeof(sd->enabled_pads) * BITS_PER_BYTE) + return -EOPNOTSUPP; + + if (!(sd->enabled_pads & BIT_ULL(pad))) { + dev_dbg(dev, "pad %u already disabled on %s\n", + pad, sd->entity.name); return -EALREADY; } /* Stop streaming when the last streams are disabled. */ - if (!(sd->enabled_streams & ~streams_mask)) { + if (!(sd->enabled_pads & ~BIT_ULL(pad))) { ret = v4l2_subdev_call(sd, video, s_stream, 0); if (ret) return ret; } - sd->enabled_streams &= ~streams_mask; + sd->enabled_pads &= ~BIT_ULL(pad); return 0; } diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index ee570dfbd791..0a8d75b009ea 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -1038,10 +1038,9 @@ struct v4l2_subdev_platform_data { * @active_state: Active state for the subdev (NULL for subdevs tracking the * state internally). Initialized by calling * v4l2_subdev_init_finalize(). - * @enabled_streams: Bitmask of enabled streams used by - * v4l2_subdev_enable_streams() and - * v4l2_subdev_disable_streams() helper functions for fallback - * cases. + * @enabled_pads: Bitmask of enabled pads used by v4l2_subdev_enable_streams() + * and v4l2_subdev_disable_streams() helper functions for + * fallback cases. * @s_stream_enabled: Tracks whether streaming has been enabled with s_stream. * This is only for call_s_stream() internal use. * @@ -1091,7 +1090,7 @@ struct v4l2_subdev { * doesn't support it. */ struct v4l2_subdev_state *active_state; - u64 enabled_streams; + u64 enabled_pads; bool s_stream_enabled; }; From a64a102e01eba9c09947a39732e9318d44df71f8 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 24 Apr 2024 18:39:09 +0300 Subject: [PATCH 400/606] media: subdev: Add v4l2_subdev_is_streaming() [ Upstream commit 5f3ce14fae742d1d23061c3122d93edb879ebf53 ] Add a helper function which returns whether the subdevice is streaming, i.e. if .s_stream or .enable_streams has been called successfully. Reviewed-by: Umang Jain Reviewed-by: Laurent Pinchart Tested-by: Umang Jain Signed-off-by: Tomi Valkeinen Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil Stable-dep-of: 36cef585e2a3 ("media: vimc: skip .s_stream() for stopped entities") Signed-off-by: Sasha Levin --- drivers/media/v4l2-core/v4l2-subdev.c | 25 +++++++++++++++++++++++++ include/media/v4l2-subdev.h | 13 +++++++++++++ 2 files changed, 38 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index f555fd3c4b76..5f115438d072 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -2240,6 +2240,31 @@ void v4l2_subdev_notify_event(struct v4l2_subdev *sd, } EXPORT_SYMBOL_GPL(v4l2_subdev_notify_event); +bool v4l2_subdev_is_streaming(struct v4l2_subdev *sd) +{ + struct v4l2_subdev_state *state; + + if (!v4l2_subdev_has_op(sd, pad, enable_streams)) + return sd->s_stream_enabled; + + if (!(sd->flags & V4L2_SUBDEV_FL_STREAMS)) + return !!sd->enabled_pads; + + state = v4l2_subdev_get_locked_active_state(sd); + + for (unsigned int i = 0; i < state->stream_configs.num_configs; ++i) { + const struct v4l2_subdev_stream_config *cfg; + + cfg = &state->stream_configs.configs[i]; + + if (cfg->enabled) + return true; + } + + return false; +} +EXPORT_SYMBOL_GPL(v4l2_subdev_is_streaming); + int v4l2_subdev_get_privacy_led(struct v4l2_subdev *sd) { #if IS_REACHABLE(CONFIG_LEDS_CLASS) diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 0a8d75b009ea..b4fcd0164048 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -1918,4 +1918,17 @@ extern const struct v4l2_subdev_ops v4l2_subdev_call_wrappers; void v4l2_subdev_notify_event(struct v4l2_subdev *sd, const struct v4l2_event *ev); +/** + * v4l2_subdev_is_streaming() - Returns if the subdevice is streaming + * @sd: The subdevice + * + * v4l2_subdev_is_streaming() tells if the subdevice is currently streaming. + * "Streaming" here means whether .s_stream() or .enable_streams() has been + * successfully called, and the streaming has not yet been disabled. + * + * If the subdevice implements .enable_streams() this function must be called + * while holding the active state lock. + */ +bool v4l2_subdev_is_streaming(struct v4l2_subdev *sd); + #endif /* _V4L2_SUBDEV_H */ From a505075730d23ccc19fc4ac382a0ed73b630c057 Mon Sep 17 00:00:00 2001 From: Nikita Zhandarovich Date: Sun, 2 Mar 2025 17:58:25 +0300 Subject: [PATCH 401/606] media: vimc: skip .s_stream() for stopped entities [ Upstream commit 36cef585e2a31e4ddf33a004b0584a7a572246de ] Syzbot reported [1] a warning prompted by a check in call_s_stream() that checks whether .s_stream() operation is warranted for unstarted or stopped subdevs. Add a simple fix in vimc_streamer_pipeline_terminate() ensuring that entities skip a call to .s_stream() unless they have been previously properly started. [1] Syzbot report: ------------[ cut here ]------------ WARNING: CPU: 0 PID: 5933 at drivers/media/v4l2-core/v4l2-subdev.c:460 call_s_stream+0x2df/0x350 drivers/media/v4l2-core/v4l2-subdev.c:460 Modules linked in: CPU: 0 UID: 0 PID: 5933 Comm: syz-executor330 Not tainted 6.13.0-rc2-syzkaller-00362-g2d8308bf5b67 #0 ... Call Trace: vimc_streamer_pipeline_terminate+0x218/0x320 drivers/media/test-drivers/vimc/vimc-streamer.c:62 vimc_streamer_pipeline_init drivers/media/test-drivers/vimc/vimc-streamer.c:101 [inline] vimc_streamer_s_stream+0x650/0x9a0 drivers/media/test-drivers/vimc/vimc-streamer.c:203 vimc_capture_start_streaming+0xa1/0x130 drivers/media/test-drivers/vimc/vimc-capture.c:256 vb2_start_streaming+0x15f/0x5a0 drivers/media/common/videobuf2/videobuf2-core.c:1789 vb2_core_streamon+0x2a7/0x450 drivers/media/common/videobuf2/videobuf2-core.c:2348 vb2_streamon drivers/media/common/videobuf2/videobuf2-v4l2.c:875 [inline] vb2_ioctl_streamon+0xf4/0x170 drivers/media/common/videobuf2/videobuf2-v4l2.c:1118 __video_do_ioctl+0xaf0/0xf00 drivers/media/v4l2-core/v4l2-ioctl.c:3122 video_usercopy+0x4d2/0x1620 drivers/media/v4l2-core/v4l2-ioctl.c:3463 v4l2_ioctl+0x1ba/0x250 drivers/media/v4l2-core/v4l2-dev.c:366 vfs_ioctl fs/ioctl.c:51 [inline] __do_sys_ioctl fs/ioctl.c:906 [inline] __se_sys_ioctl fs/ioctl.c:892 [inline] __x64_sys_ioctl+0x190/0x200 fs/ioctl.c:892 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xcd/0x250 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f2b85c01b19 ... Reported-by: syzbot+5bcd7c809d365e14c4df@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=5bcd7c809d365e14c4df Fixes: adc589d2a208 ("media: vimc: Add vimc-streamer for stream control") Cc: stable@vger.kernel.org Signed-off-by: Nikita Zhandarovich Signed-off-by: Hans Verkuil Signed-off-by: Sasha Levin --- drivers/media/test-drivers/vimc/vimc-streamer.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/media/test-drivers/vimc/vimc-streamer.c b/drivers/media/test-drivers/vimc/vimc-streamer.c index 807551a5143b..15d863f97cbf 100644 --- a/drivers/media/test-drivers/vimc/vimc-streamer.c +++ b/drivers/media/test-drivers/vimc/vimc-streamer.c @@ -59,6 +59,12 @@ static void vimc_streamer_pipeline_terminate(struct vimc_stream *stream) continue; sd = media_entity_to_v4l2_subdev(ved->ent); + /* + * Do not call .s_stream() to stop an already + * stopped/unstarted subdev. + */ + if (!v4l2_subdev_is_streaming(sd)) + continue; v4l2_subdev_call(sd, video, s_stream, 0); } } From d4f5f29c26a1744f9bf4a22c1d9d47ef190b2756 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 17 Jan 2025 14:18:50 +0000 Subject: [PATCH 402/606] soc: qcom: ice: introduce devm_of_qcom_ice_get [ Upstream commit 1c13d6060d612601a61423f2e8fbf9e48126acca ] Callers of of_qcom_ice_get() leak the device reference taken by of_find_device_by_node(). Introduce devm variant for of_qcom_ice_get(). Existing consumers need the ICE instance for the entire life of their device, thus exporting qcom_ice_put() is not required. Signed-off-by: Tudor Ambarus Reviewed-by: Krzysztof Kozlowski Reviewed-by: Abel Vesa Reviewed-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20250117-qcom-ice-fix-dev-leak-v2-1-1ffa5b6884cb@linaro.org Signed-off-by: Bjorn Andersson Stable-dep-of: cbef7442fba5 ("mmc: sdhci-msm: fix dev reference leaked through of_qcom_ice_get") Signed-off-by: Sasha Levin --- drivers/soc/qcom/ice.c | 48 ++++++++++++++++++++++++++++++++++++++++++ include/soc/qcom/ice.h | 2 ++ 2 files changed, 50 insertions(+) diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c index fbab7fe5c652..d6e205e3812a 100644 --- a/drivers/soc/qcom/ice.c +++ b/drivers/soc/qcom/ice.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -328,6 +329,53 @@ out: } EXPORT_SYMBOL_GPL(of_qcom_ice_get); +static void qcom_ice_put(const struct qcom_ice *ice) +{ + struct platform_device *pdev = to_platform_device(ice->dev); + + if (!platform_get_resource_byname(pdev, IORESOURCE_MEM, "ice")) + platform_device_put(pdev); +} + +static void devm_of_qcom_ice_put(struct device *dev, void *res) +{ + qcom_ice_put(*(struct qcom_ice **)res); +} + +/** + * devm_of_qcom_ice_get() - Devres managed helper to get an ICE instance from + * a DT node. + * @dev: device pointer for the consumer device. + * + * This function will provide an ICE instance either by creating one for the + * consumer device if its DT node provides the 'ice' reg range and the 'ice' + * clock (for legacy DT style). On the other hand, if consumer provides a + * phandle via 'qcom,ice' property to an ICE DT, the ICE instance will already + * be created and so this function will return that instead. + * + * Return: ICE pointer on success, NULL if there is no ICE data provided by the + * consumer or ERR_PTR() on error. + */ +struct qcom_ice *devm_of_qcom_ice_get(struct device *dev) +{ + struct qcom_ice *ice, **dr; + + dr = devres_alloc(devm_of_qcom_ice_put, sizeof(*dr), GFP_KERNEL); + if (!dr) + return ERR_PTR(-ENOMEM); + + ice = of_qcom_ice_get(dev); + if (!IS_ERR_OR_NULL(ice)) { + *dr = ice; + devres_add(dev, dr); + } else { + devres_free(dr); + } + + return ice; +} +EXPORT_SYMBOL_GPL(devm_of_qcom_ice_get); + static int qcom_ice_probe(struct platform_device *pdev) { struct qcom_ice *engine; diff --git a/include/soc/qcom/ice.h b/include/soc/qcom/ice.h index 5870a94599a2..d5f6a228df65 100644 --- a/include/soc/qcom/ice.h +++ b/include/soc/qcom/ice.h @@ -34,4 +34,6 @@ int qcom_ice_program_key(struct qcom_ice *ice, int slot); int qcom_ice_evict_key(struct qcom_ice *ice, int slot); struct qcom_ice *of_qcom_ice_get(struct device *dev); +struct qcom_ice *devm_of_qcom_ice_get(struct device *dev); + #endif /* __QCOM_ICE_H__ */ From 880b1c98d1b499f0500dcc3a785104b40fbda755 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 17 Jan 2025 14:18:51 +0000 Subject: [PATCH 403/606] mmc: sdhci-msm: fix dev reference leaked through of_qcom_ice_get [ Upstream commit cbef7442fba510b7eb229dcc9f39d3dde4a159a4 ] The driver leaks the device reference taken with of_find_device_by_node(). Fix the leak by using devm_of_qcom_ice_get(). Fixes: c7eed31e235c ("mmc: sdhci-msm: Switch to the new ICE API") Cc: stable@vger.kernel.org Signed-off-by: Tudor Ambarus Reviewed-by: Krzysztof Kozlowski Acked-by: Ulf Hansson Reviewed-by: Abel Vesa Reviewed-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20250117-qcom-ice-fix-dev-leak-v2-2-1ffa5b6884cb@linaro.org Signed-off-by: Bjorn Andersson Signed-off-by: Sasha Levin --- drivers/mmc/host/sdhci-msm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 945d08531de3..82808cc373f6 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -1866,7 +1866,7 @@ static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host, if (!(cqhci_readl(cq_host, CQHCI_CAP) & CQHCI_CAP_CS)) return 0; - ice = of_qcom_ice_get(dev); + ice = devm_of_qcom_ice_get(dev); if (ice == ERR_PTR(-EOPNOTSUPP)) { dev_warn(dev, "Disabling inline encryption support\n"); ice = NULL; From ab239a12fdb2d7c6591122196d941a6a959aa1f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 11 Mar 2024 22:59:23 +0100 Subject: [PATCH 404/606] auxdisplay: hd44780: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 9ea02f7cc39d484d16e8a14f3713fefcd33407c0 ] The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Geert Uytterhoeven Signed-off-by: Andy Shevchenko Stable-dep-of: 9b98a7d2e5f4 ("auxdisplay: hd44780: Fix an API misuse in hd44780.c") Signed-off-by: Sasha Levin --- drivers/auxdisplay/hd44780.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c index d56a5d508ccd..7ac0b1b1d548 100644 --- a/drivers/auxdisplay/hd44780.c +++ b/drivers/auxdisplay/hd44780.c @@ -319,7 +319,7 @@ fail1: return ret; } -static int hd44780_remove(struct platform_device *pdev) +static void hd44780_remove(struct platform_device *pdev) { struct charlcd *lcd = platform_get_drvdata(pdev); struct hd44780_common *hdc = lcd->drvdata; @@ -329,7 +329,6 @@ static int hd44780_remove(struct platform_device *pdev) kfree(lcd->drvdata); kfree(lcd); - return 0; } static const struct of_device_id hd44780_of_match[] = { @@ -340,7 +339,7 @@ MODULE_DEVICE_TABLE(of, hd44780_of_match); static struct platform_driver hd44780_driver = { .probe = hd44780_probe, - .remove = hd44780_remove, + .remove_new = hd44780_remove, .driver = { .name = "hd44780", .of_match_table = hd44780_of_match, From 83c12c052cf55481b6b56de1c4f195caf92319e2 Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Mon, 24 Feb 2025 18:15:27 +0800 Subject: [PATCH 405/606] auxdisplay: hd44780: Fix an API misuse in hd44780.c [ Upstream commit 9b98a7d2e5f4e2beeff88f6571da0cdc5883c7fb ] Variable allocated by charlcd_alloc() should be released by charlcd_free(). The following patch changed kfree() to charlcd_free() to fix an API misuse. Fixes: 718e05ed92ec ("auxdisplay: Introduce hd44780_common.[ch]") Cc: stable@vger.kernel.org Signed-off-by: Haoxiang Li Reviewed-by: Geert Uytterhoeven Signed-off-by: Andy Shevchenko Signed-off-by: Sasha Levin --- drivers/auxdisplay/hd44780.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c index 7ac0b1b1d548..8b690f59df27 100644 --- a/drivers/auxdisplay/hd44780.c +++ b/drivers/auxdisplay/hd44780.c @@ -313,7 +313,7 @@ static int hd44780_probe(struct platform_device *pdev) fail3: kfree(hd); fail2: - kfree(lcd); + charlcd_free(lcd); fail1: kfree(hdc); return ret; @@ -328,7 +328,7 @@ static void hd44780_remove(struct platform_device *pdev) kfree(hdc->hd44780); kfree(lcd->drvdata); - kfree(lcd); + charlcd_free(lcd); } static const struct of_device_id hd44780_of_match[] = { From 70d2b16cdd1214a72651f707a3d2082b046d9a59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Mon, 17 Mar 2025 18:32:49 +0100 Subject: [PATCH 406/606] net: dsa: mv88e6xxx: fix internal PHYs for 6320 family MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 52fdc41c3278c981066a461d03d5477ebfcf270c ] Fix internal PHYs definition for the 6320 family, which has only 2 internal PHYs (on ports 3 and 4). Fixes: bc3931557d1d ("net: dsa: mv88e6xxx: Add number of internal PHYs") Signed-off-by: Marek Behún Cc: # 6.6.x Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/20250317173250.28780-7-kabel@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/dsa/mv88e6xxx/chip.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index da7260e505a2..d66448f0833c 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -6114,7 +6114,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_databases = 4096, .num_macs = 8192, .num_ports = 7, - .num_internal_phys = 5, + .num_internal_phys = 2, + .internal_phys_offset = 3, .num_gpio = 15, .max_vid = 4095, .port_base_addr = 0x10, @@ -6139,7 +6140,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_databases = 4096, .num_macs = 8192, .num_ports = 7, - .num_internal_phys = 5, + .num_internal_phys = 2, + .internal_phys_offset = 3, .num_gpio = 15, .max_vid = 4095, .port_base_addr = 0x10, From 9973c8192e07ee1a17557bc138997740370af649 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Mon, 17 Mar 2025 18:32:44 +0100 Subject: [PATCH 407/606] net: dsa: mv88e6xxx: fix VTU methods for 6320 family MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit f9a457722cf5e3534be5ffab549d6b49737fca72 ] The VTU registers of the 6320 family use the 6352 semantics, not 6185. Fix it. Fixes: b8fee9571063 ("net: dsa: mv88e6xxx: add VLAN Get Next support") Signed-off-by: Marek Behún Cc: # 5.15.x Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/20250317173250.28780-2-kabel@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/dsa/mv88e6xxx/chip.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index d66448f0833c..bf93d700802b 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -5071,8 +5071,8 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait, .hardware_reset_post = mv88e6xxx_g2_eeprom_wait, .reset = mv88e6352_g1_reset, - .vtu_getnext = mv88e6185_g1_vtu_getnext, - .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge, + .vtu_getnext = mv88e6352_g1_vtu_getnext, + .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, .gpio_ops = &mv88e6352_gpio_ops, .avb_ops = &mv88e6352_avb_ops, .ptp_ops = &mv88e6352_ptp_ops, @@ -5120,8 +5120,8 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait, .hardware_reset_post = mv88e6xxx_g2_eeprom_wait, .reset = mv88e6352_g1_reset, - .vtu_getnext = mv88e6185_g1_vtu_getnext, - .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge, + .vtu_getnext = mv88e6352_g1_vtu_getnext, + .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, .gpio_ops = &mv88e6352_gpio_ops, .avb_ops = &mv88e6352_avb_ops, .ptp_ops = &mv88e6352_ptp_ops, From 860c028415d9cf12eea877d820553a0e8caf0a1e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 30 Apr 2024 16:09:54 +0200 Subject: [PATCH 408/606] ASoC: qcom: q6apm-dai: drop unused 'q6apm_dai_rtd' fields [ Upstream commit bd381c9d151467e784988bbacf22bd7ca02455d6 ] Remove few unused fields from 'struct q6apm_dai_rtd'. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240430140954.328127-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown Stable-dep-of: 3d4a4411aa8b ("ASoC: q6apm-dai: schedule all available frames to avoid dsp under-runs") Signed-off-by: Sasha Levin --- sound/soc/qcom/qdsp6/q6apm-dai.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index def05ce58d17..5573802e480b 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -70,14 +70,10 @@ struct q6apm_dai_rtd { unsigned int bytes_received; unsigned int copied_total; uint16_t bits_per_sample; - uint16_t source; /* Encoding source bit mask */ - uint16_t session_id; bool next_track; enum stream_state state; struct q6apm_graph *graph; spinlock_t lock; - uint32_t initial_samples_drop; - uint32_t trailing_samples_drop; bool notify_on_drain; }; @@ -721,14 +717,12 @@ static int q6apm_dai_compr_set_metadata(struct snd_soc_component *component, switch (metadata->key) { case SNDRV_COMPRESS_ENCODER_PADDING: - prtd->trailing_samples_drop = metadata->value[0]; q6apm_remove_trailing_silence(component->dev, prtd->graph, - prtd->trailing_samples_drop); + metadata->value[0]); break; case SNDRV_COMPRESS_ENCODER_DELAY: - prtd->initial_samples_drop = metadata->value[0]; q6apm_remove_initial_silence(component->dev, prtd->graph, - prtd->initial_samples_drop); + metadata->value[0]); break; default: ret = -EINVAL; From 0addfbfd605bcd935f4c62bc3f446e258c01b839 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 14 Mar 2025 17:47:56 +0000 Subject: [PATCH 409/606] ASoC: q6apm-dai: schedule all available frames to avoid dsp under-runs [ Upstream commit 3d4a4411aa8bbc3653ff22a1ff0432eb93d22ae0 ] With the existing code, we are only setting up one period at a time, in a ping-pong buffer style. This triggers lot of underruns in the dsp leading to jitter noise during audio playback. Fix this by scheduling all available periods, this will ensure that the dsp has enough buffer feed and ultimatley fixing the underruns and audio distortion. Fixes: 9b4fe0f1cd79 ("ASoC: qdsp6: audioreach: add q6apm-dai support") Cc: stable@vger.kernel.org Reported-by: Krzysztof Kozlowski Signed-off-by: Srinivas Kandagatla Tested-by: Krzysztof Kozlowski Tested-by: Johan Hovold Link: https://patch.msgid.link/20250314174800.10142-2-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/qcom/qdsp6/q6apm-dai.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index 5573802e480b..f188d00825c0 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -70,6 +70,7 @@ struct q6apm_dai_rtd { unsigned int bytes_received; unsigned int copied_total; uint16_t bits_per_sample; + snd_pcm_uframes_t queue_ptr; bool next_track; enum stream_state state; struct q6apm_graph *graph; @@ -134,8 +135,6 @@ static void event_handler(uint32_t opcode, uint32_t token, uint32_t *payload, vo prtd->pos += prtd->pcm_count; spin_unlock_irqrestore(&prtd->lock, flags); snd_pcm_period_elapsed(substream); - if (prtd->state == Q6APM_STREAM_RUNNING) - q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, 0); break; case APM_CLIENT_EVENT_DATA_READ_DONE: @@ -293,6 +292,27 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, return 0; } +static int q6apm_dai_ack(struct snd_soc_component *component, struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct q6apm_dai_rtd *prtd = runtime->private_data; + int i, ret = 0, avail_periods; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + avail_periods = (runtime->control->appl_ptr - prtd->queue_ptr)/runtime->period_size; + for (i = 0; i < avail_periods; i++) { + ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, NO_TIMESTAMP); + if (ret < 0) { + dev_err(component->dev, "Error queuing playback buffer %d\n", ret); + return ret; + } + prtd->queue_ptr += runtime->period_size; + } + } + + return ret; +} + static int q6apm_dai_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { @@ -304,9 +324,6 @@ static int q6apm_dai_trigger(struct snd_soc_component *component, case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - /* start writing buffers for playback only as we already queued capture buffers */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, 0); break; case SNDRV_PCM_TRIGGER_STOP: /* TODO support be handled via SoftPause Module */ @@ -834,6 +851,7 @@ static const struct snd_soc_component_driver q6apm_fe_dai_component = { .hw_params = q6apm_dai_hw_params, .pointer = q6apm_dai_pointer, .trigger = q6apm_dai_trigger, + .ack = q6apm_dai_ack, .compress_ops = &q6apm_dai_compress_ops, .use_dai_pcm_id = true, }; From 9f5d3022d8ca625a22dc6bce44c22ce0295745ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sat, 14 Oct 2023 00:19:52 +0200 Subject: [PATCH 410/606] ASoC: qcom: lpass: Make asoc_qcom_lpass_cpu_platform_remove() return void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit d0cc676c426d1958989fac2a0d45179fb9992f0a ] The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is (mostly) ignored and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. asoc_qcom_lpass_cpu_platform_remove() returned zero unconditionally. Make it return void instead and convert all users to struct platform_device::remove_new(). Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20231013221945.1489203-15-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown Stable-dep-of: a93dad6f4e6a ("ASoC: q6apm-dai: make use of q6apm_get_hw_pointer") Signed-off-by: Sasha Levin --- sound/soc/qcom/lpass-apq8016.c | 2 +- sound/soc/qcom/lpass-cpu.c | 5 +---- sound/soc/qcom/lpass-ipq806x.c | 2 +- sound/soc/qcom/lpass-sc7180.c | 2 +- sound/soc/qcom/lpass-sc7280.c | 2 +- sound/soc/qcom/lpass.h | 2 +- 6 files changed, 6 insertions(+), 9 deletions(-) diff --git a/sound/soc/qcom/lpass-apq8016.c b/sound/soc/qcom/lpass-apq8016.c index f919d46e18ca..06a4faae5087 100644 --- a/sound/soc/qcom/lpass-apq8016.c +++ b/sound/soc/qcom/lpass-apq8016.c @@ -300,7 +300,7 @@ static struct platform_driver apq8016_lpass_cpu_platform_driver = { .of_match_table = of_match_ptr(apq8016_lpass_cpu_device_id), }, .probe = asoc_qcom_lpass_cpu_platform_probe, - .remove = asoc_qcom_lpass_cpu_platform_remove, + .remove_new = asoc_qcom_lpass_cpu_platform_remove, }; module_platform_driver(apq8016_lpass_cpu_platform_driver); diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index e587455dc40a..92316768011a 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -1284,15 +1284,12 @@ err: } EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_platform_probe); -int asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev) +void asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev) { struct lpass_data *drvdata = platform_get_drvdata(pdev); if (drvdata->variant->exit) drvdata->variant->exit(pdev); - - - return 0; } EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_platform_remove); diff --git a/sound/soc/qcom/lpass-ipq806x.c b/sound/soc/qcom/lpass-ipq806x.c index 2c97f295e394..10f7e2639c42 100644 --- a/sound/soc/qcom/lpass-ipq806x.c +++ b/sound/soc/qcom/lpass-ipq806x.c @@ -172,7 +172,7 @@ static struct platform_driver ipq806x_lpass_cpu_platform_driver = { .of_match_table = of_match_ptr(ipq806x_lpass_cpu_device_id), }, .probe = asoc_qcom_lpass_cpu_platform_probe, - .remove = asoc_qcom_lpass_cpu_platform_remove, + .remove_new = asoc_qcom_lpass_cpu_platform_remove, }; module_platform_driver(ipq806x_lpass_cpu_platform_driver); diff --git a/sound/soc/qcom/lpass-sc7180.c b/sound/soc/qcom/lpass-sc7180.c index d16c0d83aaad..62e49a0d27ba 100644 --- a/sound/soc/qcom/lpass-sc7180.c +++ b/sound/soc/qcom/lpass-sc7180.c @@ -315,7 +315,7 @@ static struct platform_driver sc7180_lpass_cpu_platform_driver = { .pm = &sc7180_lpass_pm_ops, }, .probe = asoc_qcom_lpass_cpu_platform_probe, - .remove = asoc_qcom_lpass_cpu_platform_remove, + .remove_new = asoc_qcom_lpass_cpu_platform_remove, .shutdown = asoc_qcom_lpass_cpu_platform_shutdown, }; diff --git a/sound/soc/qcom/lpass-sc7280.c b/sound/soc/qcom/lpass-sc7280.c index 6b2eb25ed939..97b9053ed3b0 100644 --- a/sound/soc/qcom/lpass-sc7280.c +++ b/sound/soc/qcom/lpass-sc7280.c @@ -445,7 +445,7 @@ static struct platform_driver sc7280_lpass_cpu_platform_driver = { .pm = &sc7280_lpass_pm_ops, }, .probe = asoc_qcom_lpass_cpu_platform_probe, - .remove = asoc_qcom_lpass_cpu_platform_remove, + .remove_new = asoc_qcom_lpass_cpu_platform_remove, .shutdown = asoc_qcom_lpass_cpu_platform_shutdown, }; diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index ea12f02eca55..f821271a1146 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -400,7 +400,7 @@ struct lpass_pcm_data { /* register the platform driver from the CPU DAI driver */ int asoc_qcom_lpass_platform_register(struct platform_device *); -int asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev); +void asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev); void asoc_qcom_lpass_cpu_platform_shutdown(struct platform_device *pdev); int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev); extern const struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops; From 175cb0c28aea537f58371474a3aa50a98e9be9f1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 4 Dec 2023 11:00:48 +0100 Subject: [PATCH 411/606] ASoC: qcom: Fix trivial code style issues [ Upstream commit bb3392453d3ba44e60b85381e3bfa3c551a44e5d ] Fix few trivial code style issues, pointed out by checkpatch, so they do not get copied to new code (when old code is used as template): WARNING: Prefer "GPL" over "GPL v2" - see commit bf7fbeeae6db ("module: Cure the MODULE_LICENSE "GPL" vs. "GPL v2" bogosity") WARNING: function definition argument 'struct platform_device *' should also have an identifier name ERROR: code indent should use tabs where possible WARNING: please, no spaces at the start of a line WARNING: Missing a blank line after declarations WARNING: unnecessary whitespace before a quoted newline Signed-off-by: Krzysztof Kozlowski Link: https://msgid.link/r/20231204100048.211800-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown Stable-dep-of: a93dad6f4e6a ("ASoC: q6apm-dai: make use of q6apm_get_hw_pointer") Signed-off-by: Sasha Levin --- sound/soc/qcom/apq8016_sbc.c | 2 +- sound/soc/qcom/apq8096.c | 2 +- sound/soc/qcom/common.c | 2 +- sound/soc/qcom/lpass-apq8016.c | 2 +- sound/soc/qcom/lpass-cpu.c | 2 +- sound/soc/qcom/lpass-hdmi.c | 2 +- sound/soc/qcom/lpass-ipq806x.c | 2 +- sound/soc/qcom/lpass-platform.c | 2 +- sound/soc/qcom/lpass-sc7180.c | 2 +- sound/soc/qcom/lpass.h | 2 +- sound/soc/qcom/qdsp6/q6afe.c | 8 ++++---- sound/soc/qcom/qdsp6/q6apm-dai.c | 4 ++-- sound/soc/qcom/qdsp6/q6asm.h | 20 ++++++++++---------- sound/soc/qcom/qdsp6/topology.c | 3 ++- sound/soc/qcom/sc7180.c | 2 +- sound/soc/qcom/sc8280xp.c | 2 +- sound/soc/qcom/sdm845.c | 2 +- sound/soc/qcom/sdw.c | 2 +- sound/soc/qcom/sm8250.c | 2 +- sound/soc/qcom/storm.c | 2 +- 20 files changed, 34 insertions(+), 33 deletions(-) diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index ff9f6a1c95df..40b6a837f66b 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -343,4 +343,4 @@ module_platform_driver(apq8016_sbc_platform_driver); MODULE_AUTHOR("Srinivas Kandagatla state = Q6APM_STREAM_STOPPED; break; case APM_CLIENT_EVENT_DATA_WRITE_DONE: - spin_lock_irqsave(&prtd->lock, flags); + spin_lock_irqsave(&prtd->lock, flags); prtd->pos += prtd->pcm_count; spin_unlock_irqrestore(&prtd->lock, flags); snd_pcm_period_elapsed(substream); break; case APM_CLIENT_EVENT_DATA_READ_DONE: - spin_lock_irqsave(&prtd->lock, flags); + spin_lock_irqsave(&prtd->lock, flags); prtd->pos += prtd->pcm_count; spin_unlock_irqrestore(&prtd->lock, flags); snd_pcm_period_elapsed(substream); diff --git a/sound/soc/qcom/qdsp6/q6asm.h b/sound/soc/qcom/qdsp6/q6asm.h index 394604c34943..a33d92c7bd6b 100644 --- a/sound/soc/qcom/qdsp6/q6asm.h +++ b/sound/soc/qcom/qdsp6/q6asm.h @@ -36,16 +36,16 @@ enum { #define ASM_LAST_BUFFER_FLAG BIT(30) struct q6asm_flac_cfg { - u32 sample_rate; - u32 ext_sample_rate; - u32 min_frame_size; - u32 max_frame_size; - u16 stream_info_present; - u16 min_blk_size; - u16 max_blk_size; - u16 ch_cfg; - u16 sample_size; - u16 md5_sum; + u32 sample_rate; + u32 ext_sample_rate; + u32 min_frame_size; + u32 max_frame_size; + u16 stream_info_present; + u16 min_blk_size; + u16 max_blk_size; + u16 ch_cfg; + u16 sample_size; + u16 md5_sum; }; struct q6asm_wma_cfg { diff --git a/sound/soc/qcom/qdsp6/topology.c b/sound/soc/qcom/qdsp6/topology.c index 130b22a34fb3..70572c83e101 100644 --- a/sound/soc/qcom/qdsp6/topology.c +++ b/sound/soc/qcom/qdsp6/topology.c @@ -545,6 +545,7 @@ static struct audioreach_module *audioreach_parse_common_tokens(struct q6apm *ap if (mod) { int pn, id = 0; + mod->module_id = module_id; mod->max_ip_port = max_ip_port; mod->max_op_port = max_op_port; @@ -1271,7 +1272,7 @@ int audioreach_tplg_init(struct snd_soc_component *component) ret = request_firmware(&fw, tplg_fw_name, dev); if (ret < 0) { - dev_err(dev, "tplg firmware loading %s failed %d \n", tplg_fw_name, ret); + dev_err(dev, "tplg firmware loading %s failed %d\n", tplg_fw_name, ret); goto err; } diff --git a/sound/soc/qcom/sc7180.c b/sound/soc/qcom/sc7180.c index d1fd40e3f7a9..1367752f2b63 100644 --- a/sound/soc/qcom/sc7180.c +++ b/sound/soc/qcom/sc7180.c @@ -428,4 +428,4 @@ static struct platform_driver sc7180_snd_driver = { module_platform_driver(sc7180_snd_driver); MODULE_DESCRIPTION("sc7180 ASoC Machine Driver"); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index 6e5f194bc34b..d5cc967992d1 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -174,4 +174,4 @@ static struct platform_driver snd_sc8280xp_driver = { module_platform_driver(snd_sc8280xp_driver); MODULE_AUTHOR("Srinivas Kandagatla Date: Fri, 14 Mar 2025 17:47:58 +0000 Subject: [PATCH 412/606] ASoC: q6apm-dai: make use of q6apm_get_hw_pointer [ Upstream commit a93dad6f4e6a04a5943f6ee5686585f24abf7063 ] With the existing code, the buffer position is only reset in pointer callback, which leaves the possiblity of it going over the size of buffer size and reporting incorrect position to userspace. Without this patch, its possible to see errors like: snd-x1e80100 sound: invalid position: pcmC0D0p:0, pos = 12288, buffer size = 12288, period size = 1536 snd-x1e80100 sound: invalid position: pcmC0D0p:0, pos = 12288, buffer size = 12288, period size = 1536 Fixes: 9b4fe0f1cd791 ("ASoC: qdsp6: audioreach: add q6apm-dai support") Cc: stable@vger.kernel.org Signed-off-by: Srinivas Kandagatla Tested-by: Krzysztof Kozlowski Tested-by: Johan Hovold Link: https://patch.msgid.link/20250314174800.10142-4-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/qcom/qdsp6/q6apm-dai.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index a52304bef9d9..179f4f7386dd 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -64,7 +64,6 @@ struct q6apm_dai_rtd { phys_addr_t phys; unsigned int pcm_size; unsigned int pcm_count; - unsigned int pos; /* Buffer position */ unsigned int periods; unsigned int bytes_sent; unsigned int bytes_received; @@ -124,23 +123,16 @@ static void event_handler(uint32_t opcode, uint32_t token, uint32_t *payload, vo { struct q6apm_dai_rtd *prtd = priv; struct snd_pcm_substream *substream = prtd->substream; - unsigned long flags; switch (opcode) { case APM_CLIENT_EVENT_CMD_EOS_DONE: prtd->state = Q6APM_STREAM_STOPPED; break; case APM_CLIENT_EVENT_DATA_WRITE_DONE: - spin_lock_irqsave(&prtd->lock, flags); - prtd->pos += prtd->pcm_count; - spin_unlock_irqrestore(&prtd->lock, flags); snd_pcm_period_elapsed(substream); break; case APM_CLIENT_EVENT_DATA_READ_DONE: - spin_lock_irqsave(&prtd->lock, flags); - prtd->pos += prtd->pcm_count; - spin_unlock_irqrestore(&prtd->lock, flags); snd_pcm_period_elapsed(substream); if (prtd->state == Q6APM_STREAM_RUNNING) q6apm_read(prtd->graph); @@ -246,7 +238,6 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, } prtd->pcm_count = snd_pcm_lib_period_bytes(substream); - prtd->pos = 0; /* rate and channels are sent to audio driver */ ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg); if (ret < 0) { @@ -445,16 +436,12 @@ static snd_pcm_uframes_t q6apm_dai_pointer(struct snd_soc_component *component, struct snd_pcm_runtime *runtime = substream->runtime; struct q6apm_dai_rtd *prtd = runtime->private_data; snd_pcm_uframes_t ptr; - unsigned long flags; - spin_lock_irqsave(&prtd->lock, flags); - if (prtd->pos == prtd->pcm_size) - prtd->pos = 0; + ptr = q6apm_get_hw_pointer(prtd->graph, substream->stream) * runtime->period_size; + if (ptr) + return ptr - 1; - ptr = bytes_to_frames(runtime, prtd->pos); - spin_unlock_irqrestore(&prtd->lock, flags); - - return ptr; + return 0; } static int q6apm_dai_hw_params(struct snd_soc_component *component, @@ -669,8 +656,6 @@ static int q6apm_dai_compr_set_params(struct snd_soc_component *component, prtd->pcm_size = runtime->fragments * runtime->fragment_size; prtd->bits_per_sample = 16; - prtd->pos = 0; - if (prtd->next_track != true) { memcpy(&prtd->codec, codec, sizeof(*codec)); From 28aadcb759cfc9921d5a05ce68da5b2413426e02 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Mon, 17 Feb 2025 14:16:12 +0000 Subject: [PATCH 413/606] iio: adc: ad7768-1: Move setting of val a bit later to avoid unnecessary return value check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 0af1c801a15225304a6328258efbf2bee245c654 ] The data used is all in local variables so there is no advantage in setting *val = ret with the direct mode claim held. Move it later to after error check. Reviewed-by: Nuno Sá Link: https://patch.msgid.link/20250217141630.897334-13-jic23@kernel.org Signed-off-by: Jonathan Cameron Stable-dep-of: 8236644f5ecb ("iio: adc: ad7768-1: Fix conversion result sign") Signed-off-by: Sasha Levin --- drivers/iio/adc/ad7768-1.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c index 70a25949142c..19d604f5701d 100644 --- a/drivers/iio/adc/ad7768-1.c +++ b/drivers/iio/adc/ad7768-1.c @@ -370,12 +370,11 @@ static int ad7768_read_raw(struct iio_dev *indio_dev, return ret; ret = ad7768_scan_direct(indio_dev); - if (ret >= 0) - *val = ret; iio_device_release_direct_mode(indio_dev); if (ret < 0) return ret; + *val = ret; return IIO_VAL_INT; From 6f21dfc4fadbe7076b89aa2fcb275001af2fa566 Mon Sep 17 00:00:00 2001 From: Sergiu Cuciurean Date: Thu, 6 Mar 2025 18:00:29 -0300 Subject: [PATCH 414/606] iio: adc: ad7768-1: Fix conversion result sign [ Upstream commit 8236644f5ecb180e80ad92d691c22bc509b747bb ] The ad7768-1 ADC output code is two's complement, meaning that the voltage conversion result is a signed value.. Since the value is a 24 bit one, stored in a 32 bit variable, the sign should be extended in order to get the correct representation. Also the channel description has been updated to signed representation, to match the ADC specifications. Fixes: a5f8c7da3dbe ("iio: adc: Add AD7768-1 ADC basic support") Reviewed-by: David Lechner Reviewed-by: Marcelo Schmitt Signed-off-by: Sergiu Cuciurean Signed-off-by: Jonathan Santos Cc: Link: https://patch.msgid.link/505994d3b71c2aa38ba714d909a68e021f12124c.1741268122.git.Jonathan.Santos@analog.com Signed-off-by: Jonathan Cameron Signed-off-by: Sasha Levin --- drivers/iio/adc/ad7768-1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c index 19d604f5701d..74b0c85944bd 100644 --- a/drivers/iio/adc/ad7768-1.c +++ b/drivers/iio/adc/ad7768-1.c @@ -142,7 +142,7 @@ static const struct iio_chan_spec ad7768_channels[] = { .channel = 0, .scan_index = 0, .scan_type = { - .sign = 'u', + .sign = 's', .realbits = 24, .storagebits = 32, .shift = 8, @@ -374,7 +374,7 @@ static int ad7768_read_raw(struct iio_dev *indio_dev, iio_device_release_direct_mode(indio_dev); if (ret < 0) return ret; - *val = ret; + *val = sign_extend32(ret, chan->scan_type.realbits - 1); return IIO_VAL_INT; From e56acd53a91a1cfadbbff7b267a19ef19a89526e Mon Sep 17 00:00:00 2001 From: Ninad Malwade Date: Thu, 6 Feb 2025 22:40:34 +0000 Subject: [PATCH 415/606] arm64: tegra: Remove the Orin NX/Nano suspend key [ Upstream commit bb8a3ad25f098b6ea9b1d0f522427b4ad53a7bba ] As per the Orin Nano Dev Kit schematic, GPIO_G.02 is not available on this device family. It should not be used at all on Orin NX/Nano. Having this unused pin mapped as the suspend key can lead to unpredictable behavior for low power modes. Orin NX/Nano uses GPIO_EE.04 as both a "power" button and a "suspend" button. However, we cannot have two gpio-keys mapped to the same GPIO. Therefore remove the "suspend" key. Cc: stable@vger.kernel.org Fixes: e63472eda5ea ("arm64: tegra: Support Jetson Orin NX reference platform") Signed-off-by: Ninad Malwade Signed-off-by: Ivy Huang Link: https://lore.kernel.org/r/20250206224034.3691397-1-yijuh@nvidia.com Signed-off-by: Thierry Reding Signed-off-by: Sasha Levin --- arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi | 7 ------- 1 file changed, 7 deletions(-) diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi index 39110c1232e0..db10b4b46cca 100644 --- a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi @@ -196,13 +196,6 @@ wakeup-event-action = ; wakeup-source; }; - - key-suspend { - label = "Suspend"; - gpios = <&gpio TEGRA234_MAIN_GPIO(G, 2) GPIO_ACTIVE_LOW>; - linux,input-type = ; - linux,code = ; - }; }; fan: pwm-fan { From aa487374d7f68da919b12dd6946856e4bff9afcc Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Tue, 12 Sep 2023 07:51:34 +0300 Subject: [PATCH 416/606] clk: renesas: rzg2l: Use u32 for flag and mux_flags [ Upstream commit 897a3e34d6e73d2386715d5c44c57992f2c0eada ] flag and mux_flags are intended to keep bit masks. Use u32 type for it. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230912045157.177966-15-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven Stable-dep-of: 7f22a298d926 ("clk: renesas: r9a07g043: Fix HP clock source for RZ/Five") Signed-off-by: Sasha Levin --- drivers/clk/renesas/rzg2l-cpg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h index 91e9c2569f80..097fd8f61680 100644 --- a/drivers/clk/renesas/rzg2l-cpg.h +++ b/drivers/clk/renesas/rzg2l-cpg.h @@ -92,8 +92,8 @@ struct cpg_core_clk { unsigned int conf; const struct clk_div_table *dtable; const char * const *parent_names; - int flag; - int mux_flags; + u32 flag; + u32 mux_flags; int num_parents; }; From 2e1162149b396d33365ce48df1c217ce07700774 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 29 Sep 2023 08:38:55 +0300 Subject: [PATCH 417/606] clk: renesas: rzg2l: Add struct clk_hw_data [ Upstream commit 97c1c4ccda76d2919775d748cf223637cf0e82ae ] Add clk_hw_data struct that keeps the core part of the clock data. sd_hw_data embeds a member of type struct clk_hw_data along with other members (in the next commits). This commit prepares the field for refactoring the SD MUX clock driver. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230929053915.1530607-9-claudiu.beznea@bp.renesas.com Signed-off-by: Geert Uytterhoeven Stable-dep-of: 7f22a298d926 ("clk: renesas: r9a07g043: Fix HP clock source for RZ/Five") Signed-off-by: Sasha Levin --- drivers/clk/renesas/rzg2l-cpg.c | 52 +++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index f8dbb092b9f1..280d61f1e174 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -58,13 +58,29 @@ #define MAX_VCLK_FREQ (148500000) -struct sd_hw_data { +/** + * struct clk_hw_data - clock hardware data + * @hw: clock hw + * @conf: clock configuration (register offset, shift, width) + * @priv: CPG private data structure + */ +struct clk_hw_data { struct clk_hw hw; u32 conf; struct rzg2l_cpg_priv *priv; }; -#define to_sd_hw_data(_hw) container_of(_hw, struct sd_hw_data, hw) +#define to_clk_hw_data(_hw) container_of(_hw, struct clk_hw_data, hw) + +/** + * struct sd_hw_data - SD clock hardware data + * @hw_data: clock hw data + */ +struct sd_hw_data { + struct clk_hw_data hw_data; +}; + +#define to_sd_hw_data(_hw) container_of(_hw, struct sd_hw_data, hw_data) struct rzg2l_pll5_param { u32 pl5_fracin; @@ -183,10 +199,10 @@ rzg2l_cpg_mux_clk_register(const struct cpg_core_clk *core, static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index) { - struct sd_hw_data *hwdata = to_sd_hw_data(hw); - struct rzg2l_cpg_priv *priv = hwdata->priv; - u32 off = GET_REG_OFFSET(hwdata->conf); - u32 shift = GET_SHIFT(hwdata->conf); + struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw); + struct rzg2l_cpg_priv *priv = clk_hw_data->priv; + u32 off = GET_REG_OFFSET(clk_hw_data->conf); + u32 shift = GET_SHIFT(clk_hw_data->conf); const u32 clk_src_266 = 2; u32 msk, val, bitmask; unsigned long flags; @@ -203,7 +219,7 @@ static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index) * The clock mux has 3 input clocks(533 MHz, 400 MHz, and 266 MHz), and * the index to value mapping is done by adding 1 to the index. */ - bitmask = (GENMASK(GET_WIDTH(hwdata->conf) - 1, 0) << shift) << 16; + bitmask = (GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0) << shift) << 16; msk = off ? CPG_CLKSTATUS_SELSDHI1_STS : CPG_CLKSTATUS_SELSDHI0_STS; spin_lock_irqsave(&priv->rmw_lock, flags); if (index != clk_src_266) { @@ -232,12 +248,12 @@ unlock: static u8 rzg2l_cpg_sd_clk_mux_get_parent(struct clk_hw *hw) { - struct sd_hw_data *hwdata = to_sd_hw_data(hw); - struct rzg2l_cpg_priv *priv = hwdata->priv; - u32 val = readl(priv->base + GET_REG_OFFSET(hwdata->conf)); + struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw); + struct rzg2l_cpg_priv *priv = clk_hw_data->priv; + u32 val = readl(priv->base + GET_REG_OFFSET(clk_hw_data->conf)); - val >>= GET_SHIFT(hwdata->conf); - val &= GENMASK(GET_WIDTH(hwdata->conf) - 1, 0); + val >>= GET_SHIFT(clk_hw_data->conf); + val &= GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0); return val ? val - 1 : 0; } @@ -253,17 +269,17 @@ rzg2l_cpg_sd_mux_clk_register(const struct cpg_core_clk *core, void __iomem *base, struct rzg2l_cpg_priv *priv) { - struct sd_hw_data *clk_hw_data; + struct sd_hw_data *sd_hw_data; struct clk_init_data init; struct clk_hw *clk_hw; int ret; - clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL); - if (!clk_hw_data) + sd_hw_data = devm_kzalloc(priv->dev, sizeof(*sd_hw_data), GFP_KERNEL); + if (!sd_hw_data) return ERR_PTR(-ENOMEM); - clk_hw_data->priv = priv; - clk_hw_data->conf = core->conf; + sd_hw_data->hw_data.priv = priv; + sd_hw_data->hw_data.conf = core->conf; init.name = GET_SHIFT(core->conf) ? "sd1" : "sd0"; init.ops = &rzg2l_cpg_sd_clk_mux_ops; @@ -271,7 +287,7 @@ rzg2l_cpg_sd_mux_clk_register(const struct cpg_core_clk *core, init.num_parents = core->num_parents; init.parent_names = core->parent_names; - clk_hw = &clk_hw_data->hw; + clk_hw = &sd_hw_data->hw_data.hw; clk_hw->init = &init; ret = devm_clk_hw_register(priv->dev, clk_hw); From 1b9daac2383ee8bec088d92a2c442b8f4227c598 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 29 Sep 2023 08:38:56 +0300 Subject: [PATCH 418/606] clk: renesas: rzg2l: Remove CPG_SDHI_DSEL from generic header [ Upstream commit 3e8008fcf6b7f7c65ad2718c18fb79f37007f1a5 ] Remove CPG_SDHI_DSEL and its bits from the generic header as RZ/G3S has different offset registers and bits for this, thus avoid mixing them. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20230929053915.1530607-10-claudiu.beznea@bp.renesas.com Signed-off-by: Geert Uytterhoeven Stable-dep-of: 7f22a298d926 ("clk: renesas: r9a07g043: Fix HP clock source for RZ/Five") Signed-off-by: Sasha Levin --- drivers/clk/renesas/r9a07g043-cpg.c | 7 +++++++ drivers/clk/renesas/r9a07g044-cpg.c | 7 +++++++ drivers/clk/renesas/rzg2l-cpg.h | 4 ---- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c index 6c6bc79b2e9c..8181ddf652fd 100644 --- a/drivers/clk/renesas/r9a07g043-cpg.c +++ b/drivers/clk/renesas/r9a07g043-cpg.c @@ -14,6 +14,13 @@ #include "rzg2l-cpg.h" +/* Specific registers. */ +#define CPG_PL2SDHI_DSEL (0x218) + +/* Clock select configuration. */ +#define SEL_SDHI0 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 0, 2) +#define SEL_SDHI1 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 4, 2) + enum clk_ids { /* Core Clock Outputs exported to DT */ LAST_DT_CORE_CLK = R9A07G043_CLK_P0_DIV2, diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c index c597414a94d8..d4dcf5d896d4 100644 --- a/drivers/clk/renesas/r9a07g044-cpg.c +++ b/drivers/clk/renesas/r9a07g044-cpg.c @@ -15,6 +15,13 @@ #include "rzg2l-cpg.h" +/* Specific registers. */ +#define CPG_PL2SDHI_DSEL (0x218) + +/* Clock select configuration. */ +#define SEL_SDHI0 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 0, 2) +#define SEL_SDHI1 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 4, 2) + enum clk_ids { /* Core Clock Outputs exported to DT */ LAST_DT_CORE_CLK = R9A07G054_CLK_DRP_A, diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h index 097fd8f61680..705898bef438 100644 --- a/drivers/clk/renesas/rzg2l-cpg.h +++ b/drivers/clk/renesas/rzg2l-cpg.h @@ -19,7 +19,6 @@ #define CPG_PL2_DDIV (0x204) #define CPG_PL3A_DDIV (0x208) #define CPG_PL6_DDIV (0x210) -#define CPG_PL2SDHI_DSEL (0x218) #define CPG_CLKSTATUS (0x280) #define CPG_PL3_SSEL (0x408) #define CPG_PL6_SSEL (0x414) @@ -69,9 +68,6 @@ #define SEL_PLL6_2 SEL_PLL_PACK(CPG_PL6_ETH_SSEL, 0, 1) #define SEL_GPU2 SEL_PLL_PACK(CPG_PL6_SSEL, 12, 1) -#define SEL_SDHI0 DDIV_PACK(CPG_PL2SDHI_DSEL, 0, 2) -#define SEL_SDHI1 DDIV_PACK(CPG_PL2SDHI_DSEL, 4, 2) - #define EXTAL_FREQ_IN_MEGA_HZ (24) /** From a15ff92d5f06c2b006e01448e62b982308ca1801 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 6 Oct 2023 13:39:57 +0300 Subject: [PATCH 419/606] clk: renesas: rzg2l: Refactor SD mux driver [ Upstream commit 16b86e5c03c5b3ef35bf5126b35384faa97428f0 ] Refactor SD MUX driver to be able to reuse the same code on RZ/G3S. RZ/G2{L,UL} has a limitation with regards to switching the clock source for SD MUX (MUX clock source has to be switched to 266MHz before switching b/w 533MHz and 400MHz). Rework the handling of this limitation to use a clock notifier that is registered according to platform based initialization data, so the SD MUX code can be reused on RZ/G3S. As RZ/G2{L,UL} and RZ/G3S use different bits in different registers to check if the clock switching has been done, this configuration (register offset, register bits and bitfield width) is now passed through struct cpg_core_clk::sconf (status configuration) from platform specific initialization code. Along with struct cpg_core_clk::sconf the mux table indices are also passed from platform specific initialization code. Also, mux flags are now passed to DEF_SD_MUX() as they will be used later by RZ/G3S. CPG_WEN_BIT macro has been introduced to select properly the WEN bit of various registers. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20231006103959.197485-3-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven Stable-dep-of: 7f22a298d926 ("clk: renesas: r9a07g043: Fix HP clock source for RZ/Five") Signed-off-by: Sasha Levin --- drivers/clk/renesas/r9a07g043-cpg.c | 12 ++- drivers/clk/renesas/r9a07g044-cpg.c | 12 ++- drivers/clk/renesas/rzg2l-cpg.c | 148 ++++++++++++++++++++-------- drivers/clk/renesas/rzg2l-cpg.h | 16 ++- 4 files changed, 138 insertions(+), 50 deletions(-) diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c index 8181ddf652fd..55c58b9a9b80 100644 --- a/drivers/clk/renesas/r9a07g043-cpg.c +++ b/drivers/clk/renesas/r9a07g043-cpg.c @@ -21,6 +21,10 @@ #define SEL_SDHI0 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 0, 2) #define SEL_SDHI1 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 4, 2) +/* Clock status configuration. */ +#define SEL_SDHI0_STS SEL_PLL_PACK(CPG_CLKSTATUS, 28, 1) +#define SEL_SDHI1_STS SEL_PLL_PACK(CPG_CLKSTATUS, 29, 1) + enum clk_ids { /* Core Clock Outputs exported to DT */ LAST_DT_CORE_CLK = R9A07G043_CLK_P0_DIV2, @@ -85,6 +89,8 @@ static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" }; static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" }; static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" }; +static const u32 mtable_sdhi[] = { 1, 2, 3 }; + static const struct cpg_core_clk r9a07g043_core_clks[] __initconst = { /* External Clock Inputs */ DEF_INPUT("extal", CLK_EXTAL), @@ -130,8 +136,10 @@ static const struct cpg_core_clk r9a07g043_core_clks[] __initconst = { DEF_MUX("HP", R9A07G043_CLK_HP, SEL_PLL6_2, sel_pll6_2), DEF_FIXED("SPI0", R9A07G043_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2), DEF_FIXED("SPI1", R9A07G043_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4), - DEF_SD_MUX("SD0", R9A07G043_CLK_SD0, SEL_SDHI0, sel_shdi), - DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, sel_shdi), + DEF_SD_MUX("SD0", R9A07G043_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_shdi, + mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier), + DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, SEL_SDHI0_STS, sel_shdi, + mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier), DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G043_CLK_SD0, 1, 4), DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G043_CLK_SD1, 1, 4), }; diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c index d4dcf5d896d4..1047278c9079 100644 --- a/drivers/clk/renesas/r9a07g044-cpg.c +++ b/drivers/clk/renesas/r9a07g044-cpg.c @@ -22,6 +22,10 @@ #define SEL_SDHI0 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 0, 2) #define SEL_SDHI1 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 4, 2) +/* Clock status configuration. */ +#define SEL_SDHI0_STS SEL_PLL_PACK(CPG_CLKSTATUS, 28, 1) +#define SEL_SDHI1_STS SEL_PLL_PACK(CPG_CLKSTATUS, 29, 1) + enum clk_ids { /* Core Clock Outputs exported to DT */ LAST_DT_CORE_CLK = R9A07G054_CLK_DRP_A, @@ -105,6 +109,8 @@ static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" }; static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" }; static const char * const sel_gpu2[] = { ".pll6", ".pll3_div2_2" }; +static const u32 mtable_sdhi[] = { 1, 2, 3 }; + static const struct { struct cpg_core_clk common[56]; #ifdef CONFIG_CLK_R9A07G054 @@ -170,8 +176,10 @@ static const struct { DEF_MUX("HP", R9A07G044_CLK_HP, SEL_PLL6_2, sel_pll6_2), DEF_FIXED("SPI0", R9A07G044_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2), DEF_FIXED("SPI1", R9A07G044_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4), - DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, sel_shdi), - DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, sel_shdi), + DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_shdi, + mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier), + DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, SEL_SDHI0_STS, sel_shdi, + mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier), DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G044_CLK_SD0, 1, 4), DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G044_CLK_SD1, 1, 4), DEF_DIV("G", R9A07G044_CLK_G, CLK_SEL_GPU2, DIVGPU, dtable_1_8), diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index 280d61f1e174..77eefb6ee453 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -56,31 +56,37 @@ #define GET_REG_SAMPLL_CLK1(val) ((val >> 22) & 0xfff) #define GET_REG_SAMPLL_CLK2(val) ((val >> 12) & 0xfff) +#define CPG_WEN_BIT BIT(16) + #define MAX_VCLK_FREQ (148500000) /** * struct clk_hw_data - clock hardware data * @hw: clock hw * @conf: clock configuration (register offset, shift, width) + * @sconf: clock status configuration (register offset, shift, width) * @priv: CPG private data structure */ struct clk_hw_data { struct clk_hw hw; u32 conf; + u32 sconf; struct rzg2l_cpg_priv *priv; }; #define to_clk_hw_data(_hw) container_of(_hw, struct clk_hw_data, hw) /** - * struct sd_hw_data - SD clock hardware data + * struct sd_mux_hw_data - SD MUX clock hardware data * @hw_data: clock hw data + * @mtable: clock mux table */ -struct sd_hw_data { +struct sd_mux_hw_data { struct clk_hw_data hw_data; + const u32 *mtable; }; -#define to_sd_hw_data(_hw) container_of(_hw, struct sd_hw_data, hw_data) +#define to_sd_mux_hw_data(_hw) container_of(_hw, struct sd_mux_hw_data, hw_data) struct rzg2l_pll5_param { u32 pl5_fracin; @@ -137,6 +143,76 @@ static void rzg2l_cpg_del_clk_provider(void *data) of_clk_del_provider(data); } +/* Must be called in atomic context. */ +static int rzg2l_cpg_wait_clk_update_done(void __iomem *base, u32 conf) +{ + u32 bitmask = GENMASK(GET_WIDTH(conf) - 1, 0) << GET_SHIFT(conf); + u32 off = GET_REG_OFFSET(conf); + u32 val; + + return readl_poll_timeout_atomic(base + off, val, !(val & bitmask), 10, 200); +} + +int rzg2l_cpg_sd_clk_mux_notifier(struct notifier_block *nb, unsigned long event, + void *data) +{ + struct clk_notifier_data *cnd = data; + struct clk_hw *hw = __clk_get_hw(cnd->clk); + struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw); + struct rzg2l_cpg_priv *priv = clk_hw_data->priv; + u32 off = GET_REG_OFFSET(clk_hw_data->conf); + u32 shift = GET_SHIFT(clk_hw_data->conf); + const u32 clk_src_266 = 3; + unsigned long flags; + int ret; + + if (event != PRE_RATE_CHANGE || (cnd->new_rate / MEGA == 266)) + return NOTIFY_DONE; + + spin_lock_irqsave(&priv->rmw_lock, flags); + + /* + * As per the HW manual, we should not directly switch from 533 MHz to + * 400 MHz and vice versa. To change the setting from 2’b01 (533 MHz) + * to 2’b10 (400 MHz) or vice versa, Switch to 2’b11 (266 MHz) first, + * and then switch to the target setting (2’b01 (533 MHz) or 2’b10 + * (400 MHz)). + * Setting a value of '0' to the SEL_SDHI0_SET or SEL_SDHI1_SET clock + * switching register is prohibited. + * The clock mux has 3 input clocks(533 MHz, 400 MHz, and 266 MHz), and + * the index to value mapping is done by adding 1 to the index. + */ + + writel((CPG_WEN_BIT | clk_src_266) << shift, priv->base + off); + + /* Wait for the update done. */ + ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf); + + spin_unlock_irqrestore(&priv->rmw_lock, flags); + + if (ret) + dev_err(priv->dev, "failed to switch to safe clk source\n"); + + return notifier_from_errno(ret); +} + +static int rzg2l_register_notifier(struct clk_hw *hw, const struct cpg_core_clk *core, + struct rzg2l_cpg_priv *priv) +{ + struct notifier_block *nb; + + if (!core->notifier) + return 0; + + nb = devm_kzalloc(priv->dev, sizeof(*nb), GFP_KERNEL); + if (!nb) + return -ENOMEM; + + nb->notifier_call = core->notifier; + + return clk_notifier_register(hw->clk, nb); +} + static struct clk * __init rzg2l_cpg_div_clk_register(const struct cpg_core_clk *core, struct clk **clks, @@ -200,48 +276,27 @@ rzg2l_cpg_mux_clk_register(const struct cpg_core_clk *core, static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index) { struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw); + struct sd_mux_hw_data *sd_mux_hw_data = to_sd_mux_hw_data(clk_hw_data); struct rzg2l_cpg_priv *priv = clk_hw_data->priv; u32 off = GET_REG_OFFSET(clk_hw_data->conf); u32 shift = GET_SHIFT(clk_hw_data->conf); - const u32 clk_src_266 = 2; - u32 msk, val, bitmask; unsigned long flags; + u32 val; int ret; - /* - * As per the HW manual, we should not directly switch from 533 MHz to - * 400 MHz and vice versa. To change the setting from 2’b01 (533 MHz) - * to 2’b10 (400 MHz) or vice versa, Switch to 2’b11 (266 MHz) first, - * and then switch to the target setting (2’b01 (533 MHz) or 2’b10 - * (400 MHz)). - * Setting a value of '0' to the SEL_SDHI0_SET or SEL_SDHI1_SET clock - * switching register is prohibited. - * The clock mux has 3 input clocks(533 MHz, 400 MHz, and 266 MHz), and - * the index to value mapping is done by adding 1 to the index. - */ - bitmask = (GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0) << shift) << 16; - msk = off ? CPG_CLKSTATUS_SELSDHI1_STS : CPG_CLKSTATUS_SELSDHI0_STS; + val = clk_mux_index_to_val(sd_mux_hw_data->mtable, CLK_MUX_ROUND_CLOSEST, index); + spin_lock_irqsave(&priv->rmw_lock, flags); - if (index != clk_src_266) { - writel(bitmask | ((clk_src_266 + 1) << shift), priv->base + off); - ret = readl_poll_timeout_atomic(priv->base + CPG_CLKSTATUS, val, - !(val & msk), 10, - CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US); - if (ret) - goto unlock; - } + writel((CPG_WEN_BIT | val) << shift, priv->base + off); - writel(bitmask | ((index + 1) << shift), priv->base + off); + /* Wait for the update done. */ + ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf); - ret = readl_poll_timeout_atomic(priv->base + CPG_CLKSTATUS, val, - !(val & msk), 10, - CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US); -unlock: spin_unlock_irqrestore(&priv->rmw_lock, flags); if (ret) - dev_err(priv->dev, "failed to switch clk source\n"); + dev_err(priv->dev, "Failed to switch parent\n"); return ret; } @@ -249,13 +304,15 @@ unlock: static u8 rzg2l_cpg_sd_clk_mux_get_parent(struct clk_hw *hw) { struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw); + struct sd_mux_hw_data *sd_mux_hw_data = to_sd_mux_hw_data(clk_hw_data); struct rzg2l_cpg_priv *priv = clk_hw_data->priv; - u32 val = readl(priv->base + GET_REG_OFFSET(clk_hw_data->conf)); + u32 val; + val = readl(priv->base + GET_REG_OFFSET(clk_hw_data->conf)); val >>= GET_SHIFT(clk_hw_data->conf); val &= GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0); - return val ? val - 1 : 0; + return clk_mux_val_to_index(hw, sd_mux_hw_data->mtable, CLK_MUX_ROUND_CLOSEST, val); } static const struct clk_ops rzg2l_cpg_sd_clk_mux_ops = { @@ -269,31 +326,40 @@ rzg2l_cpg_sd_mux_clk_register(const struct cpg_core_clk *core, void __iomem *base, struct rzg2l_cpg_priv *priv) { - struct sd_hw_data *sd_hw_data; + struct sd_mux_hw_data *sd_mux_hw_data; struct clk_init_data init; struct clk_hw *clk_hw; int ret; - sd_hw_data = devm_kzalloc(priv->dev, sizeof(*sd_hw_data), GFP_KERNEL); - if (!sd_hw_data) + sd_mux_hw_data = devm_kzalloc(priv->dev, sizeof(*sd_mux_hw_data), GFP_KERNEL); + if (!sd_mux_hw_data) return ERR_PTR(-ENOMEM); - sd_hw_data->hw_data.priv = priv; - sd_hw_data->hw_data.conf = core->conf; + sd_mux_hw_data->hw_data.priv = priv; + sd_mux_hw_data->hw_data.conf = core->conf; + sd_mux_hw_data->hw_data.sconf = core->sconf; + sd_mux_hw_data->mtable = core->mtable; init.name = GET_SHIFT(core->conf) ? "sd1" : "sd0"; init.ops = &rzg2l_cpg_sd_clk_mux_ops; - init.flags = 0; + init.flags = core->flag; init.num_parents = core->num_parents; init.parent_names = core->parent_names; - clk_hw = &sd_hw_data->hw_data.hw; + clk_hw = &sd_mux_hw_data->hw_data.hw; clk_hw->init = &init; ret = devm_clk_hw_register(priv->dev, clk_hw); if (ret) return ERR_PTR(ret); + ret = rzg2l_register_notifier(clk_hw, core, priv); + if (ret) { + dev_err(priv->dev, "Failed to register notifier for %s\n", + core->name); + return ERR_PTR(ret); + } + return clk_hw->clk; } diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h index 705898bef438..e662459cc6d9 100644 --- a/drivers/clk/renesas/rzg2l-cpg.h +++ b/drivers/clk/renesas/rzg2l-cpg.h @@ -9,6 +9,8 @@ #ifndef __RENESAS_RZG2L_CPG_H__ #define __RENESAS_RZG2L_CPG_H__ +#include + #define CPG_SIPLL5_STBY (0x140) #define CPG_SIPLL5_CLK1 (0x144) #define CPG_SIPLL5_CLK3 (0x14C) @@ -42,8 +44,6 @@ #define CPG_CLKSTATUS_SELSDHI0_STS BIT(28) #define CPG_CLKSTATUS_SELSDHI1_STS BIT(29) -#define CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US 200 - /* n = 0/1/2 for PLL1/4/6 */ #define CPG_SAMPLL_CLK1(n) (0x04 + (16 * n)) #define CPG_SAMPLL_CLK2(n) (0x08 + (16 * n)) @@ -86,8 +86,11 @@ struct cpg_core_clk { unsigned int mult; unsigned int type; unsigned int conf; + unsigned int sconf; const struct clk_div_table *dtable; + const u32 *mtable; const char * const *parent_names; + notifier_fn_t notifier; u32 flag; u32 mux_flags; int num_parents; @@ -147,10 +150,11 @@ enum clk_types { .parent_names = _parent_names, \ .num_parents = ARRAY_SIZE(_parent_names), \ .mux_flags = CLK_MUX_READ_ONLY) -#define DEF_SD_MUX(_name, _id, _conf, _parent_names) \ - DEF_TYPE(_name, _id, CLK_TYPE_SD_MUX, .conf = _conf, \ +#define DEF_SD_MUX(_name, _id, _conf, _sconf, _parent_names, _mtable, _clk_flags, _notifier) \ + DEF_TYPE(_name, _id, CLK_TYPE_SD_MUX, .conf = _conf, .sconf = _sconf, \ .parent_names = _parent_names, \ - .num_parents = ARRAY_SIZE(_parent_names)) + .num_parents = ARRAY_SIZE(_parent_names), \ + .mtable = _mtable, .flag = _clk_flags, .notifier = _notifier) #define DEF_PLL5_FOUTPOSTDIV(_name, _id, _parent) \ DEF_TYPE(_name, _id, CLK_TYPE_SIPLL5, .parent = _parent) #define DEF_PLL5_4_MUX(_name, _id, _conf, _parent_names) \ @@ -269,4 +273,6 @@ extern const struct rzg2l_cpg_info r9a07g044_cpg_info; extern const struct rzg2l_cpg_info r9a07g054_cpg_info; extern const struct rzg2l_cpg_info r9a09g011_cpg_info; +int rzg2l_cpg_sd_clk_mux_notifier(struct notifier_block *nb, unsigned long event, void *data); + #endif From d56be18579093c01e7f633008c7c70bddc8d4af9 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 31 Jan 2024 12:29:29 +0200 Subject: [PATCH 420/606] clk: renesas: r9a07g04[34]: Use SEL_SDHI1_STS status configuration for SD1 mux [ Upstream commit 9b2a11c83859c06233049b134bd8ee974b284559 ] The status configuration for SD1 mux clock is SEL_SDHI1_STS. Fix it. Fixes: 16b86e5c03c5 ("clk: renesas: rzg2l: Refactor SD mux driver") Reported-by: Hien Huynh Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20240131102930.1841901-2-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven Stable-dep-of: 7f22a298d926 ("clk: renesas: r9a07g043: Fix HP clock source for RZ/Five") Signed-off-by: Sasha Levin --- drivers/clk/renesas/r9a07g043-cpg.c | 2 +- drivers/clk/renesas/r9a07g044-cpg.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c index 55c58b9a9b80..9ad7ceb3ab1b 100644 --- a/drivers/clk/renesas/r9a07g043-cpg.c +++ b/drivers/clk/renesas/r9a07g043-cpg.c @@ -138,7 +138,7 @@ static const struct cpg_core_clk r9a07g043_core_clks[] __initconst = { DEF_FIXED("SPI1", R9A07G043_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4), DEF_SD_MUX("SD0", R9A07G043_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_shdi, mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier), - DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, SEL_SDHI0_STS, sel_shdi, + DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, SEL_SDHI1_STS, sel_shdi, mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier), DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G043_CLK_SD0, 1, 4), DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G043_CLK_SD1, 1, 4), diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c index 1047278c9079..bc822b9fd7ce 100644 --- a/drivers/clk/renesas/r9a07g044-cpg.c +++ b/drivers/clk/renesas/r9a07g044-cpg.c @@ -178,7 +178,7 @@ static const struct { DEF_FIXED("SPI1", R9A07G044_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4), DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_shdi, mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier), - DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, SEL_SDHI0_STS, sel_shdi, + DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, SEL_SDHI1_STS, sel_shdi, mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier), DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G044_CLK_SD0, 1, 4), DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G044_CLK_SD1, 1, 4), From 3b6f9b555d5bbfee2f3c68041f2e4c03f2a2d070 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 31 Jan 2024 12:29:30 +0200 Subject: [PATCH 421/606] clk: renesas: r9a07g04[34]: Fix typo for sel_shdi variable [ Upstream commit 46fb5dd9ca289953fa791b2bb060dac7f8002ae0 ] Fix typo for sel_shdi variable. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20240131102930.1841901-3-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven Stable-dep-of: 7f22a298d926 ("clk: renesas: r9a07g043: Fix HP clock source for RZ/Five") Signed-off-by: Sasha Levin --- drivers/clk/renesas/r9a07g043-cpg.c | 6 +++--- drivers/clk/renesas/r9a07g044-cpg.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c index 9ad7ceb3ab1b..3a717dcecba5 100644 --- a/drivers/clk/renesas/r9a07g043-cpg.c +++ b/drivers/clk/renesas/r9a07g043-cpg.c @@ -87,7 +87,7 @@ static const struct clk_div_table dtable_1_32[] = { /* Mux clock tables */ static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" }; static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" }; -static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" }; +static const char * const sel_sdhi[] = { ".clk_533", ".clk_400", ".clk_266" }; static const u32 mtable_sdhi[] = { 1, 2, 3 }; @@ -136,9 +136,9 @@ static const struct cpg_core_clk r9a07g043_core_clks[] __initconst = { DEF_MUX("HP", R9A07G043_CLK_HP, SEL_PLL6_2, sel_pll6_2), DEF_FIXED("SPI0", R9A07G043_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2), DEF_FIXED("SPI1", R9A07G043_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4), - DEF_SD_MUX("SD0", R9A07G043_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_shdi, + DEF_SD_MUX("SD0", R9A07G043_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_sdhi, mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier), - DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, SEL_SDHI1_STS, sel_shdi, + DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, SEL_SDHI1_STS, sel_sdhi, mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier), DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G043_CLK_SD0, 1, 4), DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G043_CLK_SD1, 1, 4), diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c index bc822b9fd7ce..48404cafea3f 100644 --- a/drivers/clk/renesas/r9a07g044-cpg.c +++ b/drivers/clk/renesas/r9a07g044-cpg.c @@ -106,7 +106,7 @@ static const struct clk_div_table dtable_16_128[] = { static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" }; static const char * const sel_pll5_4[] = { ".pll5_foutpostdiv", ".pll5_fout1ph0" }; static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" }; -static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" }; +static const char * const sel_sdhi[] = { ".clk_533", ".clk_400", ".clk_266" }; static const char * const sel_gpu2[] = { ".pll6", ".pll3_div2_2" }; static const u32 mtable_sdhi[] = { 1, 2, 3 }; @@ -176,9 +176,9 @@ static const struct { DEF_MUX("HP", R9A07G044_CLK_HP, SEL_PLL6_2, sel_pll6_2), DEF_FIXED("SPI0", R9A07G044_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2), DEF_FIXED("SPI1", R9A07G044_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4), - DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_shdi, + DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_sdhi, mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier), - DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, SEL_SDHI1_STS, sel_shdi, + DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, SEL_SDHI1_STS, sel_sdhi, mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier), DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G044_CLK_SD0, 1, 4), DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G044_CLK_SD1, 1, 4), From 9549391bb64b72d12deb521794eaad7d3c4d9472 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Mon, 27 Jan 2025 17:31:59 +0000 Subject: [PATCH 422/606] clk: renesas: r9a07g043: Fix HP clock source for RZ/Five [ Upstream commit 7f22a298d926664b51fcfe2f8ea5feb7f8b79952 ] According to the Rev.1.20 hardware manual for the RZ/Five SoC, the clock source for HP is derived from PLL6 divided by 2. Correct the implementation by configuring HP as a fixed clock source instead of a MUX. The `CPG_PL6_ETH_SSEL' register, which is available on the RZ/G2UL SoC, is not present on the RZ/Five SoC, necessitating this change. Fixes: 95d48d270305ad2c ("clk: renesas: r9a07g043: Add support for RZ/Five SoC") Cc: stable@vger.kernel.org Reported-by: Hien Huynh Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/20250127173159.34572-1-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven Signed-off-by: Sasha Levin --- drivers/clk/renesas/r9a07g043-cpg.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c index 3a717dcecba5..865d47800791 100644 --- a/drivers/clk/renesas/r9a07g043-cpg.c +++ b/drivers/clk/renesas/r9a07g043-cpg.c @@ -86,7 +86,9 @@ static const struct clk_div_table dtable_1_32[] = { /* Mux clock tables */ static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" }; +#ifdef CONFIG_ARM64 static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" }; +#endif static const char * const sel_sdhi[] = { ".clk_533", ".clk_400", ".clk_266" }; static const u32 mtable_sdhi[] = { 1, 2, 3 }; @@ -133,7 +135,12 @@ static const struct cpg_core_clk r9a07g043_core_clks[] __initconst = { DEF_DIV("P2", R9A07G043_CLK_P2, CLK_PLL3_DIV2_4_2, DIVPL3A, dtable_1_32), DEF_FIXED("M0", R9A07G043_CLK_M0, CLK_PLL3_DIV2_4, 1, 1), DEF_FIXED("ZT", R9A07G043_CLK_ZT, CLK_PLL3_DIV2_4_2, 1, 1), +#ifdef CONFIG_ARM64 DEF_MUX("HP", R9A07G043_CLK_HP, SEL_PLL6_2, sel_pll6_2), +#endif +#ifdef CONFIG_RISCV + DEF_FIXED("HP", R9A07G043_CLK_HP, CLK_PLL6_250, 1, 1), +#endif DEF_FIXED("SPI0", R9A07G043_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2), DEF_FIXED("SPI1", R9A07G043_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4), DEF_SD_MUX("SD0", R9A07G043_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_sdhi, From f549a4d2e0293a7220fb86c413cb86d0c5595455 Mon Sep 17 00:00:00 2001 From: "Rob Herring (Arm)" Date: Sun, 9 Feb 2025 20:59:02 +0800 Subject: [PATCH 423/606] of: resolver: Simplify of_resolve_phandles() using __free() [ Upstream commit 5275e8b5293f65cc82a5ee5eab02dd573b911d6e ] Use the __free() cleanup to simplify of_resolve_phandles() and remove all the goto's. Signed-off-by: Rob Herring (Arm) Stable-dep-of: a46a0805635d ("of: resolver: Fix device node refcount leakage in of_resolve_phandles()") Signed-off-by: Sasha Levin --- drivers/of/resolver.c | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c index b278ab4338ce..2dd19dc6987c 100644 --- a/drivers/of/resolver.c +++ b/drivers/of/resolver.c @@ -263,24 +263,20 @@ static int adjust_local_phandle_references(struct device_node *local_fixups, int of_resolve_phandles(struct device_node *overlay) { struct device_node *child, *local_fixups, *refnode; - struct device_node *tree_symbols, *overlay_fixups; + struct device_node *overlay_fixups; struct property *prop; const char *refpath; phandle phandle, phandle_delta; int err; - tree_symbols = NULL; - if (!overlay) { pr_err("null overlay\n"); - err = -EINVAL; - goto out; + return -EINVAL; } if (!of_node_check_flag(overlay, OF_DETACHED)) { pr_err("overlay not detached\n"); - err = -EINVAL; - goto out; + return -EINVAL; } phandle_delta = live_tree_max_phandle() + 1; @@ -292,7 +288,7 @@ int of_resolve_phandles(struct device_node *overlay) err = adjust_local_phandle_references(local_fixups, overlay, phandle_delta); if (err) - goto out; + return err; overlay_fixups = NULL; @@ -301,16 +297,13 @@ int of_resolve_phandles(struct device_node *overlay) overlay_fixups = child; } - if (!overlay_fixups) { - err = 0; - goto out; - } + if (!overlay_fixups) + return 0; - tree_symbols = of_find_node_by_path("/__symbols__"); + struct device_node __free(device_node) *tree_symbols = of_find_node_by_path("/__symbols__"); if (!tree_symbols) { pr_err("no symbols in root of device tree.\n"); - err = -EINVAL; - goto out; + return -EINVAL; } for_each_property_of_node(overlay_fixups, prop) { @@ -324,14 +317,12 @@ int of_resolve_phandles(struct device_node *overlay) if (err) { pr_err("node label '%s' not found in live devicetree symbols table\n", prop->name); - goto out; + return err; } refnode = of_find_node_by_path(refpath); - if (!refnode) { - err = -ENOENT; - goto out; - } + if (!refnode) + return -ENOENT; phandle = refnode->phandle; of_node_put(refnode); @@ -341,11 +332,8 @@ int of_resolve_phandles(struct device_node *overlay) break; } -out: if (err) pr_err("overlay phandle fixup failed: %d\n", err); - of_node_put(tree_symbols); - return err; } EXPORT_SYMBOL_GPL(of_resolve_phandles); From 81435b85b2ebc7f5df404290e709e69f35749493 Mon Sep 17 00:00:00 2001 From: Zijun Hu Date: Mon, 24 Feb 2025 17:01:55 -0600 Subject: [PATCH 424/606] of: resolver: Fix device node refcount leakage in of_resolve_phandles() [ Upstream commit a46a0805635d07de50c2ac71588345323c13b2f9 ] In of_resolve_phandles(), refcount of device node @local_fixups will be increased if the for_each_child_of_node() exits early, but nowhere to decrease the refcount, so cause refcount leakage for the node. Fix by using __free() on @local_fixups. Fixes: da56d04c806a ("of/resolver: Switch to new local fixups format.") Cc: stable@vger.kernel.org Signed-off-by: Zijun Hu Link: https://lore.kernel.org/r/20250209-of_irq_fix-v2-9-93e3a2659aa7@quicinc.com [robh: Use __free() instead] Signed-off-by: Rob Herring (Arm) Signed-off-by: Sasha Levin --- drivers/of/resolver.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c index 2dd19dc6987c..d5c1b2a126a5 100644 --- a/drivers/of/resolver.c +++ b/drivers/of/resolver.c @@ -262,8 +262,9 @@ static int adjust_local_phandle_references(struct device_node *local_fixups, */ int of_resolve_phandles(struct device_node *overlay) { - struct device_node *child, *local_fixups, *refnode; + struct device_node *child, *refnode; struct device_node *overlay_fixups; + struct device_node __free(device_node) *local_fixups = NULL; struct property *prop; const char *refpath; phandle phandle, phandle_delta; From bd2a352a0d72575f1842d28c14c10089f0cfe1ae Mon Sep 17 00:00:00 2001 From: Ma Ke Date: Tue, 25 Feb 2025 10:14:40 +0800 Subject: [PATCH 425/606] PCI: Fix reference leak in pci_register_host_bridge() [ Upstream commit 804443c1f27883926de94c849d91f5b7d7d696e9 ] If device_register() fails, call put_device() to give up the reference to avoid a memory leak, per the comment at device_register(). Found by code review. Link: https://lore.kernel.org/r/20250225021440.3130264-1-make24@iscas.ac.cn Fixes: 37d6a0a6f470 ("PCI: Add pci_register_host_bridge() interface") Signed-off-by: Ma Ke [bhelgaas: squash Dan Carpenter's double free fix from https://lore.kernel.org/r/db806a6c-a91b-4e5a-a84b-6b7e01bdac85@stanley.mountain] Signed-off-by: Bjorn Helgaas Cc: stable@vger.kernel.org Signed-off-by: Sasha Levin --- drivers/pci/probe.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 8e5d818c29a9..b7cec139d816 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -885,6 +885,7 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge) resource_size_t offset, next_offset; LIST_HEAD(resources); struct resource *res, *next_res; + bool bus_registered = false; char addr[64], *fmt; const char *name; int err; @@ -948,6 +949,7 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge) name = dev_name(&bus->dev); err = device_register(&bus->dev); + bus_registered = true; if (err) goto unregister; @@ -1031,12 +1033,15 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge) unregister: put_device(&bridge->dev); device_del(&bridge->dev); - free: #ifdef CONFIG_PCI_DOMAINS_GENERIC pci_bus_release_domain_nr(bus, parent); #endif - kfree(bus); + if (bus_registered) + put_device(&bus->dev); + else + kfree(bus); + return err; } From ada8d7fa0ad49a2a078f97f7f6e02d24d3c357a3 Mon Sep 17 00:00:00 2001 From: Vincent Guittot Date: Wed, 22 Nov 2023 14:39:03 +0100 Subject: [PATCH 426/606] sched/cpufreq: Rework schedutil governor performance estimation [ Upstream commit 9c0b4bb7f6303c9c4e2e34984c46f5a86478f84d ] The current method to take into account uclamp hints when estimating the target frequency can end in a situation where the selected target frequency is finally higher than uclamp hints, whereas there are no real needs. Such cases mainly happen because we are currently mixing the traditional scheduler utilization signal with the uclamp performance hints. By adding these 2 metrics, we loose an important information when it comes to select the target frequency, and we have to make some assumptions which can't fit all cases. Rework the interface between the scheduler and schedutil governor in order to propagate all information down to the cpufreq governor. effective_cpu_util() interface changes and now returns the actual utilization of the CPU with 2 optional inputs: - The minimum performance for this CPU; typically the capacity to handle the deadline task and the interrupt pressure. But also uclamp_min request when available. - The maximum targeting performance for this CPU which reflects the maximum level that we would like to not exceed. By default it will be the CPU capacity but can be reduced because of some performance hints set with uclamp. The value can be lower than actual utilization and/or min performance level. A new sugov_effective_cpu_perf() interface is also available to compute the final performance level that is targeted for the CPU, after applying some cpufreq headroom and taking into account all inputs. With these 2 functions, schedutil is now able to decide when it must go above uclamp hints. It now also has a generic way to get the min performance level. The dependency between energy model and cpufreq governor and its headroom policy doesn't exist anymore. eenv_pd_max_util() asks schedutil for the targeted performance after applying the impact of the waking task. [ mingo: Refined the changelog & C comments. ] Signed-off-by: Vincent Guittot Signed-off-by: Ingo Molnar Acked-by: Rafael J. Wysocki Link: https://lore.kernel.org/r/20231122133904.446032-2-vincent.guittot@linaro.org Stable-dep-of: 79443a7e9da3 ("cpufreq/sched: Explicitly synchronize limits_changed flag handling") Signed-off-by: Sasha Levin --- include/linux/energy_model.h | 1 - kernel/sched/core.c | 90 ++++++++++++++------------------ kernel/sched/cpufreq_schedutil.c | 35 +++++++++---- kernel/sched/fair.c | 22 ++++++-- kernel/sched/sched.h | 24 +++------ 5 files changed, 89 insertions(+), 83 deletions(-) diff --git a/include/linux/energy_model.h b/include/linux/energy_model.h index b9caa01dfac4..adec808b371a 100644 --- a/include/linux/energy_model.h +++ b/include/linux/energy_model.h @@ -243,7 +243,6 @@ static inline unsigned long em_cpu_energy(struct em_perf_domain *pd, scale_cpu = arch_scale_cpu_capacity(cpu); ps = &pd->table[pd->nr_perf_states - 1]; - max_util = map_util_perf(max_util); max_util = min(max_util, allowed_cpu_cap); freq = map_util_freq(max_util, ps->frequency, scale_cpu); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 41f035744683..760a6c3781cb 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -7406,18 +7406,13 @@ int sched_core_idle_cpu(int cpu) * required to meet deadlines. */ unsigned long effective_cpu_util(int cpu, unsigned long util_cfs, - enum cpu_util_type type, - struct task_struct *p) + unsigned long *min, + unsigned long *max) { - unsigned long dl_util, util, irq, max; + unsigned long util, irq, scale; struct rq *rq = cpu_rq(cpu); - max = arch_scale_cpu_capacity(cpu); - - if (!uclamp_is_used() && - type == FREQUENCY_UTIL && rt_rq_is_runnable(&rq->rt)) { - return max; - } + scale = arch_scale_cpu_capacity(cpu); /* * Early check to see if IRQ/steal time saturates the CPU, can be @@ -7425,45 +7420,49 @@ unsigned long effective_cpu_util(int cpu, unsigned long util_cfs, * update_irq_load_avg(). */ irq = cpu_util_irq(rq); - if (unlikely(irq >= max)) - return max; + if (unlikely(irq >= scale)) { + if (min) + *min = scale; + if (max) + *max = scale; + return scale; + } + + if (min) { + /* + * The minimum utilization returns the highest level between: + * - the computed DL bandwidth needed with the IRQ pressure which + * steals time to the deadline task. + * - The minimum performance requirement for CFS and/or RT. + */ + *min = max(irq + cpu_bw_dl(rq), uclamp_rq_get(rq, UCLAMP_MIN)); + + /* + * When an RT task is runnable and uclamp is not used, we must + * ensure that the task will run at maximum compute capacity. + */ + if (!uclamp_is_used() && rt_rq_is_runnable(&rq->rt)) + *min = max(*min, scale); + } /* * Because the time spend on RT/DL tasks is visible as 'lost' time to * CFS tasks and we use the same metric to track the effective * utilization (PELT windows are synchronized) we can directly add them * to obtain the CPU's actual utilization. - * - * CFS and RT utilization can be boosted or capped, depending on - * utilization clamp constraints requested by currently RUNNABLE - * tasks. - * When there are no CFS RUNNABLE tasks, clamps are released and - * frequency will be gracefully reduced with the utilization decay. */ util = util_cfs + cpu_util_rt(rq); - if (type == FREQUENCY_UTIL) - util = uclamp_rq_util_with(rq, util, p); - - dl_util = cpu_util_dl(rq); + util += cpu_util_dl(rq); /* - * For frequency selection we do not make cpu_util_dl() a permanent part - * of this sum because we want to use cpu_bw_dl() later on, but we need - * to check if the CFS+RT+DL sum is saturated (ie. no idle time) such - * that we select f_max when there is no idle time. - * - * NOTE: numerical errors or stop class might cause us to not quite hit - * saturation when we should -- something for later. + * The maximum hint is a soft bandwidth requirement, which can be lower + * than the actual utilization because of uclamp_max requirements. */ - if (util + dl_util >= max) - return max; + if (max) + *max = min(scale, uclamp_rq_get(rq, UCLAMP_MAX)); - /* - * OTOH, for energy computation we need the estimated running time, so - * include util_dl and ignore dl_bw. - */ - if (type == ENERGY_UTIL) - util += dl_util; + if (util >= scale) + return scale; /* * There is still idle time; further improve the number by using the @@ -7474,28 +7473,15 @@ unsigned long effective_cpu_util(int cpu, unsigned long util_cfs, * U' = irq + --------- * U * max */ - util = scale_irq_capacity(util, irq, max); + util = scale_irq_capacity(util, irq, scale); util += irq; - /* - * Bandwidth required by DEADLINE must always be granted while, for - * FAIR and RT, we use blocked utilization of IDLE CPUs as a mechanism - * to gracefully reduce the frequency when no tasks show up for longer - * periods of time. - * - * Ideally we would like to set bw_dl as min/guaranteed freq and util + - * bw_dl as requested freq. However, cpufreq is not yet ready for such - * an interface. So, we only do the latter for now. - */ - if (type == FREQUENCY_UTIL) - util += cpu_bw_dl(rq); - - return min(max, util); + return min(scale, util); } unsigned long sched_cpu_util(int cpu) { - return effective_cpu_util(cpu, cpu_util_cfs(cpu), ENERGY_UTIL, NULL); + return effective_cpu_util(cpu, cpu_util_cfs(cpu), NULL, NULL); } #endif /* CONFIG_SMP */ diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c index 259521b179aa..f84473f73ed0 100644 --- a/kernel/sched/cpufreq_schedutil.c +++ b/kernel/sched/cpufreq_schedutil.c @@ -47,7 +47,7 @@ struct sugov_cpu { u64 last_update; unsigned long util; - unsigned long bw_dl; + unsigned long bw_min; /* The field below is for single-CPU policies only: */ #ifdef CONFIG_NO_HZ_COMMON @@ -155,7 +155,6 @@ static unsigned int get_next_freq(struct sugov_policy *sg_policy, unsigned int freq = arch_scale_freq_invariant() ? policy->cpuinfo.max_freq : policy->cur; - util = map_util_perf(util); freq = map_util_freq(util, freq, max); if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update) @@ -165,14 +164,30 @@ static unsigned int get_next_freq(struct sugov_policy *sg_policy, return cpufreq_driver_resolve_freq(policy, freq); } +unsigned long sugov_effective_cpu_perf(int cpu, unsigned long actual, + unsigned long min, + unsigned long max) +{ + /* Add dvfs headroom to actual utilization */ + actual = map_util_perf(actual); + /* Actually we don't need to target the max performance */ + if (actual < max) + max = actual; + + /* + * Ensure at least minimum performance while providing more compute + * capacity when possible. + */ + return max(min, max); +} + static void sugov_get_util(struct sugov_cpu *sg_cpu) { - unsigned long util = cpu_util_cfs_boost(sg_cpu->cpu); - struct rq *rq = cpu_rq(sg_cpu->cpu); + unsigned long min, max, util = cpu_util_cfs_boost(sg_cpu->cpu); - sg_cpu->bw_dl = cpu_bw_dl(rq); - sg_cpu->util = effective_cpu_util(sg_cpu->cpu, util, - FREQUENCY_UTIL, NULL); + util = effective_cpu_util(sg_cpu->cpu, util, &min, &max); + sg_cpu->bw_min = min; + sg_cpu->util = sugov_effective_cpu_perf(sg_cpu->cpu, util, min, max); } /** @@ -318,7 +333,7 @@ static inline bool sugov_cpu_is_busy(struct sugov_cpu *sg_cpu) { return false; } */ static inline void ignore_dl_rate_limit(struct sugov_cpu *sg_cpu) { - if (cpu_bw_dl(cpu_rq(sg_cpu->cpu)) > sg_cpu->bw_dl) + if (cpu_bw_dl(cpu_rq(sg_cpu->cpu)) > sg_cpu->bw_min) sg_cpu->sg_policy->limits_changed = true; } @@ -419,8 +434,8 @@ static void sugov_update_single_perf(struct update_util_data *hook, u64 time, sugov_cpu_is_busy(sg_cpu) && sg_cpu->util < prev_util) sg_cpu->util = prev_util; - cpufreq_driver_adjust_perf(sg_cpu->cpu, map_util_perf(sg_cpu->bw_dl), - map_util_perf(sg_cpu->util), max_cap); + cpufreq_driver_adjust_perf(sg_cpu->cpu, sg_cpu->bw_min, + sg_cpu->util, max_cap); sg_cpu->sg_policy->last_freq_update_time = time; } diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 050cc41585f8..268e2a49b964 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -7859,7 +7859,7 @@ static inline void eenv_pd_busy_time(struct energy_env *eenv, for_each_cpu(cpu, pd_cpus) { unsigned long util = cpu_util(cpu, p, -1, 0); - busy_time += effective_cpu_util(cpu, util, ENERGY_UTIL, NULL); + busy_time += effective_cpu_util(cpu, util, NULL, NULL); } eenv->pd_busy_time = min(eenv->pd_cap, busy_time); @@ -7882,7 +7882,7 @@ eenv_pd_max_util(struct energy_env *eenv, struct cpumask *pd_cpus, for_each_cpu(cpu, pd_cpus) { struct task_struct *tsk = (cpu == dst_cpu) ? p : NULL; unsigned long util = cpu_util(cpu, p, dst_cpu, 1); - unsigned long eff_util; + unsigned long eff_util, min, max; /* * Performance domain frequency: utilization clamping @@ -7891,7 +7891,23 @@ eenv_pd_max_util(struct energy_env *eenv, struct cpumask *pd_cpus, * NOTE: in case RT tasks are running, by default the * FREQUENCY_UTIL's utilization can be max OPP. */ - eff_util = effective_cpu_util(cpu, util, FREQUENCY_UTIL, tsk); + eff_util = effective_cpu_util(cpu, util, &min, &max); + + /* Task's uclamp can modify min and max value */ + if (tsk && uclamp_is_used()) { + min = max(min, uclamp_eff_value(p, UCLAMP_MIN)); + + /* + * If there is no active max uclamp constraint, + * directly use task's one, otherwise keep max. + */ + if (uclamp_rq_is_idle(cpu_rq(cpu))) + max = uclamp_eff_value(p, UCLAMP_MAX); + else + max = max(max, uclamp_eff_value(p, UCLAMP_MAX)); + } + + eff_util = sugov_effective_cpu_perf(cpu, eff_util, min, max); max_util = max(max_util, eff_util); } diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index f84b2e9feeb6..60dc51f43dd9 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -2984,24 +2984,14 @@ static inline void cpufreq_update_util(struct rq *rq, unsigned int flags) {} #endif #ifdef CONFIG_SMP -/** - * enum cpu_util_type - CPU utilization type - * @FREQUENCY_UTIL: Utilization used to select frequency - * @ENERGY_UTIL: Utilization used during energy calculation - * - * The utilization signals of all scheduling classes (CFS/RT/DL) and IRQ time - * need to be aggregated differently depending on the usage made of them. This - * enum is used within effective_cpu_util() to differentiate the types of - * utilization expected by the callers, and adjust the aggregation accordingly. - */ -enum cpu_util_type { - FREQUENCY_UTIL, - ENERGY_UTIL, -}; - unsigned long effective_cpu_util(int cpu, unsigned long util_cfs, - enum cpu_util_type type, - struct task_struct *p); + unsigned long *min, + unsigned long *max); + +unsigned long sugov_effective_cpu_perf(int cpu, unsigned long actual, + unsigned long min, + unsigned long max); + /* * Verify the fitness of task @p to run on @cpu taking into account the From 485104cd63533cc513432f2b490bad14243552d3 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 17 Jan 2025 14:18:52 +0000 Subject: [PATCH 427/606] scsi: ufs: qcom: fix dev reference leaked through of_qcom_ice_get [ Upstream commit ded40f32b55f7f2f4ed9627dd3c37a1fe89ed8c6 ] The driver leaks the device reference taken with of_find_device_by_node(). Fix the leak by using devm_of_qcom_ice_get(). Fixes: 56541c7c4468 ("scsi: ufs: ufs-qcom: Switch to the new ICE API") Cc: stable@vger.kernel.org Signed-off-by: Tudor Ambarus Reviewed-by: Krzysztof Kozlowski Reviewed-by: Abel Vesa Acked-by: Martin K. Petersen # SCSI Reviewed-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20250117-qcom-ice-fix-dev-leak-v2-3-1ffa5b6884cb@linaro.org Signed-off-by: Bjorn Andersson Signed-off-by: Sasha Levin --- drivers/ufs/host/ufs-qcom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 51ed40529f9a..c6417ef074a4 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -121,7 +121,7 @@ static int ufs_qcom_ice_init(struct ufs_qcom_host *host) struct device *dev = hba->dev; struct qcom_ice *ice; - ice = of_qcom_ice_get(dev); + ice = devm_of_qcom_ice_get(dev); if (ice == ERR_PTR(-EOPNOTSUPP)) { dev_warn(dev, "Disabling inline encryption support\n"); ice = NULL; From 7fc781ca938fde88b11a75d4678c9a457c221199 Mon Sep 17 00:00:00 2001 From: Vincent Guittot Date: Mon, 9 Oct 2023 12:36:16 +0200 Subject: [PATCH 428/606] sched/topology: Consolidate and clean up access to a CPU's max compute capacity [ Upstream commit 7bc263840bc3377186cb06b003ac287bb2f18ce2 ] Remove the rq::cpu_capacity_orig field and use arch_scale_cpu_capacity() instead. The scheduler uses 3 methods to get access to a CPU's max compute capacity: - arch_scale_cpu_capacity(cpu) which is the default way to get a CPU's capacity. - cpu_capacity_orig field which is periodically updated with arch_scale_cpu_capacity(). - capacity_orig_of(cpu) which encapsulates rq->cpu_capacity_orig. There is no real need to save the value returned by arch_scale_cpu_capacity() in struct rq. arch_scale_cpu_capacity() returns: - either a per_cpu variable. - or a const value for systems which have only one capacity. Remove rq::cpu_capacity_orig and use arch_scale_cpu_capacity() everywhere. No functional changes. Some performance tests on Arm64: - small SMP device (hikey): no noticeable changes - HMP device (RB5): hackbench shows minor improvement (1-2%) - large smp (thx2): hackbench and tbench shows minor improvement (1%) Signed-off-by: Vincent Guittot Signed-off-by: Ingo Molnar Reviewed-by: Dietmar Eggemann Link: https://lore.kernel.org/r/20231009103621.374412-2-vincent.guittot@linaro.org Stable-dep-of: 79443a7e9da3 ("cpufreq/sched: Explicitly synchronize limits_changed flag handling") Signed-off-by: Sasha Levin --- Documentation/scheduler/sched-capacity.rst | 13 +++++++------ kernel/sched/core.c | 2 +- kernel/sched/cpudeadline.c | 2 +- kernel/sched/deadline.c | 4 ++-- kernel/sched/fair.c | 18 ++++++++---------- kernel/sched/rt.c | 2 +- kernel/sched/sched.h | 6 ------ kernel/sched/topology.c | 7 +++++-- 8 files changed, 25 insertions(+), 29 deletions(-) diff --git a/Documentation/scheduler/sched-capacity.rst b/Documentation/scheduler/sched-capacity.rst index e2c1cf743158..de414b33dd2a 100644 --- a/Documentation/scheduler/sched-capacity.rst +++ b/Documentation/scheduler/sched-capacity.rst @@ -39,14 +39,15 @@ per Hz, leading to:: ------------------- Two different capacity values are used within the scheduler. A CPU's -``capacity_orig`` is its maximum attainable capacity, i.e. its maximum -attainable performance level. A CPU's ``capacity`` is its ``capacity_orig`` to -which some loss of available performance (e.g. time spent handling IRQs) is -subtracted. +``original capacity`` is its maximum attainable capacity, i.e. its maximum +attainable performance level. This original capacity is returned by +the function arch_scale_cpu_capacity(). A CPU's ``capacity`` is its ``original +capacity`` to which some loss of available performance (e.g. time spent +handling IRQs) is subtracted. Note that a CPU's ``capacity`` is solely intended to be used by the CFS class, -while ``capacity_orig`` is class-agnostic. The rest of this document will use -the term ``capacity`` interchangeably with ``capacity_orig`` for the sake of +while ``original capacity`` is class-agnostic. The rest of this document will use +the term ``capacity`` interchangeably with ``original capacity`` for the sake of brevity. 1.3 Platform examples diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 8c5f75af07db..41f035744683 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -10048,7 +10048,7 @@ void __init sched_init(void) #ifdef CONFIG_SMP rq->sd = NULL; rq->rd = NULL; - rq->cpu_capacity = rq->cpu_capacity_orig = SCHED_CAPACITY_SCALE; + rq->cpu_capacity = SCHED_CAPACITY_SCALE; rq->balance_callback = &balance_push_callback; rq->active_balance = 0; rq->next_balance = jiffies; diff --git a/kernel/sched/cpudeadline.c b/kernel/sched/cpudeadline.c index 57c92d751bcd..95baa12a1029 100644 --- a/kernel/sched/cpudeadline.c +++ b/kernel/sched/cpudeadline.c @@ -131,7 +131,7 @@ int cpudl_find(struct cpudl *cp, struct task_struct *p, if (!dl_task_fits_capacity(p, cpu)) { cpumask_clear_cpu(cpu, later_mask); - cap = capacity_orig_of(cpu); + cap = arch_scale_cpu_capacity(cpu); if (cap > max_cap || (cpu == task_cpu(p) && cap == max_cap)) { diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index 6c639e48e49a..a15cf7969953 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -132,7 +132,7 @@ static inline unsigned long __dl_bw_capacity(const struct cpumask *mask) int i; for_each_cpu_and(i, mask, cpu_active_mask) - cap += capacity_orig_of(i); + cap += arch_scale_cpu_capacity(i); return cap; } @@ -144,7 +144,7 @@ static inline unsigned long __dl_bw_capacity(const struct cpumask *mask) static inline unsigned long dl_bw_capacity(int i) { if (!sched_asym_cpucap_active() && - capacity_orig_of(i) == SCHED_CAPACITY_SCALE) { + arch_scale_cpu_capacity(i) == SCHED_CAPACITY_SCALE) { return dl_bw_cpus(i) << SCHED_CAPACITY_SHIFT; } else { RCU_LOCKDEP_WARN(!rcu_read_lock_sched_held(), diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 2808dbdd0384..050cc41585f8 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -4951,7 +4951,7 @@ static inline void util_est_update(struct cfs_rq *cfs_rq, * To avoid overestimation of actual task utilization, skip updates if * we cannot grant there is idle time in this CPU. */ - if (task_util(p) > capacity_orig_of(cpu_of(rq_of(cfs_rq)))) + if (task_util(p) > arch_scale_cpu_capacity(cpu_of(rq_of(cfs_rq)))) return; /* @@ -4999,14 +4999,14 @@ static inline int util_fits_cpu(unsigned long util, return fits; /* - * We must use capacity_orig_of() for comparing against uclamp_min and + * We must use arch_scale_cpu_capacity() for comparing against uclamp_min and * uclamp_max. We only care about capacity pressure (by using * capacity_of()) for comparing against the real util. * * If a task is boosted to 1024 for example, we don't want a tiny * pressure to skew the check whether it fits a CPU or not. * - * Similarly if a task is capped to capacity_orig_of(little_cpu), it + * Similarly if a task is capped to arch_scale_cpu_capacity(little_cpu), it * should fit a little cpu even if there's some pressure. * * Only exception is for thermal pressure since it has a direct impact @@ -5018,7 +5018,7 @@ static inline int util_fits_cpu(unsigned long util, * For uclamp_max, we can tolerate a drop in performance level as the * goal is to cap the task. So it's okay if it's getting less. */ - capacity_orig = capacity_orig_of(cpu); + capacity_orig = arch_scale_cpu_capacity(cpu); capacity_orig_thermal = capacity_orig - arch_scale_thermal_pressure(cpu); /* @@ -7515,7 +7515,7 @@ select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target) * Look for the CPU with best capacity. */ else if (fits < 0) - cpu_cap = capacity_orig_of(cpu) - thermal_load_avg(cpu_rq(cpu)); + cpu_cap = arch_scale_cpu_capacity(cpu) - thermal_load_avg(cpu_rq(cpu)); /* * First, select CPU which fits better (-1 being better than 0). @@ -7757,7 +7757,7 @@ cpu_util(int cpu, struct task_struct *p, int dst_cpu, int boost) util = max(util, util_est); } - return min(util, capacity_orig_of(cpu)); + return min(util, arch_scale_cpu_capacity(cpu)); } unsigned long cpu_util_cfs(int cpu) @@ -9544,8 +9544,6 @@ static void update_cpu_capacity(struct sched_domain *sd, int cpu) unsigned long capacity = scale_rt_capacity(cpu); struct sched_group *sdg = sd->groups; - cpu_rq(cpu)->cpu_capacity_orig = arch_scale_cpu_capacity(cpu); - if (!capacity) capacity = 1; @@ -9621,7 +9619,7 @@ static inline int check_cpu_capacity(struct rq *rq, struct sched_domain *sd) { return ((rq->cpu_capacity * sd->imbalance_pct) < - (rq->cpu_capacity_orig * 100)); + (arch_scale_cpu_capacity(cpu_of(rq)) * 100)); } /* @@ -9632,7 +9630,7 @@ check_cpu_capacity(struct rq *rq, struct sched_domain *sd) static inline int check_misfit_status(struct rq *rq, struct sched_domain *sd) { return rq->misfit_task_load && - (rq->cpu_capacity_orig < rq->rd->max_cpu_capacity || + (arch_scale_cpu_capacity(rq->cpu) < rq->rd->max_cpu_capacity || check_cpu_capacity(rq, sd)); } diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index b89223a97316..91b1ee0d81fc 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -519,7 +519,7 @@ static inline bool rt_task_fits_capacity(struct task_struct *p, int cpu) min_cap = uclamp_eff_value(p, UCLAMP_MIN); max_cap = uclamp_eff_value(p, UCLAMP_MAX); - cpu_cap = capacity_orig_of(cpu); + cpu_cap = arch_scale_cpu_capacity(cpu); return cpu_cap >= min(min_cap, max_cap); } diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index d48c6a292a83..f84b2e9feeb6 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1048,7 +1048,6 @@ struct rq { struct sched_domain __rcu *sd; unsigned long cpu_capacity; - unsigned long cpu_capacity_orig; struct balance_callback *balance_callback; @@ -2985,11 +2984,6 @@ static inline void cpufreq_update_util(struct rq *rq, unsigned int flags) {} #endif #ifdef CONFIG_SMP -static inline unsigned long capacity_orig_of(int cpu) -{ - return cpu_rq(cpu)->cpu_capacity_orig; -} - /** * enum cpu_util_type - CPU utilization type * @FREQUENCY_UTIL: Utilization used to select frequency diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c index 2ed884bb3621..c61698cff0f3 100644 --- a/kernel/sched/topology.c +++ b/kernel/sched/topology.c @@ -2486,12 +2486,15 @@ build_sched_domains(const struct cpumask *cpu_map, struct sched_domain_attr *att /* Attach the domains */ rcu_read_lock(); for_each_cpu(i, cpu_map) { + unsigned long capacity; + rq = cpu_rq(i); sd = *per_cpu_ptr(d.sd, i); + capacity = arch_scale_cpu_capacity(i); /* Use READ_ONCE()/WRITE_ONCE() to avoid load/store tearing: */ - if (rq->cpu_capacity_orig > READ_ONCE(d.rd->max_cpu_capacity)) - WRITE_ONCE(d.rd->max_cpu_capacity, rq->cpu_capacity_orig); + if (capacity > READ_ONCE(d.rd->max_cpu_capacity)) + WRITE_ONCE(d.rd->max_cpu_capacity, capacity); cpu_attach_domain(sd, d.rd, i); } From d70c078c26c0ae27d4a55336ac40cb724333ef87 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 15 Apr 2025 11:59:15 +0200 Subject: [PATCH 429/606] cpufreq/sched: Explicitly synchronize limits_changed flag handling [ Upstream commit 79443a7e9da3c9f68290a8653837e23aba0fa89f ] The handling of the limits_changed flag in struct sugov_policy needs to be explicitly synchronized to ensure that cpufreq policy limits updates will not be missed in some cases. Without that synchronization it is theoretically possible that the limits_changed update in sugov_should_update_freq() will be reordered with respect to the reads of the policy limits in cpufreq_driver_resolve_freq() and in that case, if the limits_changed update in sugov_limits() clobbers the one in sugov_should_update_freq(), the new policy limits may not take effect for a long time. Likewise, the limits_changed update in sugov_limits() may theoretically get reordered with respect to the updates of the policy limits in cpufreq_set_policy() and if sugov_should_update_freq() runs between them, the policy limits change may be missed. To ensure that the above situations will not take place, add memory barriers preventing the reordering in question from taking place and add READ_ONCE() and WRITE_ONCE() annotations around all of the limits_changed flag updates to prevent the compiler from messing up with that code. Fixes: 600f5badb78c ("cpufreq: schedutil: Don't skip freq update when limits change") Cc: 5.3+ # 5.3+ Signed-off-by: Rafael J. Wysocki Reviewed-by: Christian Loehle Link: https://patch.msgid.link/3376719.44csPzL39Z@rjwysocki.net Signed-off-by: Sasha Levin --- kernel/sched/cpufreq_schedutil.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c index f84473f73ed0..776be0549162 100644 --- a/kernel/sched/cpufreq_schedutil.c +++ b/kernel/sched/cpufreq_schedutil.c @@ -81,9 +81,20 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time) if (!cpufreq_this_cpu_can_update(sg_policy->policy)) return false; - if (unlikely(sg_policy->limits_changed)) { - sg_policy->limits_changed = false; + if (unlikely(READ_ONCE(sg_policy->limits_changed))) { + WRITE_ONCE(sg_policy->limits_changed, false); sg_policy->need_freq_update = true; + + /* + * The above limits_changed update must occur before the reads + * of policy limits in cpufreq_driver_resolve_freq() or a policy + * limits update might be missed, so use a memory barrier to + * ensure it. + * + * This pairs with the write memory barrier in sugov_limits(). + */ + smp_mb(); + return true; } @@ -334,7 +345,7 @@ static inline bool sugov_cpu_is_busy(struct sugov_cpu *sg_cpu) { return false; } static inline void ignore_dl_rate_limit(struct sugov_cpu *sg_cpu) { if (cpu_bw_dl(cpu_rq(sg_cpu->cpu)) > sg_cpu->bw_min) - sg_cpu->sg_policy->limits_changed = true; + WRITE_ONCE(sg_cpu->sg_policy->limits_changed, true); } static inline bool sugov_update_single_common(struct sugov_cpu *sg_cpu, @@ -844,7 +855,16 @@ static void sugov_limits(struct cpufreq_policy *policy) mutex_unlock(&sg_policy->work_lock); } - sg_policy->limits_changed = true; + /* + * The limits_changed update below must take place before the updates + * of policy limits in cpufreq_set_policy() or a policy limits update + * might be missed, so use a memory barrier to ensure it. + * + * This pairs with the memory barrier in sugov_should_update_freq(). + */ + smp_wmb(); + + WRITE_ONCE(sg_policy->limits_changed, true); } struct cpufreq_governor schedutil_gov = { From f55e7f8abbd3f6f2402882183051f3bbc49a7b4c Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 12 Mar 2025 10:47:11 +0000 Subject: [PATCH 430/606] ceph: Fix incorrect flush end position calculation [ Upstream commit f452a2204614fc10e2c3b85904c4bd300c2789dc ] In ceph, in fill_fscrypt_truncate(), the end flush position is calculated by: loff_t lend = orig_pos + CEPH_FSCRYPT_BLOCK_SHIFT - 1; but that's using the block shift not the block size. Fix this to use the block size instead. Fixes: 5c64737d2536 ("ceph: add truncate size handling support for fscrypt") Signed-off-by: David Howells Reviewed-by: Viacheslav Dubeyko Signed-off-by: Ilya Dryomov Signed-off-by: Sasha Levin --- fs/ceph/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index db6977c15c28..f0befbeb6cb8 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -2319,7 +2319,7 @@ static int fill_fscrypt_truncate(struct inode *inode, /* Try to writeback the dirty pagecaches */ if (issued & (CEPH_CAP_FILE_BUFFER)) { - loff_t lend = orig_pos + CEPH_FSCRYPT_BLOCK_SHIFT - 1; + loff_t lend = orig_pos + CEPH_FSCRYPT_BLOCK_SIZE - 1; ret = filemap_write_and_wait_range(inode->i_mapping, orig_pos, lend); From 92d55d7051833116af0fc8664599f458e3dfa858 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 9 Apr 2025 17:15:42 +0200 Subject: [PATCH 431/606] dma/contiguous: avoid warning about unused size_bytes [ Upstream commit d7b98ae5221007d3f202746903d4c21c7caf7ea9 ] When building with W=1, this variable is unused for configs with CONFIG_CMA_SIZE_SEL_PERCENTAGE=y: kernel/dma/contiguous.c:67:26: error: 'size_bytes' defined but not used [-Werror=unused-const-variable=] Change this to a macro to avoid the warning. Fixes: c64be2bb1c6e ("drivers: add Contiguous Memory Allocator") Signed-off-by: Arnd Bergmann Signed-off-by: Marek Szyprowski Link: https://lore.kernel.org/r/20250409151557.3890443-1-arnd@kernel.org Signed-off-by: Sasha Levin --- kernel/dma/contiguous.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c index f005c66f378c..a60081979963 100644 --- a/kernel/dma/contiguous.c +++ b/kernel/dma/contiguous.c @@ -70,8 +70,7 @@ struct cma *dma_contiguous_default_area; * Users, who want to set the size of global CMA area for their system * should use cma= kernel parameter. */ -static const phys_addr_t size_bytes __initconst = - (phys_addr_t)CMA_SIZE_MBYTES * SZ_1M; +#define size_bytes ((phys_addr_t)CMA_SIZE_MBYTES * SZ_1M) static phys_addr_t size_cmdline __initdata = -1; static phys_addr_t base_cmdline __initdata; static phys_addr_t limit_cmdline __initdata; From 1053dcf8a504d4933bb3f73df22bc363298d194b Mon Sep 17 00:00:00 2001 From: Henry Martin Date: Wed, 9 Apr 2025 20:48:13 +0800 Subject: [PATCH 432/606] cpufreq: apple-soc: Fix null-ptr-deref in apple_soc_cpufreq_get_rate() [ Upstream commit 9992649f6786921873a9b89dafa5e04d8c5fef2b ] cpufreq_cpu_get_raw() can return NULL when the target CPU is not present in the policy->cpus mask. apple_soc_cpufreq_get_rate() does not check for this case, which results in a NULL pointer dereference. Fixes: 6286bbb40576 ("cpufreq: apple-soc: Add new driver to control Apple SoC CPU P-states") Signed-off-by: Henry Martin Signed-off-by: Viresh Kumar Signed-off-by: Sasha Levin --- drivers/cpufreq/apple-soc-cpufreq.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/apple-soc-cpufreq.c b/drivers/cpufreq/apple-soc-cpufreq.c index 021f423705e1..9ba6b09775f6 100644 --- a/drivers/cpufreq/apple-soc-cpufreq.c +++ b/drivers/cpufreq/apple-soc-cpufreq.c @@ -103,11 +103,17 @@ static const struct of_device_id apple_soc_cpufreq_of_match[] = { static unsigned int apple_soc_cpufreq_get_rate(unsigned int cpu) { - struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu); - struct apple_cpu_priv *priv = policy->driver_data; + struct cpufreq_policy *policy; + struct apple_cpu_priv *priv; struct cpufreq_frequency_table *p; unsigned int pstate; + policy = cpufreq_cpu_get_raw(cpu); + if (unlikely(!policy)) + return 0; + + priv = policy->driver_data; + if (priv->info->cur_pstate_mask) { u64 reg = readq_relaxed(priv->reg_base + APPLE_DVFS_STATUS); From ea834c90aa7cc80a1b456f7a91432734d5087d16 Mon Sep 17 00:00:00 2001 From: Henry Martin Date: Tue, 8 Apr 2025 23:03:53 +0800 Subject: [PATCH 433/606] cpufreq: scmi: Fix null-ptr-deref in scmi_cpufreq_get_rate() [ Upstream commit 484d3f15cc6cbaa52541d6259778e715b2c83c54 ] cpufreq_cpu_get_raw() can return NULL when the target CPU is not present in the policy->cpus mask. scmi_cpufreq_get_rate() does not check for this case, which results in a NULL pointer dereference. Add NULL check after cpufreq_cpu_get_raw() to prevent this issue. Fixes: 99d6bdf33877 ("cpufreq: add support for CPU DVFS based on SCMI message protocol") Signed-off-by: Henry Martin Acked-by: Sudeep Holla Signed-off-by: Viresh Kumar Signed-off-by: Sasha Levin --- drivers/cpufreq/scmi-cpufreq.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c index 079940c69ee0..e4989764efe2 100644 --- a/drivers/cpufreq/scmi-cpufreq.c +++ b/drivers/cpufreq/scmi-cpufreq.c @@ -33,11 +33,17 @@ static const struct scmi_perf_proto_ops *perf_ops; static unsigned int scmi_cpufreq_get_rate(unsigned int cpu) { - struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu); - struct scmi_data *priv = policy->driver_data; + struct cpufreq_policy *policy; + struct scmi_data *priv; unsigned long rate; int ret; + policy = cpufreq_cpu_get_raw(cpu); + if (unlikely(!policy)) + return 0; + + priv = policy->driver_data; + ret = perf_ops->freq_get(ph, priv->domain_id, &rate, false); if (ret) return 0; From 19e0eaa62e8831f2bc0285fef3bf8faaa7f3e09b Mon Sep 17 00:00:00 2001 From: Henry Martin Date: Tue, 8 Apr 2025 23:03:54 +0800 Subject: [PATCH 434/606] cpufreq: scpi: Fix null-ptr-deref in scpi_cpufreq_get_rate() [ Upstream commit 73b24dc731731edf762f9454552cb3a5b7224949 ] cpufreq_cpu_get_raw() can return NULL when the target CPU is not present in the policy->cpus mask. scpi_cpufreq_get_rate() does not check for this case, which results in a NULL pointer dereference. Fixes: 343a8d17fa8d ("cpufreq: scpi: remove arm_big_little dependency") Signed-off-by: Henry Martin Acked-by: Sudeep Holla Signed-off-by: Viresh Kumar Signed-off-by: Sasha Levin --- drivers/cpufreq/scpi-cpufreq.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c index bfc2e65e1e50..2aef39bff7d6 100644 --- a/drivers/cpufreq/scpi-cpufreq.c +++ b/drivers/cpufreq/scpi-cpufreq.c @@ -29,9 +29,16 @@ static struct scpi_ops *scpi_ops; static unsigned int scpi_cpufreq_get_rate(unsigned int cpu) { - struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu); - struct scpi_data *priv = policy->driver_data; - unsigned long rate = clk_get_rate(priv->clk); + struct cpufreq_policy *policy; + struct scpi_data *priv; + unsigned long rate; + + policy = cpufreq_cpu_get_raw(cpu); + if (unlikely(!policy)) + return 0; + + priv = policy->driver_data; + rate = clk_get_rate(priv->clk); return rate / 1000; } From d6979fabe812a168d5053e5a41d5a2e9b8afd7bf Mon Sep 17 00:00:00 2001 From: Chenyuan Yang Date: Wed, 9 Apr 2025 19:13:20 -0500 Subject: [PATCH 435/606] scsi: ufs: mcq: Add NULL check in ufshcd_mcq_abort() [ Upstream commit 4c324085062919d4e21c69e5e78456dcec0052fe ] A race can occur between the MCQ completion path and the abort handler: once a request completes, __blk_mq_free_request() sets rq->mq_hctx to NULL, meaning the subsequent ufshcd_mcq_req_to_hwq() call in ufshcd_mcq_abort() can return a NULL pointer. If this NULL pointer is dereferenced, the kernel will crash. Add a NULL check for the returned hwq pointer. If hwq is NULL, log an error and return FAILED, preventing a potential NULL-pointer dereference. As suggested by Bart, the ufshcd_cmd_inflight() check is removed. This is similar to the fix in commit 74736103fb41 ("scsi: ufs: core: Fix ufshcd_abort_one racing issue"). This is found by our static analysis tool KNighter. Signed-off-by: Chenyuan Yang Link: https://lore.kernel.org/r/20250410001320.2219341-1-chenyuan0y@gmail.com Fixes: f1304d442077 ("scsi: ufs: mcq: Added ufshcd_mcq_abort()") Reviewed-by: Bart Van Assche Reviewed-by: Peter Wang Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin --- drivers/ufs/core/ufs-mcq.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c index da8c1734d333..411109a5ebbf 100644 --- a/drivers/ufs/core/ufs-mcq.c +++ b/drivers/ufs/core/ufs-mcq.c @@ -632,13 +632,6 @@ int ufshcd_mcq_abort(struct scsi_cmnd *cmd) unsigned long flags; int err; - if (!ufshcd_cmd_inflight(lrbp->cmd)) { - dev_err(hba->dev, - "%s: skip abort. cmd at tag %d already completed.\n", - __func__, tag); - return FAILED; - } - /* Skip task abort in case previous aborts failed and report failure */ if (lrbp->req_abort_skip) { dev_err(hba->dev, "%s: skip abort. tag %d failed earlier\n", @@ -647,6 +640,11 @@ int ufshcd_mcq_abort(struct scsi_cmnd *cmd) } hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(cmd)); + if (!hwq) { + dev_err(hba->dev, "%s: skip abort. cmd at tag %d already completed.\n", + __func__, tag); + return FAILED; + } if (ufshcd_mcq_sqe_search(hba, hwq, tag)) { /* From 1845e03ea78786bf01a94331145e1a2f413dffaa Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Sun, 13 Apr 2025 11:11:42 +0100 Subject: [PATCH 436/606] cpufreq: cppc: Fix invalid return value in .get() callback [ Upstream commit 2b8e6b58889c672e1ae3601d9b2b070be4dc2fbc ] Returning a negative error code in a function with an unsigned return type is a pretty bad idea. It is probably worse when the justification for the change is "our static analisys tool found it". Fixes: cf7de25878a1 ("cppc_cpufreq: Fix possible null pointer dereference") Signed-off-by: Marc Zyngier Cc: "Rafael J. Wysocki" Cc: Viresh Kumar Reviewed-by: Lifeng Zheng Signed-off-by: Viresh Kumar Signed-off-by: Sasha Levin --- drivers/cpufreq/cppc_cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index c8447ecad797..aa34af940cb5 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -773,7 +773,7 @@ static unsigned int cppc_cpufreq_get_rate(unsigned int cpu) int ret; if (!policy) - return -ENODEV; + return 0; cpu_data = policy->driver_data; From 4a1b61f91078bc79f95b3a903adb8ccfa9d856d9 Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Sat, 29 Mar 2025 17:46:35 +1030 Subject: [PATCH 437/606] btrfs: avoid page_lockend underflow in btrfs_punch_hole_lock_range() [ Upstream commit bc2dbc4983afedd198490cca043798f57c93e9bf ] [BUG] When running btrfs/004 with 4K fs block size and 64K page size, sometimes fsstress workload can take 100% CPU for a while, but not long enough to trigger a 120s hang warning. [CAUSE] When such 100% CPU usage happens, btrfs_punch_hole_lock_range() is always in the call trace. One example when this problem happens, the function btrfs_punch_hole_lock_range() got the following parameters: lock_start = 4096, lockend = 20469 Then we calculate @page_lockstart by rounding up lock_start to page boundary, which is 64K (page size is 64K). For @page_lockend, we round down the value towards page boundary, which result 0. Then since we need to pass an inclusive end to filemap_range_has_page(), we subtract 1 from the rounded down value, resulting in (u64)-1. In the above case, the range is inside the same page, and we do not even need to call filemap_range_has_page(), not to mention to call it with (u64)-1 at the end. This behavior will cause btrfs_punch_hole_lock_range() to busy loop waiting for irrelevant range to have its pages dropped. [FIX] Calculate @page_lockend by just rounding down @lockend, without decreasing the value by one. So @page_lockend will no longer overflow. Then exit early if @page_lockend is no larger than @page_lockstart. As it means either the range is inside the same page, or the two pages are adjacent already. Finally only decrease @page_lockend when calling filemap_range_has_page(). Fixes: 0528476b6ac7 ("btrfs: fix the filemap_range_has_page() call in btrfs_punch_hole_lock_range()") Reviewed-by: Filipe Manana Signed-off-by: Qu Wenruo Signed-off-by: David Sterba Signed-off-by: Sasha Levin --- fs/btrfs/file.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 68092b64e29e..e794606e7c78 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -2225,15 +2225,20 @@ static void btrfs_punch_hole_lock_range(struct inode *inode, * will always return true. * So here we need to do extra page alignment for * filemap_range_has_page(). + * + * And do not decrease page_lockend right now, as it can be 0. */ const u64 page_lockstart = round_up(lockstart, PAGE_SIZE); - const u64 page_lockend = round_down(lockend + 1, PAGE_SIZE) - 1; + const u64 page_lockend = round_down(lockend + 1, PAGE_SIZE); while (1) { truncate_pagecache_range(inode, lockstart, lockend); lock_extent(&BTRFS_I(inode)->io_tree, lockstart, lockend, cached_state); + /* The same page or adjacent pages. */ + if (page_lockend <= page_lockstart) + break; /* * We can't have ordered extents in the range, nor dirty/writeback * pages, because we have locked the inode's VFS lock in exclusive @@ -2245,7 +2250,7 @@ static void btrfs_punch_hole_lock_range(struct inode *inode, * we do, unlock the range and retry. */ if (!filemap_range_has_page(inode->i_mapping, page_lockstart, - page_lockend)) + page_lockend - 1)) break; unlock_extent(&BTRFS_I(inode)->io_tree, lockstart, lockend, From 4d6919dd7c69fe7591a0006d5527d6861f79c8de Mon Sep 17 00:00:00 2001 From: Anastasia Kovaleva Date: Mon, 24 Mar 2025 11:49:33 +0300 Subject: [PATCH 438/606] scsi: core: Clear flags for scsi_cmnd that did not complete [ Upstream commit 54bebe46871d4e56e05fcf55c1a37e7efa24e0a8 ] Commands that have not been completed with scsi_done() do not clear the SCMD_INITIALIZED flag and therefore will not be properly reinitialized. Thus, the next time the scsi_cmnd structure is used, the command may fail in scsi_cmd_runtime_exceeded() due to the old jiffies_at_alloc value: kernel: sd 16:0:1:84: [sdts] tag#405 timing out command, waited 720s kernel: sd 16:0:1:84: [sdts] tag#405 FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_OK cmd_age=66636s Clear flags for commands that have not been completed by SCSI. Fixes: 4abafdc4360d ("block: remove the initialize_rq_fn blk_mq_ops method") Signed-off-by: Anastasia Kovaleva Link: https://lore.kernel.org/r/20250324084933.15932-2-a.kovaleva@yadro.com Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin --- drivers/scsi/scsi_lib.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index e6dc2c556fde..bd75e3ebc14d 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1152,8 +1152,12 @@ EXPORT_SYMBOL_GPL(scsi_alloc_request); */ static void scsi_cleanup_rq(struct request *rq) { + struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq); + + cmd->flags = 0; + if (rq->rq_flags & RQF_DONTPREP) { - scsi_mq_uninit_cmd(blk_mq_rq_to_pdu(rq)); + scsi_mq_uninit_cmd(cmd); rq->rq_flags &= ~RQF_DONTPREP; } } From d5093d6486d7e6fac7b168743a5fb8983a36119b Mon Sep 17 00:00:00 2001 From: Justin Iurman Date: Wed, 16 Apr 2025 18:07:16 +0200 Subject: [PATCH 439/606] net: lwtunnel: disable BHs when required [ Upstream commit c03a49f3093a4903c8a93c8b5c9a297b5343b169 ] In lwtunnel_{output|xmit}(), dev_xmit_recursion() may be called in preemptible scope for PREEMPT kernels. This patch disables BHs before calling dev_xmit_recursion(). BHs are re-enabled only at the end, since we must ensure the same CPU is used for both dev_xmit_recursion_inc() and dev_xmit_recursion_dec() (and any other recursion levels in some cases) in order to maintain valid per-cpu counters. Reported-by: Alexei Starovoitov Closes: https://lore.kernel.org/netdev/CAADnVQJFWn3dBFJtY+ci6oN1pDFL=TzCmNbRgey7MdYxt_AP2g@mail.gmail.com/ Reported-by: Eduard Zingerman Closes: https://lore.kernel.org/netdev/m2h62qwf34.fsf@gmail.com/ Fixes: 986ffb3a57c5 ("net: lwtunnel: fix recursion loops") Signed-off-by: Justin Iurman Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250416160716.8823-1-justin.iurman@uliege.be Signed-off-by: Paolo Abeni Signed-off-by: Sasha Levin --- net/core/lwtunnel.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c index 4417a18b3e95..f63586c9ce02 100644 --- a/net/core/lwtunnel.c +++ b/net/core/lwtunnel.c @@ -332,6 +332,8 @@ int lwtunnel_output(struct net *net, struct sock *sk, struct sk_buff *skb) struct dst_entry *dst; int ret; + local_bh_disable(); + if (dev_xmit_recursion()) { net_crit_ratelimited("%s(): recursion limit reached on datapath\n", __func__); @@ -347,8 +349,10 @@ int lwtunnel_output(struct net *net, struct sock *sk, struct sk_buff *skb) lwtstate = dst->lwtstate; if (lwtstate->type == LWTUNNEL_ENCAP_NONE || - lwtstate->type > LWTUNNEL_ENCAP_MAX) - return 0; + lwtstate->type > LWTUNNEL_ENCAP_MAX) { + ret = 0; + goto out; + } ret = -EOPNOTSUPP; rcu_read_lock(); @@ -363,11 +367,13 @@ int lwtunnel_output(struct net *net, struct sock *sk, struct sk_buff *skb) if (ret == -EOPNOTSUPP) goto drop; - return ret; + goto out; drop: kfree_skb(skb); +out: + local_bh_enable(); return ret; } EXPORT_SYMBOL_GPL(lwtunnel_output); @@ -379,6 +385,8 @@ int lwtunnel_xmit(struct sk_buff *skb) struct dst_entry *dst; int ret; + local_bh_disable(); + if (dev_xmit_recursion()) { net_crit_ratelimited("%s(): recursion limit reached on datapath\n", __func__); @@ -395,8 +403,10 @@ int lwtunnel_xmit(struct sk_buff *skb) lwtstate = dst->lwtstate; if (lwtstate->type == LWTUNNEL_ENCAP_NONE || - lwtstate->type > LWTUNNEL_ENCAP_MAX) - return 0; + lwtstate->type > LWTUNNEL_ENCAP_MAX) { + ret = 0; + goto out; + } ret = -EOPNOTSUPP; rcu_read_lock(); @@ -411,11 +421,13 @@ int lwtunnel_xmit(struct sk_buff *skb) if (ret == -EOPNOTSUPP) goto drop; - return ret; + goto out; drop: kfree_skb(skb); +out: + local_bh_enable(); return ret; } EXPORT_SYMBOL_GPL(lwtunnel_xmit); @@ -427,6 +439,8 @@ int lwtunnel_input(struct sk_buff *skb) struct dst_entry *dst; int ret; + DEBUG_NET_WARN_ON_ONCE(!in_softirq()); + if (dev_xmit_recursion()) { net_crit_ratelimited("%s(): recursion limit reached on datapath\n", __func__); From 618541a6cc1511064dfa58c89b3445e21844092f Mon Sep 17 00:00:00 2001 From: Qingfang Deng Date: Thu, 17 Apr 2025 11:25:56 +0800 Subject: [PATCH 440/606] net: phy: leds: fix memory leak [ Upstream commit b7f0ee992adf601aa00c252418266177eb7ac2bc ] A network restart test on a router led to an out-of-memory condition, which was traced to a memory leak in the PHY LED trigger code. The root cause is misuse of the devm API. The registration function (phy_led_triggers_register) is called from phy_attach_direct, not phy_probe, and the unregister function (phy_led_triggers_unregister) is called from phy_detach, not phy_remove. This means the register and unregister functions can be called multiple times for the same PHY device, but devm-allocated memory is not freed until the driver is unbound. This also prevents kmemleak from detecting the leak, as the devm API internally stores the allocated pointer. Fix this by replacing devm_kzalloc/devm_kcalloc with standard kzalloc/kcalloc, and add the corresponding kfree calls in the unregister path. Fixes: 3928ee6485a3 ("net: phy: leds: Add support for "link" trigger") Fixes: 2e0bc452f472 ("net: phy: leds: add support for led triggers on phy link state change") Signed-off-by: Hao Guan Signed-off-by: Qingfang Deng Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/20250417032557.2929427-1-dqfext@gmail.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/phy/phy_led_triggers.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/net/phy/phy_led_triggers.c b/drivers/net/phy/phy_led_triggers.c index f550576eb9da..6f9d8da76c4d 100644 --- a/drivers/net/phy/phy_led_triggers.c +++ b/drivers/net/phy/phy_led_triggers.c @@ -91,9 +91,8 @@ int phy_led_triggers_register(struct phy_device *phy) if (!phy->phy_num_led_triggers) return 0; - phy->led_link_trigger = devm_kzalloc(&phy->mdio.dev, - sizeof(*phy->led_link_trigger), - GFP_KERNEL); + phy->led_link_trigger = kzalloc(sizeof(*phy->led_link_trigger), + GFP_KERNEL); if (!phy->led_link_trigger) { err = -ENOMEM; goto out_clear; @@ -103,10 +102,9 @@ int phy_led_triggers_register(struct phy_device *phy) if (err) goto out_free_link; - phy->phy_led_triggers = devm_kcalloc(&phy->mdio.dev, - phy->phy_num_led_triggers, - sizeof(struct phy_led_trigger), - GFP_KERNEL); + phy->phy_led_triggers = kcalloc(phy->phy_num_led_triggers, + sizeof(struct phy_led_trigger), + GFP_KERNEL); if (!phy->phy_led_triggers) { err = -ENOMEM; goto out_unreg_link; @@ -127,11 +125,11 @@ int phy_led_triggers_register(struct phy_device *phy) out_unreg: while (i--) phy_led_trigger_unregister(&phy->phy_led_triggers[i]); - devm_kfree(&phy->mdio.dev, phy->phy_led_triggers); + kfree(phy->phy_led_triggers); out_unreg_link: phy_led_trigger_unregister(phy->led_link_trigger); out_free_link: - devm_kfree(&phy->mdio.dev, phy->led_link_trigger); + kfree(phy->led_link_trigger); phy->led_link_trigger = NULL; out_clear: phy->phy_num_led_triggers = 0; @@ -145,8 +143,13 @@ void phy_led_triggers_unregister(struct phy_device *phy) for (i = 0; i < phy->phy_num_led_triggers; i++) phy_led_trigger_unregister(&phy->phy_led_triggers[i]); + kfree(phy->phy_led_triggers); + phy->phy_led_triggers = NULL; - if (phy->led_link_trigger) + if (phy->led_link_trigger) { phy_led_trigger_unregister(phy->led_link_trigger); + kfree(phy->led_link_trigger); + phy->led_link_trigger = NULL; + } } EXPORT_SYMBOL_GPL(phy_led_triggers_unregister); From dd6cb0a8575b00fbd503e96903184125176f4fa3 Mon Sep 17 00:00:00 2001 From: Tung Nguyen Date: Thu, 17 Apr 2025 14:47:15 +0700 Subject: [PATCH 441/606] tipc: fix NULL pointer dereference in tipc_mon_reinit_self() [ Upstream commit d63527e109e811ef11abb1c2985048fdb528b4cb ] syzbot reported: tipc: Node number set to 1055423674 Oops: general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] SMP KASAN NOPTI KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] CPU: 3 UID: 0 PID: 6017 Comm: kworker/3:5 Not tainted 6.15.0-rc1-syzkaller-00246-g900241a5cc15 #0 PREEMPT(full) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 Workqueue: events tipc_net_finalize_work RIP: 0010:tipc_mon_reinit_self+0x11c/0x210 net/tipc/monitor.c:719 ... RSP: 0018:ffffc9000356fb68 EFLAGS: 00010246 RAX: 0000000000000000 RBX: 0000000000000000 RCX: 000000003ee87cba RDX: 0000000000000000 RSI: ffffffff8dbc56a7 RDI: ffff88804c2cc010 RBP: dffffc0000000000 R08: 0000000000000001 R09: 0000000000000000 R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000007 R13: fffffbfff2111097 R14: ffff88804ead8000 R15: ffff88804ead9010 FS: 0000000000000000(0000) GS:ffff888097ab9000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000f720eb00 CR3: 000000000e182000 CR4: 0000000000352ef0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: tipc_net_finalize+0x10b/0x180 net/tipc/net.c:140 process_one_work+0x9cc/0x1b70 kernel/workqueue.c:3238 process_scheduled_works kernel/workqueue.c:3319 [inline] worker_thread+0x6c8/0xf10 kernel/workqueue.c:3400 kthread+0x3c2/0x780 kernel/kthread.c:464 ret_from_fork+0x45/0x80 arch/x86/kernel/process.c:153 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 ... RIP: 0010:tipc_mon_reinit_self+0x11c/0x210 net/tipc/monitor.c:719 ... RSP: 0018:ffffc9000356fb68 EFLAGS: 00010246 RAX: 0000000000000000 RBX: 0000000000000000 RCX: 000000003ee87cba RDX: 0000000000000000 RSI: ffffffff8dbc56a7 RDI: ffff88804c2cc010 RBP: dffffc0000000000 R08: 0000000000000001 R09: 0000000000000000 R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000007 R13: fffffbfff2111097 R14: ffff88804ead8000 R15: ffff88804ead9010 FS: 0000000000000000(0000) GS:ffff888097ab9000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000f720eb00 CR3: 000000000e182000 CR4: 0000000000352ef0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 There is a racing condition between workqueue created when enabling bearer and another thread created when disabling bearer right after that as follow: enabling_bearer | disabling_bearer --------------- | ---------------- tipc_disc_timeout() | { | bearer_disable() ... | { schedule_work(&tn->work); | tipc_mon_delete() ... | { } | ... | write_lock_bh(&mon->lock); | mon->self = NULL; | write_unlock_bh(&mon->lock); | ... | } tipc_net_finalize_work() | } { | ... | tipc_net_finalize() | { | ... | tipc_mon_reinit_self() | { | ... | write_lock_bh(&mon->lock); | mon->self->addr = tipc_own_addr(net); | write_unlock_bh(&mon->lock); | ... | } | ... | } | ... | } | 'mon->self' is set to NULL in disabling_bearer thread and dereferenced later in enabling_bearer thread. This commit fixes this issue by validating 'mon->self' before assigning node address to it. Reported-by: syzbot+ed60da8d686dc709164c@syzkaller.appspotmail.com Fixes: 46cb01eeeb86 ("tipc: update mon's self addr when node addr generated") Signed-off-by: Tung Nguyen Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250417074826.578115-1-tung.quang.nguyen@est.tech Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- net/tipc/monitor.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/tipc/monitor.c b/net/tipc/monitor.c index 77a3d016cade..ddc3e4e5e18d 100644 --- a/net/tipc/monitor.c +++ b/net/tipc/monitor.c @@ -716,7 +716,8 @@ void tipc_mon_reinit_self(struct net *net) if (!mon) continue; write_lock_bh(&mon->lock); - mon->self->addr = tipc_own_addr(net); + if (mon->self) + mon->self->addr = tipc_own_addr(net); write_unlock_bh(&mon->lock); } } From e9f67da07753028184e4d1cffc812f686953bfdb Mon Sep 17 00:00:00 2001 From: Bo-Cun Chen Date: Thu, 17 Apr 2025 17:41:07 +0100 Subject: [PATCH 442/606] net: ethernet: mtk_eth_soc: net: revise NETSYSv3 hardware configuration [ Upstream commit 491ef1117c56476f199b481f8c68820fe4c3a7c2 ] Change hardware configuration for the NETSYSv3. - Enable PSE dummy page mechanism for the GDM1/2/3 - Enable PSE drop mechanism when the WDMA Rx ring full - Enable PSE no-drop mechanism for packets from the WDMA Tx - Correct PSE free drop threshold - Correct PSE CDMA high threshold Fixes: 1953f134a1a8b ("net: ethernet: mtk_eth_soc: add NETSYS_V3 version support") Signed-off-by: Bo-Cun Chen Signed-off-by: Daniel Golle Reviewed-by: Simon Horman Link: https://patch.msgid.link/b71f8fd9d4bb69c646c4d558f9331dd965068606.1744907886.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 24 +++++++++++++++++---- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 10 ++++++++- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index c201ea20e404..dc89dbc13b25 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -3949,11 +3949,27 @@ static int mtk_hw_init(struct mtk_eth *eth, bool reset) mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP); if (mtk_is_netsys_v3_or_greater(eth)) { - /* PSE should not drop port1, port8 and port9 packets */ - mtk_w32(eth, 0x00000302, PSE_DROP_CFG); + /* PSE dummy page mechanism */ + mtk_w32(eth, PSE_DUMMY_WORK_GDM(1) | PSE_DUMMY_WORK_GDM(2) | + PSE_DUMMY_WORK_GDM(3) | DUMMY_PAGE_THR, PSE_DUMY_REQ); + + /* PSE free buffer drop threshold */ + mtk_w32(eth, 0x00600009, PSE_IQ_REV(8)); + + /* PSE should not drop port8, port9 and port13 packets from + * WDMA Tx + */ + mtk_w32(eth, 0x00002300, PSE_DROP_CFG); + + /* PSE should drop packets to port8, port9 and port13 on WDMA Rx + * ring full + */ + mtk_w32(eth, 0x00002300, PSE_PPE_DROP(0)); + mtk_w32(eth, 0x00002300, PSE_PPE_DROP(1)); + mtk_w32(eth, 0x00002300, PSE_PPE_DROP(2)); /* GDM and CDM Threshold */ - mtk_w32(eth, 0x00000707, MTK_CDMW0_THRES); + mtk_w32(eth, 0x08000707, MTK_CDMW0_THRES); mtk_w32(eth, 0x00000077, MTK_CDMW1_THRES); /* Disable GDM1 RX CRC stripping */ @@ -3970,7 +3986,7 @@ static int mtk_hw_init(struct mtk_eth *eth, bool reset) mtk_w32(eth, 0x00000300, PSE_DROP_CFG); /* PSE should drop packets to port 8/9 on WDMA Rx ring full */ - mtk_w32(eth, 0x00000300, PSE_PPE0_DROP); + mtk_w32(eth, 0x00000300, PSE_PPE_DROP(0)); /* PSE Free Queue Flow Control */ mtk_w32(eth, 0x01fa01f4, PSE_FQFC_CFG2); diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h index 403219d987ef..d1c7b5f1ee4a 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -149,7 +149,15 @@ #define PSE_FQFC_CFG1 0x100 #define PSE_FQFC_CFG2 0x104 #define PSE_DROP_CFG 0x108 -#define PSE_PPE0_DROP 0x110 +#define PSE_PPE_DROP(x) (0x110 + ((x) * 0x4)) + +/* PSE Last FreeQ Page Request Control */ +#define PSE_DUMY_REQ 0x10C +/* PSE_DUMY_REQ is not a typo but actually called like that also in + * MediaTek's datasheet + */ +#define PSE_DUMMY_WORK_GDM(x) BIT(16 + (x)) +#define DUMMY_PAGE_THR 0x1 /* PSE Input Queue Reservation Register*/ #define PSE_IQ_REV(x) (0x140 + (((x) - 1) << 2)) From 4f435c1f4c48ff84968e2d9159f6fa41f46cf998 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 23 Apr 2025 02:30:34 +0100 Subject: [PATCH 443/606] fix a couple of races in MNT_TREE_BENEATH handling by do_move_mount() [ Upstream commit 0d039eac6e5950f9d1ecc9e410c2fd1feaeab3b6 ] Normally do_lock_mount(path, _) is locking a mountpoint pinned by *path and at the time when matching unlock_mount() unlocks that location it is still pinned by the same thing. Unfortunately, for 'beneath' case it's no longer that simple - the object being locked is not the one *path points to. It's the mountpoint of path->mnt. The thing is, without sufficient locking ->mnt_parent may change under us and none of the locks are held at that point. The rules are * mount_lock stabilizes m->mnt_parent for any mount m. * namespace_sem stabilizes m->mnt_parent, provided that m is mounted. * if either of the above holds and refcount of m is positive, we are guaranteed the same for refcount of m->mnt_parent. namespace_sem nests inside inode_lock(), so do_lock_mount() has to take inode_lock() before grabbing namespace_sem. It does recheck that path->mnt is still mounted in the same place after getting namespace_sem, and it does take care to pin the dentry. It is needed, since otherwise we might end up with racing mount --move (or umount) happening while we were getting locks; in that case dentry would no longer be a mountpoint and could've been evicted on memory pressure along with its inode - not something you want when grabbing lock on that inode. However, pinning a dentry is not enough - the matching mount is also pinned only by the fact that path->mnt is mounted on top it and at that point we are not holding any locks whatsoever, so the same kind of races could end up with all references to that mount gone just as we are about to enter inode_lock(). If that happens, we are left with filesystem being shut down while we are holding a dentry reference on it; results are not pretty. What we need to do is grab both dentry and mount at the same time; that makes inode_lock() safe *and* avoids the problem with fs getting shut down under us. After taking namespace_sem we verify that path->mnt is still mounted (which stabilizes its ->mnt_parent) and check that it's still mounted at the same place. From that point on to the matching namespace_unlock() we are guaranteed that mount/dentry pair we'd grabbed are also pinned by being the mountpoint of path->mnt, so we can quietly drop both the dentry reference (as the current code does) and mnt one - it's OK to do under namespace_sem, since we are not dropping the final refs. That solves the problem on do_lock_mount() side; unlock_mount() also has one, since dentry is guaranteed to stay pinned only until the namespace_unlock(). That's easy to fix - just have inode_unlock() done earlier, while it's still pinned by mp->m_dentry. Fixes: 6ac392815628 "fs: allow to mount beneath top mount" # v6.5+ Signed-off-by: Al Viro Signed-off-by: Christian Brauner Signed-off-by: Sasha Levin --- fs/namespace.c | 69 ++++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 671e266b8fc5..5a885d35efe9 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2439,56 +2439,62 @@ static struct mountpoint *do_lock_mount(struct path *path, bool beneath) struct vfsmount *mnt = path->mnt; struct dentry *dentry; struct mountpoint *mp = ERR_PTR(-ENOENT); + struct path under = {}; for (;;) { - struct mount *m; + struct mount *m = real_mount(mnt); if (beneath) { - m = real_mount(mnt); + path_put(&under); read_seqlock_excl(&mount_lock); - dentry = dget(m->mnt_mountpoint); + under.mnt = mntget(&m->mnt_parent->mnt); + under.dentry = dget(m->mnt_mountpoint); read_sequnlock_excl(&mount_lock); + dentry = under.dentry; } else { dentry = path->dentry; } inode_lock(dentry->d_inode); - if (unlikely(cant_mount(dentry))) { - inode_unlock(dentry->d_inode); - goto out; - } - namespace_lock(); - if (beneath && (!is_mounted(mnt) || m->mnt_mountpoint != dentry)) { + if (unlikely(cant_mount(dentry) || !is_mounted(mnt))) + break; // not to be mounted on + + if (beneath && unlikely(m->mnt_mountpoint != dentry || + &m->mnt_parent->mnt != under.mnt)) { namespace_unlock(); inode_unlock(dentry->d_inode); - goto out; + continue; // got moved } mnt = lookup_mnt(path); - if (likely(!mnt)) + if (unlikely(mnt)) { + namespace_unlock(); + inode_unlock(dentry->d_inode); + path_put(path); + path->mnt = mnt; + path->dentry = dget(mnt->mnt_root); + continue; // got overmounted + } + mp = get_mountpoint(dentry); + if (IS_ERR(mp)) break; - - namespace_unlock(); - inode_unlock(dentry->d_inode); - if (beneath) - dput(dentry); - path_put(path); - path->mnt = mnt; - path->dentry = dget(mnt->mnt_root); + if (beneath) { + /* + * @under duplicates the references that will stay + * at least until namespace_unlock(), so the path_put() + * below is safe (and OK to do under namespace_lock - + * we are not dropping the final references here). + */ + path_put(&under); + } + return mp; } - - mp = get_mountpoint(dentry); - if (IS_ERR(mp)) { - namespace_unlock(); - inode_unlock(dentry->d_inode); - } - -out: + namespace_unlock(); + inode_unlock(dentry->d_inode); if (beneath) - dput(dentry); - + path_put(&under); return mp; } @@ -2499,14 +2505,11 @@ static inline struct mountpoint *lock_mount(struct path *path) static void unlock_mount(struct mountpoint *where) { - struct dentry *dentry = where->m_dentry; - + inode_unlock(where->m_dentry->d_inode); read_seqlock_excl(&mount_lock); put_mountpoint(where); read_sequnlock_excl(&mount_lock); - namespace_unlock(); - inode_unlock(dentry->d_inode); } static int graft_tree(struct mount *mnt, struct mount *p, struct mountpoint *mp) From 3aa852e3605000d5c47035c3fc3a986d14ccfa9f Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Thu, 17 Apr 2025 11:47:30 -0700 Subject: [PATCH 444/606] net_sched: hfsc: Fix a UAF vulnerability in class handling [ Upstream commit 3df275ef0a6ae181e8428a6589ef5d5231e58b5c ] This patch fixes a Use-After-Free vulnerability in the HFSC qdisc class handling. The issue occurs due to a time-of-check/time-of-use condition in hfsc_change_class() when working with certain child qdiscs like netem or codel. The vulnerability works as follows: 1. hfsc_change_class() checks if a class has packets (q.qlen != 0) 2. It then calls qdisc_peek_len(), which for certain qdiscs (e.g., codel, netem) might drop packets and empty the queue 3. The code continues assuming the queue is still non-empty, adding the class to vttree 4. This breaks HFSC scheduler assumptions that only non-empty classes are in vttree 5. Later, when the class is destroyed, this can lead to a Use-After-Free The fix adds a second queue length check after qdisc_peek_len() to verify the queue wasn't emptied. Fixes: 21f4d5cc25ec ("net_sched/hfsc: fix curve activation in hfsc_change_class()") Reported-by: Gerrard Tai Reviewed-by: Konstantin Khlebnikov Signed-off-by: Cong Wang Reviewed-by: Jamal Hadi Salim Link: https://patch.msgid.link/20250417184732.943057-2-xiyou.wangcong@gmail.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- net/sched/sch_hfsc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 880c5f16b29c..90801b6fe2b0 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -958,6 +958,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, if (cl != NULL) { int old_flags; + int len = 0; if (parentid) { if (cl->cl_parent && @@ -988,9 +989,13 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, if (usc != NULL) hfsc_change_usc(cl, usc, cur_time); + if (cl->qdisc->q.qlen != 0) + len = qdisc_peek_len(cl->qdisc); + /* Check queue length again since some qdisc implementations + * (e.g., netem/codel) might empty the queue during the peek + * operation. + */ if (cl->qdisc->q.qlen != 0) { - int len = qdisc_peek_len(cl->qdisc); - if (cl->cl_flags & HFSC_RSC) { if (old_flags & HFSC_RSC) update_ed(cl, len); From 76c4c22c2437d3d3880efc0f62eca06ef078d290 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Thu, 17 Apr 2025 11:47:31 -0700 Subject: [PATCH 445/606] net_sched: hfsc: Fix a potential UAF in hfsc_dequeue() too [ Upstream commit 6ccbda44e2cc3d26fd22af54c650d6d5d801addf ] Similarly to the previous patch, we need to safe guard hfsc_dequeue() too. But for this one, we don't have a reliable reproducer. Fixes: 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 ("Linux-2.6.12-rc2") Reported-by: Gerrard Tai Signed-off-by: Cong Wang Reviewed-by: Jamal Hadi Salim Link: https://patch.msgid.link/20250417184732.943057-3-xiyou.wangcong@gmail.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- net/sched/sch_hfsc.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 90801b6fe2b0..371255e62433 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -1638,10 +1638,16 @@ hfsc_dequeue(struct Qdisc *sch) if (cl->qdisc->q.qlen != 0) { /* update ed */ next_len = qdisc_peek_len(cl->qdisc); - if (realtime) - update_ed(cl, next_len); - else - update_d(cl, next_len); + /* Check queue length again since some qdisc implementations + * (e.g., netem/codel) might empty the queue during the peek + * operation. + */ + if (cl->qdisc->q.qlen != 0) { + if (realtime) + update_ed(cl, next_len); + else + update_d(cl, next_len); + } } else { /* the class becomes passive */ eltree_remove(cl); From 49083dc3cbb37b300a2d6e80f9f50fe33def23ef Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Tue, 22 Apr 2025 04:10:20 +0100 Subject: [PATCH 446/606] net: dsa: mt7530: sync driver-specific behavior of MT7531 variants [ Upstream commit 497041d763016c2e8314d2f6a329a9b77c3797ca ] MT7531 standalone and MMIO variants found in MT7988 and EN7581 share most basic properties. Despite that, assisted_learning_on_cpu_port and mtu_enforcement_ingress were only applied for MT7531 but not for MT7988 or EN7581, causing the expected issues on MMIO devices. Apply both settings equally also for MT7988 and EN7581 by moving both assignments form mt7531_setup() to mt7531_setup_common(). This fixes unwanted flooding of packets due to unknown unicast during DA lookup, as well as issues with heterogenous MTU settings. Fixes: 7f54cc9772ce ("net: dsa: mt7530: split-off common parts from mt7531_setup") Signed-off-by: Daniel Golle Reviewed-by: Chester A. Unal Link: https://patch.msgid.link/89ed7ec6d4fa0395ac53ad2809742bb1ce61ed12.1745290867.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/dsa/mt7530.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index 90ab2f1058ce..2d18a03d9274 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -2596,6 +2596,9 @@ mt7531_setup_common(struct dsa_switch *ds) struct mt7530_priv *priv = ds->priv; int ret, i; + ds->assisted_learning_on_cpu_port = true; + ds->mtu_enforcement_ingress = true; + mt753x_trap_frames(priv); /* Enable and reset MIB counters */ @@ -2735,9 +2738,6 @@ mt7531_setup(struct dsa_switch *ds) mt7531_setup_common(ds); - ds->assisted_learning_on_cpu_port = true; - ds->mtu_enforcement_ingress = true; - return 0; } From cdd784c96fe2e5edbf0ed9b3e96fe776e8092385 Mon Sep 17 00:00:00 2001 From: Brett Creeley Date: Mon, 21 Apr 2025 10:46:04 -0700 Subject: [PATCH 447/606] pds_core: handle unsupported PDS_CORE_CMD_FW_CONTROL result [ Upstream commit 2567daad69cd1107fc0ec29b1615f110d7cf7385 ] If the FW doesn't support the PDS_CORE_CMD_FW_CONTROL command the driver might at the least print garbage and at the worst crash when the user runs the "devlink dev info" devlink command. This happens because the stack variable fw_list is not 0 initialized which results in fw_list.num_fw_slots being a garbage value from the stack. Then the driver tries to access fw_list.fw_names[i] with i >= ARRAY_SIZE and runs off the end of the array. Fix this by initializing the fw_list and by not failing completely if the devcmd fails because other useful information is printed via devlink dev info even if the devcmd fails. Fixes: 45d76f492938 ("pds_core: set up device and adminq") Signed-off-by: Brett Creeley Reviewed-by: Simon Horman Signed-off-by: Shannon Nelson Reviewed-by: Jacob Keller Link: https://patch.msgid.link/20250421174606.3892-3-shannon.nelson@amd.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/amd/pds_core/devlink.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/amd/pds_core/devlink.c b/drivers/net/ethernet/amd/pds_core/devlink.c index 971d4278280d..0032e8e35181 100644 --- a/drivers/net/ethernet/amd/pds_core/devlink.c +++ b/drivers/net/ethernet/amd/pds_core/devlink.c @@ -101,7 +101,7 @@ int pdsc_dl_info_get(struct devlink *dl, struct devlink_info_req *req, .fw_control.opcode = PDS_CORE_CMD_FW_CONTROL, .fw_control.oper = PDS_CORE_FW_GET_LIST, }; - struct pds_core_fw_list_info fw_list; + struct pds_core_fw_list_info fw_list = {}; struct pdsc *pdsc = devlink_priv(dl); union pds_core_dev_comp comp; char buf[32]; @@ -114,8 +114,6 @@ int pdsc_dl_info_get(struct devlink *dl, struct devlink_info_req *req, if (!err) memcpy_fromio(&fw_list, pdsc->cmd_regs->data, sizeof(fw_list)); mutex_unlock(&pdsc->devcmd_lock); - if (err && err != -EIO) - return err; listlen = min(fw_list.num_fw_slots, ARRAY_SIZE(fw_list.fw_names)); for (i = 0; i < listlen; i++) { From c918ce100d17226470beda7d76bdd0d0a86cf1e6 Mon Sep 17 00:00:00 2001 From: Brett Creeley Date: Mon, 21 Apr 2025 10:46:05 -0700 Subject: [PATCH 448/606] pds_core: Remove unnecessary check in pds_client_adminq_cmd() [ Upstream commit f9559d818205a4a0b9cd87181ef46e101ea11157 ] When the pds_core driver was first created there were some race conditions around using the adminq, especially for client drivers. To reduce the possibility of a race condition there's a check against pf->state in pds_client_adminq_cmd(). This is problematic for a couple of reasons: 1. The PDSC_S_INITING_DRIVER bit is set during probe, but not cleared until after everything in probe is complete, which includes creating the auxiliary devices. For pds_fwctl this means it can't make any adminq commands until after pds_core's probe is complete even though the adminq is fully up by the time pds_fwctl's auxiliary device is created. 2. The race conditions around using the adminq have been fixed and this path is already protected against client drivers calling pds_client_adminq_cmd() if the adminq isn't ready, i.e. see pdsc_adminq_post() -> pdsc_adminq_inc_if_up(). Fix this by removing the pf->state check in pds_client_adminq_cmd() because invalid accesses to pds_core's adminq is already handled by pdsc_adminq_post()->pdsc_adminq_inc_if_up(). Fixes: 10659034c622 ("pds_core: add the aux client API") Reviewed-by: Simon Horman Signed-off-by: Brett Creeley Signed-off-by: Shannon Nelson Reviewed-by: Jacob Keller Link: https://patch.msgid.link/20250421174606.3892-4-shannon.nelson@amd.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/amd/pds_core/auxbus.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/ethernet/amd/pds_core/auxbus.c b/drivers/net/ethernet/amd/pds_core/auxbus.c index fd1a5149c003..fb7a5403e630 100644 --- a/drivers/net/ethernet/amd/pds_core/auxbus.c +++ b/drivers/net/ethernet/amd/pds_core/auxbus.c @@ -107,9 +107,6 @@ int pds_client_adminq_cmd(struct pds_auxiliary_dev *padev, dev_dbg(pf->dev, "%s: %s opcode %d\n", __func__, dev_name(&padev->aux_dev.dev), req->opcode); - if (pf->state) - return -ENXIO; - /* Wrap the client's request */ cmd.client_request.opcode = PDS_AQ_CMD_CLIENT_CMD; cmd.client_request.client_id = cpu_to_le16(padev->client_id); From 1d7c4b2b0bbfb09b55b2dc0e2355d7936bf89381 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Mon, 21 Apr 2025 10:46:06 -0700 Subject: [PATCH 449/606] pds_core: make wait_context part of q_info [ Upstream commit 3f77c3dfffc7063428b100c4945ca2a7a8680380 ] Make the wait_context a full part of the q_info struct rather than a stack variable that goes away after pdsc_adminq_post() is done so that the context is still available after the wait loop has given up. There was a case where a slow development firmware caused the adminq request to time out, but then later the FW finally finished the request and sent the interrupt. The handler tried to complete_all() the completion context that had been created on the stack in pdsc_adminq_post() but no longer existed. This caused bad pointer usage, kernel crashes, and much wailing and gnashing of teeth. Fixes: 01ba61b55b20 ("pds_core: Add adminq processing and commands") Reviewed-by: Simon Horman Signed-off-by: Shannon Nelson Reviewed-by: Jacob Keller Link: https://patch.msgid.link/20250421174606.3892-5-shannon.nelson@amd.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/amd/pds_core/adminq.c | 36 +++++++++------------- drivers/net/ethernet/amd/pds_core/core.c | 4 ++- drivers/net/ethernet/amd/pds_core/core.h | 2 +- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/drivers/net/ethernet/amd/pds_core/adminq.c b/drivers/net/ethernet/amd/pds_core/adminq.c index ea773cfa0af6..733f133d69e7 100644 --- a/drivers/net/ethernet/amd/pds_core/adminq.c +++ b/drivers/net/ethernet/amd/pds_core/adminq.c @@ -5,11 +5,6 @@ #include "core.h" -struct pdsc_wait_context { - struct pdsc_qcq *qcq; - struct completion wait_completion; -}; - static int pdsc_process_notifyq(struct pdsc_qcq *qcq) { union pds_core_notifyq_comp *comp; @@ -110,10 +105,10 @@ void pdsc_process_adminq(struct pdsc_qcq *qcq) q_info = &q->info[q->tail_idx]; q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1); - /* Copy out the completion data */ - memcpy(q_info->dest, comp, sizeof(*comp)); - - complete_all(&q_info->wc->wait_completion); + if (!completion_done(&q_info->completion)) { + memcpy(q_info->dest, comp, sizeof(*comp)); + complete(&q_info->completion); + } if (cq->tail_idx == cq->num_descs - 1) cq->done_color = !cq->done_color; @@ -166,8 +161,7 @@ irqreturn_t pdsc_adminq_isr(int irq, void *data) static int __pdsc_adminq_post(struct pdsc *pdsc, struct pdsc_qcq *qcq, union pds_core_adminq_cmd *cmd, - union pds_core_adminq_comp *comp, - struct pdsc_wait_context *wc) + union pds_core_adminq_comp *comp) { struct pdsc_queue *q = &qcq->q; struct pdsc_q_info *q_info; @@ -209,9 +203,9 @@ static int __pdsc_adminq_post(struct pdsc *pdsc, /* Post the request */ index = q->head_idx; q_info = &q->info[index]; - q_info->wc = wc; q_info->dest = comp; memcpy(q_info->desc, cmd, sizeof(*cmd)); + reinit_completion(&q_info->completion); dev_dbg(pdsc->dev, "head_idx %d tail_idx %d\n", q->head_idx, q->tail_idx); @@ -235,16 +229,13 @@ int pdsc_adminq_post(struct pdsc *pdsc, union pds_core_adminq_comp *comp, bool fast_poll) { - struct pdsc_wait_context wc = { - .wait_completion = - COMPLETION_INITIALIZER_ONSTACK(wc.wait_completion), - }; unsigned long poll_interval = 1; unsigned long poll_jiffies; unsigned long time_limit; unsigned long time_start; unsigned long time_done; unsigned long remaining; + struct completion *wc; int err = 0; int index; @@ -254,20 +245,19 @@ int pdsc_adminq_post(struct pdsc *pdsc, return -ENXIO; } - wc.qcq = &pdsc->adminqcq; - index = __pdsc_adminq_post(pdsc, &pdsc->adminqcq, cmd, comp, &wc); + index = __pdsc_adminq_post(pdsc, &pdsc->adminqcq, cmd, comp); if (index < 0) { err = index; goto err_out; } + wc = &pdsc->adminqcq.q.info[index].completion; time_start = jiffies; time_limit = time_start + HZ * pdsc->devcmd_timeout; do { /* Timeslice the actual wait to catch IO errors etc early */ poll_jiffies = msecs_to_jiffies(poll_interval); - remaining = wait_for_completion_timeout(&wc.wait_completion, - poll_jiffies); + remaining = wait_for_completion_timeout(wc, poll_jiffies); if (remaining) break; @@ -296,9 +286,11 @@ int pdsc_adminq_post(struct pdsc *pdsc, dev_dbg(pdsc->dev, "%s: elapsed %d msecs\n", __func__, jiffies_to_msecs(time_done - time_start)); - /* Check the results */ - if (time_after_eq(time_done, time_limit)) + /* Check the results and clear an un-completed timeout */ + if (time_after_eq(time_done, time_limit) && !completion_done(wc)) { err = -ETIMEDOUT; + complete(wc); + } dev_dbg(pdsc->dev, "read admin queue completion idx %d:\n", index); dynamic_hex_dump("comp ", DUMP_PREFIX_OFFSET, 16, 1, diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c index eb73c921dc1e..b3fa867c8ccd 100644 --- a/drivers/net/ethernet/amd/pds_core/core.c +++ b/drivers/net/ethernet/amd/pds_core/core.c @@ -169,8 +169,10 @@ static void pdsc_q_map(struct pdsc_queue *q, void *base, dma_addr_t base_pa) q->base = base; q->base_pa = base_pa; - for (i = 0, cur = q->info; i < q->num_descs; i++, cur++) + for (i = 0, cur = q->info; i < q->num_descs; i++, cur++) { cur->desc = base + (i * q->desc_size); + init_completion(&cur->completion); + } } static void pdsc_cq_map(struct pdsc_cq *cq, void *base, dma_addr_t base_pa) diff --git a/drivers/net/ethernet/amd/pds_core/core.h b/drivers/net/ethernet/amd/pds_core/core.h index f410f7d13205..858bebf79776 100644 --- a/drivers/net/ethernet/amd/pds_core/core.h +++ b/drivers/net/ethernet/amd/pds_core/core.h @@ -96,7 +96,7 @@ struct pdsc_q_info { unsigned int bytes; unsigned int nbufs; struct pdsc_buf_info bufs[PDS_CORE_MAX_FRAGS]; - struct pdsc_wait_context *wc; + struct completion completion; void *dest; }; From 415f3481ca764318099f05c2c8edefe070922a95 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 4 Apr 2025 12:38:20 -0700 Subject: [PATCH 450/606] iommu/amd: Return an error if vCPU affinity is set for non-vCPU IRTE [ Upstream commit 07172206a26dcf3f0bf7c3ecaadd4242b008ea54 ] Return -EINVAL instead of success if amd_ir_set_vcpu_affinity() is invoked without use_vapic; lying to KVM about whether or not the IRTE was configured to post IRQs is all kinds of bad. Fixes: d98de49a53e4 ("iommu/amd: Enable vAPIC interrupt remapping mode by default") Signed-off-by: Sean Christopherson Message-ID: <20250404193923.1413163-6-seanjc@google.com> Signed-off-by: Paolo Bonzini Signed-off-by: Sasha Levin --- drivers/iommu/amd/iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c index 95bd7c25ba6f..83c5d786686d 100644 --- a/drivers/iommu/amd/iommu.c +++ b/drivers/iommu/amd/iommu.c @@ -3619,7 +3619,7 @@ static int amd_ir_set_vcpu_affinity(struct irq_data *data, void *vcpu_info) * we should not modify the IRTE */ if (!dev_data || !dev_data->use_vapic) - return 0; + return -EINVAL; ir_data->cfg = irqd_cfg(data); pi_data->ir_data = ir_data; From 9e0d94a292227d1ef89fe1e241971611cbd02325 Mon Sep 17 00:00:00 2001 From: "T.J. Mercier" Date: Wed, 23 Apr 2025 18:00:23 +0000 Subject: [PATCH 451/606] splice: remove duplicate noinline from pipe_clear_nowait [ Upstream commit e6f141b332ddd9007756751b6afd24f799488fd8 ] pipe_clear_nowait has two noinline macros, but we only need one. I checked the whole tree, and this is the only occurrence: $ grep -r "noinline .* noinline" fs/splice.c:static noinline void noinline pipe_clear_nowait(struct file *file) $ Fixes: 0f99fc513ddd ("splice: clear FMODE_NOWAIT on file if splice/vmsplice is used") Signed-off-by: "T.J. Mercier" Link: https://lore.kernel.org/20250423180025.2627670-1-tjmercier@google.com Reviewed-by: Jens Axboe Signed-off-by: Christian Brauner Signed-off-by: Sasha Levin --- fs/splice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/splice.c b/fs/splice.c index d983d375ff11..6f9b06bbb860 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -45,7 +45,7 @@ * here if set to avoid blocking other users of this pipe if splice is * being done on it. */ -static noinline void noinline pipe_clear_nowait(struct file *file) +static noinline void pipe_clear_nowait(struct file *file) { fmode_t fmode = READ_ONCE(file->f_mode); From cd5970e001f708626e6ec9a483df2dc8fd8c551e Mon Sep 17 00:00:00 2001 From: Luo Gengkun Date: Wed, 23 Apr 2025 06:47:24 +0000 Subject: [PATCH 452/606] perf/x86: Fix non-sampling (counting) events on certain x86 platforms [ Upstream commit 1a97fea9db9e9b9c4839d4232dde9f505ff5b4cc ] Perf doesn't work at perf stat for hardware events on certain x86 platforms: $perf stat -- sleep 1 Performance counter stats for 'sleep 1': 16.44 msec task-clock # 0.016 CPUs utilized 2 context-switches # 121.691 /sec 0 cpu-migrations # 0.000 /sec 54 page-faults # 3.286 K/sec cycles instructions branches branch-misses The reason is that the check in x86_pmu_hw_config() for sampling events is unexpectedly applied to counting events as well. It should only impact x86 platforms with limit_period used for non-PEBS events. For Intel platforms, it should only impact some older platforms, e.g., HSW, BDW and NHM. Fixes: 88ec7eedbbd2 ("perf/x86: Fix low freqency setting issue") Signed-off-by: Luo Gengkun Signed-off-by: Ingo Molnar Reviewed-by: Kan Liang Cc: Alexander Shishkin Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Ravi Bangoria Link: https://lore.kernel.org/r/20250423064724.3716211-1-luogengkun@huaweicloud.com Signed-off-by: Sasha Levin --- arch/x86/events/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 1458ccaa6a05..ad63bd408cd9 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -623,7 +623,7 @@ int x86_pmu_hw_config(struct perf_event *event) if (event->attr.type == event->pmu->type) event->hw.config |= event->attr.config & X86_RAW_EVENT_MASK; - if (!event->attr.freq && x86_pmu.limit_period) { + if (is_sampling_event(event) && !event->attr.freq && x86_pmu.limit_period) { s64 left = event->attr.sample_period; x86_pmu.limit_period(event, &left); if (left > event->attr.sample_period) From 5767f4ac64284e97284ca29ac47824ec423766c6 Mon Sep 17 00:00:00 2001 From: Yuli Wang Date: Thu, 24 Apr 2025 20:15:22 +0800 Subject: [PATCH 453/606] LoongArch: Select ARCH_USE_MEMTEST [ Upstream commit fb8e9f59d6f292c3d9fea6c155c22ea5fc3053ab ] As of commit dce44566192e ("mm/memtest: add ARCH_USE_MEMTEST"), architectures must select ARCH_USE_MEMTESET to enable CONFIG_MEMTEST. Commit 628c3bb40e9a ("LoongArch: Add boot and setup routines") added support for early_memtest but did not select ARCH_USE_MEMTESET. Fixes: 628c3bb40e9a ("LoongArch: Add boot and setup routines") Tested-by: Erpeng Xu Tested-by: Yuli Wang Signed-off-by: Yuli Wang Signed-off-by: Huacai Chen Signed-off-by: Sasha Levin --- arch/loongarch/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig index 623cf80639de..25aa993abebc 100644 --- a/arch/loongarch/Kconfig +++ b/arch/loongarch/Kconfig @@ -59,6 +59,7 @@ config LOONGARCH select ARCH_SUPPORTS_NUMA_BALANCING select ARCH_USE_BUILTIN_BSWAP select ARCH_USE_CMPXCHG_LOCKREF + select ARCH_USE_MEMTEST select ARCH_USE_QUEUED_RWLOCKS select ARCH_USE_QUEUED_SPINLOCKS select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT From eaa0849818ebdcb063c95a0cb7abd1218f71990e Mon Sep 17 00:00:00 2001 From: Tiezhu Yang Date: Thu, 24 Apr 2025 20:15:41 +0800 Subject: [PATCH 454/606] LoongArch: Make regs_irqs_disabled() more clear [ Upstream commit bb0511d59db9b3e40c8d51f0d151ccd0fd44071d ] In the current code, the definition of regs_irqs_disabled() is actually "!(regs->csr_prmd & CSR_CRMD_IE)" because arch_irqs_disabled_flags() is defined as "!(flags & CSR_CRMD_IE)", it looks a little strange. Define regs_irqs_disabled() as !(regs->csr_prmd & CSR_PRMD_PIE) directly to make it more clear, no functional change. While at it, the return value of regs_irqs_disabled() is true or false, so change its type to reflect that and also make it always inline. Fixes: 803b0fc5c3f2 ("LoongArch: Add process management") Signed-off-by: Tiezhu Yang Signed-off-by: Huacai Chen Signed-off-by: Sasha Levin --- arch/loongarch/include/asm/ptrace.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/loongarch/include/asm/ptrace.h b/arch/loongarch/include/asm/ptrace.h index f3ddaed9ef7f..a5b63c84f854 100644 --- a/arch/loongarch/include/asm/ptrace.h +++ b/arch/loongarch/include/asm/ptrace.h @@ -33,9 +33,9 @@ struct pt_regs { unsigned long __last[]; } __aligned(8); -static inline int regs_irqs_disabled(struct pt_regs *regs) +static __always_inline bool regs_irqs_disabled(struct pt_regs *regs) { - return arch_irqs_disabled_flags(regs->csr_prmd); + return !(regs->csr_prmd & CSR_PRMD_PIE); } static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) From b74fb07153dc940ef18354107a9795733545d42b Mon Sep 17 00:00:00 2001 From: Tiezhu Yang Date: Thu, 24 Apr 2025 20:15:41 +0800 Subject: [PATCH 455/606] LoongArch: Make do_xyz() exception handlers more robust [ Upstream commit cc73cc6bcdb5f959670e3ff9abdc62461452ddff ] Currently, interrupts need to be disabled before single-step mode is set, it requires that CSR_PRMD_PIE be cleared in save_local_irqflag() which is called by setup_singlestep(), this is reasonable. But in the first kprobe breakpoint exception, if the irq is enabled at the beginning of do_bp(), it will not be disabled at the end of do_bp() due to the CSR_PRMD_PIE has been cleared in save_local_irqflag(). So for this case, it may corrupt exception context when restoring the exception after do_bp() in handle_bp(), this is not reasonable. In order to restore exception safely in handle_bp(), it needs to ensure the irq is disabled at the end of do_bp(), so just add a local variable to record the original interrupt status in the parent context, then use it as the check condition to enable and disable irq in do_bp(). While at it, do the similar thing for other do_xyz() exception handlers to make them more robust. Fixes: 6d4cc40fb5f5 ("LoongArch: Add kprobes support") Suggested-by: Jinyang He Suggested-by: Huacai Chen Co-developed-by: Tianyang Zhang Signed-off-by: Tianyang Zhang Signed-off-by: Tiezhu Yang Signed-off-by: Huacai Chen Signed-off-by: Sasha Levin --- arch/loongarch/kernel/traps.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/arch/loongarch/kernel/traps.c b/arch/loongarch/kernel/traps.c index d59052c03d9b..2b4b99b4e6c9 100644 --- a/arch/loongarch/kernel/traps.c +++ b/arch/loongarch/kernel/traps.c @@ -527,9 +527,10 @@ asmlinkage void noinstr do_ale(struct pt_regs *regs) die_if_kernel("Kernel ale access", regs); force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)regs->csr_badvaddr); #else + bool pie = regs_irqs_disabled(regs); unsigned int *pc; - if (regs->csr_prmd & CSR_PRMD_PIE) + if (!pie) local_irq_enable(); perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, regs->csr_badvaddr); @@ -556,7 +557,7 @@ sigbus: die_if_kernel("Kernel ale access", regs); force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)regs->csr_badvaddr); out: - if (regs->csr_prmd & CSR_PRMD_PIE) + if (!pie) local_irq_disable(); #endif irqentry_exit(regs, state); @@ -588,12 +589,13 @@ static void bug_handler(struct pt_regs *regs) asmlinkage void noinstr do_bce(struct pt_regs *regs) { bool user = user_mode(regs); + bool pie = regs_irqs_disabled(regs); unsigned long era = exception_era(regs); u64 badv = 0, lower = 0, upper = ULONG_MAX; union loongarch_instruction insn; irqentry_state_t state = irqentry_enter(regs); - if (regs->csr_prmd & CSR_PRMD_PIE) + if (!pie) local_irq_enable(); current->thread.trap_nr = read_csr_excode(); @@ -659,7 +661,7 @@ asmlinkage void noinstr do_bce(struct pt_regs *regs) force_sig_bnderr((void __user *)badv, (void __user *)lower, (void __user *)upper); out: - if (regs->csr_prmd & CSR_PRMD_PIE) + if (!pie) local_irq_disable(); irqentry_exit(regs, state); @@ -677,11 +679,12 @@ bad_era: asmlinkage void noinstr do_bp(struct pt_regs *regs) { bool user = user_mode(regs); + bool pie = regs_irqs_disabled(regs); unsigned int opcode, bcode; unsigned long era = exception_era(regs); irqentry_state_t state = irqentry_enter(regs); - if (regs->csr_prmd & CSR_PRMD_PIE) + if (!pie) local_irq_enable(); if (__get_inst(&opcode, (u32 *)era, user)) @@ -747,7 +750,7 @@ asmlinkage void noinstr do_bp(struct pt_regs *regs) } out: - if (regs->csr_prmd & CSR_PRMD_PIE) + if (!pie) local_irq_disable(); irqentry_exit(regs, state); @@ -982,6 +985,7 @@ static void init_restore_lbt(void) asmlinkage void noinstr do_lbt(struct pt_regs *regs) { + bool pie = regs_irqs_disabled(regs); irqentry_state_t state = irqentry_enter(regs); /* @@ -991,7 +995,7 @@ asmlinkage void noinstr do_lbt(struct pt_regs *regs) * (including the user using 'MOVGR2GCSR' to turn on TM, which * will not trigger the BTE), we need to check PRMD first. */ - if (regs->csr_prmd & CSR_PRMD_PIE) + if (!pie) local_irq_enable(); if (!cpu_has_lbt) { @@ -1005,7 +1009,7 @@ asmlinkage void noinstr do_lbt(struct pt_regs *regs) preempt_enable(); out: - if (regs->csr_prmd & CSR_PRMD_PIE) + if (!pie) local_irq_disable(); irqentry_exit(regs, state); From ad787442af7b48d6bf6393fb6d2cda28d9d9304d Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Sat, 22 Mar 2025 01:29:54 +0100 Subject: [PATCH 456/606] virtio_console: fix missing byte order handling for cols and rows commit fbd3039a64b01b769040677c4fc68badeca8e3b2 upstream. As per virtio spec the fields cols and rows are specified as little endian. Although there is no legacy interface requirement that would state that cols and rows need to be handled as native endian when legacy interface is used, unlike for the fields of the adjacent struct virtio_console_control, I decided to err on the side of caution based on some non-conclusive virtio spec repo archaeology and opt for using virtio16_to_cpu() much like for virtio_console_control.event. Strictly by the letter of the spec virtio_le_to_cpu() would have been sufficient. But when the legacy interface is not used, it boils down to the same. And when using the legacy interface, the device formatting these as little endian when the guest is big endian would surprise me more than it using guest native byte order (which would make it compatible with the current implementation). Nevertheless somebody trying to implement the spec following it to the letter could end up forcing little endian byte order when the legacy interface is in use. So IMHO this ultimately needs a judgement call by the maintainers. Fixes: 8345adbf96fc1 ("virtio: console: Accept console size along with resize control message") Signed-off-by: Halil Pasic Cc: stable@vger.kernel.org # v2.6.35+ Message-Id: <20250322002954.3129282-1-pasic@linux.ibm.com> Signed-off-by: Michael S. Tsirkin Signed-off-by: Greg Kroah-Hartman --- drivers/char/virtio_console.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 796ab9a4e48f..80e0f485170a 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -1612,8 +1612,8 @@ static void handle_control_message(struct virtio_device *vdev, break; case VIRTIO_CONSOLE_RESIZE: { struct { - __u16 rows; - __u16 cols; + __virtio16 rows; + __virtio16 cols; } size; if (!is_console_port(port)) @@ -1621,7 +1621,8 @@ static void handle_control_message(struct virtio_device *vdev, memcpy(&size, buf->buf + buf->offset + sizeof(*cpkt), sizeof(size)); - set_console_size(port, size.rows, size.cols); + set_console_size(port, virtio16_to_cpu(vdev, size.rows), + virtio16_to_cpu(vdev, size.cols)); port->cons.hvc->irq_requested = 1; resize_console(port); From 284db2f35b39081b00b2e76b92949463b7fc460a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Tue, 22 Apr 2025 11:57:18 +0200 Subject: [PATCH 457/606] crypto: atmel-sha204a - Set hwrng quality to lowest possible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 8006aff15516a170640239c5a8e6696c0ba18d8e upstream. According to the review by Bill Cox [1], the Atmel SHA204A random number generator produces random numbers with very low entropy. Set the lowest possible entropy for this chip just to be safe. [1] https://www.metzdowd.com/pipermail/cryptography/2014-December/023858.html Fixes: da001fb651b00e1d ("crypto: atmel-i2c - add support for SHA204A random number generator") Cc: Signed-off-by: Marek Behún Acked-by: Ard Biesheuvel Reviewed-by: Linus Walleij Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- drivers/crypto/atmel-sha204a.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c index c77f482d2a97..5bc809146ffe 100644 --- a/drivers/crypto/atmel-sha204a.c +++ b/drivers/crypto/atmel-sha204a.c @@ -107,6 +107,12 @@ static int atmel_sha204a_probe(struct i2c_client *client) i2c_priv->hwrng.name = dev_name(&client->dev); i2c_priv->hwrng.read = atmel_sha204a_rng_read; + /* + * According to review by Bill Cox [1], this HWRNG has very low entropy. + * [1] https://www.metzdowd.com/pipermail/cryptography/2014-December/023858.html + */ + i2c_priv->hwrng.quality = 1; + ret = devm_hwrng_register(&client->dev, &i2c_priv->hwrng); if (ret) dev_warn(&client->dev, "failed to register RNG (%d)\n", ret); From cefd8a2e2de46209ce66e6d30c237eb59b6c5bfa Mon Sep 17 00:00:00 2001 From: Alexey Nepomnyashih Date: Thu, 17 Apr 2025 12:21:17 +0000 Subject: [PATCH 458/606] xen-netfront: handle NULL returned by xdp_convert_buff_to_frame() commit cc3628dcd851ddd8d418bf0c897024b4621ddc92 upstream. The function xdp_convert_buff_to_frame() may return NULL if it fails to correctly convert the XDP buffer into an XDP frame due to memory constraints, internal errors, or invalid data. Failing to check for NULL may lead to a NULL pointer dereference if the result is used later in processing, potentially causing crashes, data corruption, or undefined behavior. On XDP redirect failure, the associated page must be released explicitly if it was previously retained via get_page(). Failing to do so may result in a memory leak, as the pages reference count is not decremented. Cc: stable@vger.kernel.org # v5.9+ Fixes: 6c5aa6fc4def ("xen networking: add basic XDP support for xen-netfront") Signed-off-by: Alexey Nepomnyashih Link: https://patch.msgid.link/20250417122118.1009824-1-sdl@nppct.ru Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- drivers/net/xen-netfront.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index bcb5651f18e0..0115f8f5b724 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -985,20 +985,27 @@ static u32 xennet_run_xdp(struct netfront_queue *queue, struct page *pdata, act = bpf_prog_run_xdp(prog, xdp); switch (act) { case XDP_TX: - get_page(pdata); xdpf = xdp_convert_buff_to_frame(xdp); - err = xennet_xdp_xmit(queue->info->netdev, 1, &xdpf, 0); - if (unlikely(!err)) - xdp_return_frame_rx_napi(xdpf); - else if (unlikely(err < 0)) + if (unlikely(!xdpf)) { trace_xdp_exception(queue->info->netdev, prog, act); + break; + } + get_page(pdata); + err = xennet_xdp_xmit(queue->info->netdev, 1, &xdpf, 0); + if (unlikely(err <= 0)) { + if (err < 0) + trace_xdp_exception(queue->info->netdev, prog, act); + xdp_return_frame_rx_napi(xdpf); + } break; case XDP_REDIRECT: get_page(pdata); err = xdp_do_redirect(queue->info->netdev, xdp, prog); *need_xdp_flush = true; - if (unlikely(err)) + if (unlikely(err)) { trace_xdp_exception(queue->info->netdev, prog, act); + xdp_return_buff(xdp); + } break; case XDP_PASS: case XDP_DROP: From a7b8358eb4030559e054d7fc8981a15d9eaf39be Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Wed, 16 Apr 2025 18:01:25 +0200 Subject: [PATCH 459/606] net: selftests: initialize TCP header and skb payload with zero commit 9e8d1013b0c38910cbc9e60de74dbe883878469d upstream. Zero-initialize TCP header via memset() to avoid garbage values that may affect checksum or behavior during test transmission. Also zero-fill allocated payload and padding regions using memset() after skb_put(), ensuring deterministic content for all outgoing test packets. Fixes: 3e1e58d64c3d ("net: add generic selftest support") Signed-off-by: Oleksij Rempel Cc: stable@vger.kernel.org Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250416160125.2914724-1-o.rempel@pengutronix.de Signed-off-by: Paolo Abeni Signed-off-by: Greg Kroah-Hartman --- net/core/selftests.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/net/core/selftests.c b/net/core/selftests.c index acb1ee97bbd3..7af99d07762e 100644 --- a/net/core/selftests.c +++ b/net/core/selftests.c @@ -100,10 +100,10 @@ static struct sk_buff *net_test_get_skb(struct net_device *ndev, ehdr->h_proto = htons(ETH_P_IP); if (attr->tcp) { + memset(thdr, 0, sizeof(*thdr)); thdr->source = htons(attr->sport); thdr->dest = htons(attr->dport); thdr->doff = sizeof(struct tcphdr) / 4; - thdr->check = 0; } else { uhdr->source = htons(attr->sport); uhdr->dest = htons(attr->dport); @@ -144,10 +144,18 @@ static struct sk_buff *net_test_get_skb(struct net_device *ndev, attr->id = net_test_next_id; shdr->id = net_test_next_id++; - if (attr->size) - skb_put(skb, attr->size); - if (attr->max_size && attr->max_size > skb->len) - skb_put(skb, attr->max_size - skb->len); + if (attr->size) { + void *payload = skb_put(skb, attr->size); + + memset(payload, 0, attr->size); + } + + if (attr->max_size && attr->max_size > skb->len) { + size_t pad_len = attr->max_size - skb->len; + void *pad = skb_put(skb, pad_len); + + memset(pad, 0, pad_len); + } skb->csum = 0; skb->ip_summed = CHECKSUM_PARTIAL; From 689d5be94faaec2c518956c82da18114927e7ea1 Mon Sep 17 00:00:00 2001 From: Fiona Klute Date: Wed, 16 Apr 2025 12:24:13 +0200 Subject: [PATCH 460/606] net: phy: microchip: force IRQ polling mode for lan88xx commit 30a41ed32d3088cd0d682a13d7f30b23baed7e93 upstream. With lan88xx based devices the lan78xx driver can get stuck in an interrupt loop while bringing the device up, flooding the kernel log with messages like the following: lan78xx 2-3:1.0 enp1s0u3: kevent 4 may have been dropped Removing interrupt support from the lan88xx PHY driver forces the driver to use polling instead, which avoids the problem. The issue has been observed with Raspberry Pi devices at least since 4.14 (see [1], bug report for their downstream kernel), as well as with Nvidia devices [2] in 2020, where disabling interrupts was the vendor-suggested workaround (together with the claim that phylib changes in 4.9 made the interrupt handling in lan78xx incompatible). Iperf reports well over 900Mbits/sec per direction with client in --dualtest mode, so there does not seem to be a significant impact on throughput (lan88xx device connected via switch to the peer). [1] https://github.com/raspberrypi/linux/issues/2447 [2] https://forums.developer.nvidia.com/t/jetson-xavier-and-lan7800-problem/142134/11 Link: https://lore.kernel.org/0901d90d-3f20-4a10-b680-9c978e04ddda@lunn.ch Fixes: 792aec47d59d ("add microchip LAN88xx phy driver") Signed-off-by: Fiona Klute Cc: kernel-list@raspberrypi.com Cc: stable@vger.kernel.org Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/20250416102413.30654-1-fiona.klute@gmx.de Signed-off-by: Paolo Abeni Signed-off-by: Greg Kroah-Hartman --- drivers/net/phy/microchip.c | 46 +++---------------------------------- 1 file changed, 3 insertions(+), 43 deletions(-) diff --git a/drivers/net/phy/microchip.c b/drivers/net/phy/microchip.c index 0b88635f4fbc..623607fd2cef 100644 --- a/drivers/net/phy/microchip.c +++ b/drivers/net/phy/microchip.c @@ -31,47 +31,6 @@ static int lan88xx_write_page(struct phy_device *phydev, int page) return __phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, page); } -static int lan88xx_phy_config_intr(struct phy_device *phydev) -{ - int rc; - - if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { - /* unmask all source and clear them before enable */ - rc = phy_write(phydev, LAN88XX_INT_MASK, 0x7FFF); - rc = phy_read(phydev, LAN88XX_INT_STS); - rc = phy_write(phydev, LAN88XX_INT_MASK, - LAN88XX_INT_MASK_MDINTPIN_EN_ | - LAN88XX_INT_MASK_LINK_CHANGE_); - } else { - rc = phy_write(phydev, LAN88XX_INT_MASK, 0); - if (rc) - return rc; - - /* Ack interrupts after they have been disabled */ - rc = phy_read(phydev, LAN88XX_INT_STS); - } - - return rc < 0 ? rc : 0; -} - -static irqreturn_t lan88xx_handle_interrupt(struct phy_device *phydev) -{ - int irq_status; - - irq_status = phy_read(phydev, LAN88XX_INT_STS); - if (irq_status < 0) { - phy_error(phydev); - return IRQ_NONE; - } - - if (!(irq_status & LAN88XX_INT_STS_LINK_CHANGE_)) - return IRQ_NONE; - - phy_trigger_machine(phydev); - - return IRQ_HANDLED; -} - static int lan88xx_suspend(struct phy_device *phydev) { struct lan88xx_priv *priv = phydev->priv; @@ -392,8 +351,9 @@ static struct phy_driver microchip_phy_driver[] = { .config_aneg = lan88xx_config_aneg, .link_change_notify = lan88xx_link_change_notify, - .config_intr = lan88xx_phy_config_intr, - .handle_interrupt = lan88xx_handle_interrupt, + /* Interrupt handling is broken, do not define related + * functions to force polling. + */ .suspend = lan88xx_suspend, .resume = genphy_resume, From 253827297c4dc62b4abb281350ffcc8a7072c0f4 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Tue, 1 Apr 2025 17:05:10 -0400 Subject: [PATCH 461/606] drm/amd/display: Fix gpu reset in multidisplay config commit 7eb287beeb60be1e4437be2b4e4e9f0da89aab97 upstream. [Why] The indexing of stream_status in dm_gpureset_commit_state() is incorrect. That leads to asserts in multi-display configuration after gpu reset. [How] Adjust the indexing logic to align stream_status with surface_updates. Fixes: cdaae8371aa9 ("drm/amd/display: Handle GPU reset for DC block") Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3808 Reviewed-by: Aurabindo Pillai Reviewed-by: Mario Limonciello Signed-off-by: Roman Li Signed-off-by: Zaeem Mohamed Tested-by: Mark Broadworth Signed-off-by: Alex Deucher (cherry picked from commit d91bc901398741d317d9b55c59ca949d4bc7394b) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 28f2b4022d34..56cc670a0022 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2789,16 +2789,16 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state, for (k = 0; k < dc_state->stream_count; k++) { bundle->stream_update.stream = dc_state->streams[k]; - for (m = 0; m < dc_state->stream_status->plane_count; m++) { + for (m = 0; m < dc_state->stream_status[k].plane_count; m++) { bundle->surface_updates[m].surface = - dc_state->stream_status->plane_states[m]; + dc_state->stream_status[k].plane_states[m]; bundle->surface_updates[m].surface->force_full_update = true; } update_planes_and_stream_adapter(dm->dc, UPDATE_TYPE_FULL, - dc_state->stream_status->plane_count, + dc_state->stream_status[k].plane_count, dc_state->streams[k], &bundle->stream_update, bundle->surface_updates); From 3d36fae38312d061279b42a3c2269ee372189bbc Mon Sep 17 00:00:00 2001 From: Roman Li Date: Wed, 26 Mar 2025 10:33:51 -0400 Subject: [PATCH 462/606] drm/amd/display: Force full update in gpu reset commit 67fe574651c73fe5cc176e35f28f2ec1ba498d14 upstream. [Why] While system undergoing gpu reset always do full update to sync the dc state before and after reset. [How] Return true in should_reset_plane() if gpu reset detected Reviewed-by: Aurabindo Pillai Reviewed-by: Mario Limonciello Signed-off-by: Roman Li Signed-off-by: Zaeem Mohamed Tested-by: Mark Broadworth Signed-off-by: Alex Deucher (cherry picked from commit 2ba8619b9a378ad218ad6c2e2ccaee8f531e08de) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 56cc670a0022..e6bc59053319 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -9590,6 +9590,9 @@ static bool should_reset_plane(struct drm_atomic_state *state, if (adev->ip_versions[DCE_HWIP][0] < IP_VERSION(3, 2, 0) && state->allow_modeset) return true; + if (amdgpu_in_reset(adev) && state->allow_modeset) + return true; + /* Exit early if we know that we're adding or removing the plane. */ if (old_plane_state->crtc != new_plane_state->crtc) return true; From 2f2803e4b5e4df2b08d378deaab78b1681ef9b30 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 22 Apr 2025 17:16:16 +0100 Subject: [PATCH 463/606] irqchip/gic-v2m: Prevent use after free of gicv2m_get_fwnode() commit 3318dc299b072a0511d6dfd8367f3304fb6d9827 upstream. With ACPI in place, gicv2m_get_fwnode() is registered with the pci subsystem as pci_msi_get_fwnode_cb(), which may get invoked at runtime during a PCI host bridge probe. But, the call back is wrongly marked as __init, causing it to be freed, while being registered with the PCI subsystem and could trigger: Unable to handle kernel paging request at virtual address ffff8000816c0400 gicv2m_get_fwnode+0x0/0x58 (P) pci_set_bus_msi_domain+0x74/0x88 pci_register_host_bridge+0x194/0x548 This is easily reproducible on a Juno board with ACPI boot. Retain the function for later use. Fixes: 0644b3daca28 ("irqchip/gic-v2m: acpi: Introducing GICv2m ACPI support") Signed-off-by: Suzuki K Poulose Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar Reviewed-by: Marc Zyngier Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/irqchip/irq-gic-v2m.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c index d83c2c85962c..683e8721e3b4 100644 --- a/drivers/irqchip/irq-gic-v2m.c +++ b/drivers/irqchip/irq-gic-v2m.c @@ -454,7 +454,7 @@ static int __init gicv2m_of_init(struct fwnode_handle *parent_handle, #ifdef CONFIG_ACPI static int acpi_num_msi; -static __init struct fwnode_handle *gicv2m_get_fwnode(struct device *dev) +static struct fwnode_handle *gicv2m_get_fwnode(struct device *dev) { struct v2m_data *data; From 2ca9380b12711afe95b3589bd82b59623b3c96b3 Mon Sep 17 00:00:00 2001 From: Ming Wang Date: Thu, 24 Apr 2025 20:15:47 +0800 Subject: [PATCH 464/606] LoongArch: Return NULL from huge_pte_offset() for invalid PMD commit bd51834d1cf65a2c801295d230c220aeebf87a73 upstream. LoongArch's huge_pte_offset() currently returns a pointer to a PMD slot even if the underlying entry points to invalid_pte_table (indicating no mapping). Callers like smaps_hugetlb_range() fetch this invalid entry value (the address of invalid_pte_table) via this pointer. The generic is_swap_pte() check then incorrectly identifies this address as a swap entry on LoongArch, because it satisfies the "!pte_present() && !pte_none()" conditions. This misinterpretation, combined with a coincidental match by is_migration_entry() on the address bits, leads to kernel crashes in pfn_swap_entry_to_page(). Fix this at the architecture level by modifying huge_pte_offset() to check the PMD entry's content using pmd_none() before returning. If the entry is invalid (i.e., it points to invalid_pte_table), return NULL instead of the pointer to the slot. Cc: stable@vger.kernel.org Acked-by: Peter Xu Co-developed-by: Hongchen Zhang Signed-off-by: Hongchen Zhang Signed-off-by: Ming Wang Signed-off-by: Huacai Chen Signed-off-by: Greg Kroah-Hartman --- arch/loongarch/mm/hugetlbpage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/loongarch/mm/hugetlbpage.c b/arch/loongarch/mm/hugetlbpage.c index 1e76fcb83093..41308429f446 100644 --- a/arch/loongarch/mm/hugetlbpage.c +++ b/arch/loongarch/mm/hugetlbpage.c @@ -47,7 +47,7 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr, pmd = pmd_offset(pud, addr); } } - return (pte_t *) pmd; + return pmd_none(pmdp_get(pmd)) ? NULL : (pte_t *) pmd; } int pmd_huge(pmd_t pmd) From 20a3f73dd424e4ac5a2d5c78430721cae6352dda Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Thu, 24 Apr 2025 20:15:41 +0800 Subject: [PATCH 465/606] LoongArch: Remove a bogus reference to ZONE_DMA commit c37325cbd91abe3bfab280b3b09947155abe8e07 upstream. Remove dead code. LoongArch does not have a DMA memory zone (24bit DMA). The architecture does not even define MAX_DMA_PFN. Cc: stable@vger.kernel.org Reviewed-by: Mike Rapoport (Microsoft) Signed-off-by: Petr Tesarik Signed-off-by: Huacai Chen Signed-off-by: Greg Kroah-Hartman --- arch/loongarch/mm/init.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/loongarch/mm/init.c b/arch/loongarch/mm/init.c index 4dd53427f657..a5bf96993bb1 100644 --- a/arch/loongarch/mm/init.c +++ b/arch/loongarch/mm/init.c @@ -64,9 +64,6 @@ void __init paging_init(void) { unsigned long max_zone_pfns[MAX_NR_ZONES]; -#ifdef CONFIG_ZONE_DMA - max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN; -#endif #ifdef CONFIG_ZONE_DMA32 max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN; #endif From b675b4c863f1dcfef44b6dc6f4c06212ae44288e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 24 Apr 2025 10:28:14 -0600 Subject: [PATCH 466/606] io_uring: fix 'sync' handling of io_fallback_tw() commit edd43f4d6f50ec3de55a0c9e9df6348d1da51965 upstream. A previous commit added a 'sync' parameter to io_fallback_tw(), which if true, means the caller wants to wait on the fallback thread handling it. But the logic is somewhat messed up, ensure that ctxs are swapped and flushed appropriately. Cc: stable@vger.kernel.org Fixes: dfbe5561ae93 ("io_uring: flush offloaded and delayed task_work on exit") Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- io_uring/io_uring.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c index efa7849b82c1..9883fd16cde4 100644 --- a/io_uring/io_uring.c +++ b/io_uring/io_uring.c @@ -1247,21 +1247,22 @@ static __cold void io_fallback_tw(struct io_uring_task *tctx, bool sync) while (node) { req = container_of(node, struct io_kiocb, io_task_work.node); node = node->next; - if (sync && last_ctx != req->ctx) { + if (last_ctx != req->ctx) { if (last_ctx) { - flush_delayed_work(&last_ctx->fallback_work); + if (sync) + flush_delayed_work(&last_ctx->fallback_work); percpu_ref_put(&last_ctx->refs); } last_ctx = req->ctx; percpu_ref_get(&last_ctx->refs); } - if (llist_add(&req->io_task_work.node, - &req->ctx->fallback_llist)) - schedule_delayed_work(&req->ctx->fallback_work, 1); + if (llist_add(&req->io_task_work.node, &last_ctx->fallback_llist)) + schedule_delayed_work(&last_ctx->fallback_work, 1); } if (last_ctx) { - flush_delayed_work(&last_ctx->fallback_work); + if (sync) + flush_delayed_work(&last_ctx->fallback_work); percpu_ref_put(&last_ctx->refs); } } From ff826d60d9a86c978e0da128a072d94c29a27b9c Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 4 Apr 2025 12:38:16 -0700 Subject: [PATCH 467/606] KVM: SVM: Allocate IR data using atomic allocation commit 7537deda36521fa8fff9133b39c46e31893606f2 upstream. Allocate SVM's interrupt remapping metadata using GFP_ATOMIC as svm_ir_list_add() is called with IRQs are disabled and irqfs.lock held when kvm_irq_routing_update() reacts to GSI routing changes. Fixes: 411b44ba80ab ("svm: Implements update_pi_irte hook to setup posted interrupt") Cc: stable@vger.kernel.org Signed-off-by: Sean Christopherson Message-ID: <20250404193923.1413163-2-seanjc@google.com> Signed-off-by: Paolo Bonzini Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/svm/avic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c index 4b74ea91f4e6..0785c7e9c852 100644 --- a/arch/x86/kvm/svm/avic.c +++ b/arch/x86/kvm/svm/avic.c @@ -820,7 +820,7 @@ static int svm_ir_list_add(struct vcpu_svm *svm, struct amd_iommu_pi_data *pi) * Allocating new amd_iommu_pi_data, which will get * add to the per-vcpu ir_list. */ - ir = kzalloc(sizeof(struct amd_svm_iommu_ir), GFP_KERNEL_ACCOUNT); + ir = kzalloc(sizeof(struct amd_svm_iommu_ir), GFP_ATOMIC | __GFP_ACCOUNT); if (!ir) { ret = -ENOMEM; goto out; From 406ca74adea0f6f34a8ea1060b2ddadd9dd282c9 Mon Sep 17 00:00:00 2001 From: Smita Koralahalli Date: Mon, 7 Apr 2025 19:27:34 +0000 Subject: [PATCH 468/606] cxl/core/regs.c: Skip Memory Space Enable check for RCD and RCH Ports commit 078d3ee7c162cd66d76171579c02d7890bd77daf upstream. According to CXL r3.2 section 8.2.1.2, the PCI_COMMAND register fields, including Memory Space Enable bit, have no effect on the behavior of an RCD Upstream Port. Retaining this check may incorrectly cause cxl_pci_probe() to fail on a valid RCD upstream Port. While the specification is explicit only for RCD Upstream Ports, this check is solely for accessing the RCRB, which is always mapped through memory space. Therefore, its safe to remove the check entirely. In practice, firmware reliably enables the Memory Space Enable bit for RCH Downstream Ports and no failures have been observed. Removing the check simplifies the code and avoids unnecessary special-casing, while relying on BIOS/firmware to configure devices correctly. Moreover, any failures due to inaccessible RCRB regions will still be caught either in __rcrb_to_component() or while parsing the component register block. The following failure was observed in dmesg when the check was present: cxl_pci 0000:7f:00.0: No component registers (-6) Fixes: d5b1a27143cb ("cxl/acpi: Extract component registers of restricted hosts from RCRB") Signed-off-by: Smita Koralahalli Cc: Reviewed-by: Ira Weiny Reviewed-by: Terry Bowman Reviewed-by: Dave Jiang Reviewed-by: Robert Richter Link: https://patch.msgid.link/20250407192734.70631-1-Smita.KoralahalliChannabasappa@amd.com Signed-off-by: Dave Jiang Signed-off-by: Greg Kroah-Hartman --- drivers/cxl/core/regs.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c index bab4592db647..92ef68849fbe 100644 --- a/drivers/cxl/core/regs.c +++ b/drivers/cxl/core/regs.c @@ -478,7 +478,6 @@ resource_size_t __rcrb_to_component(struct device *dev, struct cxl_rcrb_info *ri resource_size_t rcrb = ri->base; void __iomem *addr; u32 bar0, bar1; - u16 cmd; u32 id; if (which == CXL_RCRB_UPSTREAM) @@ -500,7 +499,6 @@ resource_size_t __rcrb_to_component(struct device *dev, struct cxl_rcrb_info *ri } id = readl(addr + PCI_VENDOR_ID); - cmd = readw(addr + PCI_COMMAND); bar0 = readl(addr + PCI_BASE_ADDRESS_0); bar1 = readl(addr + PCI_BASE_ADDRESS_1); iounmap(addr); @@ -515,8 +513,6 @@ resource_size_t __rcrb_to_component(struct device *dev, struct cxl_rcrb_info *ri dev_err(dev, "Failed to access Downstream Port RCRB\n"); return CXL_RESOURCE_NONE; } - if (!(cmd & PCI_COMMAND_MEMORY)) - return CXL_RESOURCE_NONE; /* The RCRB is a Memory Window, and the MEM_TYPE_1M bit is obsolete */ if (bar0 & (PCI_BASE_ADDRESS_MEM_TYPE_1M | PCI_BASE_ADDRESS_SPACE_IO)) return CXL_RESOURCE_NONE; From 96838eb1836fd372e42be5db84f0b333b65146a6 Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Mon, 10 Mar 2025 09:46:57 +0100 Subject: [PATCH 469/606] mcb: fix a double free bug in chameleon_parse_gdd() commit 7c7f1bfdb2249f854a736d9b79778c7e5a29a150 upstream. In chameleon_parse_gdd(), if mcb_device_register() fails, 'mdev' would be released in mcb_device_register() via put_device(). Thus, goto 'err' label and free 'mdev' again causes a double free. Just return if mcb_device_register() fails. Fixes: 3764e82e5150 ("drivers: Introduce MEN Chameleon Bus") Cc: stable Signed-off-by: Haoxiang Li Signed-off-by: Johannes Thumshirn Link: https://lore.kernel.org/r/6201d09e2975ae5789879f79a6de4c38de9edd4a.1741596225.git.jth@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/mcb/mcb-parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mcb/mcb-parse.c b/drivers/mcb/mcb-parse.c index 1ae37e693de0..d080e21df666 100644 --- a/drivers/mcb/mcb-parse.c +++ b/drivers/mcb/mcb-parse.c @@ -101,7 +101,7 @@ static int chameleon_parse_gdd(struct mcb_bus *bus, ret = mcb_device_register(bus, mdev); if (ret < 0) - goto err; + return ret; return 0; From f92d5d7134d1f4e15935d54405f250ebffaa2192 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Mon, 14 Apr 2025 10:25:05 +0900 Subject: [PATCH 470/606] ata: libata-scsi: Improve CDL control commit 17e897a456752ec9c2d7afb3d9baf268b442451b upstream. With ATA devices supporting the CDL feature, using CDL requires that the feature be enabled with a SET FEATURES command. This command is issued as the translated command for the MODE SELECT command issued by scsi_cdl_enable() when the user enables CDL through the device cdl_enable sysfs attribute. Currently, ata_mselect_control_ata_feature() always translates a MODE SELECT command for the ATA features subpage of the control mode page to a SET FEATURES command to enable or disable CDL based on the cdl_ctrl field. However, there is no need to issue the SET FEATURES command if: 1) The MODE SELECT command requests disabling CDL and CDL is already disabled. 2) The MODE SELECT command requests enabling CDL and CDL is already enabled. Fix ata_mselect_control_ata_feature() to issue the SET FEATURES command only when necessary. Since enabling CDL also implies a reset of the CDL statistics log page, avoiding useless CDL enable operations also avoids clearing the CDL statistics log. Also add debug messages to clearly signal when CDL is being enabled or disabled using a SET FEATURES command. Fixes: df60f9c64576 ("scsi: ata: libata: Add ATA feature control sub-page translation") Cc: stable@vger.kernel.org Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel Reviewed-by: Igor Pylypiv Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-scsi.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 5377d094bf75..4c6a20bd9340 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3787,17 +3787,27 @@ static unsigned int ata_mselect_control_ata_feature(struct ata_queued_cmd *qc, /* Check cdl_ctrl */ switch (buf[0] & 0x03) { case 0: - /* Disable CDL */ + /* Disable CDL if it is enabled */ + if (!(dev->flags & ATA_DFLAG_CDL_ENABLED)) + return 0; + ata_dev_dbg(dev, "Disabling CDL\n"); cdl_action = 0; dev->flags &= ~ATA_DFLAG_CDL_ENABLED; break; case 0x02: - /* Enable CDL T2A/T2B: NCQ priority must be disabled */ + /* + * Enable CDL if not already enabled. Since this is mutually + * exclusive with NCQ priority, allow this only if NCQ priority + * is disabled. + */ + if (dev->flags & ATA_DFLAG_CDL_ENABLED) + return 0; if (dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLED) { ata_dev_err(dev, "NCQ priority must be disabled to enable CDL\n"); return -EINVAL; } + ata_dev_dbg(dev, "Enabling CDL\n"); cdl_action = 1; dev->flags |= ATA_DFLAG_CDL_ENABLED; break; From f0a1b054871ff86ad25b5bd57874af457f5e42c0 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Fri, 18 Apr 2025 15:40:14 +0900 Subject: [PATCH 471/606] ata: libata-scsi: Fix ata_mselect_control_ata_feature() return type commit db91586b1e8f36122a9e5b8fbced11741488dd22 upstream. The function ata_mselect_control_ata_feature() has a return type defined as unsigned int but this function may return negative error codes, which are correctly propagated up the call chain as integers. Fix ata_mselect_control_ata_feature() to have the correct int return type. While at it, also fix a typo in this function description comment. Fixes: df60f9c64576 ("scsi: ata: libata: Add ATA feature control sub-page translation") Cc: stable@vger.kernel.org Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel Reviewed-by: Igor Pylypiv Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-scsi.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 4c6a20bd9340..61d399bc2702 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3764,12 +3764,11 @@ static int ata_mselect_control_spg0(struct ata_queued_cmd *qc, } /* - * Translate MODE SELECT control mode page, sub-pages f2h (ATA feature mode + * Translate MODE SELECT control mode page, sub-page f2h (ATA feature mode * page) into a SET FEATURES command. */ -static unsigned int ata_mselect_control_ata_feature(struct ata_queued_cmd *qc, - const u8 *buf, int len, - u16 *fp) +static int ata_mselect_control_ata_feature(struct ata_queued_cmd *qc, + const u8 *buf, int len, u16 *fp) { struct ata_device *dev = qc->dev; struct ata_taskfile *tf = &qc->tf; From ff733a91a06bf46cf1b7cdd637214e6a76f2eb0b Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Sun, 13 Apr 2025 14:45:30 +0900 Subject: [PATCH 472/606] ata: libata-scsi: Fix ata_msense_control_ata_feature() commit 88474ad734fb2000805c63e01cc53ea930adf2c7 upstream. For the ATA features subpage of the control mode page, the T10 SAT-6 specifications state that: For a MODE SENSE command, the SATL shall return the CDL_CTRL field value that was last set by an application client. However, the function ata_msense_control_ata_feature() always sets the CDL_CTRL field to the 0x02 value to indicate support for the CDL T2A and T2B pages. This is thus incorrect and the value 0x02 must be reported only after the user enables the CDL feature, which is indicated with the ATA_DFLAG_CDL_ENABLED device flag. When this flag is not set, the CDL_CTRL field of the ATA feature subpage of the control mode page must report a value of 0x00. Fix ata_msense_control_ata_feature() to report the correct values for the CDL_CTRL field, according to the enable/disable state of the device CDL feature. Fixes: df60f9c64576 ("scsi: ata: libata: Add ATA feature control sub-page translation") Cc: stable@vger.kernel.org Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel Reviewed-by: Igor Pylypiv Signed-off-by: Greg Kroah-Hartman --- drivers/ata/libata-scsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 61d399bc2702..6a1460d35447 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2354,8 +2354,8 @@ static unsigned int ata_msense_control_ata_feature(struct ata_device *dev, */ put_unaligned_be16(ATA_FEATURE_SUB_MPAGE_LEN - 4, &buf[2]); - if (dev->flags & ATA_DFLAG_CDL) - buf[4] = 0x02; /* Support T2A and T2B pages */ + if (dev->flags & ATA_DFLAG_CDL_ENABLED) + buf[4] = 0x02; /* T2A and T2B pages enabled */ else buf[4] = 0; From 4c2de359b1a227555234bd398bca52e2ec488534 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 3 Apr 2025 19:59:45 +0200 Subject: [PATCH 473/606] USB: storage: quirk for ADATA Portable HDD CH94 commit 9ab75eee1a056f896b87d139044dd103adc532b9 upstream. Version 1.60 specifically needs this quirk. Version 2.00 is known good. Cc: stable Signed-off-by: Oliver Neukum Link: https://lore.kernel.org/r/20250403180004.343133-1-oneukum@suse.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_uas.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/storage/unusual_uas.h b/drivers/usb/storage/unusual_uas.h index 1f8c9b16a0fb..d460d71b4257 100644 --- a/drivers/usb/storage/unusual_uas.h +++ b/drivers/usb/storage/unusual_uas.h @@ -83,6 +83,13 @@ UNUSUAL_DEV(0x0bc2, 0x331a, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_REPORT_LUNS), +/* Reported-by: Oliver Neukum */ +UNUSUAL_DEV(0x125f, 0xa94a, 0x0160, 0x0160, + "ADATA", + "Portable HDD CH94", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_NO_ATA_1X), + /* Reported-by: Benjamin Tissoires */ UNUSUAL_DEV(0x13fd, 0x3940, 0x0000, 0x9999, "Initio Corporation", From 164bc7e26d89219cd1f1d4308f17024fe23a8286 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Sun, 13 Apr 2025 11:24:47 +0900 Subject: [PATCH 474/606] scsi: Improve CDL control commit 14a3cc755825ef7b34c986aa2786ea815023e9c5 upstream. With ATA devices supporting the CDL feature, using CDL requires that the feature be enabled with a SET FEATURES command. This command is issued as the translated command for the MODE SELECT command issued by scsi_cdl_enable() when the user enables CDL through the device cdl_enable sysfs attribute. However, the implementation of scsi_cdl_enable() always issues a MODE SELECT command for ATA devices when the enable argument is true, even if CDL is already enabled on the device. While this does not cause any issue with using CDL descriptors with read/write commands (the CDL feature will be enabled on the drive), issuing the MODE SELECT command even when the device CDL feature is already enabled will cause a reset of the ATA device CDL statistics log page (as defined in ACS, any CDL enable action must reset the device statistics). Avoid this needless actions (and the implied statistics log page reset) by modifying scsi_cdl_enable() to issue the MODE SELECT command to enable CDL if and only if CDL is not reported as already enabled on the device. And while at it, simplify the initialization of the is_ata boolean variable and move the declaration of the scsi mode data and sense header variables to within the scope of ATA device handling. Fixes: 1b22cfb14142 ("scsi: core: Allow enabling and disabling command duration limits") Cc: stable@vger.kernel.org Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel Reviewed-by: Igor Pylypiv Reviewed-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/scsi.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 22bdce0bc327..9c0142a010ba 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -693,26 +693,23 @@ void scsi_cdl_check(struct scsi_device *sdev) */ int scsi_cdl_enable(struct scsi_device *sdev, bool enable) { - struct scsi_mode_data data; - struct scsi_sense_hdr sshdr; - struct scsi_vpd *vpd; - bool is_ata = false; char buf[64]; + bool is_ata; int ret; if (!sdev->cdl_supported) return -EOPNOTSUPP; rcu_read_lock(); - vpd = rcu_dereference(sdev->vpd_pg89); - if (vpd) - is_ata = true; + is_ata = rcu_dereference(sdev->vpd_pg89); rcu_read_unlock(); /* * For ATA devices, CDL needs to be enabled with a SET FEATURES command. */ if (is_ata) { + struct scsi_mode_data data; + struct scsi_sense_hdr sshdr; char *buf_data; int len; @@ -721,16 +718,30 @@ int scsi_cdl_enable(struct scsi_device *sdev, bool enable) if (ret) return -EINVAL; - /* Enable CDL using the ATA feature page */ + /* Enable or disable CDL using the ATA feature page */ len = min_t(size_t, sizeof(buf), data.length - data.header_length - data.block_descriptor_length); buf_data = buf + data.header_length + data.block_descriptor_length; - if (enable) - buf_data[4] = 0x02; - else - buf_data[4] = 0; + + /* + * If we want to enable CDL and CDL is already enabled on the + * device, do nothing. This avoids needlessly resetting the CDL + * statistics on the device as that is implied by the CDL enable + * action. Similar to this, there is no need to do anything if + * we want to disable CDL and CDL is already disabled. + */ + if (enable) { + if ((buf_data[4] & 0x03) == 0x02) + goto out; + buf_data[4] &= ~0x03; + buf_data[4] |= 0x02; + } else { + if ((buf_data[4] & 0x03) == 0x00) + goto out; + buf_data[4] &= ~0x03; + } ret = scsi_mode_select(sdev, 1, 0, buf_data, len, 5 * HZ, 3, &data, &sshdr); @@ -742,6 +753,7 @@ int scsi_cdl_enable(struct scsi_device *sdev, bool enable) } } +out: sdev->cdl_enable = enable; return 0; From ac0fe095ac21dd6012be82e3d8572e10050eb8a4 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Tue, 8 Apr 2025 16:00:05 +0300 Subject: [PATCH 475/606] mei: me: add panther lake H DID commit 86ce5c0a1dec02e21b4c864b2bc0cc5880a2c13c upstream. Add Panther Lake H device id. Cc: stable Co-developed-by: Tomas Winkler Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin Link: https://lore.kernel.org/r/20250408130005.1358140-1-alexander.usyskin@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me-regs.h | 1 + drivers/misc/mei/pci-me.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h index a4668ddd9455..4adfa5af162f 100644 --- a/drivers/misc/mei/hw-me-regs.h +++ b/drivers/misc/mei/hw-me-regs.h @@ -117,6 +117,7 @@ #define MEI_DEV_ID_LNL_M 0xA870 /* Lunar Lake Point M */ +#define MEI_DEV_ID_PTL_H 0xE370 /* Panther Lake H */ #define MEI_DEV_ID_PTL_P 0xE470 /* Panther Lake P */ /* diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index 6826cc50d29f..93b98a7f4c7f 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -124,6 +124,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = { {MEI_PCI_DEVICE(MEI_DEV_ID_LNL_M, MEI_ME_PCH15_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_PTL_H, MEI_ME_PCH15_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_PTL_P, MEI_ME_PCH15_CFG)}, /* required last entry */ From 9514202882a00d20a051e342241ddd4f540244c9 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 4 Apr 2025 12:38:18 -0700 Subject: [PATCH 476/606] KVM: x86: Explicitly treat routing entry type changes as changes commit bcda70c56f3e718465cab2aad260cf34183ce1ce upstream. Explicitly treat type differences as GSI routing changes, as comparing MSI data between two entries could get a false negative, e.g. if userspace changed the type but left the type-specific data as-is. Fixes: 515a0c79e796 ("kvm: irqfd: avoid update unmodified entries of the routing") Cc: stable@vger.kernel.org Signed-off-by: Sean Christopherson Message-ID: <20250404193923.1413163-4-seanjc@google.com> Signed-off-by: Paolo Bonzini Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/x86.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 2a2dbeb56897..f67fe8a65820 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -13297,7 +13297,8 @@ int kvm_arch_update_irqfd_routing(struct kvm *kvm, unsigned int host_irq, bool kvm_arch_irqfd_route_changed(struct kvm_kernel_irq_routing_entry *old, struct kvm_kernel_irq_routing_entry *new) { - if (new->type != KVM_IRQ_ROUTING_MSI) + if (old->type != KVM_IRQ_ROUTING_MSI || + new->type != KVM_IRQ_ROUTING_MSI) return true; return !!memcmp(&old->msi, &new->msi, sizeof(new->msi)); From 3481fd96d801715942b6f69fe251133128156f30 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 4 Apr 2025 12:38:17 -0700 Subject: [PATCH 477/606] KVM: x86: Reset IRTE to host control if *new* route isn't postable commit 9bcac97dc42d2f4da8229d18feb0fe2b1ce523a2 upstream. Restore an IRTE back to host control (remapped or posted MSI mode) if the *new* GSI route prevents posting the IRQ directly to a vCPU, regardless of the GSI routing type. Updating the IRTE if and only if the new GSI is an MSI results in KVM leaving an IRTE posting to a vCPU. The dangling IRTE can result in interrupts being incorrectly delivered to the guest, and in the worst case scenario can result in use-after-free, e.g. if the VM is torn down, but the underlying host IRQ isn't freed. Fixes: efc644048ecd ("KVM: x86: Update IRTE for posted-interrupts") Fixes: 411b44ba80ab ("svm: Implements update_pi_irte hook to setup posted interrupt") Cc: stable@vger.kernel.org Signed-off-by: Sean Christopherson Message-ID: <20250404193923.1413163-3-seanjc@google.com> Signed-off-by: Paolo Bonzini Signed-off-by: Greg Kroah-Hartman --- arch/x86/kvm/svm/avic.c | 58 ++++++++++++++++++---------------- arch/x86/kvm/vmx/posted_intr.c | 28 ++++++---------- 2 files changed, 41 insertions(+), 45 deletions(-) diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c index 0785c7e9c852..6970b11a6b4c 100644 --- a/arch/x86/kvm/svm/avic.c +++ b/arch/x86/kvm/svm/avic.c @@ -896,6 +896,7 @@ int avic_pi_update_irte(struct kvm *kvm, unsigned int host_irq, { struct kvm_kernel_irq_routing_entry *e; struct kvm_irq_routing_table *irq_rt; + bool enable_remapped_mode = true; int idx, ret = 0; if (!kvm_arch_has_assigned_device(kvm) || @@ -933,6 +934,8 @@ int avic_pi_update_irte(struct kvm *kvm, unsigned int host_irq, kvm_vcpu_apicv_active(&svm->vcpu)) { struct amd_iommu_pi_data pi; + enable_remapped_mode = false; + /* Try to enable guest_mode in IRTE */ pi.base = __sme_set(page_to_phys(svm->avic_backing_page) & AVIC_HPA_MASK); @@ -951,33 +954,6 @@ int avic_pi_update_irte(struct kvm *kvm, unsigned int host_irq, */ if (!ret && pi.is_guest_mode) svm_ir_list_add(svm, &pi); - } else { - /* Use legacy mode in IRTE */ - struct amd_iommu_pi_data pi; - - /** - * Here, pi is used to: - * - Tell IOMMU to use legacy mode for this interrupt. - * - Retrieve ga_tag of prior interrupt remapping data. - */ - pi.prev_ga_tag = 0; - pi.is_guest_mode = false; - ret = irq_set_vcpu_affinity(host_irq, &pi); - - /** - * Check if the posted interrupt was previously - * setup with the guest_mode by checking if the ga_tag - * was cached. If so, we need to clean up the per-vcpu - * ir_list. - */ - if (!ret && pi.prev_ga_tag) { - int id = AVIC_GATAG_TO_VCPUID(pi.prev_ga_tag); - struct kvm_vcpu *vcpu; - - vcpu = kvm_get_vcpu_by_id(kvm, id); - if (vcpu) - svm_ir_list_del(to_svm(vcpu), &pi); - } } if (!ret && svm) { @@ -993,6 +969,34 @@ int avic_pi_update_irte(struct kvm *kvm, unsigned int host_irq, } ret = 0; + if (enable_remapped_mode) { + /* Use legacy mode in IRTE */ + struct amd_iommu_pi_data pi; + + /** + * Here, pi is used to: + * - Tell IOMMU to use legacy mode for this interrupt. + * - Retrieve ga_tag of prior interrupt remapping data. + */ + pi.prev_ga_tag = 0; + pi.is_guest_mode = false; + ret = irq_set_vcpu_affinity(host_irq, &pi); + + /** + * Check if the posted interrupt was previously + * setup with the guest_mode by checking if the ga_tag + * was cached. If so, we need to clean up the per-vcpu + * ir_list. + */ + if (!ret && pi.prev_ga_tag) { + int id = AVIC_GATAG_TO_VCPUID(pi.prev_ga_tag); + struct kvm_vcpu *vcpu; + + vcpu = kvm_get_vcpu_by_id(kvm, id); + if (vcpu) + svm_ir_list_del(to_svm(vcpu), &pi); + } + } out: srcu_read_unlock(&kvm->irq_srcu, idx); return ret; diff --git a/arch/x86/kvm/vmx/posted_intr.c b/arch/x86/kvm/vmx/posted_intr.c index af662312fd07..b54e0cb86e5d 100644 --- a/arch/x86/kvm/vmx/posted_intr.c +++ b/arch/x86/kvm/vmx/posted_intr.c @@ -274,6 +274,7 @@ int vmx_pi_update_irte(struct kvm *kvm, unsigned int host_irq, { struct kvm_kernel_irq_routing_entry *e; struct kvm_irq_routing_table *irq_rt; + bool enable_remapped_mode = true; struct kvm_lapic_irq irq; struct kvm_vcpu *vcpu; struct vcpu_data vcpu_info; @@ -312,21 +313,8 @@ int vmx_pi_update_irte(struct kvm *kvm, unsigned int host_irq, kvm_set_msi_irq(kvm, e, &irq); if (!kvm_intr_is_single_vcpu(kvm, &irq, &vcpu) || - !kvm_irq_is_postable(&irq)) { - /* - * Make sure the IRTE is in remapped mode if - * we don't handle it in posted mode. - */ - ret = irq_set_vcpu_affinity(host_irq, NULL); - if (ret < 0) { - printk(KERN_INFO - "failed to back to remapped mode, irq: %u\n", - host_irq); - goto out; - } - + !kvm_irq_is_postable(&irq)) continue; - } vcpu_info.pi_desc_addr = __pa(vcpu_to_pi_desc(vcpu)); vcpu_info.vector = irq.vector; @@ -334,11 +322,12 @@ int vmx_pi_update_irte(struct kvm *kvm, unsigned int host_irq, trace_kvm_pi_irte_update(host_irq, vcpu->vcpu_id, e->gsi, vcpu_info.vector, vcpu_info.pi_desc_addr, set); - if (set) - ret = irq_set_vcpu_affinity(host_irq, &vcpu_info); - else - ret = irq_set_vcpu_affinity(host_irq, NULL); + if (!set) + continue; + enable_remapped_mode = false; + + ret = irq_set_vcpu_affinity(host_irq, &vcpu_info); if (ret < 0) { printk(KERN_INFO "%s: failed to update PI IRTE\n", __func__); @@ -346,6 +335,9 @@ int vmx_pi_update_irte(struct kvm *kvm, unsigned int host_irq, } } + if (enable_remapped_mode) + ret = irq_set_vcpu_affinity(host_irq, NULL); + ret = 0; out: srcu_read_unlock(&kvm->irq_srcu, idx); From 5f253cc40e8d45a1a586b81b34b3c24a399d2406 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Mon, 17 Mar 2025 10:59:55 -0300 Subject: [PATCH 478/606] char: misc: register chrdev region with all possible minors commit c876be906ce7e518d9ef9926478669c151999e69 upstream. register_chrdev will only register the first 256 minors of a major chrdev. That means that dynamically allocated misc devices with minor above 255 will fail to open with -ENXIO. This was found by kernel test robot when testing a different change that makes all dynamically allocated minors be above 255. This has, however, been separately tested by creating 256 serio_raw devices with the help of userio driver. Ever since allowing misc devices with minors above 128, this has been possible. Fix it by registering all minor numbers from 0 to MINORMASK + 1 for MISC_MAJOR. Reported-by: kernel test robot Cc: stable Closes: https://lore.kernel.org/oe-lkp/202503171507.6c8093d0-lkp@intel.com Fixes: ab760791c0cf ("char: misc: Increase the maximum number of dynamic misc devices to 1048448") Signed-off-by: Thadeu Lima de Souza Cascardo Tested-by: Hou Wenlong Link: https://lore.kernel.org/r/20250317-misc-chrdev-v1-1-6cd05da11aef@igalia.com Signed-off-by: Greg Kroah-Hartman --- drivers/char/misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/misc.c b/drivers/char/misc.c index f7dd455dd0dd..dda466f9181a 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -315,7 +315,7 @@ static int __init misc_init(void) goto fail_remove; err = -EIO; - if (register_chrdev(MISC_MAJOR, "misc", &misc_fops)) + if (__register_chrdev(MISC_MAJOR, 0, MINORMASK + 1, "misc", &misc_fops)) goto fail_printk; return 0; From 62957f58ab3aa7fa792dc6ff3575624062539a4d Mon Sep 17 00:00:00 2001 From: Rengarajan S Date: Thu, 13 Mar 2025 22:38:55 +0530 Subject: [PATCH 479/606] misc: microchip: pci1xxxx: Fix Kernel panic during IRQ handler registration commit 18eb77c75ed01439f96ae5c0f33461eb5134b907 upstream. Resolve kernel panic while accessing IRQ handler associated with the generated IRQ. This is done by acquiring the spinlock and storing the current interrupt state before handling the interrupt request using generic_handle_irq. A previous fix patch was submitted where 'generic_handle_irq' was replaced with 'handle_nested_irq'. However, this change also causes the kernel panic where after determining which GPIO triggered the interrupt and attempting to call handle_nested_irq with the mapped IRQ number, leads to a failure in locating the registered handler. Fixes: 194f9f94a516 ("misc: microchip: pci1xxxx: Resolve kernel panic during GPIO IRQ handling") Cc: stable Signed-off-by: Rengarajan S Link: https://lore.kernel.org/r/20250313170856.20868-2-rengarajan.s@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c b/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c index 3c1359d8d4e6..88a405b72125 100644 --- a/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c +++ b/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c @@ -37,6 +37,7 @@ struct pci1xxxx_gpio { struct auxiliary_device *aux_dev; void __iomem *reg_base; + raw_spinlock_t wa_lock; struct gpio_chip gpio; spinlock_t lock; int irq_base; @@ -254,6 +255,7 @@ static irqreturn_t pci1xxxx_gpio_irq_handler(int irq, void *dev_id) struct pci1xxxx_gpio *priv = dev_id; struct gpio_chip *gc = &priv->gpio; unsigned long int_status = 0; + unsigned long wa_flags; unsigned long flags; u8 pincount; int bit; @@ -277,7 +279,9 @@ static irqreturn_t pci1xxxx_gpio_irq_handler(int irq, void *dev_id) writel(BIT(bit), priv->reg_base + INTR_STATUS_OFFSET(gpiobank)); spin_unlock_irqrestore(&priv->lock, flags); irq = irq_find_mapping(gc->irq.domain, (bit + (gpiobank * 32))); - handle_nested_irq(irq); + raw_spin_lock_irqsave(&priv->wa_lock, wa_flags); + generic_handle_irq(irq); + raw_spin_unlock_irqrestore(&priv->wa_lock, wa_flags); } } spin_lock_irqsave(&priv->lock, flags); From 5d5e8a880c48d4901632a8c4ade7e2e8ab81489f Mon Sep 17 00:00:00 2001 From: Rengarajan S Date: Thu, 13 Mar 2025 22:38:56 +0530 Subject: [PATCH 480/606] misc: microchip: pci1xxxx: Fix incorrect IRQ status handling during ack commit e9d7748a7468581859d2b85b378135f9688a0aff upstream. Under irq_ack, pci1xxxx_assign_bit reads the current interrupt status, modifies and writes the entire value back. Since, the IRQ status bit gets cleared on writing back, the better approach is to directly write the bitmask to the register in order to preserve the value. Fixes: 1f4d8ae231f4 ("misc: microchip: pci1xxxx: Add gpio irq handler and irq helper functions irq_ack, irq_mask, irq_unmask and irq_set_type of irq_chip.") Cc: stable Signed-off-by: Rengarajan S Link: https://lore.kernel.org/r/20250313170856.20868-3-rengarajan.s@microchip.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c b/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c index 88a405b72125..55b892f982e9 100644 --- a/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c +++ b/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gpio.c @@ -165,7 +165,7 @@ static void pci1xxxx_gpio_irq_ack(struct irq_data *data) unsigned long flags; spin_lock_irqsave(&priv->lock, flags); - pci1xxx_assign_bit(priv->reg_base, INTR_STAT_OFFSET(gpio), (gpio % 32), true); + writel(BIT(gpio % 32), priv->reg_base + INTR_STAT_OFFSET(gpio)); spin_unlock_irqrestore(&priv->lock, flags); } From c2af265beab7fc480880aade4fae818dba96a589 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Tue, 8 Apr 2025 19:22:47 +0200 Subject: [PATCH 481/606] serial: msm: Configure correct working mode before starting earlycon commit 7094832b5ac861b0bd7ed8866c93cb15ef619996 upstream. The MSM UART DM controller supports different working modes, e.g. DMA or the "single-character mode", where all reads/writes operate on a single character rather than 4 chars (32-bit) at once. When using earlycon, __msm_console_write() always writes 4 characters at a time, but we don't know which mode the bootloader was using and we don't set the mode either. This causes garbled output if the bootloader was using the single-character mode, because only every 4th character appears in the serial console, e.g. "[ 00oni pi 000xf0[ 00i s 5rm9(l)l s 1 1 SPMTA 7:C 5[ 00A ade k d[ 00ano:ameoi .Q1B[ 00ac _idaM00080oo'" If the bootloader was using the DMA ("DM") mode, output would likely fail entirely. Later, when the full serial driver probes, the port is re-initialized and output works as expected. Fix this also for earlycon by clearing the DMEN register and reset+re-enable the transmitter to apply the change. This ensures the transmitter is in the expected state before writing any output. Cc: stable Fixes: 0efe72963409 ("tty: serial: msm: Add earlycon support") Signed-off-by: Stephan Gerhold Reviewed-by: Neil Armstrong Link: https://lore.kernel.org/r/20250408-msm-serial-earlycon-v1-1-429080127530@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/msm_serial.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index 90953e679e38..76b6429fb9e9 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -1741,6 +1741,12 @@ msm_serial_early_console_setup_dm(struct earlycon_device *device, if (!device->port.membase) return -ENODEV; + /* Disable DM / single-character modes */ + msm_write(&device->port, 0, UARTDM_DMEN); + msm_write(&device->port, MSM_UART_CR_CMD_RESET_RX, MSM_UART_CR); + msm_write(&device->port, MSM_UART_CR_CMD_RESET_TX, MSM_UART_CR); + msm_write(&device->port, MSM_UART_CR_TX_ENABLE, MSM_UART_CR); + device->con->write = msm_serial_early_write_dm; return 0; } From 3b377f805e97be62041cfca8dba669b91ab0c882 Mon Sep 17 00:00:00 2001 From: Ryo Takakura Date: Sat, 12 Apr 2025 09:18:47 +0900 Subject: [PATCH 482/606] serial: sifive: lock port in startup()/shutdown() callbacks commit e1ca3ff28ab1e2c1e70713ef3fa7943c725742c3 upstream. startup()/shutdown() callbacks access SIFIVE_SERIAL_IE_OFFS. The register is also accessed from write() callback. If console were printing and startup()/shutdown() callback gets called, its access to the register could be overwritten. Add port->lock to startup()/shutdown() callbacks to make sure their access to SIFIVE_SERIAL_IE_OFFS is synchronized against write() callback. Fixes: 45c054d0815b ("tty: serial: add driver for the SiFive UART") Signed-off-by: Ryo Takakura Reviewed-by: Petr Mladek Cc: stable@vger.kernel.org Reviewed-by: John Ogness Rule: add Link: https://lore.kernel.org/stable/20250330003522.386632-1-ryotkkr98%40gmail.com Link: https://lore.kernel.org/r/20250412001847.183221-1-ryotkkr98@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sifive.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/tty/serial/sifive.c b/drivers/tty/serial/sifive.c index d195c5de52e7..e86b00873d0e 100644 --- a/drivers/tty/serial/sifive.c +++ b/drivers/tty/serial/sifive.c @@ -562,8 +562,11 @@ static void sifive_serial_break_ctl(struct uart_port *port, int break_state) static int sifive_serial_startup(struct uart_port *port) { struct sifive_serial_port *ssp = port_to_sifive_serial_port(port); + unsigned long flags; + uart_port_lock_irqsave(&ssp->port, &flags); __ssp_enable_rxwm(ssp); + uart_port_unlock_irqrestore(&ssp->port, flags); return 0; } @@ -571,9 +574,12 @@ static int sifive_serial_startup(struct uart_port *port) static void sifive_serial_shutdown(struct uart_port *port) { struct sifive_serial_port *ssp = port_to_sifive_serial_port(port); + unsigned long flags; + uart_port_lock_irqsave(&ssp->port, &flags); __ssp_disable_rxwm(ssp); __ssp_disable_txwm(ssp); + uart_port_unlock_irqrestore(&ssp->port, flags); } /** From c6dc3b71bd4b49a77d3345339067b5c606a26a78 Mon Sep 17 00:00:00 2001 From: Michael Ehrenreich Date: Mon, 17 Mar 2025 06:17:15 +0100 Subject: [PATCH 483/606] USB: serial: ftdi_sio: add support for Abacus Electrics Optical Probe commit b399078f882b6e5d32da18b6c696cc84b12f90d5 upstream. Abacus Electrics makes optical probes for interacting with smart meters over an optical interface. At least one version uses an FT232B chip (as detected by ftdi_sio) with a custom USB PID, which needs to be added to the list to make the device work in a plug-and-play fashion. Signed-off-by: Michael Ehrenreich Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 2 ++ drivers/usb/serial/ftdi_sio_ids.h | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index b8e2bfd42828..b583b31ea5e7 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1093,6 +1093,8 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602E_PID, 1) }, { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602E_PID, 2) }, { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602E_PID, 3) }, + /* Abacus Electrics */ + { USB_DEVICE(FTDI_VID, ABACUS_OPTICAL_PROBE_PID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 52be47d684ea..9acb6f837327 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -442,6 +442,11 @@ #define LINX_FUTURE_1_PID 0xF44B /* Linx future device */ #define LINX_FUTURE_2_PID 0xF44C /* Linx future device */ +/* + * Abacus Electrics + */ +#define ABACUS_OPTICAL_PROBE_PID 0xf458 /* ABACUS ELECTRICS Optical Probe */ + /* * Oceanic product ids */ From 51d4b23ae5e674e63bf9009508bf117c52bda702 Mon Sep 17 00:00:00 2001 From: Adam Xue Date: Mon, 14 Apr 2025 14:14:37 -0700 Subject: [PATCH 484/606] USB: serial: option: add Sierra Wireless EM9291 commit 968e1cbb1f6293c3add9607f80b5ce3d29f57583 upstream. Add Sierra Wireless EM9291. Interface 0: MBIM control 1: MBIM data 3: AT port 4: Diagnostic port T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=480 MxCh= 0 D: Ver= 2.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1199 ProdID=90e3 Rev=00.06 S: Manufacturer=Sierra Wireless, Incorporated S: Product=Sierra Wireless EM9291 S: SerialNumber=xxxxxxxxxxxxxxxx C: #Ifs= 4 Cfg#= 1 Atr=a0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=0e Prot=00 Driver=cdc_mbim E: Ad=81(I) Atr=03(Int.) MxPS= 64 Ivl=32ms I: If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim E: Ad=0f(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8e(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=(none) E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=(none) E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms Signed-off-by: Adam Xue Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index a9f95bb35bb0..5d6695116098 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -611,6 +611,7 @@ static void option_instat_callback(struct urb *urb); /* Sierra Wireless products */ #define SIERRA_VENDOR_ID 0x1199 #define SIERRA_PRODUCT_EM9191 0x90d3 +#define SIERRA_PRODUCT_EM9291 0x90e3 /* UNISOC (Spreadtrum) products */ #define UNISOC_VENDOR_ID 0x1782 @@ -2432,6 +2433,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x30) }, { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x40) }, { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0, 0) }, + { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9291, 0xff, 0xff, 0x30) }, + { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9291, 0xff, 0xff, 0x40) }, { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) }, { USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0530, 0xff), /* TCL IK512 MBIM */ From 01eeddf93a8ab5621c0cc240fadd3c05c8836f36 Mon Sep 17 00:00:00 2001 From: Craig Hesling Date: Tue, 8 Apr 2025 16:27:03 -0700 Subject: [PATCH 485/606] USB: serial: simple: add OWON HDS200 series oscilloscope support commit 4cc01410e1c1dd075df10f750775c81d1cb6672b upstream. Add serial support for OWON HDS200 series oscilloscopes and likely many other pieces of OWON test equipment. OWON HDS200 series devices host two USB endpoints, designed to facilitate bidirectional SCPI. SCPI is a predominately ASCII text protocol for test/measurement equipment. Having a serial/tty interface for these devices lowers the barrier to entry for anyone trying to write programs to communicate with them. The following shows the USB descriptor for the OWON HDS272S running firmware V5.7.1: Bus 001 Device 068: ID 5345:1234 Owon PDS6062T Oscilloscope Negotiated speed: Full Speed (12Mbps) Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 0 [unknown] bDeviceSubClass 0 [unknown] bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x5345 Owon idProduct 0x1234 PDS6062T Oscilloscope bcdDevice 1.00 iManufacturer 1 oscilloscope iProduct 2 oscilloscope iSerial 3 oscilloscope bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 0x0029 bNumInterfaces 1 bConfigurationValue 1 iConfiguration 0 bmAttributes 0x80 (Bus Powered) MaxPower 100mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 2 bInterfaceClass 5 Physical Interface Device bInterfaceSubClass 0 [unknown] bInterfaceProtocol 0 iInterface 0 ** UNRECOGNIZED: 09 21 11 01 00 01 22 5f 00 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0040 1x 64 bytes bInterval 32 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x01 EP 1 OUT bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0040 1x 64 bytes bInterval 32 Device Status: 0x0000 (Bus Powered) OWON appears to be using the same USB Vendor and Product ID for many of their oscilloscopes. Looking at the discussion about the USB vendor/product ID, in the link bellow, suggests that this VID/PID is shared with VDS, SDS, PDS, and now the HDS series oscilloscopes. Available documentation for these devices seems to indicate that all use a similar SCPI protocol, some with RS232 options. It is likely that this same simple serial setup would work correctly for them all. Link: https://usb-ids.gowdy.us/read/UD/5345/1234 Signed-off-by: Craig Hesling Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial-simple.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/serial/usb-serial-simple.c b/drivers/usb/serial/usb-serial-simple.c index 24b8772a345e..bac5ab6377ae 100644 --- a/drivers/usb/serial/usb-serial-simple.c +++ b/drivers/usb/serial/usb-serial-simple.c @@ -101,6 +101,11 @@ DEVICE(nokia, NOKIA_IDS); { USB_DEVICE(0x09d7, 0x0100) } /* NovAtel FlexPack GPS */ DEVICE_N(novatel_gps, NOVATEL_IDS, 3); +/* OWON electronic test and measurement equipment driver */ +#define OWON_IDS() \ + { USB_DEVICE(0x5345, 0x1234) } /* HDS200 oscilloscopes and others */ +DEVICE(owon, OWON_IDS); + /* Siemens USB/MPI adapter */ #define SIEMENS_IDS() \ { USB_DEVICE(0x908, 0x0004) } @@ -135,6 +140,7 @@ static struct usb_serial_driver * const serial_drivers[] = { &motorola_tetra_device, &nokia_device, &novatel_gps_device, + &owon_device, &siemens_mpi_device, &suunto_device, &vivopay_device, @@ -154,6 +160,7 @@ static const struct usb_device_id id_table[] = { MOTOROLA_TETRA_IDS(), NOKIA_IDS(), NOVATEL_IDS(), + OWON_IDS(), SIEMENS_IDS(), SUUNTO_IDS(), VIVOPAY_IDS(), From 142273a49f2c315eabdbdf5a71c15e479b75ca91 Mon Sep 17 00:00:00 2001 From: Michal Pecio Date: Thu, 10 Apr 2025 18:18:26 +0300 Subject: [PATCH 486/606] usb: xhci: Fix invalid pointer dereference in Etron workaround commit 1ea050da5562af9b930d17cbbe9632d30f5df43a upstream. This check is performed before prepare_transfer() and prepare_ring(), so enqueue can already point at the final link TRB of a segment. And indeed it will, some 0.4% of times this code is called. Then enqueue + 1 is an invalid pointer. It will crash the kernel right away or load some junk which may look like a link TRB and cause the real link TRB to be replaced with a NOOP. This wouldn't end well. Use a functionally equivalent test which doesn't dereference the pointer and always gives correct result. Something has crashed my machine twice in recent days while playing with an Etron HC, and a control transfer stress test ran for confirmation has just crashed it again. The same test passes with this patch applied. Fixes: 5e1c67abc930 ("xhci: Fix control transfer error on Etron xHCI host") Cc: stable@vger.kernel.org Signed-off-by: Michal Pecio Signed-off-by: Mathias Nyman Reviewed-by: Kuangyi Chiang Link: https://lore.kernel.org/r/20250410151828.2868740-5-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 4a081685a195..e66bb87c4217 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3876,7 +3876,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, * enqueue a No Op TRB, this can prevent the Setup and Data Stage * TRB to be breaked by the Link TRB. */ - if (trb_is_link(ep_ring->enqueue + 1)) { + if (last_trb_on_seg(ep_ring->enq_seg, ep_ring->enqueue + 1)) { field = TRB_TYPE(TRB_TR_NOOP) | ep_ring->cycle_state; queue_trb(xhci, ep_ring, false, 0, 0, TRB_INTR_TARGET(0), field); From 48a62deb857f0694f611949015e70ad194d97159 Mon Sep 17 00:00:00 2001 From: Ralph Siemsen Date: Tue, 18 Mar 2025 11:09:32 -0400 Subject: [PATCH 487/606] usb: cdns3: Fix deadlock when using NCM gadget commit a1059896f2bfdcebcdc7153c3be2307ea319501f upstream. The cdns3 driver has the same NCM deadlock as fixed in cdnsp by commit 58f2fcb3a845 ("usb: cdnsp: Fix deadlock issue during using NCM gadget"). Under PREEMPT_RT the deadlock can be readily triggered by heavy network traffic, for example using "iperf --bidir" over NCM ethernet link. The deadlock occurs because the threaded interrupt handler gets preempted by a softirq, but both are protected by the same spinlock. Prevent deadlock by disabling softirq during threaded irq handler. Cc: stable Fixes: 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver") Signed-off-by: Ralph Siemsen Acked-by: Peter Chen Reviewed-by: Sebastian Andrzej Siewior Link: https://lore.kernel.org/r/20250318-rfs-cdns3-deadlock-v2-1-bfd9cfcee732@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/cdns3/cdns3-gadget.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c index b1b46c7c63f8..05e8414c31df 100644 --- a/drivers/usb/cdns3/cdns3-gadget.c +++ b/drivers/usb/cdns3/cdns3-gadget.c @@ -1962,6 +1962,7 @@ static irqreturn_t cdns3_device_thread_irq_handler(int irq, void *data) unsigned int bit; unsigned long reg; + local_bh_disable(); spin_lock_irqsave(&priv_dev->lock, flags); reg = readl(&priv_dev->regs->usb_ists); @@ -2003,6 +2004,7 @@ static irqreturn_t cdns3_device_thread_irq_handler(int irq, void *data) irqend: writel(~0, &priv_dev->regs->ep_ien); spin_unlock_irqrestore(&priv_dev->lock, flags); + local_bh_enable(); return ret; } From 121e9f80ea5478bca3a8f3f26593fd66f87da649 Mon Sep 17 00:00:00 2001 From: Fedor Pchelkin Date: Sun, 16 Mar 2025 13:26:54 +0300 Subject: [PATCH 488/606] usb: chipidea: ci_hdrc_imx: fix usbmisc handling commit 4e28f79e3dffa52d327b46d1a78dac16efb5810b upstream. usbmisc is an optional device property so it is totally valid for the corresponding data->usbmisc_data to have a NULL value. Check that before dereferencing the pointer. Found by Linux Verification Center (linuxtesting.org) with Svace static analysis tool. Fixes: 74adad500346 ("usb: chipidea: ci_hdrc_imx: decrement device's refcount in .remove() and in the error path of .probe()") Cc: stable Signed-off-by: Fedor Pchelkin Acked-by: Peter Chen Link: https://lore.kernel.org/r/20250316102658.490340-2-pchelkin@ispras.ru Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/ci_hdrc_imx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index b3cbca361a96..1a050bdf7bdb 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c @@ -520,7 +520,8 @@ disable_hsic_regulator: cpu_latency_qos_remove_request(&data->pm_qos_req); data->ci_pdev = NULL; err_put: - put_device(data->usbmisc_data->dev); + if (data->usbmisc_data) + put_device(data->usbmisc_data->dev); return ret; } @@ -544,7 +545,8 @@ static void ci_hdrc_imx_remove(struct platform_device *pdev) if (data->hsic_pad_regulator) regulator_disable(data->hsic_pad_regulator); } - put_device(data->usbmisc_data->dev); + if (data->usbmisc_data) + put_device(data->usbmisc_data->dev); } static void ci_hdrc_imx_shutdown(struct platform_device *pdev) From 15120673da696621936b85a84ea46ba1f45b9a02 Mon Sep 17 00:00:00 2001 From: Fedor Pchelkin Date: Sun, 16 Mar 2025 13:26:55 +0300 Subject: [PATCH 489/606] usb: chipidea: ci_hdrc_imx: fix call balance of regulator routines commit 8cab0e9a3f3e8d700179e0d6141643d54a267fd5 upstream. Upon encountering errors during the HSIC pinctrl handling section the regulator should be disabled. Use devm_add_action_or_reset() to let the regulator-disabling routine be handled by device resource management stack. Found by Linux Verification Center (linuxtesting.org). Fixes: 4d6141288c33 ("usb: chipidea: imx: pinctrl for HSIC is optional") Cc: stable Signed-off-by: Fedor Pchelkin Acked-by: Peter Chen Link: https://lore.kernel.org/r/20250316102658.490340-3-pchelkin@ispras.ru Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/ci_hdrc_imx.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index 1a050bdf7bdb..4e495c94d79c 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c @@ -328,6 +328,13 @@ static int ci_hdrc_imx_notify_event(struct ci_hdrc *ci, unsigned int event) return ret; } +static void ci_hdrc_imx_disable_regulator(void *arg) +{ + struct ci_hdrc_imx_data *data = arg; + + regulator_disable(data->hsic_pad_regulator); +} + static int ci_hdrc_imx_probe(struct platform_device *pdev) { struct ci_hdrc_imx_data *data; @@ -386,6 +393,13 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) "Failed to enable HSIC pad regulator\n"); goto err_put; } + ret = devm_add_action_or_reset(dev, + ci_hdrc_imx_disable_regulator, data); + if (ret) { + dev_err(dev, + "Failed to add regulator devm action\n"); + goto err_put; + } } } @@ -424,11 +438,11 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) ret = imx_get_clks(dev); if (ret) - goto disable_hsic_regulator; + goto qos_remove_request; ret = imx_prepare_enable_clks(dev); if (ret) - goto disable_hsic_regulator; + goto qos_remove_request; data->phy = devm_usb_get_phy_by_phandle(dev, "fsl,usbphy", 0); if (IS_ERR(data->phy)) { @@ -512,10 +526,7 @@ disable_device: ci_hdrc_remove_device(data->ci_pdev); err_clk: imx_disable_unprepare_clks(dev); -disable_hsic_regulator: - if (data->hsic_pad_regulator) - /* don't overwrite original ret (cf. EPROBE_DEFER) */ - regulator_disable(data->hsic_pad_regulator); +qos_remove_request: if (pdata.flags & CI_HDRC_PMQOS) cpu_latency_qos_remove_request(&data->pm_qos_req); data->ci_pdev = NULL; @@ -542,8 +553,6 @@ static void ci_hdrc_imx_remove(struct platform_device *pdev) imx_disable_unprepare_clks(&pdev->dev); if (data->plat_data->flags & CI_HDRC_PMQOS) cpu_latency_qos_remove_request(&data->pm_qos_req); - if (data->hsic_pad_regulator) - regulator_disable(data->hsic_pad_regulator); } if (data->usbmisc_data) put_device(data->usbmisc_data->dev); From 23d4bb3b06989b3902be28d48c0043511bbb5f61 Mon Sep 17 00:00:00 2001 From: Fedor Pchelkin Date: Sun, 16 Mar 2025 13:26:56 +0300 Subject: [PATCH 490/606] usb: chipidea: ci_hdrc_imx: implement usb_phy_init() error handling commit 8c531e0a8c2d82509ad97c6d3a1e6217c7ed136d upstream. usb_phy_init() may return an error code if e.g. its implementation fails to prepare/enable some clocks. And properly rollback on probe error path by calling the counterpart usb_phy_shutdown(). Found by Linux Verification Center (linuxtesting.org). Fixes: be9cae2479f4 ("usb: chipidea: imx: Fix ULPI on imx53") Cc: stable Signed-off-by: Fedor Pchelkin Acked-by: Peter Chen Link: https://lore.kernel.org/r/20250316102658.490340-4-pchelkin@ispras.ru Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/ci_hdrc_imx.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index 4e495c94d79c..73d5b9466676 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c @@ -472,7 +472,11 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI) { pdata.flags |= CI_HDRC_OVERRIDE_PHY_CONTROL; data->override_phy_control = true; - usb_phy_init(pdata.usb_phy); + ret = usb_phy_init(pdata.usb_phy); + if (ret) { + dev_err(dev, "Failed to init phy\n"); + goto err_clk; + } } if (pdata.flags & CI_HDRC_SUPPORTS_RUNTIME_PM) @@ -481,7 +485,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) ret = imx_usbmisc_init(data->usbmisc_data); if (ret) { dev_err(dev, "usbmisc init failed, ret=%d\n", ret); - goto err_clk; + goto phy_shutdown; } data->ci_pdev = ci_hdrc_add_device(dev, @@ -490,7 +494,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) if (IS_ERR(data->ci_pdev)) { ret = PTR_ERR(data->ci_pdev); dev_err_probe(dev, ret, "ci_hdrc_add_device failed\n"); - goto err_clk; + goto phy_shutdown; } if (data->usbmisc_data) { @@ -524,6 +528,9 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) disable_device: ci_hdrc_remove_device(data->ci_pdev); +phy_shutdown: + if (data->override_phy_control) + usb_phy_shutdown(data->phy); err_clk: imx_disable_unprepare_clks(dev); qos_remove_request: From 6a91a198cd30cf79b65878459a23ba372d8d86de Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Fri, 28 Mar 2025 12:00:59 +0800 Subject: [PATCH 491/606] USB: OHCI: Add quirk for LS7A OHCI controller (rev 0x02) commit bcb60d438547355b8f9ad48645909139b64d3482 upstream. The OHCI controller (rev 0x02) under LS7A PCI host has a hardware flaw. MMIO register with offset 0x60/0x64 is treated as legacy PS2-compatible keyboard/mouse interface, which confuse the OHCI controller. Since OHCI only use a 4KB BAR resource indeed, the LS7A OHCI controller's 32KB BAR is wrapped around (the second 4KB BAR space is the same as the first 4KB internally). So we can add an 4KB offset (0x1000) to the OHCI registers (from the PCI BAR resource) as a quirk. Cc: stable Suggested-by: Bjorn Helgaas Reviewed-by: Alan Stern Tested-by: Mingcong Bai Signed-off-by: Huacai Chen Link: https://lore.kernel.org/r/20250328040059.3672979-1-chenhuacai@loongson.cn Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-pci.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 900ea0d368e0..9f0a6b27e47c 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -165,6 +165,25 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd) return 0; } +static int ohci_quirk_loongson(struct usb_hcd *hcd) +{ + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); + + /* + * Loongson's LS7A OHCI controller (rev 0x02) has a + * flaw. MMIO register with offset 0x60/64 is treated + * as legacy PS2-compatible keyboard/mouse interface. + * Since OHCI only use 4KB BAR resource, LS7A OHCI's + * 32KB BAR is wrapped around (the 2nd 4KB BAR space + * is the same as the 1st 4KB internally). So add 4KB + * offset (0x1000) to the OHCI registers as a quirk. + */ + if (pdev->revision == 0x2) + hcd->regs += SZ_4K; /* SZ_4K = 0x1000 */ + + return 0; +} + static int ohci_quirk_qemu(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); @@ -224,6 +243,10 @@ static const struct pci_device_id ohci_pci_quirks[] = { PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399), .driver_data = (unsigned long)ohci_quirk_amd700, }, + { + PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, 0x7a24), + .driver_data = (unsigned long)ohci_quirk_loongson, + }, { .vendor = PCI_VENDOR_ID_APPLE, .device = 0x003f, From c4d80e41cb42008dceb35e5dbf52574d93beac0d Mon Sep 17 00:00:00 2001 From: Frode Isaksen Date: Thu, 3 Apr 2025 09:28:03 +0200 Subject: [PATCH 492/606] usb: dwc3: gadget: check that event count does not exceed event buffer length commit 63ccd26cd1f6600421795f6ca3e625076be06c9f upstream. The event count is read from register DWC3_GEVNTCOUNT. There is a check for the count being zero, but not for exceeding the event buffer length. Check that event count does not exceed event buffer length, avoiding an out-of-bounds access when memcpy'ing the event. Crash log: Unable to handle kernel paging request at virtual address ffffffc0129be000 pc : __memcpy+0x114/0x180 lr : dwc3_check_event_buf+0xec/0x348 x3 : 0000000000000030 x2 : 000000000000dfc4 x1 : ffffffc0129be000 x0 : ffffff87aad60080 Call trace: __memcpy+0x114/0x180 dwc3_interrupt+0x24/0x34 Signed-off-by: Frode Isaksen Fixes: 72246da40f37 ("usb: Introduce DesignWare USB3 DRD Driver") Cc: stable Acked-by: Thinh Nguyen Link: https://lore.kernel.org/r/20250403072907.448524-1-fisaksen@baylibre.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/gadget.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index fdaace1564f9..8b2292420581 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -4570,6 +4570,12 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt) if (!count) return IRQ_NONE; + if (count > evt->length) { + dev_err_ratelimited(dwc->dev, "invalid count(%u) > evt->length(%u)\n", + count, evt->length); + return IRQ_NONE; + } + evt->count = count; evt->flags |= DWC3_EVENT_PENDING; From 127b6aba32d84a1e12104c86747af2249c836bda Mon Sep 17 00:00:00 2001 From: Mike Looijmans Date: Tue, 18 Mar 2025 07:44:52 +0100 Subject: [PATCH 493/606] usb: dwc3: xilinx: Prevent spike in reset signal commit 38d6e60b6f3a99f8f13bee22eab616136c2c0675 upstream. The "reset" GPIO controls the RESET signal to an external, usually ULPI PHY, chip. The original code path acquires the signal in LOW state, and then immediately asserts it HIGH again, if the reset signal defaulted to asserted, there'd be a short "spike" before the reset. Here is what happens depending on the pre-existing state of the reset signal: Reset (previously asserted): ~~~|_|~~~~|_______ Reset (previously deasserted): _____|~~~~|_______ ^ ^ ^ A B C At point A, the low going transition is because the reset line is requested using GPIOD_OUT_LOW. If the line is successfully requested, the first thing we do is set it high _without_ any delay. This is point B. So, a glitch occurs between A and B. Requesting the line using GPIOD_OUT_HIGH eliminates the A and B transitions. Instead we get: Reset (previously asserted) : ~~~~~~~~~~|______ Reset (previously deasserted): ____|~~~~~|______ ^ ^ A C Where A and C are the points described above in the code. Point B has been eliminated. The issue was found during code inspection. Also remove the cryptic "toggle ulpi .." comment. Fixes: ca05b38252d7 ("usb: dwc3: xilinx: Add gpio-reset support") Cc: stable Signed-off-by: Mike Looijmans Reviewed-by: Radhey Shyam Pandey Acked-by: Thinh Nguyen Link: https://lore.kernel.org/r/20250318064518.9320-1-mike.looijmans@topic.nl Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/dwc3-xilinx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c index d19a5d2d65ad..ae30aa50a582 100644 --- a/drivers/usb/dwc3/dwc3-xilinx.c +++ b/drivers/usb/dwc3/dwc3-xilinx.c @@ -207,15 +207,13 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data) skip_usb3_phy: /* ulpi reset via gpio-modepin or gpio-framework driver */ - reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); + reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(reset_gpio)) { return dev_err_probe(dev, PTR_ERR(reset_gpio), "Failed to request reset GPIO\n"); } if (reset_gpio) { - /* Toggle ulpi to reset the phy. */ - gpiod_set_value_cansleep(reset_gpio, 1); usleep_range(5000, 10000); gpiod_set_value_cansleep(reset_gpio, 0); usleep_range(5000, 10000); From 57beab8ea4ffdbf025a475fc66ab6d360fbdff26 Mon Sep 17 00:00:00 2001 From: Miao Li Date: Tue, 1 Apr 2025 10:30:27 +0800 Subject: [PATCH 494/606] usb: quirks: add DELAY_INIT quirk for Silicon Motion Flash Drive commit 2932b6b547ec36ad2ed60fbf2117c0e46bb7d40a upstream. Silicon Motion Flash Drive connects to Huawei hisi platforms and performs a system reboot test for two thousand circles, it will randomly work incorrectly on boot, set DELAY_INIT quirk can workaround this issue. Signed-off-by: Miao Li Cc: stable Link: https://lore.kernel.org/r/20250401023027.44894-1-limiao870622@163.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/quirks.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 6926bd639ec6..e500ecf08f1d 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -383,6 +383,9 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x0904, 0x6103), .driver_info = USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL }, + /* Silicon Motion Flash Drive */ + { USB_DEVICE(0x090c, 0x1000), .driver_info = USB_QUIRK_DELAY_INIT }, + /* Sound Devices USBPre2 */ { USB_DEVICE(0x0926, 0x0202), .driver_info = USB_QUIRK_ENDPOINT_IGNORE }, From 097d3c27f871de2c937fdd81fc2cef4ec6c62909 Mon Sep 17 00:00:00 2001 From: Miao Li Date: Mon, 14 Apr 2025 14:29:35 +0800 Subject: [PATCH 495/606] usb: quirks: Add delay init quirk for SanDisk 3.2Gen1 Flash Drive commit 37ffdbd695c02189dbf23d6e7d2385e0299587ca upstream. The SanDisk 3.2Gen1 Flash Drive, which VID:PID is in 0781:55a3, just like Silicon Motion Flash Drive: https://lore.kernel.org/r/20250401023027.44894-1-limiao870622@163.com also needs the DELAY_INIT quirk, or it will randomly work incorrectly (e.g.: lsusb and can't list this device info) when connecting Huawei hisi platforms and doing thousand of reboot test circles. Cc: stable Signed-off-by: Miao Li Signed-off-by: Lei Huang Link: https://lore.kernel.org/r/20250414062935.159024-1-limiao870622@163.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/quirks.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index e500ecf08f1d..3a2484b07d8d 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -369,6 +369,9 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x0781, 0x5583), .driver_info = USB_QUIRK_NO_LPM }, { USB_DEVICE(0x0781, 0x5591), .driver_info = USB_QUIRK_NO_LPM }, + /* SanDisk Corp. SanDisk 3.2Gen1 */ + { USB_DEVICE(0x0781, 0x55a3), .driver_info = USB_QUIRK_DELAY_INIT }, + /* Realforce 87U Keyboard */ { USB_DEVICE(0x0853, 0x011b), .driver_info = USB_QUIRK_NO_LPM }, From e455bf315eee146d200541c0fe175010f4d0b558 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 8 Apr 2025 15:57:46 +0200 Subject: [PATCH 496/606] USB: VLI disk crashes if LPM is used commit e00b39a4f3552c730f1e24c8d62c4a8c6aad4e5d upstream. This device needs the NO_LPM quirk. Cc: stable Signed-off-by: Oliver Neukum Link: https://lore.kernel.org/r/20250408135800.792515-1-oneukum@suse.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/quirks.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 3a2484b07d8d..4903c733d37a 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -542,6 +542,9 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x2040, 0x7200), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, + /* VLI disk */ + { USB_DEVICE(0x2109, 0x0711), .driver_info = USB_QUIRK_NO_LPM }, + /* Raydium Touchscreen */ { USB_DEVICE(0x2386, 0x3114), .driver_info = USB_QUIRK_NO_LPM }, From 8312053acc99e27ed705a672446b0fde15ac91fe Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 1 Apr 2025 10:45:38 +0200 Subject: [PATCH 497/606] USB: wdm: handle IO errors in wdm_wwan_port_start commit 9697f5efcf5fdea65b8390b5eb81bebe746ceedc upstream. In case submitting the URB fails we must undo what we've done so far. Fixes: cac6fb015f71 ("usb: class: cdc-wdm: WWAN framework integration") Cc: stable Signed-off-by: Oliver Neukum Link: https://lore.kernel.org/r/20250401084749.175246-2-oneukum@suse.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 6830be4419e2..2be1dc906514 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -829,6 +829,7 @@ static struct usb_class_driver wdm_class = { static int wdm_wwan_port_start(struct wwan_port *port) { struct wdm_device *desc = wwan_port_get_drvdata(port); + int rv; /* The interface is both exposed via the WWAN framework and as a * legacy usbmisc chardev. If chardev is already open, just fail @@ -848,7 +849,15 @@ static int wdm_wwan_port_start(struct wwan_port *port) wwan_port_txon(port); /* Start getting events */ - return usb_submit_urb(desc->validity, GFP_KERNEL); + rv = usb_submit_urb(desc->validity, GFP_KERNEL); + if (rv < 0) { + wwan_port_txoff(port); + desc->manage_power(desc->intf, 0); + /* this must be last lest we race with chardev open */ + clear_bit(WDM_WWAN_IN_USE, &desc->flags); + } + + return rv; } static void wdm_wwan_port_stop(struct wwan_port *port) From 54f7f8978af19f899dec80bcc71c8d4855dfbd72 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 1 Apr 2025 10:45:39 +0200 Subject: [PATCH 498/606] USB: wdm: close race between wdm_open and wdm_wwan_port_stop commit c1846ed4eb527bdfe6b3b7dd2c78e2af4bf98f4f upstream. Clearing WDM_WWAN_IN_USE must be the last action or we can open a chardev whose URBs are still poisoned Fixes: cac6fb015f71 ("usb: class: cdc-wdm: WWAN framework integration") Cc: stable Signed-off-by: Oliver Neukum Link: https://lore.kernel.org/r/20250401084749.175246-3-oneukum@suse.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 2be1dc906514..5da3eb10bbaa 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -726,7 +726,7 @@ static int wdm_open(struct inode *inode, struct file *file) rv = -EBUSY; goto out; } - + smp_rmb(); /* ordered against wdm_wwan_port_stop() */ rv = usb_autopm_get_interface(desc->intf); if (rv < 0) { dev_err(&desc->intf->dev, "Error autopm - %d\n", rv); @@ -868,8 +868,10 @@ static void wdm_wwan_port_stop(struct wwan_port *port) poison_urbs(desc); desc->manage_power(desc->intf, 0); clear_bit(WDM_READ, &desc->flags); - clear_bit(WDM_WWAN_IN_USE, &desc->flags); unpoison_urbs(desc); + smp_wmb(); /* ordered against wdm_open() */ + /* this must be last lest we open a poisoned device */ + clear_bit(WDM_WWAN_IN_USE, &desc->flags); } static void wdm_wwan_port_tx_complete(struct urb *urb) From 4b0369c53088c2ca2c94b9cc5d843a059456467e Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 1 Apr 2025 10:45:40 +0200 Subject: [PATCH 499/606] USB: wdm: wdm_wwan_port_tx_complete mutex in atomic context commit 1fdc4dca350c0b8ada0b8ebf212504e1ad55e511 upstream. wdm_wwan_port_tx_complete is called from a completion handler with irqs disabled and possible in IRQ context usb_autopm_put_interface can take a mutex. Hence usb_autopm_put_interface_async must be used. Fixes: cac6fb015f71 ("usb: class: cdc-wdm: WWAN framework integration") Cc: stable Signed-off-by: Oliver Neukum Link: https://lore.kernel.org/r/20250401084749.175246-4-oneukum@suse.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 5da3eb10bbaa..52a25e80e4c3 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -879,7 +879,7 @@ static void wdm_wwan_port_tx_complete(struct urb *urb) struct sk_buff *skb = urb->context; struct wdm_device *desc = skb_shinfo(skb)->destructor_arg; - usb_autopm_put_interface(desc->intf); + usb_autopm_put_interface_async(desc->intf); wwan_port_txon(desc->wwanp); kfree_skb(skb); } From 9c97886f80854d1ea2453bfeddebc3ff11f89a39 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 1 Apr 2025 10:45:41 +0200 Subject: [PATCH 500/606] USB: wdm: add annotation commit 73e9cc1ffd3650b12c4eb059dfdafd56e725ceda upstream. This is not understandable without a comment on endianness Fixes: afba937e540c9 ("USB: CDC WDM driver") Cc: stable Signed-off-by: Oliver Neukum Link: https://lore.kernel.org/r/20250401084749.175246-5-oneukum@suse.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 52a25e80e4c3..559c121f0923 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -909,7 +909,7 @@ static int wdm_wwan_port_tx(struct wwan_port *port, struct sk_buff *skb) req->bRequestType = (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE); req->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND; req->wValue = 0; - req->wIndex = desc->inum; + req->wIndex = desc->inum; /* already converted */ req->wLength = cpu_to_le16(skb->len); skb_shinfo(skb)->destructor_arg = desc; From 979ba0d694ea431d5b84f56fd935c3e27df15ec4 Mon Sep 17 00:00:00 2001 From: Chenyuan Yang Date: Mon, 10 Feb 2025 17:25:52 -0600 Subject: [PATCH 501/606] pinctrl: renesas: rza2: Fix potential NULL pointer dereference [ Upstream commit f752ee5b5b86b5f88a5687c9eb0ef9b39859b908 ] `chip.label` in rza2_gpio_register() could be NULL. Add the missing check. Signed-off-by: Chenyuan Yang Reviewed-by: Geert Uytterhoeven Reviewed-by: Matthias Brugger Link: https://lore.kernel.org/20250210232552.1545887-1-chenyuan0y@gmail.com Signed-off-by: Geert Uytterhoeven Signed-off-by: Sasha Levin --- drivers/pinctrl/renesas/pinctrl-rza2.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/pinctrl/renesas/pinctrl-rza2.c b/drivers/pinctrl/renesas/pinctrl-rza2.c index c5d733216508..df660b7e1300 100644 --- a/drivers/pinctrl/renesas/pinctrl-rza2.c +++ b/drivers/pinctrl/renesas/pinctrl-rza2.c @@ -243,6 +243,9 @@ static int rza2_gpio_register(struct rza2_pinctrl_priv *priv) int ret; chip.label = devm_kasprintf(priv->dev, GFP_KERNEL, "%pOFn", np); + if (!chip.label) + return -ENOMEM; + chip.parent = priv->dev; chip.ngpio = priv->npins; From 02f53b8f2ffc125b51c12dc8d9be96874b7f8ac5 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Thu, 23 Jan 2025 12:01:56 +0100 Subject: [PATCH 502/606] MIPS: cm: Detect CM quirks from device tree [ Upstream commit e27fbe16af5cfc40639de4ced67d1a866a1953e9 ] Some information that should be retrieved at runtime for the Coherence Manager can be either absent or wrong. This patch allows checking if some of this information is available from the device tree and updates the internal variable accordingly. For now, only the compatible string associated with the broken HCI is being retrieved. Signed-off-by: Gregory CLEMENT Signed-off-by: Thomas Bogendoerfer Signed-off-by: Sasha Levin --- arch/mips/include/asm/mips-cm.h | 22 ++++++++++++++++++++++ arch/mips/kernel/mips-cm.c | 14 ++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index 696b40beb774..0f31324998c0 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -47,6 +47,16 @@ extern phys_addr_t __mips_cm_phys_base(void); */ extern int mips_cm_is64; +/* + * mips_cm_is_l2_hci_broken - determine if HCI is broken + * + * Some CM reports show that Hardware Cache Initialization is + * complete, but in reality it's not the case. They also incorrectly + * indicate that Hardware Cache Initialization is supported. This + * flags allows warning about this broken feature. + */ +extern bool mips_cm_is_l2_hci_broken; + /** * mips_cm_error_report - Report CM cache errors */ @@ -85,6 +95,18 @@ static inline bool mips_cm_present(void) #endif } +/** + * mips_cm_update_property - update property from the device tree + * + * Retrieve the properties from the device tree if a CM node exist and + * update the internal variable based on this. + */ +#ifdef CONFIG_MIPS_CM +extern void mips_cm_update_property(void); +#else +static void mips_cm_update_property(void) {} +#endif + /** * mips_cm_has_l2sync - determine whether an L2-only sync region is present * diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c index 3f00788b0871..4f75160f0894 100644 --- a/arch/mips/kernel/mips-cm.c +++ b/arch/mips/kernel/mips-cm.c @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -14,6 +15,7 @@ void __iomem *mips_gcr_base; void __iomem *mips_cm_l2sync_base; int mips_cm_is64; +bool mips_cm_is_l2_hci_broken; static char *cm2_tr[8] = { "mem", "gcr", "gic", "mmio", @@ -243,6 +245,18 @@ static void mips_cm_probe_l2sync(void) mips_cm_l2sync_base = ioremap(addr, MIPS_CM_L2SYNC_SIZE); } +void mips_cm_update_property(void) +{ + struct device_node *cm_node; + + cm_node = of_find_compatible_node(of_root, NULL, "mobileye,eyeq6-cm"); + if (!cm_node) + return; + pr_info("HCI (Hardware Cache Init for the L2 cache) in GCR_L2_RAM_CONFIG from the CM3 is broken"); + mips_cm_is_l2_hci_broken = true; + of_node_put(cm_node); +} + int mips_cm_probe(void) { phys_addr_t addr; From d999b11302c4b44e9d04233fc4fd8f1749863ee0 Mon Sep 17 00:00:00 2001 From: Devaraj Rangasamy Date: Fri, 7 Feb 2025 03:41:52 +0530 Subject: [PATCH 503/606] crypto: ccp - Add support for PCI device 0x1134 [ Upstream commit 6cb345939b8cc4be79909875276aa9dc87d16757 ] PCI device 0x1134 shares same register features as PCI device 0x17E0. Hence reuse same data for the new PCI device ID 0x1134. Signed-off-by: Devaraj Rangasamy Acked-by: Tom Lendacky Reviewed-by: Mario Limonciello Signed-off-by: Herbert Xu Signed-off-by: Sasha Levin --- drivers/crypto/ccp/sp-pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c index 0caa57dafc52..b1e60542351a 100644 --- a/drivers/crypto/ccp/sp-pci.c +++ b/drivers/crypto/ccp/sp-pci.c @@ -577,6 +577,7 @@ static const struct pci_device_id sp_pci_table[] = { { PCI_VDEVICE(AMD, 0x14CA), (kernel_ulong_t)&dev_vdata[5] }, { PCI_VDEVICE(AMD, 0x15C7), (kernel_ulong_t)&dev_vdata[6] }, { PCI_VDEVICE(AMD, 0x1649), (kernel_ulong_t)&dev_vdata[6] }, + { PCI_VDEVICE(AMD, 0x1134), (kernel_ulong_t)&dev_vdata[7] }, { PCI_VDEVICE(AMD, 0x17E0), (kernel_ulong_t)&dev_vdata[7] }, { PCI_VDEVICE(AMD, 0x156E), (kernel_ulong_t)&dev_vdata[8] }, /* Last entry must be zero */ From 1b66a5920b7fc7cc6251192a3fcad115b6d75dd5 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 12 Feb 2025 14:10:07 +0800 Subject: [PATCH 504/606] crypto: null - Use spin lock instead of mutex [ Upstream commit dcc47a028c24e793ce6d6efebfef1a1e92f80297 ] As the null algorithm may be freed in softirq context through af_alg, use spin locks instead of mutexes to protect the default null algorithm. Reported-by: syzbot+b3e02953598f447d4d2a@syzkaller.appspotmail.com Signed-off-by: Herbert Xu Signed-off-by: Sasha Levin --- crypto/crypto_null.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/crypto/crypto_null.c b/crypto/crypto_null.c index 5b84b0f7cc17..337867028653 100644 --- a/crypto/crypto_null.c +++ b/crypto/crypto_null.c @@ -17,10 +17,10 @@ #include #include #include -#include +#include #include -static DEFINE_MUTEX(crypto_default_null_skcipher_lock); +static DEFINE_SPINLOCK(crypto_default_null_skcipher_lock); static struct crypto_sync_skcipher *crypto_default_null_skcipher; static int crypto_default_null_skcipher_refcnt; @@ -152,23 +152,32 @@ MODULE_ALIAS_CRYPTO("cipher_null"); struct crypto_sync_skcipher *crypto_get_default_null_skcipher(void) { + struct crypto_sync_skcipher *ntfm = NULL; struct crypto_sync_skcipher *tfm; - mutex_lock(&crypto_default_null_skcipher_lock); + spin_lock_bh(&crypto_default_null_skcipher_lock); tfm = crypto_default_null_skcipher; if (!tfm) { - tfm = crypto_alloc_sync_skcipher("ecb(cipher_null)", 0, 0); - if (IS_ERR(tfm)) - goto unlock; + spin_unlock_bh(&crypto_default_null_skcipher_lock); - crypto_default_null_skcipher = tfm; + ntfm = crypto_alloc_sync_skcipher("ecb(cipher_null)", 0, 0); + if (IS_ERR(ntfm)) + return ntfm; + + spin_lock_bh(&crypto_default_null_skcipher_lock); + tfm = crypto_default_null_skcipher; + if (!tfm) { + tfm = ntfm; + ntfm = NULL; + crypto_default_null_skcipher = tfm; + } } crypto_default_null_skcipher_refcnt++; + spin_unlock_bh(&crypto_default_null_skcipher_lock); -unlock: - mutex_unlock(&crypto_default_null_skcipher_lock); + crypto_free_sync_skcipher(ntfm); return tfm; } @@ -176,12 +185,16 @@ EXPORT_SYMBOL_GPL(crypto_get_default_null_skcipher); void crypto_put_default_null_skcipher(void) { - mutex_lock(&crypto_default_null_skcipher_lock); + struct crypto_sync_skcipher *tfm = NULL; + + spin_lock_bh(&crypto_default_null_skcipher_lock); if (!--crypto_default_null_skcipher_refcnt) { - crypto_free_sync_skcipher(crypto_default_null_skcipher); + tfm = crypto_default_null_skcipher; crypto_default_null_skcipher = NULL; } - mutex_unlock(&crypto_default_null_skcipher_lock); + spin_unlock_bh(&crypto_default_null_skcipher_lock); + + crypto_free_sync_skcipher(tfm); } EXPORT_SYMBOL_GPL(crypto_put_default_null_skcipher); From b5a528a34e1f613565115a7a6016862ccbfcb9ac Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Mon, 24 Feb 2025 14:16:37 -0800 Subject: [PATCH 505/606] bpf: Fix deadlock between rcu_tasks_trace and event_mutex. [ Upstream commit 4580f4e0ebdf8dc8d506ae926b88510395a0c1d1 ] Fix the following deadlock: CPU A _free_event() perf_kprobe_destroy() mutex_lock(&event_mutex) perf_trace_event_unreg() synchronize_rcu_tasks_trace() There are several paths where _free_event() grabs event_mutex and calls sync_rcu_tasks_trace. Above is one such case. CPU B bpf_prog_test_run_syscall() rcu_read_lock_trace() bpf_prog_run_pin_on_cpu() bpf_prog_load() bpf_tracing_func_proto() trace_set_clr_event() mutex_lock(&event_mutex) Delegate trace_set_clr_event() to workqueue to avoid such lock dependency. Signed-off-by: Alexei Starovoitov Signed-off-by: Andrii Nakryiko Acked-by: Andrii Nakryiko Link: https://lore.kernel.org/bpf/20250224221637.4780-1-alexei.starovoitov@gmail.com Signed-off-by: Sasha Levin --- kernel/trace/bpf_trace.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 545393601be8..97f660a8ddc7 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -400,7 +400,7 @@ static const struct bpf_func_proto bpf_trace_printk_proto = { .arg2_type = ARG_CONST_SIZE, }; -static void __set_printk_clr_event(void) +static void __set_printk_clr_event(struct work_struct *work) { /* * This program might be calling bpf_trace_printk, @@ -413,10 +413,11 @@ static void __set_printk_clr_event(void) if (trace_set_clr_event("bpf_trace", "bpf_trace_printk", 1)) pr_warn_ratelimited("could not enable bpf_trace_printk events"); } +static DECLARE_WORK(set_printk_work, __set_printk_clr_event); const struct bpf_func_proto *bpf_get_trace_printk_proto(void) { - __set_printk_clr_event(); + schedule_work(&set_printk_work); return &bpf_trace_printk_proto; } @@ -459,7 +460,7 @@ static const struct bpf_func_proto bpf_trace_vprintk_proto = { const struct bpf_func_proto *bpf_get_trace_vprintk_proto(void) { - __set_printk_clr_event(); + schedule_work(&set_printk_work); return &bpf_trace_vprintk_proto; } From 51ae5b7aa96c0d6c08831c99dad6cedeb3195983 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Sat, 22 Feb 2025 23:37:33 +0100 Subject: [PATCH 506/606] clk: check for disabled clock-provider in of_clk_get_hw_from_clkspec() [ Upstream commit b20150d499b3ee5c2d632fbc5ac94f98dd33accf ] of_clk_get_hw_from_clkspec() checks all available clock-providers by comparing their of nodes to the one from the clkspec. If no matching clock provider is found, the function returns -EPROBE_DEFER to cause a re-check at a later date. If a matching clock provider is found, an authoritative answer can be retrieved from it whether the clock exists or not. This does not take into account that the clock-provider may never appear, because it's node is disabled. This can happen when a clock is optional, provided by a separate block which never gets enabled. One example of this happening is the rk3588's VOP, which has optional additional display clocks coming from PLLs inside the hdmiphy blocks. These can be used for better rates, but the system will also work without them. The problem around that is described in the followups to[1]. As we already know the of node of the presumed clock provider, add a check via of_device_is_available() whether this is a "valid" device node. This prevents eternal defer loops. Link: https://lore.kernel.org/dri-devel/20250215-vop2-hdmi1-disp-modes-v1-3-81962a7151d6@collabora.com/ [1] Reviewed-by: Sebastian Reichel Tested-by: Cristian Ciocaltea Signed-off-by: Heiko Stuebner Link: https://lore.kernel.org/r/20250222223733.2990179-1-heiko@sntech.de [sboyd@kernel.org: Reword commit text a bit] Signed-off-by: Stephen Boyd Signed-off-by: Sasha Levin --- drivers/clk/clk.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 5bbd036f5295..8474099e2cac 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -5216,6 +5216,10 @@ of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec) if (!clkspec) return ERR_PTR(-EINVAL); + /* Check if node in clkspec is in disabled/fail state */ + if (!of_device_is_available(clkspec->np)) + return ERR_PTR(-ENOENT); + mutex_lock(&of_clk_mutex); list_for_each_entry(provider, &of_clk_providers, link) { if (provider->node == clkspec->np) { From 96eab3c96a24268d1a98838dbe27d2a567aaf9e0 Mon Sep 17 00:00:00 2001 From: Yu-Chun Lin Date: Sun, 9 Feb 2025 01:43:04 +0800 Subject: [PATCH 507/606] parisc: PDT: Fix missing prototype warning [ Upstream commit b899981750dcb958ceffa4462d903963ee494aa2 ] As reported by the kernel test robot, the following error occurs: arch/parisc/kernel/pdt.c:65:6: warning: no previous prototype for 'arch_report_meminfo' [-Wmissing-prototypes] 65 | void arch_report_meminfo(struct seq_file *m) | ^~~~~~~~~~~~~~~~~~~ arch_report_meminfo() is declared in include/linux/proc_fs.h and only defined when CONFIG_PROC_FS is enabled. Wrap its definition in #ifdef CONFIG_PROC_FS to fix the -Wmissing-prototypes warning. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202502082315.IPaHaTyM-lkp@intel.com/ Signed-off-by: Yu-Chun Lin Signed-off-by: Helge Deller Signed-off-by: Sasha Levin --- arch/parisc/kernel/pdt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/parisc/kernel/pdt.c b/arch/parisc/kernel/pdt.c index 0f9b3b5914cf..b70b67adb855 100644 --- a/arch/parisc/kernel/pdt.c +++ b/arch/parisc/kernel/pdt.c @@ -63,6 +63,7 @@ static unsigned long pdt_entry[MAX_PDT_ENTRIES] __page_aligned_bss; #define PDT_ADDR_PERM_ERR (pdt_type != PDT_PDC ? 2UL : 0UL) #define PDT_ADDR_SINGLE_ERR 1UL +#ifdef CONFIG_PROC_FS /* report PDT entries via /proc/meminfo */ void arch_report_meminfo(struct seq_file *m) { @@ -74,6 +75,7 @@ void arch_report_meminfo(struct seq_file *m) seq_printf(m, "PDT_cur_entries: %7lu\n", pdt_status.pdt_entries); } +#endif static int get_info_pat_new(void) { From 28e5a867aa542e369e211c2baba7044228809a99 Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Tue, 18 Feb 2025 10:52:16 +0800 Subject: [PATCH 508/606] s390/sclp: Add check for get_zeroed_page() [ Upstream commit 3db42c75a921854a99db0a2775814fef97415bac ] Add check for the return value of get_zeroed_page() in sclp_console_init() to prevent null pointer dereference. Furthermore, to solve the memory leak caused by the loop allocation, add a free helper to do the free job. Signed-off-by: Haoxiang Li Acked-by: Heiko Carstens Link: https://lore.kernel.org/r/20250218025216.2421548-1-haoxiang_li2024@163.com Signed-off-by: Vasily Gorbik Signed-off-by: Sasha Levin --- drivers/s390/char/sclp_con.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c index e5d947c763ea..6a030ba38bf3 100644 --- a/drivers/s390/char/sclp_con.c +++ b/drivers/s390/char/sclp_con.c @@ -263,6 +263,19 @@ static struct console sclp_console = .index = 0 /* ttyS0 */ }; +/* + * Release allocated pages. + */ +static void __init __sclp_console_free_pages(void) +{ + struct list_head *page, *p; + + list_for_each_safe(page, p, &sclp_con_pages) { + list_del(page); + free_page((unsigned long)page); + } +} + /* * called by console_init() in drivers/char/tty_io.c at boot-time. */ @@ -282,6 +295,10 @@ sclp_console_init(void) /* Allocate pages for output buffering */ for (i = 0; i < sclp_console_pages; i++) { page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); + if (!page) { + __sclp_console_free_pages(); + return -ENOMEM; + } list_add_tail(page, &sclp_con_pages); } sclp_conbuf = NULL; From 7f30987294b7ce36670333bf42f9386706e90a50 Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Tue, 18 Feb 2025 11:41:04 +0800 Subject: [PATCH 509/606] s390/tty: Fix a potential memory leak bug [ Upstream commit ad9bb8f049717d64c5e62b2a44954be9f681c65b ] The check for get_zeroed_page() leads to a direct return and overlooked the memory leak caused by loop allocation. Add a free helper to free spaces allocated by get_zeroed_page(). Signed-off-by: Haoxiang Li Acked-by: Heiko Carstens Link: https://lore.kernel.org/r/20250218034104.2436469-1-haoxiang_li2024@163.com Signed-off-by: Vasily Gorbik Signed-off-by: Sasha Levin --- drivers/s390/char/sclp_tty.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c index 892c18d2f87e..d3edacb6ee14 100644 --- a/drivers/s390/char/sclp_tty.c +++ b/drivers/s390/char/sclp_tty.c @@ -490,6 +490,17 @@ static const struct tty_operations sclp_ops = { .flush_buffer = sclp_tty_flush_buffer, }; +/* Release allocated pages. */ +static void __init __sclp_tty_free_pages(void) +{ + struct list_head *page, *p; + + list_for_each_safe(page, p, &sclp_tty_pages) { + list_del(page); + free_page((unsigned long)page); + } +} + static int __init sclp_tty_init(void) { @@ -516,6 +527,7 @@ sclp_tty_init(void) for (i = 0; i < MAX_KMEM_PAGES; i++) { page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); if (page == NULL) { + __sclp_tty_free_pages(); tty_driver_kref_put(driver); return -ENOMEM; } From c487fcc632e7465befbaf3484e127bec162abd16 Mon Sep 17 00:00:00 2001 From: Sewon Nam Date: Tue, 11 Mar 2025 12:12:37 +0900 Subject: [PATCH 510/606] bpf: bpftool: Setting error code in do_loader() [ Upstream commit 02a4694107b4c830d4bd6d194e98b3ac0bc86f29 ] We are missing setting error code in do_loader() when bpf_object__open_file() fails. This means the command's exit status code will be successful, even though the operation failed. So make sure to return the correct error code. To maintain consistency with other locations where bpf_object__open_file() is called, return -1. [0] Closes: https://github.com/libbpf/bpftool/issues/156 Reported-by: Dan Carpenter Signed-off-by: Sewon Nam Signed-off-by: Andrii Nakryiko Tested-by: Quentin Monnet Reviewed-by: Quentin Monnet Link: https://lore.kernel.org/bpf/d3b5b4b4-19bb-4619-b4dd-86c958c4a367@stanley.mountain/t/#u Link: https://lore.kernel.org/bpf/20250311031238.14865-1-swnam0729@gmail.com Signed-off-by: Alexei Starovoitov Signed-off-by: Sasha Levin --- tools/bpf/bpftool/prog.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index 90ae2ea61324..174e076e56af 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c @@ -1924,6 +1924,7 @@ static int do_loader(int argc, char **argv) obj = bpf_object__open_file(file, &open_opts); if (!obj) { + err = -1; p_err("failed to open object file"); goto err_close_obj; } From 4ed42d1a4a5b1e78a235fa765bfd50d0f8cf7439 Mon Sep 17 00:00:00 2001 From: Martin KaFai Lau Date: Tue, 18 Mar 2025 11:27:59 -0700 Subject: [PATCH 511/606] bpf: Only fails the busy counter check in bpf_cgrp_storage_get if it creates storage [ Upstream commit f4edc66e48a694b3e6d164cc71f059de542dfaec ] The current cgrp storage has a percpu counter, bpf_cgrp_storage_busy, to detect potential deadlock at a spin_lock that the local storage acquires during new storage creation. There are false positives. It turns out to be too noisy in production. For example, a bpf prog may be doing a bpf_cgrp_storage_get on map_a. An IRQ comes in and triggers another bpf_cgrp_storage_get on a different map_b. It will then trigger the false positive deadlock check in the percpu counter. On top of that, both are doing lookup only and no need to create new storage, so practically it does not need to acquire the spin_lock. The bpf_task_storage_get already has a strategy to minimize this false positive by only failing if the bpf_task_storage_get needs to create a new storage and the percpu counter is busy. Creating a new storage is the only time it must acquire the spin_lock. This patch borrows the same idea. Unlike task storage that has a separate variant for tracing (_recur) and non-tracing, this patch stays with one bpf_cgrp_storage_get helper to keep it simple for now in light of the upcoming res_spin_lock. The variable could potentially use a better name noTbusy instead of nobusy. This patch follows the same naming in bpf_task_storage_get for now. I have tested it by temporarily adding noinline to the cgroup_storage_lookup(), traced it by fentry, and the fentry program succeeded in calling bpf_cgrp_storage_get(). Signed-off-by: Martin KaFai Lau Link: https://lore.kernel.org/r/20250318182759.3676094-1-martin.lau@linux.dev Signed-off-by: Alexei Starovoitov Signed-off-by: Sasha Levin --- kernel/bpf/bpf_cgrp_storage.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/kernel/bpf/bpf_cgrp_storage.c b/kernel/bpf/bpf_cgrp_storage.c index ee1c7b77096e..fbbf3b6b9f83 100644 --- a/kernel/bpf/bpf_cgrp_storage.c +++ b/kernel/bpf/bpf_cgrp_storage.c @@ -162,6 +162,7 @@ BPF_CALL_5(bpf_cgrp_storage_get, struct bpf_map *, map, struct cgroup *, cgroup, void *, value, u64, flags, gfp_t, gfp_flags) { struct bpf_local_storage_data *sdata; + bool nobusy; WARN_ON_ONCE(!bpf_rcu_lock_held()); if (flags & ~(BPF_LOCAL_STORAGE_GET_F_CREATE)) @@ -170,21 +171,21 @@ BPF_CALL_5(bpf_cgrp_storage_get, struct bpf_map *, map, struct cgroup *, cgroup, if (!cgroup) return (unsigned long)NULL; - if (!bpf_cgrp_storage_trylock()) - return (unsigned long)NULL; + nobusy = bpf_cgrp_storage_trylock(); - sdata = cgroup_storage_lookup(cgroup, map, true); + sdata = cgroup_storage_lookup(cgroup, map, nobusy); if (sdata) goto unlock; /* only allocate new storage, when the cgroup is refcounted */ if (!percpu_ref_is_dying(&cgroup->self.refcnt) && - (flags & BPF_LOCAL_STORAGE_GET_F_CREATE)) + (flags & BPF_LOCAL_STORAGE_GET_F_CREATE) && nobusy) sdata = bpf_local_storage_update(cgroup, (struct bpf_local_storage_map *)map, value, BPF_NOEXIST, gfp_flags); unlock: - bpf_cgrp_storage_unlock(); + if (nobusy) + bpf_cgrp_storage_unlock(); return IS_ERR_OR_NULL(sdata) ? (unsigned long)NULL : (unsigned long)sdata->data; } From 10cf3135c6dc6c764ecfcef10600539f30713450 Mon Sep 17 00:00:00 2001 From: Yafang Shao Date: Tue, 18 Mar 2025 19:44:46 +0800 Subject: [PATCH 512/606] bpf: Reject attaching fexit/fmod_ret to __noreturn functions [ Upstream commit cfe816d469dce9c0864062cf65dd7b3c42adc6f8 ] If we attach fexit/fmod_ret to __noreturn functions, it will cause an issue that the bpf trampoline image will be left over even if the bpf link has been destroyed. Take attaching do_exit() with fexit for example. The fexit works as follows, bpf_trampoline + __bpf_tramp_enter + percpu_ref_get(&tr->pcref); + call do_exit() + __bpf_tramp_exit + percpu_ref_put(&tr->pcref); Since do_exit() never returns, the refcnt of the trampoline image is never decremented, preventing it from being freed. That can be verified with as follows, $ bpftool link show <<<< nothing output $ grep "bpf_trampoline_[0-9]" /proc/kallsyms ffffffffc04cb000 t bpf_trampoline_6442526459 [bpf] <<<< leftover In this patch, all functions annotated with __noreturn are rejected, except for the following cases: - Functions that result in a system reboot, such as panic, machine_real_restart and rust_begin_unwind - Functions that are never executed by tasks, such as rest_init and cpu_startup_entry - Functions implemented in assembly, such as rewind_stack_and_make_dead and xen_cpu_bringup_again, lack an associated BTF ID. With this change, attaching fexit probes to functions like do_exit() will be rejected. $ ./fexit libbpf: prog 'fexit': BPF program load failed: -EINVAL libbpf: prog 'fexit': -- BEGIN PROG LOAD LOG -- Attaching fexit/fmod_ret to __noreturn functions is rejected. Signed-off-by: Yafang Shao Link: https://lore.kernel.org/r/20250318114447.75484-2-laoar.shao@gmail.com Signed-off-by: Alexei Starovoitov Signed-off-by: Sasha Levin --- kernel/bpf/verifier.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index d6a4102312fa..e443506b0a65 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -20106,6 +20106,33 @@ BTF_ID(func, __rcu_read_unlock) #endif BTF_SET_END(btf_id_deny) +/* fexit and fmod_ret can't be used to attach to __noreturn functions. + * Currently, we must manually list all __noreturn functions here. Once a more + * robust solution is implemented, this workaround can be removed. + */ +BTF_SET_START(noreturn_deny) +#ifdef CONFIG_IA32_EMULATION +BTF_ID(func, __ia32_sys_exit) +BTF_ID(func, __ia32_sys_exit_group) +#endif +#ifdef CONFIG_KUNIT +BTF_ID(func, __kunit_abort) +BTF_ID(func, kunit_try_catch_throw) +#endif +#ifdef CONFIG_MODULES +BTF_ID(func, __module_put_and_kthread_exit) +#endif +#ifdef CONFIG_X86_64 +BTF_ID(func, __x64_sys_exit) +BTF_ID(func, __x64_sys_exit_group) +#endif +BTF_ID(func, do_exit) +BTF_ID(func, do_group_exit) +BTF_ID(func, kthread_complete_and_exit) +BTF_ID(func, kthread_exit) +BTF_ID(func, make_task_dead) +BTF_SET_END(noreturn_deny) + static bool can_be_sleepable(struct bpf_prog *prog) { if (prog->type == BPF_PROG_TYPE_TRACING) { @@ -20194,6 +20221,11 @@ static int check_attach_btf_id(struct bpf_verifier_env *env) } else if (prog->type == BPF_PROG_TYPE_TRACING && btf_id_set_contains(&btf_id_deny, btf_id)) { return -EINVAL; + } else if ((prog->expected_attach_type == BPF_TRACE_FEXIT || + prog->expected_attach_type == BPF_MODIFY_RETURN) && + btf_id_set_contains(&noreturn_deny, btf_id)) { + verbose(env, "Attaching fexit/fmod_ret to __noreturn functions is rejected.\n"); + return -EINVAL; } key = bpf_trampoline_compute_key(tgt_prog, prog->aux->attach_btf, btf_id); From a6e3026e0ad60cba5b9ea046c7781171e4e268be Mon Sep 17 00:00:00 2001 From: Huisong Li Date: Thu, 13 Mar 2025 15:28:47 +0000 Subject: [PATCH 513/606] mailbox: pcc: Fix the possible race in updation of chan_in_use flag [ Upstream commit 9779d45c749340ab461d595c1a4a664cb28f3007 ] The function mbox_chan_received_data() calls the Rx callback of the mailbox client driver. The callback might set chan_in_use flag from pcc_send_data(). This flag's status determines whether the PCC channel is in use. However, there is a potential race condition where chan_in_use is updated incorrectly due to concurrency between the interrupt handler (pcc_mbox_irq()) and the command sender(pcc_send_data()). The 'chan_in_use' flag of a channel is set to true after sending a command. And the flag of the new command may be cleared erroneous by the interrupt handler afer mbox_chan_received_data() returns, As a result, the interrupt being level triggered can't be cleared in pcc_mbox_irq() and it will be disabled after the number of handled times exceeds the specified value. The error log is as follows: | kunpeng_hccs HISI04B2:00: PCC command executed timeout! | kunpeng_hccs HISI04B2:00: get port link status info failed, ret = -110 | irq 13: nobody cared (try booting with the "irqpoll" option) | Call trace: | dump_backtrace+0x0/0x210 | show_stack+0x1c/0x2c | dump_stack+0xec/0x130 | __report_bad_irq+0x50/0x190 | note_interrupt+0x1e4/0x260 | handle_irq_event+0x144/0x17c | handle_fasteoi_irq+0xd0/0x240 | __handle_domain_irq+0x80/0xf0 | gic_handle_irq+0x74/0x2d0 | el1_irq+0xbc/0x140 | mnt_clone_write+0x0/0x70 | file_update_time+0xcc/0x160 | fault_dirty_shared_page+0xe8/0x150 | do_shared_fault+0x80/0x1d0 | do_fault+0x118/0x1a4 | handle_pte_fault+0x154/0x230 | __handle_mm_fault+0x1ac/0x390 | handle_mm_fault+0xf0/0x250 | do_page_fault+0x184/0x454 | do_translation_fault+0xac/0xd4 | do_mem_abort+0x44/0xb4 | el0_da+0x40/0x74 | el0_sync_handler+0x60/0xb4 | el0_sync+0x168/0x180 | handlers: | pcc_mbox_irq | Disabling IRQ #13 To solve this issue, pcc_mbox_irq() must clear 'chan_in_use' flag before the call to mbox_chan_received_data(). Tested-by: Adam Young Tested-by: Robbie King Signed-off-by: Huisong Li (sudeep.holla: Minor updates to the subject, commit message and comment) Signed-off-by: Sudeep Holla Signed-off-by: Jassi Brar Signed-off-by: Sasha Levin --- drivers/mailbox/pcc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c index 82102a4c5d68..8fd4d0f79b09 100644 --- a/drivers/mailbox/pcc.c +++ b/drivers/mailbox/pcc.c @@ -333,10 +333,16 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p) if (pcc_chan_reg_read_modify_write(&pchan->plat_irq_ack)) return IRQ_NONE; + /* + * Clear this flag after updating interrupt ack register and just + * before mbox_chan_received_data() which might call pcc_send_data() + * where the flag is set again to start new transfer. This is + * required to avoid any possible race in updatation of this flag. + */ + pchan->chan_in_use = false; mbox_chan_received_data(chan, NULL); check_and_ack(pchan, chan); - pchan->chan_in_use = false; return IRQ_HANDLED; } From 1a0a2d8c6d771f5a588793cdb910cc7716134e03 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 13 Mar 2025 15:28:48 +0000 Subject: [PATCH 514/606] mailbox: pcc: Always clear the platform ack interrupt first [ Upstream commit cf1338c0e02880cd235a4590eeb15e2039c873bc ] The PCC mailbox interrupt handler (pcc_mbox_irq()) currently checks for command completion flags and any error status before clearing the interrupt. The below sequence highlights an issue in the handling of PCC mailbox interrupts, specifically when dealing with doorbell notifications and acknowledgment between the OSPM and the platform where type3 and type4 channels are sharing the interrupt. ------------------------------------------------------------------------- | T | Platform Firmware | OSPM/Linux PCC driver | |---|---------------------------------|---------------------------------| | 1 | | Build message in shmem | | 2 | | Ring Type3 chan doorbell | | 3 | Receives the doorbell interrupt | | | 4 | Process the message from OSPM | | | 5 | Build response for the message | | | 6 | Ring Platform ACK interrupt on | | | | Type3 chan to OSPM | Received the interrupt | | 7 | Build Notification in Type4 Chan| | | 8 | | Start processing interrupt in | | | | pcc_mbox_irq() handler | | 9 | | Enter PCC handler for Type4 chan| |10 | | Check command complete cleared | |11 | | Read the notification | |12 | | Clear Platform ACK interrupt | | | No effect from the previous step yet as the Platform ACK | | | interrupt has not yet been triggered for this channel | |13 | Ring Platform ACK interrupt on | | | | Type4 chan to OSPM | | |14 | | Enter PCC handler for Type3 chan| |15 | | Command complete is set. | |16 | | Read the response. | |17 | | Clear Platform ACK interrupt | |18 | | Leave PCC handler for Type3 | |19 | | Leave pcc_mbox_irq() handler | |20 | | Re-enter pcc_mbox_irq() handler | |21 | | Enter PCC handler for Type4 chan| |22 | | Leave PCC handler for Type4 chan| |23 | | Enter PCC handler for Type3 chan| |24 | | Leave PCC handler for Type3 chan| |25 | | Leave pcc_mbox_irq() handler | ------------------------------------------------------------------------- The key issue occurs when OSPM tries to acknowledge platform ack interrupt for a notification which is ready to be read and processed but the interrupt itself is not yet triggered by the platform. This ineffective acknowledgment leads to an issue later in time where the interrupt remains pending as we exit the interrupt handler without clearing the platform ack interrupt as there is no pending response or notification. The interrupt acknowledgment order is incorrect. To resolve this issue, the platform acknowledgment interrupt should always be cleared before processing the interrupt for any notifications or response. Reported-by: Robbie King Reviewed-by: Huisong Li Tested-by: Huisong Li Tested-by: Adam Young Tested-by: Robbie King Signed-off-by: Sudeep Holla Signed-off-by: Jassi Brar Signed-off-by: Sasha Levin --- drivers/mailbox/pcc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c index 8fd4d0f79b09..f8215a8f656a 100644 --- a/drivers/mailbox/pcc.c +++ b/drivers/mailbox/pcc.c @@ -313,6 +313,10 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p) int ret; pchan = chan->con_priv; + + if (pcc_chan_reg_read_modify_write(&pchan->plat_irq_ack)) + return IRQ_NONE; + if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_MASTER_SUBSPACE && !pchan->chan_in_use) return IRQ_NONE; @@ -330,9 +334,6 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p) return IRQ_NONE; } - if (pcc_chan_reg_read_modify_write(&pchan->plat_irq_ack)) - return IRQ_NONE; - /* * Clear this flag after updating interrupt ack register and just * before mbox_chan_received_data() which might call pcc_send_data() From 46a150788e16923e8fefd103ffa5a2745648d18c Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Tue, 28 Jan 2025 20:51:13 +0100 Subject: [PATCH 515/606] usb: host: max3421-hcd: Add missing spi_device_id table [ Upstream commit 41d5e3806cf589f658f92c75195095df0b66f66a ] "maxim,max3421" DT compatible is missing its SPI device ID entry, not allowing module autoloading and leading to the following message: "SPI driver max3421-hcd has no spi_device_id for maxim,max3421" Fix this by adding the spi_device_id table. Signed-off-by: Alexander Stein Link: https://lore.kernel.org/r/20250128195114.56321-1-alexander.stein@mailbox.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin --- drivers/usb/host/max3421-hcd.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c index a219260ad3e6..cc1f579f02de 100644 --- a/drivers/usb/host/max3421-hcd.c +++ b/drivers/usb/host/max3421-hcd.c @@ -1946,6 +1946,12 @@ max3421_remove(struct spi_device *spi) usb_put_hcd(hcd); } +static const struct spi_device_id max3421_spi_ids[] = { + { "max3421" }, + { }, +}; +MODULE_DEVICE_TABLE(spi, max3421_spi_ids); + static const struct of_device_id max3421_of_match_table[] = { { .compatible = "maxim,max3421", }, {}, @@ -1955,6 +1961,7 @@ MODULE_DEVICE_TABLE(of, max3421_of_match_table); static struct spi_driver max3421_driver = { .probe = max3421_probe, .remove = max3421_remove, + .id_table = max3421_spi_ids, .driver = { .name = "max3421-hcd", .of_match_table = max3421_of_match_table, From db56636beb3e687c761dbf5e52d6b17d74f95de2 Mon Sep 17 00:00:00 2001 From: Edward Adam Davis Date: Mon, 14 Oct 2024 20:16:38 +0800 Subject: [PATCH 516/606] fs/ntfs3: Fix WARNING in ntfs_extend_initialized_size [ Upstream commit ff355926445897cc9fdea3b00611e514232c213c ] Syzbot reported a WARNING in ntfs_extend_initialized_size. The data type of in->i_valid and to is u64 in ntfs_file_mmap(). If their values are greater than LLONG_MAX, overflow will occur because the data types of the parameters valid and new_valid corresponding to the function ntfs_extend_initialized_size() are loff_t. Before calling ntfs_extend_initialized_size() in the ntfs_file_mmap(), the "ni->i_valid < to" has been determined, so the same WARN_ON determination is not required in ntfs_extend_initialized_size(). Just execute the ntfs_extend_initialized_size() in ntfs_extend() to make a WARN_ON check. Reported-and-tested-by: syzbot+e37dd1dfc814b10caa55@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=e37dd1dfc814b10caa55 Signed-off-by: Edward Adam Davis Signed-off-by: Konstantin Komarov Signed-off-by: Sasha Levin --- fs/ntfs3/file.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 2ecd0303f942..4aea45821611 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -335,6 +335,7 @@ static int ntfs_extend(struct inode *inode, loff_t pos, size_t count, } if (extend_init && !is_compressed(ni)) { + WARN_ON(ni->i_valid >= pos); err = ntfs_extend_initialized_size(file, ni, ni->i_valid, pos); if (err) goto out; From e5aabc76d1018db57285aa1dbdabbf12686424f8 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 12 Feb 2025 21:28:02 +0200 Subject: [PATCH 517/606] usb: dwc3: gadget: Refactor loop to avoid NULL endpoints [ Upstream commit eafba0205426091354f050381c32ad1567c35844 ] Prepare the gadget driver to handle the reserved endpoints that will be not allocated at the initialisation time. While at it, add a warning where the NULL endpoint should never happen. Signed-off-by: Andy Shevchenko Tested-by: Ferry Toth Acked-by: Thinh Nguyen Link: https://lore.kernel.org/r/20250212193116.2487289-3-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin --- drivers/usb/dwc3/gadget.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 8b2292420581..f51d743bb3ec 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -548,6 +548,7 @@ static int dwc3_gadget_set_xfer_resource(struct dwc3_ep *dep) int dwc3_gadget_start_config(struct dwc3 *dwc, unsigned int resource_index) { struct dwc3_gadget_ep_cmd_params params; + struct dwc3_ep *dep; u32 cmd; int i; int ret; @@ -564,8 +565,13 @@ int dwc3_gadget_start_config(struct dwc3 *dwc, unsigned int resource_index) return ret; /* Reset resource allocation flags */ - for (i = resource_index; i < dwc->num_eps && dwc->eps[i]; i++) - dwc->eps[i]->flags &= ~DWC3_EP_RESOURCE_ALLOCATED; + for (i = resource_index; i < dwc->num_eps; i++) { + dep = dwc->eps[i]; + if (!dep) + continue; + + dep->flags &= ~DWC3_EP_RESOURCE_ALLOCATED; + } return 0; } @@ -752,9 +758,11 @@ void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc) dwc->last_fifo_depth = fifo_depth; /* Clear existing TXFIFO for all IN eps except ep0 */ - for (num = 3; num < min_t(int, dwc->num_eps, DWC3_ENDPOINTS_NUM); - num += 2) { + for (num = 3; num < min_t(int, dwc->num_eps, DWC3_ENDPOINTS_NUM); num += 2) { dep = dwc->eps[num]; + if (!dep) + continue; + /* Don't change TXFRAMNUM on usb31 version */ size = DWC3_IP_IS(DWC3) ? 0 : dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(num >> 1)) & @@ -3670,6 +3678,8 @@ out: for (i = 0; i < DWC3_ENDPOINTS_NUM; i++) { dep = dwc->eps[i]; + if (!dep) + continue; if (!(dep->flags & DWC3_EP_ENABLED)) continue; @@ -3858,6 +3868,10 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, u8 epnum = event->endpoint_number; dep = dwc->eps[epnum]; + if (!dep) { + dev_warn(dwc->dev, "spurious event, endpoint %u is not allocated\n", epnum); + return; + } if (!(dep->flags & DWC3_EP_ENABLED)) { if ((epnum > 1) && !(dep->flags & DWC3_EP_TRANSFER_STARTED)) From a7f9991e4e3c544f3a492025112909648edfac9a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 12 Feb 2025 21:28:04 +0200 Subject: [PATCH 518/606] usb: dwc3: gadget: Avoid using reserved endpoints on Intel Merrifield MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 461f24bff86808ee5fbfe74751a825f8a7ab24e0 ] Intel Merrifield SoC uses these endpoints for tracing and they cannot be re-allocated if being used because the side band flow control signals are hard wired to certain endpoints: • 1 High BW Bulk IN (IN#1) (RTIT) • 1 1KB BW Bulk IN (IN#8) + 1 1KB BW Bulk OUT (Run Control) (OUT#8) In device mode, since RTIT (EP#1) and EXI/RunControl (EP#8) uses External Buffer Control (EBC) mode, these endpoints are to be mapped to EBC mode (to be done by EXI target driver). Additionally TRB for RTIT and EXI are maintained in STM (System Trace Module) unit and the EXI target driver will as well configure the TRB location for EP #1 IN and EP#8 (IN and OUT). Since STM/PTI and EXI hardware blocks manage these endpoints and interface to OTG3 controller through EBC interface, there is no need to enable any events (such as XferComplete etc) for these end points. Signed-off-by: Andy Shevchenko Tested-by: Ferry Toth Acked-by: Thinh Nguyen Link: https://lore.kernel.org/r/20250212193116.2487289-5-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin --- drivers/usb/dwc3/dwc3-pci.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 052852f80146..54a4ee2b90b7 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -148,11 +148,21 @@ static const struct property_entry dwc3_pci_intel_byt_properties[] = { {} }; +/* + * Intel Merrifield SoC uses these endpoints for tracing and they cannot + * be re-allocated if being used because the side band flow control signals + * are hard wired to certain endpoints: + * - 1 High BW Bulk IN (IN#1) (RTIT) + * - 1 1KB BW Bulk IN (IN#8) + 1 1KB BW Bulk OUT (Run Control) (OUT#8) + */ +static const u8 dwc3_pci_mrfld_reserved_endpoints[] = { 3, 16, 17 }; + static const struct property_entry dwc3_pci_mrfld_properties[] = { PROPERTY_ENTRY_STRING("dr_mode", "otg"), PROPERTY_ENTRY_STRING("linux,extcon-name", "mrfld_bcove_pwrsrc"), PROPERTY_ENTRY_BOOL("snps,dis_u3_susphy_quirk"), PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"), + PROPERTY_ENTRY_U8_ARRAY("snps,reserved-endpoints", dwc3_pci_mrfld_reserved_endpoints), PROPERTY_ENTRY_BOOL("snps,usb2-gadget-lpm-disable"), PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"), {} From 5be9407b41eae20eef9140f5cfbfcbc3d01aaf45 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 16 Jan 2025 11:40:59 -0800 Subject: [PATCH 519/606] sound/virtio: Fix cancel_sync warnings on uninitialized work_structs [ Upstream commit 3c7df2e27346eb40a0e86230db1ccab195c97cfe ] Betty reported hitting the following warning: [ 8.709131][ T221] WARNING: CPU: 2 PID: 221 at kernel/workqueue.c:4182 ... [ 8.713282][ T221] Call trace: [ 8.713365][ T221] __flush_work+0x8d0/0x914 [ 8.713468][ T221] __cancel_work_sync+0xac/0xfc [ 8.713570][ T221] cancel_work_sync+0x24/0x34 [ 8.713667][ T221] virtsnd_remove+0xa8/0xf8 [virtio_snd ab15f34d0dd772f6d11327e08a81d46dc9c36276] [ 8.713868][ T221] virtsnd_probe+0x48c/0x664 [virtio_snd ab15f34d0dd772f6d11327e08a81d46dc9c36276] [ 8.714035][ T221] virtio_dev_probe+0x28c/0x390 [ 8.714139][ T221] really_probe+0x1bc/0x4c8 ... It seems we're hitting the error path in virtsnd_probe(), which triggers a virtsnd_remove() which iterates over the substreams calling cancel_work_sync() on the elapsed_period work_struct. Looking at the code, from earlier in: virtsnd_probe()->virtsnd_build_devs()->virtsnd_pcm_parse_cfg() We set snd->nsubstreams, allocate the snd->substreams, and if we then hit an error on the info allocation or something in virtsnd_ctl_query_info() fails, we will exit without having initialized the elapsed_period work_struct. When that error path unwinds we then call virtsnd_remove() which as long as the substreams array is allocated, will iterate through calling cancel_work_sync() on the uninitialized work struct hitting this warning. Takashi Iwai suggested this fix, which initializes the substreams structure right after allocation, so that if we hit the error paths we avoid trying to cleanup uninitialized data. Note: I have not yet managed to reproduce the issue myself, so this patch has had limited testing. Feedback or thoughts would be appreciated! Cc: Anton Yakovlev Cc: "Michael S. Tsirkin" Cc: Jaroslav Kysela Cc: Takashi Iwai Cc: virtualization@lists.linux.dev Cc: linux-sound@vger.kernel.org Cc: kernel-team@android.com Reported-by: Betty Zhou Suggested-by: Takashi Iwai Signed-off-by: John Stultz Message-Id: <20250116194114.3375616-1-jstultz@google.com> Signed-off-by: Michael S. Tsirkin Signed-off-by: Sasha Levin --- sound/virtio/virtio_pcm.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/sound/virtio/virtio_pcm.c b/sound/virtio/virtio_pcm.c index c10d91fff2fb..1ddec1f4f05d 100644 --- a/sound/virtio/virtio_pcm.c +++ b/sound/virtio/virtio_pcm.c @@ -337,6 +337,21 @@ int virtsnd_pcm_parse_cfg(struct virtio_snd *snd) if (!snd->substreams) return -ENOMEM; + /* + * Initialize critical substream fields early in case we hit an + * error path and end up trying to clean up uninitialized structures + * elsewhere. + */ + for (i = 0; i < snd->nsubstreams; ++i) { + struct virtio_pcm_substream *vss = &snd->substreams[i]; + + vss->snd = snd; + vss->sid = i; + INIT_WORK(&vss->elapsed_period, virtsnd_pcm_period_elapsed); + init_waitqueue_head(&vss->msg_empty); + spin_lock_init(&vss->lock); + } + info = kcalloc(snd->nsubstreams, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -350,12 +365,6 @@ int virtsnd_pcm_parse_cfg(struct virtio_snd *snd) struct virtio_pcm_substream *vss = &snd->substreams[i]; struct virtio_pcm *vpcm; - vss->snd = snd; - vss->sid = i; - INIT_WORK(&vss->elapsed_period, virtsnd_pcm_period_elapsed); - init_waitqueue_head(&vss->msg_empty); - spin_lock_init(&vss->lock); - rc = virtsnd_pcm_build_hw(vss, &info[i]); if (rc) goto on_exit; From 2c6a11eaec650c3c3fde42c54edc375bad5f4aac Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Wed, 5 Mar 2025 15:00:06 -0800 Subject: [PATCH 520/606] dmaengine: dmatest: Fix dmatest waiting less when interrupted [ Upstream commit e87ca16e99118ab4e130a41bdf12abbf6a87656c ] Change the "wait for operation finish" logic to take interrupts into account. When using dmatest with idxd DMA engine, it's possible that during longer tests, the interrupt notifying the finish of an operation happens during wait_event_freezable_timeout(), which causes dmatest to cleanup all the resources, some of which might still be in use. This fix ensures that the wait logic correctly handles interrupts, preventing premature cleanup of resources. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-lkp/202502171134.8c403348-lkp@intel.com Signed-off-by: Vinicius Costa Gomes Reviewed-by: Dave Jiang Link: https://lore.kernel.org/r/20250305230007.590178-1-vinicius.gomes@intel.com Signed-off-by: Vinod Koul Signed-off-by: Sasha Levin --- drivers/dma/dmatest.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index ffe621695e47..78b8a97b2363 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -827,9 +827,9 @@ static int dmatest_func(void *data) } else { dma_async_issue_pending(chan); - wait_event_freezable_timeout(thread->done_wait, - done->done, - msecs_to_jiffies(params->timeout)); + wait_event_timeout(thread->done_wait, + done->done, + msecs_to_jiffies(params->timeout)); status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); From 8b26eb1d8bb2393d81c4af99dbe2ae35b0950d37 Mon Sep 17 00:00:00 2001 From: Michal Pecio Date: Tue, 11 Mar 2025 17:45:51 +0200 Subject: [PATCH 521/606] usb: xhci: Avoid Stop Endpoint retry loop if the endpoint seems Running [ Upstream commit 28a76fcc4c85dd39633fb96edb643c91820133e3 ] Nothing prevents a broken HC from claiming that an endpoint is Running and repeatedly rejecting Stop Endpoint with Context State Error. Avoid infinite retries and give back cancelled TDs. No such cases known so far, but HCs have bugs. Signed-off-by: Michal Pecio Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20250311154551.4035726-4-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin --- drivers/usb/host/xhci-ring.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index e66bb87c4217..cb9443962945 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1214,16 +1214,19 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id, * Stopped state, but it will soon change to Running. * * Assume this bug on unexpected Stop Endpoint failures. - * Keep retrying until the EP starts and stops again, on - * chips where this is known to help. Wait for 100ms. + * Keep retrying until the EP starts and stops again. */ - if (time_is_before_jiffies(ep->stop_time + msecs_to_jiffies(100))) - break; fallthrough; case EP_STATE_RUNNING: /* Race, HW handled stop ep cmd before ep was running */ xhci_dbg(xhci, "Stop ep completion ctx error, ctx_state %d\n", GET_EP_CTX_STATE(ep_ctx)); + /* + * Don't retry forever if we guessed wrong or a defective HC never starts + * the EP or says 'Running' but fails the command. We must give back TDs. + */ + if (time_is_before_jiffies(ep->stop_time + msecs_to_jiffies(100))) + break; command = xhci_alloc_command(xhci, false, GFP_ATOMIC); if (!command) { From cfa7984f69359761b07a7831c1258c0fde1e0389 Mon Sep 17 00:00:00 2001 From: Chenyuan Yang Date: Mon, 10 Mar 2025 20:27:05 -0500 Subject: [PATCH 522/606] usb: gadget: aspeed: Add NULL pointer check in ast_vhub_init_dev() [ Upstream commit 8c75f3e6a433d92084ad4e78b029ae680865420f ] The variable d->name, returned by devm_kasprintf(), could be NULL. A pointer check is added to prevent potential NULL pointer dereference. This is similar to the fix in commit 3027e7b15b02 ("ice: Fix some null pointer dereference issues in ice_ptp.c"). This issue is found by our static analysis tool Signed-off-by: Chenyuan Yang Link: https://lore.kernel.org/r/20250311012705.1233829-1-chenyuan0y@gmail.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin --- drivers/usb/gadget/udc/aspeed-vhub/dev.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/gadget/udc/aspeed-vhub/dev.c b/drivers/usb/gadget/udc/aspeed-vhub/dev.c index 573109ca5b79..a09f72772e6e 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/dev.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/dev.c @@ -548,6 +548,9 @@ int ast_vhub_init_dev(struct ast_vhub *vhub, unsigned int idx) d->vhub = vhub; d->index = idx; d->name = devm_kasprintf(parent, GFP_KERNEL, "port%d", idx+1); + if (!d->name) + return -ENOMEM; + d->regs = vhub->regs + 0x100 + 0x10 * idx; ast_vhub_init_ep0(vhub, &d->ep0, d); From e59fc484d4247c0774f4b55bd1ee1b2bf9b14fdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Lebrun?= Date: Wed, 5 Feb 2025 18:36:46 +0100 Subject: [PATCH 523/606] usb: host: xhci-plat: mvebu: use ->quirks instead of ->init_quirk() func MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 64eb182d5f7a5ec30227bce4f6922ff663432f44 ] Compatible "marvell,armada3700-xhci" match data uses the struct xhci_plat_priv::init_quirk() function pointer to add XHCI_RESET_ON_RESUME as quirk on XHCI. Instead, use the struct xhci_plat_priv::quirks field. Signed-off-by: Théo Lebrun Link: https://lore.kernel.org/r/20250205-s2r-cdns-v7-1-13658a271c3c@bootlin.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin --- drivers/usb/host/xhci-mvebu.c | 10 ---------- drivers/usb/host/xhci-mvebu.h | 6 ------ drivers/usb/host/xhci-plat.c | 2 +- 3 files changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/usb/host/xhci-mvebu.c b/drivers/usb/host/xhci-mvebu.c index 87f1597a0e5a..257e4d79971f 100644 --- a/drivers/usb/host/xhci-mvebu.c +++ b/drivers/usb/host/xhci-mvebu.c @@ -73,13 +73,3 @@ int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd) return 0; } - -int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd) -{ - struct xhci_hcd *xhci = hcd_to_xhci(hcd); - - /* Without reset on resume, the HC won't work at all */ - xhci->quirks |= XHCI_RESET_ON_RESUME; - - return 0; -} diff --git a/drivers/usb/host/xhci-mvebu.h b/drivers/usb/host/xhci-mvebu.h index 3be021793cc8..9d26e22c4842 100644 --- a/drivers/usb/host/xhci-mvebu.h +++ b/drivers/usb/host/xhci-mvebu.h @@ -12,16 +12,10 @@ struct usb_hcd; #if IS_ENABLED(CONFIG_USB_XHCI_MVEBU) int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd); -int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd); #else static inline int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd) { return 0; } - -static inline int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd) -{ - return 0; -} #endif #endif /* __LINUX_XHCI_MVEBU_H */ diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index d68e9abcdc69..8832e0cedada 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -106,7 +106,7 @@ static const struct xhci_plat_priv xhci_plat_marvell_armada = { }; static const struct xhci_plat_priv xhci_plat_marvell_armada3700 = { - .init_quirk = xhci_mvebu_a3700_init_quirk, + .quirks = XHCI_RESET_ON_RESUME, }; static const struct xhci_plat_priv xhci_plat_brcm = { From d5ada7bf3dc8b936b222432e590376649e8ae825 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 4 Mar 2025 10:53:21 +0200 Subject: [PATCH 524/606] thunderbolt: Scan retimers after device router has been enumerated [ Upstream commit 75749d2c1d8cef439f8b69fa1f4f36d0fc3193e6 ] Thomas reported connection issues on AMD system with Pluggable UD-4VPD dock. After some experiments it looks like the device has some sort of internal timeout that triggers reconnect. This is completely against the USB4 spec, as there is no requirement for the host to enumerate the device right away or even at all. In Linux case the delay is caused by scanning of retimers on the link so we can work this around by doing the scanning after the device router has been enumerated. Reported-by: Thomas Lynema Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219748 Reviewed-by: Mario Limonciello Signed-off-by: Mika Westerberg Signed-off-by: Sasha Levin --- drivers/thunderbolt/tb.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index 7c3310a2b28a..b92a8a5b2e8c 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -1370,11 +1370,15 @@ static void tb_scan_port(struct tb_port *port) goto out_rpm_put; } - tb_retimer_scan(port, true); - sw = tb_switch_alloc(port->sw->tb, &port->sw->dev, tb_downstream_route(port)); if (IS_ERR(sw)) { + /* + * Make the downstream retimers available even if there + * is no router connected. + */ + tb_retimer_scan(port, true); + /* * If there is an error accessing the connected switch * it may be connected to another domain. Also we allow @@ -1424,6 +1428,14 @@ static void tb_scan_port(struct tb_port *port) upstream_port = tb_upstream_port(sw); tb_configure_link(port, upstream_port, sw); + /* + * Scan for downstream retimers. We only scan them after the + * router has been enumerated to avoid issues with certain + * Pluggable devices that expect the host to enumerate them + * within certain timeout. + */ + tb_retimer_scan(port, true); + /* * CL0s and CL1 are enabled and supported together. * Silently ignore CLx enabling in case CLx is not supported. From 97f70d27bee2a67002264023a0e64af916f5f9aa Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Mon, 24 Mar 2025 14:55:57 -0700 Subject: [PATCH 525/606] objtool: Silence more KCOV warnings [ Upstream commit 6b023c7842048c4bbeede802f3cf36b96c7a8b25 ] In the past there were issues with KCOV triggering unreachable instruction warnings, which is why unreachable warnings are now disabled with CONFIG_KCOV. Now some new KCOV warnings are showing up with GCC 14: vmlinux.o: warning: objtool: cpuset_write_resmask() falls through to next function cpuset_update_active_cpus.cold() drivers/usb/core/driver.o: error: objtool: usb_deregister() falls through to next function usb_match_device() sound/soc/codecs/snd-soc-wcd934x.o: warning: objtool: .text.wcd934x_slim_irq_handler: unexpected end of section All are caused by GCC KCOV not finishing an optimization, leaving behind a never-taken conditional branch to a basic block which falls through to the next function (or end of section). At a high level this is similar to the unreachable warnings mentioned above, in that KCOV isn't fully removing dead code. Treat it the same way by adding these to the list of warnings to ignore with CONFIG_KCOV. Reported-by: Ingo Molnar Reported-by: kernel test robot Signed-off-by: Josh Poimboeuf Signed-off-by: Ingo Molnar Cc: Linus Torvalds Link: https://lore.kernel.org/r/66a61a0b65d74e072d3dc02384e395edb2adc3c5.1742852846.git.jpoimboe@kernel.org Closes: https://lore.kernel.org/Z9iTsI09AEBlxlHC@gmail.com Closes: https://lore.kernel.org/oe-kbuild-all/202503180044.oH9gyPeg-lkp@intel.com/ Signed-off-by: Sasha Levin --- tools/objtool/check.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/objtool/check.c b/tools/objtool/check.c index 8ba5bcfd5cd5..ddf3da6eccd0 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -3569,6 +3569,9 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, !strncmp(func->name, "__pfx_", 6)) return 0; + if (file->ignore_unreachables) + return 0; + WARN("%s() falls through to next function %s()", func->name, insn_func(insn)->name); return 1; @@ -3788,6 +3791,9 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, if (!next_insn) { if (state.cfi.cfa.base == CFI_UNDEFINED) return 0; + if (file->ignore_unreachables) + return 0; + WARN("%s: unexpected end of section", sec->name); return 1; } From 4ab980b5c3098facdf140b8818ec7f1869ff7545 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Mon, 24 Mar 2025 14:56:07 -0700 Subject: [PATCH 526/606] objtool, panic: Disable SMAP in __stack_chk_fail() [ Upstream commit 72c774aa9d1e16bfd247096935e7dae194d84929 ] __stack_chk_fail() can be called from uaccess-enabled code. Make sure uaccess gets disabled before calling panic(). Fixes the following warning: kernel/trace/trace_branch.o: error: objtool: ftrace_likely_update+0x1ea: call to __stack_chk_fail() with UACCESS enabled Signed-off-by: Josh Poimboeuf Signed-off-by: Ingo Molnar Cc: Kees Cook Cc: Andrew Morton Cc: Linus Torvalds Link: https://lore.kernel.org/r/a3e97e0119e1b04c725a8aa05f7bc83d98e657eb.1742852847.git.jpoimboe@kernel.org Signed-off-by: Sasha Levin --- kernel/panic.c | 6 ++++++ tools/objtool/check.c | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/kernel/panic.c b/kernel/panic.c index ef9f9a4e928d..d7973e975474 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -763,9 +763,15 @@ device_initcall(register_warn_debugfs); */ __visible noinstr void __stack_chk_fail(void) { + unsigned long flags; + instrumentation_begin(); + flags = user_access_save(); + panic("stack-protector: Kernel stack is corrupted in: %pB", __builtin_return_address(0)); + + user_access_restore(flags); instrumentation_end(); } EXPORT_SYMBOL(__stack_chk_fail); diff --git a/tools/objtool/check.c b/tools/objtool/check.c index ddf3da6eccd0..eb6d7025ee49 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -1225,12 +1225,15 @@ static const char *uaccess_safe_builtin[] = { "__ubsan_handle_load_invalid_value", /* STACKLEAK */ "stackleak_track_stack", + /* TRACE_BRANCH_PROFILING */ + "ftrace_likely_update", + /* STACKPROTECTOR */ + "__stack_chk_fail", /* misc */ "csum_partial_copy_generic", "copy_mc_fragile", "copy_mc_fragile_handle_tail", "copy_mc_enhanced_fast_string", - "ftrace_likely_update", /* CONFIG_TRACE_BRANCH_PROFILING */ "rep_stos_alternative", "rep_movs_alternative", "__copy_user_nocache", From 547695db502cba408fe2fe502281ac0e4cbd5bc5 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Mon, 24 Mar 2025 14:56:09 -0700 Subject: [PATCH 527/606] objtool, ASoC: codecs: wcd934x: Remove potential undefined behavior in wcd934x_slim_irq_handler() [ Upstream commit 060aed9c0093b341480770457093449771cf1496 ] If 'port_id' is negative, the shift counts in wcd934x_slim_irq_handler() also become negative, resulting in undefined behavior due to shift out of bounds. If I'm reading the code correctly, that appears to be not possible, but with KCOV enabled, Clang's range analysis isn't always able to determine that and generates undefined behavior. As a result the code generation isn't optimal, and undefined behavior should be avoided regardless. Improve code generation and remove the undefined behavior by converting the signed variables to unsigned. Fixes the following warning with UBSAN: sound/soc/codecs/snd-soc-wcd934x.o: warning: objtool: .text.wcd934x_slim_irq_handler: unexpected end of section Reported-by: kernel test robot Signed-off-by: Josh Poimboeuf Signed-off-by: Ingo Molnar Acked-by: Mark Brown Cc: Srinivas Kandagatla Cc: Liam Girdwood Cc: Jaroslav Kysela Cc: Takashi Iwai Cc: Linus Torvalds Link: https://lore.kernel.org/r/7e863839ec7301bf9c0f429a03873d44e484c31c.1742852847.git.jpoimboe@kernel.org Closes: https://lore.kernel.org/oe-kbuild-all/202503180044.oH9gyPeg-lkp@intel.com/ Signed-off-by: Sasha Levin --- sound/soc/codecs/wcd934x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index 1b6e376f3833..fe222c4b74c0 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -2281,7 +2281,7 @@ static irqreturn_t wcd934x_slim_irq_handler(int irq, void *data) { struct wcd934x_codec *wcd = data; unsigned long status = 0; - int i, j, port_id; + unsigned int i, j, port_id; unsigned int val, int_val = 0; irqreturn_t ret = IRQ_NONE; bool tx; From 11c16b644934675fcae949589b940a7169894c1a Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Mon, 24 Mar 2025 14:56:10 -0700 Subject: [PATCH 528/606] objtool, regulator: rk808: Remove potential undefined behavior in rk806_set_mode_dcdc() [ Upstream commit 29c578c848402a34e8c8e115bf66cb6008b77062 ] If 'ctr_bit' is negative, the shift counts become negative, causing a shift of bounds and undefined behavior. Presumably that's not possible in normal operation, but the code generation isn't optimal. And undefined behavior should be avoided regardless. Improve code generation and remove the undefined behavior by converting the signed variables to unsigned. Fixes the following warning with an UBSAN kernel: vmlinux.o: warning: objtool: rk806_set_mode_dcdc() falls through to next function rk806_get_mode_dcdc() vmlinux.o: warning: objtool: .text.rk806_set_mode_dcdc: unexpected end of section Reported-by: kernel test robot Signed-off-by: Josh Poimboeuf Signed-off-by: Ingo Molnar Acked-by: Mark Brown Cc: Liam Girdwood Cc: Linus Torvalds Link: https://lore.kernel.org/r/2023abcddf3f524ba478d64339996f25dc4097d2.1742852847.git.jpoimboe@kernel.org Closes: https://lore.kernel.org/oe-kbuild-all/202503182350.52KeHGD4-lkp@intel.com/ Signed-off-by: Sasha Levin --- drivers/regulator/rk808-regulator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index 374d80dc6d17..bec22a001a5d 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -267,8 +267,8 @@ static const unsigned int rk817_buck1_4_ramp_table[] = { static int rk806_set_mode_dcdc(struct regulator_dev *rdev, unsigned int mode) { - int rid = rdev_get_id(rdev); - int ctr_bit, reg; + unsigned int rid = rdev_get_id(rdev); + unsigned int ctr_bit, reg; reg = RK806_POWER_FPWM_EN0 + rid / 8; ctr_bit = rid % 8; From db437e985469e2cace95604761eb8ba768f025ec Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Mon, 24 Mar 2025 14:56:12 -0700 Subject: [PATCH 529/606] objtool, lkdtm: Obfuscate the do_nothing() pointer [ Upstream commit 05026ea01e95ffdeb0e5ac8fb7fb1b551e3a8726 ] If execute_location()'s memcpy of do_nothing() gets inlined and unrolled by the compiler, it copies one word at a time: mov 0x0(%rip),%rax R_X86_64_PC32 .text+0x1374 mov %rax,0x38(%rbx) mov 0x0(%rip),%rax R_X86_64_PC32 .text+0x136c mov %rax,0x30(%rbx) ... Those .text references point to the middle of the function, causing objtool to complain about their lack of ENDBR. Prevent that by resolving the function pointer at runtime rather than build time. This fixes the following warning: drivers/misc/lkdtm/lkdtm.o: warning: objtool: execute_location+0x23: relocation to !ENDBR: .text+0x1378 Reported-by: kernel test robot Signed-off-by: Josh Poimboeuf Signed-off-by: Ingo Molnar Reviewed-by: Kees Cook Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Linus Torvalds Link: https://lore.kernel.org/r/30b9abffbddeb43c4f6320b1270fa9b4d74c54ed.1742852847.git.jpoimboe@kernel.org Closes: https://lore.kernel.org/oe-kbuild-all/202503191453.uFfxQy5R-lkp@intel.com/ Signed-off-by: Sasha Levin --- drivers/misc/lkdtm/perms.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/misc/lkdtm/perms.c b/drivers/misc/lkdtm/perms.c index 5b861dbff27e..6c24426104ba 100644 --- a/drivers/misc/lkdtm/perms.c +++ b/drivers/misc/lkdtm/perms.c @@ -28,6 +28,13 @@ static const unsigned long rodata = 0xAA55AA55; /* This is marked __ro_after_init, so it should ultimately be .rodata. */ static unsigned long ro_after_init __ro_after_init = 0x55AA5500; +/* + * This is a pointer to do_nothing() which is initialized at runtime rather + * than build time to avoid objtool IBT validation warnings caused by an + * inlined unrolled memcpy() in execute_location(). + */ +static void __ro_after_init *do_nothing_ptr; + /* * This just returns to the caller. It is designed to be copied into * non-executable memory regions. @@ -65,13 +72,12 @@ static noinline __nocfi void execute_location(void *dst, bool write) { void (*func)(void); func_desc_t fdesc; - void *do_nothing_text = dereference_function_descriptor(do_nothing); - pr_info("attempting ok execution at %px\n", do_nothing_text); + pr_info("attempting ok execution at %px\n", do_nothing_ptr); do_nothing(); if (write == CODE_WRITE) { - memcpy(dst, do_nothing_text, EXEC_SIZE); + memcpy(dst, do_nothing_ptr, EXEC_SIZE); flush_icache_range((unsigned long)dst, (unsigned long)dst + EXEC_SIZE); } @@ -267,6 +273,8 @@ static void lkdtm_ACCESS_NULL(void) void __init lkdtm_perms_init(void) { + do_nothing_ptr = dereference_function_descriptor(do_nothing); + /* Make sure we can write to __ro_after_init values during __init */ ro_after_init |= 0xAA; } From 5d53e88d8370b9ab14dd830abb410d9a2671edb6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 13 May 2024 17:50:34 -0600 Subject: [PATCH 530/606] qibfs: fix _another_ leak [ Upstream commit bdb43af4fdb39f844ede401bdb1258f67a580a27 ] failure to allocate inode => leaked dentry... this one had been there since the initial merge; to be fair, if we are that far OOM, the odds of failing at that particular allocation are low... Signed-off-by: Al Viro Signed-off-by: Sasha Levin --- drivers/infiniband/hw/qib/qib_fs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c index 11155e0fb839..35d777976c29 100644 --- a/drivers/infiniband/hw/qib/qib_fs.c +++ b/drivers/infiniband/hw/qib/qib_fs.c @@ -55,6 +55,7 @@ static int qibfs_mknod(struct inode *dir, struct dentry *dentry, struct inode *inode = new_inode(dir->i_sb); if (!inode) { + dput(dentry); error = -EPERM; goto bail; } From 27f6ee168c00c4cd2d2b537f048155bbf2b6059c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 21 Feb 2025 09:57:25 +0100 Subject: [PATCH 531/606] ntb: reduce stack usage in idt_scan_mws [ Upstream commit aff12700b8dd7422bfe2277696e192af4df9de8f ] idt_scan_mws() puts a large fixed-size array on the stack and copies it into a smaller dynamically allocated array at the end. On 32-bit targets, the fixed size can easily exceed the warning limit for possible stack overflow: drivers/ntb/hw/idt/ntb_hw_idt.c:1041:27: error: stack frame size (1032) exceeds limit (1024) in 'idt_scan_mws' [-Werror,-Wframe-larger-than] Change it to instead just always use dynamic allocation for the array from the start. It's too big for the stack, but not actually all that much for a permanent allocation. Reported-by: kernel test robot Closes: https://lore.kernel.org/all/202205111109.PiKTruEj-lkp@intel.com/ Signed-off-by: Arnd Bergmann Reviewed-by: Dave Jiang Reviewed-by: Damien Le Moal Signed-off-by: Jon Mason Signed-off-by: Sasha Levin --- drivers/ntb/hw/idt/ntb_hw_idt.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/ntb/hw/idt/ntb_hw_idt.c b/drivers/ntb/hw/idt/ntb_hw_idt.c index 48823b53ede3..22aaa60d2d38 100644 --- a/drivers/ntb/hw/idt/ntb_hw_idt.c +++ b/drivers/ntb/hw/idt/ntb_hw_idt.c @@ -1041,7 +1041,7 @@ static inline char *idt_get_mw_name(enum idt_mw_type mw_type) static struct idt_mw_cfg *idt_scan_mws(struct idt_ntb_dev *ndev, int port, unsigned char *mw_cnt) { - struct idt_mw_cfg mws[IDT_MAX_NR_MWS], *ret_mws; + struct idt_mw_cfg *mws; const struct idt_ntb_bar *bars; enum idt_mw_type mw_type; unsigned char widx, bidx, en_cnt; @@ -1049,6 +1049,11 @@ static struct idt_mw_cfg *idt_scan_mws(struct idt_ntb_dev *ndev, int port, int aprt_size; u32 data; + mws = devm_kcalloc(&ndev->ntb.pdev->dev, IDT_MAX_NR_MWS, + sizeof(*mws), GFP_KERNEL); + if (!mws) + return ERR_PTR(-ENOMEM); + /* Retrieve the array of the BARs registers */ bars = portdata_tbl[port].bars; @@ -1103,16 +1108,7 @@ static struct idt_mw_cfg *idt_scan_mws(struct idt_ntb_dev *ndev, int port, } } - /* Allocate memory for memory window descriptors */ - ret_mws = devm_kcalloc(&ndev->ntb.pdev->dev, *mw_cnt, sizeof(*ret_mws), - GFP_KERNEL); - if (!ret_mws) - return ERR_PTR(-ENOMEM); - - /* Copy the info of detected memory windows */ - memcpy(ret_mws, mws, (*mw_cnt)*sizeof(*ret_mws)); - - return ret_mws; + return mws; } /* From 04ebabdbe99d4118898ddfce82a69b805e2101e8 Mon Sep 17 00:00:00 2001 From: Basavaraj Natikar Date: Wed, 12 Mar 2025 20:02:16 +0530 Subject: [PATCH 532/606] ntb_hw_amd: Add NTB PCI ID for new gen CPU [ Upstream commit bf8a7ce7e4c7267a6f5f2b2023cfc459b330b25e ] Add NTB support for new generation of processor. Signed-off-by: Basavaraj Natikar Signed-off-by: Jon Mason Signed-off-by: Sasha Levin --- drivers/ntb/hw/amd/ntb_hw_amd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ntb/hw/amd/ntb_hw_amd.c b/drivers/ntb/hw/amd/ntb_hw_amd.c index d687e8c2cc78..63ceed89b62e 100644 --- a/drivers/ntb/hw/amd/ntb_hw_amd.c +++ b/drivers/ntb/hw/amd/ntb_hw_amd.c @@ -1318,6 +1318,7 @@ static const struct pci_device_id amd_ntb_pci_tbl[] = { { PCI_VDEVICE(AMD, 0x148b), (kernel_ulong_t)&dev_data[1] }, { PCI_VDEVICE(AMD, 0x14c0), (kernel_ulong_t)&dev_data[1] }, { PCI_VDEVICE(AMD, 0x14c3), (kernel_ulong_t)&dev_data[1] }, + { PCI_VDEVICE(AMD, 0x155a), (kernel_ulong_t)&dev_data[1] }, { PCI_VDEVICE(HYGON, 0x145b), (kernel_ulong_t)&dev_data[0] }, { 0, } }; From a68768e280b7d0c967ea509e791bb9b90adc94a5 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Wed, 19 Mar 2025 20:20:15 +0900 Subject: [PATCH 533/606] 9p/net: fix improper handling of bogus negative read/write replies [ Upstream commit d0259a856afca31d699b706ed5e2adf11086c73b ] In p9_client_write() and p9_client_read_once(), if the server incorrectly replies with success but a negative write/read count then we would consider written (negative) <= rsize (positive) because both variables were signed. Make variables unsigned to avoid this problem. The reproducer linked below now fails with the following error instead of a null pointer deref: 9pnet: bogus RWRITE count (4294967295 > 3) Reported-by: Robert Morris Closes: https://lore.kernel.org/16271.1734448631@26-5-164.dynamic.csail.mit.edu Message-ID: <20250319-9p_unsigned_rw-v3-1-71327f1503d0@codewreck.org> Reviewed-by: Christian Schoenebeck Signed-off-by: Dominique Martinet Signed-off-by: Sasha Levin --- net/9p/client.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/net/9p/client.c b/net/9p/client.c index d841d82e908f..cf73fe306219 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -1547,7 +1547,8 @@ p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to, struct p9_client *clnt = fid->clnt; struct p9_req_t *req; int count = iov_iter_count(to); - int rsize, received, non_zc = 0; + u32 rsize, received; + bool non_zc = false; char *dataptr; *err = 0; @@ -1570,7 +1571,7 @@ p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to, 0, 11, "dqd", fid->fid, offset, rsize); } else { - non_zc = 1; + non_zc = true; req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, rsize); } @@ -1591,11 +1592,11 @@ p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to, return 0; } if (rsize < received) { - pr_err("bogus RREAD count (%d > %d)\n", received, rsize); + pr_err("bogus RREAD count (%u > %u)\n", received, rsize); received = rsize; } - p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", received); + p9_debug(P9_DEBUG_9P, "<<< RREAD count %u\n", received); if (non_zc) { int n = copy_to_iter(dataptr, received, to); @@ -1622,9 +1623,9 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err) *err = 0; while (iov_iter_count(from)) { - int count = iov_iter_count(from); - int rsize = fid->iounit; - int written; + size_t count = iov_iter_count(from); + u32 rsize = fid->iounit; + u32 written; if (!rsize || rsize > clnt->msize - P9_IOHDRSZ) rsize = clnt->msize - P9_IOHDRSZ; @@ -1632,7 +1633,7 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err) if (count < rsize) rsize = count; - p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %d (/%d)\n", + p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %u (/%zu)\n", fid->fid, offset, rsize, count); /* Don't bother zerocopy for small IO (< 1024) */ @@ -1658,11 +1659,11 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err) break; } if (rsize < written) { - pr_err("bogus RWRITE count (%d > %d)\n", written, rsize); + pr_err("bogus RWRITE count (%u > %u)\n", written, rsize); written = rsize; } - p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", written); + p9_debug(P9_DEBUG_9P, "<<< RWRITE count %u\n", written); p9_req_put(clnt, req); iov_iter_revert(from, count - written - iov_iter_count(from)); @@ -2049,7 +2050,8 @@ EXPORT_SYMBOL_GPL(p9_client_xattrcreate); int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) { - int err, rsize, non_zc = 0; + int err, non_zc = 0; + u32 rsize; struct p9_client *clnt; struct p9_req_t *req; char *dataptr; @@ -2058,7 +2060,7 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) iov_iter_kvec(&to, ITER_DEST, &kv, 1, count); - p9_debug(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %d\n", + p9_debug(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %u\n", fid->fid, offset, count); clnt = fid->clnt; @@ -2093,11 +2095,11 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) goto free_and_error; } if (rsize < count) { - pr_err("bogus RREADDIR count (%d > %d)\n", count, rsize); + pr_err("bogus RREADDIR count (%u > %u)\n", count, rsize); count = rsize; } - p9_debug(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count); + p9_debug(P9_DEBUG_9P, "<<< RREADDIR count %u\n", count); if (non_zc) memmove(data, dataptr, count); From 7e9b836182c18c42c51842af464deee172922aea Mon Sep 17 00:00:00 2001 From: Lukas Stockmann Date: Mon, 20 Jan 2025 10:34:49 +0100 Subject: [PATCH 534/606] rtc: pcf85063: do a SW reset if POR failed [ Upstream commit 2b7cbd98495f6ee4cd6422fe77828a19e9edf87f ] Power-on Reset has a documented issue in PCF85063, refer to its datasheet, section "Software reset": "There is a low probability that some devices will have corruption of the registers after the automatic power-on reset if the device is powered up with a residual VDD level. It is required that the VDD starts at zero volts at power up or upon power cycling to ensure that there is no corruption of the registers. If this is not possible, a reset must be initiated after power-up (i.e. when power is stable) with the software reset command" Trigger SW reset if there is an indication that POR has failed. Link: https://www.nxp.com/docs/en/data-sheet/PCF85063A.pdf Signed-off-by: Lukas Stockmann Signed-off-by: Alexander Sverdlin Link: https://lore.kernel.org/r/20250120093451.30778-1-alexander.sverdlin@siemens.com Signed-off-by: Alexandre Belloni Signed-off-by: Sasha Levin --- drivers/rtc/rtc-pcf85063.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c index 905986c61655..73848f764559 100644 --- a/drivers/rtc/rtc-pcf85063.c +++ b/drivers/rtc/rtc-pcf85063.c @@ -35,6 +35,7 @@ #define PCF85063_REG_CTRL1_CAP_SEL BIT(0) #define PCF85063_REG_CTRL1_STOP BIT(5) #define PCF85063_REG_CTRL1_EXT_TEST BIT(7) +#define PCF85063_REG_CTRL1_SWR 0x58 #define PCF85063_REG_CTRL2 0x01 #define PCF85063_CTRL2_AF BIT(6) @@ -589,7 +590,7 @@ static int pcf85063_probe(struct i2c_client *client) i2c_set_clientdata(client, pcf85063); - err = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL1, &tmp); + err = regmap_read(pcf85063->regmap, PCF85063_REG_SC, &tmp); if (err) { dev_err(&client->dev, "RTC chip is not present\n"); return err; @@ -599,6 +600,22 @@ static int pcf85063_probe(struct i2c_client *client) if (IS_ERR(pcf85063->rtc)) return PTR_ERR(pcf85063->rtc); + /* + * If a Power loss is detected, SW reset the device. + * From PCF85063A datasheet: + * There is a low probability that some devices will have corruption + * of the registers after the automatic power-on reset... + */ + if (tmp & PCF85063_REG_SC_OS) { + dev_warn(&client->dev, + "POR issue detected, sending a SW reset\n"); + err = regmap_write(pcf85063->regmap, PCF85063_REG_CTRL1, + PCF85063_REG_CTRL1_SWR); + if (err < 0) + dev_warn(&client->dev, + "SW reset failed, trying to continue\n"); + } + err = pcf85063_load_capacitance(pcf85063, client->dev.of_node, config->force_cap_7000 ? 7000 : 0); if (err < 0) From c5d4d103005d8926cdad344f9fc947e651c9f2f7 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Thu, 3 Apr 2025 12:29:30 +0100 Subject: [PATCH 535/606] io_uring: always do atomic put from iowq [ Upstream commit 390513642ee6763c7ada07f0a1470474986e6c1c ] io_uring always switches requests to atomic refcounting for iowq execution before there is any parallilism by setting REQ_F_REFCOUNT, and the flag is not cleared until the request completes. That should be fine as long as the compiler doesn't make up a non existing value for the flags, however KCSAN still complains when the request owner changes oter flag bits: BUG: KCSAN: data-race in io_req_task_cancel / io_wq_free_work ... read to 0xffff888117207448 of 8 bytes by task 3871 on cpu 0: req_ref_put_and_test io_uring/refs.h:22 [inline] Skip REQ_F_REFCOUNT checks for iowq, we know it's set. Reported-by: syzbot+903a2ad71fb3f1e47cf5@syzkaller.appspotmail.com Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/d880bc27fb8c3209b54641be4ff6ac02b0e5789a.1743679736.git.asml.silence@gmail.com Signed-off-by: Jens Axboe Signed-off-by: Sasha Levin --- io_uring/io_uring.c | 2 +- io_uring/refs.h | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c index 9883fd16cde4..3ce93418e015 100644 --- a/io_uring/io_uring.c +++ b/io_uring/io_uring.c @@ -1917,7 +1917,7 @@ struct io_wq_work *io_wq_free_work(struct io_wq_work *work) struct io_kiocb *req = container_of(work, struct io_kiocb, work); struct io_kiocb *nxt = NULL; - if (req_ref_put_and_test(req)) { + if (req_ref_put_and_test_atomic(req)) { if (req->flags & IO_REQ_LINK_FLAGS) nxt = io_req_find_next(req); io_free_req(req); diff --git a/io_uring/refs.h b/io_uring/refs.h index 1336de3f2a30..21a379b0f22d 100644 --- a/io_uring/refs.h +++ b/io_uring/refs.h @@ -17,6 +17,13 @@ static inline bool req_ref_inc_not_zero(struct io_kiocb *req) return atomic_inc_not_zero(&req->refs); } +static inline bool req_ref_put_and_test_atomic(struct io_kiocb *req) +{ + WARN_ON_ONCE(!(data_race(req->flags) & REQ_F_REFCOUNT)); + WARN_ON_ONCE(req_ref_zero_or_close_to_overflow(req)); + return atomic_dec_and_test(&req->refs); +} + static inline bool req_ref_put_and_test(struct io_kiocb *req) { if (likely(!(req->flags & REQ_F_REFCOUNT))) From b205d02726b32c2f491a1a267557da5344432428 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Sun, 30 Mar 2025 15:49:55 +0200 Subject: [PATCH 536/606] sched/isolation: Make CONFIG_CPU_ISOLATION depend on CONFIG_SMP [ Upstream commit 975776841e689dd8ba36df9fa72ac3eca3c2957a ] kernel/sched/isolation.c obviously makes no sense without CONFIG_SMP, but the Kconfig entry we have right now: config CPU_ISOLATION bool "CPU isolation" depends on SMP || COMPILE_TEST allows the creation of pointless .config's which cause build failures. Reported-by: kernel test robot Signed-off-by: Oleg Nesterov Signed-off-by: Ingo Molnar Link: https://lore.kernel.org/r/20250330134955.GA7910@redhat.com Closes: https://lore.kernel.org/oe-kbuild-all/202503260646.lrUqD3j5-lkp@intel.com/ Signed-off-by: Sasha Levin --- init/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init/Kconfig b/init/Kconfig index 1105cb53f391..8b630143c720 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -689,7 +689,7 @@ endmenu # "CPU/Task time and stats accounting" config CPU_ISOLATION bool "CPU isolation" - depends on SMP || COMPILE_TEST + depends on SMP default y help Make sure that CPUs running critical tasks are not disturbed by From 1b2c45697f430a5537b2b8c5b1c613b0b82d1316 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Mon, 17 Feb 2025 14:13:56 +0100 Subject: [PATCH 537/606] KVM: s390: Don't use %pK through tracepoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 6c9567e0850be2f0f94ab64fa6512413fd1a1eb1 ] Restricted pointers ("%pK") are not meant to be used through TP_format(). It can unintentionally expose security sensitive, raw pointer values. Use regular pointer formatting instead. Link: https://lore.kernel.org/lkml/20250113171731-dc10e3c1-da64-4af0-b767-7c7070468023@linutronix.de/ Signed-off-by: Thomas Weißschuh Reviewed-by: Michael Mueller Link: https://lore.kernel.org/r/20250217-restricted-pointers-s390-v1-1-0e4ace75d8aa@linutronix.de Signed-off-by: Janosch Frank Message-ID: <20250217-restricted-pointers-s390-v1-1-0e4ace75d8aa@linutronix.de> Signed-off-by: Sasha Levin --- arch/s390/kvm/trace-s390.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/s390/kvm/trace-s390.h b/arch/s390/kvm/trace-s390.h index 6f0209d45164..9c5f546a2e1a 100644 --- a/arch/s390/kvm/trace-s390.h +++ b/arch/s390/kvm/trace-s390.h @@ -56,7 +56,7 @@ TRACE_EVENT(kvm_s390_create_vcpu, __entry->sie_block = sie_block; ), - TP_printk("create cpu %d at 0x%pK, sie block at 0x%pK", + TP_printk("create cpu %d at 0x%p, sie block at 0x%p", __entry->id, __entry->vcpu, __entry->sie_block) ); @@ -255,7 +255,7 @@ TRACE_EVENT(kvm_s390_enable_css, __entry->kvm = kvm; ), - TP_printk("enabling channel I/O support (kvm @ %pK)\n", + TP_printk("enabling channel I/O support (kvm @ %p)\n", __entry->kvm) ); From 6234a3c727843262568c4813d50c3e418a01cdcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Mon, 17 Feb 2025 14:13:57 +0100 Subject: [PATCH 538/606] KVM: s390: Don't use %pK through debug printing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 0c7fbae5bc782429c97d68dc40fb126748d7e352 ] Restricted pointers ("%pK") are only meant to be used when directly printing to a file from task context. Otherwise it can unintentionally expose security sensitive, raw pointer values. Use regular pointer formatting instead. Link: https://lore.kernel.org/lkml/20250113171731-dc10e3c1-da64-4af0-b767-7c7070468023@linutronix.de/ Signed-off-by: Thomas Weißschuh Reviewed-by: Michael Mueller Tested-by: Michael Mueller Link: https://lore.kernel.org/r/20250217-restricted-pointers-s390-v1-2-0e4ace75d8aa@linutronix.de Signed-off-by: Janosch Frank Message-ID: <20250217-restricted-pointers-s390-v1-2-0e4ace75d8aa@linutronix.de> Signed-off-by: Sasha Levin --- arch/s390/kvm/intercept.c | 2 +- arch/s390/kvm/interrupt.c | 8 ++++---- arch/s390/kvm/kvm-s390.c | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index b16352083ff9..f0be263b334c 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c @@ -94,7 +94,7 @@ static int handle_validity(struct kvm_vcpu *vcpu) vcpu->stat.exit_validity++; trace_kvm_s390_intercept_validity(vcpu, viwhy); - KVM_EVENT(3, "validity intercept 0x%x for pid %u (kvm 0x%pK)", viwhy, + KVM_EVENT(3, "validity intercept 0x%x for pid %u (kvm 0x%p)", viwhy, current->pid, vcpu->kvm); /* do not warn on invalid runtime instrumentation mode */ diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index efaebba5ee19..fe4841104ed9 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -3161,7 +3161,7 @@ void kvm_s390_gisa_clear(struct kvm *kvm) if (!gi->origin) return; gisa_clear_ipm(gi->origin); - VM_EVENT(kvm, 3, "gisa 0x%pK cleared", gi->origin); + VM_EVENT(kvm, 3, "gisa 0x%p cleared", gi->origin); } void kvm_s390_gisa_init(struct kvm *kvm) @@ -3178,7 +3178,7 @@ void kvm_s390_gisa_init(struct kvm *kvm) gi->timer.function = gisa_vcpu_kicker; memset(gi->origin, 0, sizeof(struct kvm_s390_gisa)); gi->origin->next_alert = (u32)virt_to_phys(gi->origin); - VM_EVENT(kvm, 3, "gisa 0x%pK initialized", gi->origin); + VM_EVENT(kvm, 3, "gisa 0x%p initialized", gi->origin); } void kvm_s390_gisa_enable(struct kvm *kvm) @@ -3219,7 +3219,7 @@ void kvm_s390_gisa_destroy(struct kvm *kvm) process_gib_alert_list(); hrtimer_cancel(&gi->timer); gi->origin = NULL; - VM_EVENT(kvm, 3, "gisa 0x%pK destroyed", gisa); + VM_EVENT(kvm, 3, "gisa 0x%p destroyed", gisa); } void kvm_s390_gisa_disable(struct kvm *kvm) @@ -3468,7 +3468,7 @@ int __init kvm_s390_gib_init(u8 nisc) } } - KVM_EVENT(3, "gib 0x%pK (nisc=%d) initialized", gib, gib->nisc); + KVM_EVENT(3, "gib 0x%p (nisc=%d) initialized", gib, gib->nisc); goto out; out_unreg_gal: diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 348d030d2660..890d850f51f0 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -990,7 +990,7 @@ static int kvm_s390_set_mem_control(struct kvm *kvm, struct kvm_device_attr *att } mutex_unlock(&kvm->lock); VM_EVENT(kvm, 3, "SET: max guest address: %lu", new_limit); - VM_EVENT(kvm, 3, "New guest asce: 0x%pK", + VM_EVENT(kvm, 3, "New guest asce: 0x%p", (void *) kvm->arch.gmap->asce); break; } @@ -3418,7 +3418,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) kvm_s390_gisa_init(kvm); INIT_LIST_HEAD(&kvm->arch.pv.need_cleanup); kvm->arch.pv.set_aside = NULL; - KVM_EVENT(3, "vm 0x%pK created by pid %u", kvm, current->pid); + KVM_EVENT(3, "vm 0x%p created by pid %u", kvm, current->pid); return 0; out_err: @@ -3481,7 +3481,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm) kvm_s390_destroy_adapters(kvm); kvm_s390_clear_float_irqs(kvm); kvm_s390_vsie_destroy(kvm); - KVM_EVENT(3, "vm 0x%pK destroyed", kvm); + KVM_EVENT(3, "vm 0x%p destroyed", kvm); } /* Section: vcpu related */ @@ -3602,7 +3602,7 @@ static int sca_switch_to_extended(struct kvm *kvm) free_page((unsigned long)old_sca); - VM_EVENT(kvm, 2, "Switched to ESCA (0x%pK -> 0x%pK)", + VM_EVENT(kvm, 2, "Switched to ESCA (0x%p -> 0x%p)", old_sca, kvm->arch.sca); return 0; } @@ -3974,7 +3974,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) goto out_free_sie_block; } - VM_EVENT(vcpu->kvm, 3, "create cpu %d at 0x%pK, sie block at 0x%pK", + VM_EVENT(vcpu->kvm, 3, "create cpu %d at 0x%p, sie block at 0x%p", vcpu->vcpu_id, vcpu, vcpu->arch.sie_block); trace_kvm_s390_create_vcpu(vcpu->vcpu_id, vcpu, vcpu->arch.sie_block); From b2ff4e9c599b000833d16a917f519aa2e4a75de2 Mon Sep 17 00:00:00 2001 From: Xiaogang Chen Date: Fri, 21 Mar 2025 11:41:26 -0500 Subject: [PATCH 539/606] udmabuf: fix a buf size overflow issue during udmabuf creation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 021ba7f1babd029e714d13a6bf2571b08af96d0f ] by casting size_limit_mb to u64 when calculate pglimit. Signed-off-by: Xiaogang Chen Link: https://patchwork.freedesktop.org/patch/msgid/20250321164126.329638-1-xiaogang.chen@amd.com Signed-off-by: Christian König Signed-off-by: Sasha Levin --- drivers/dma-buf/udmabuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c index d1fcdd1f9aae..373282beeb60 100644 --- a/drivers/dma-buf/udmabuf.c +++ b/drivers/dma-buf/udmabuf.c @@ -214,7 +214,7 @@ static long udmabuf_create(struct miscdevice *device, if (!ubuf) return -ENOMEM; - pglimit = (size_limit_mb * 1024 * 1024) >> PAGE_SHIFT; + pglimit = ((u64)size_limit_mb * 1024 * 1024) >> PAGE_SHIFT; for (i = 0; i < head->count; i++) { if (!IS_ALIGNED(list[i].offset, PAGE_SIZE)) goto err; From eee189ccd46b46e4a4b9d787cd65dda5025549e8 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Fri, 4 Apr 2025 08:18:49 +0800 Subject: [PATCH 540/606] selftests: ublk: fix test_stripe_04 [ Upstream commit 72070e57b0a518ec8e562a2b68fdfc796ef5c040 ] Commit 57ed58c13256 ("selftests: ublk: enable zero copy for stripe target") added test entry of test_stripe_04, but forgot to add the test script. So fix the test by adding the script file. Reported-by: Uday Shankar Signed-off-by: Ming Lei Reviewed-by: Uday Shankar Link: https://lore.kernel.org/r/20250404001849.1443064-1-ming.lei@redhat.com Signed-off-by: Jens Axboe Signed-off-by: Sasha Levin --- .../testing/selftests/ublk/test_stripe_04.sh | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100755 tools/testing/selftests/ublk/test_stripe_04.sh diff --git a/tools/testing/selftests/ublk/test_stripe_04.sh b/tools/testing/selftests/ublk/test_stripe_04.sh new file mode 100755 index 000000000000..1f2b642381d1 --- /dev/null +++ b/tools/testing/selftests/ublk/test_stripe_04.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh + +TID="stripe_04" +ERR_CODE=0 + +_prep_test "stripe" "mkfs & mount & umount on zero copy" + +backfile_0=$(_create_backfile 256M) +backfile_1=$(_create_backfile 256M) +dev_id=$(_add_ublk_dev -t stripe -z -q 2 "$backfile_0" "$backfile_1") +_check_add_dev $TID $? "$backfile_0" "$backfile_1" + +_mkfs_mount_test /dev/ublkb"${dev_id}" +ERR_CODE=$? + +_cleanup_test "stripe" + +_remove_backfile "$backfile_0" +_remove_backfile "$backfile_1" + +_show_result $TID $ERR_CODE From 1fe9b92eede32574dbe05b5bdb6ad666b350bed0 Mon Sep 17 00:00:00 2001 From: Gabriel Shahrouzi Date: Sat, 5 Apr 2025 16:30:36 -0400 Subject: [PATCH 541/606] perf/core: Fix WARN_ON(!ctx) in __free_event() for partial init [ Upstream commit 0ba3a4ab76fd3367b9cb680cad70182c896c795c ] Move the get_ctx(child_ctx) call and the child_event->ctx assignment to occur immediately after the child event is allocated. Ensure that child_event->ctx is non-NULL before any subsequent error path within inherit_event calls free_event(), satisfying the assumptions of the cleanup code. Details: There's no clear Fixes tag, because this bug is a side-effect of multiple interacting commits over time (up to 15 years old), not a single regression. The code initially incremented refcount then assigned context immediately after the child_event was created. Later, an early validity check for child_event was added before the refcount/assignment. Even later, a WARN_ON_ONCE() cleanup check was added, assuming event->ctx is valid if the pmu_ctx is valid. The problem is that the WARN_ON_ONCE() could trigger after the initial check passed but before child_event->ctx was assigned, violating its precondition. The solution is to assign child_event->ctx right after its initial validation. This ensures the context exists for any subsequent checks or cleanup routines, resolving the WARN_ON_ONCE(). To resolve it, defer the refcount update and child_event->ctx assignment directly after child_event->pmu_ctx is set but before checking if the parent event is orphaned. The cleanup routine depends on event->pmu_ctx being non-NULL before it verifies event->ctx is non-NULL. This also maintains the author's original intent of passing in child_ctx to find_get_pmu_context before its refcount/assignment. [ mingo: Expanded the changelog from another email by Gabriel Shahrouzi. ] Reported-by: syzbot+ff3aa851d46ab82953a3@syzkaller.appspotmail.com Signed-off-by: Gabriel Shahrouzi Signed-off-by: Ingo Molnar Cc: Peter Zijlstra Cc: Ravi Bangoria Cc: Kan Liang Cc: Oleg Nesterov Cc: Alexander Shishkin Link: https://lore.kernel.org/r/20250405203036.582721-1-gshahrouzi@gmail.com Closes: https://syzkaller.appspot.com/bug?extid=ff3aa851d46ab82953a3 Signed-off-by: Sasha Levin --- kernel/events/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index b710976fb01b..987807b1040a 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -13419,6 +13419,9 @@ inherit_event(struct perf_event *parent_event, if (IS_ERR(child_event)) return child_event; + get_ctx(child_ctx); + child_event->ctx = child_ctx; + pmu_ctx = find_get_pmu_context(child_event->pmu, child_ctx, child_event); if (IS_ERR(pmu_ctx)) { free_event(child_event); @@ -13441,8 +13444,6 @@ inherit_event(struct perf_event *parent_event, return NULL; } - get_ctx(child_ctx); - /* * Make the child state follow the state of the parent event, * not its attr.disabled bit. We hold the parent's mutex, @@ -13463,7 +13464,6 @@ inherit_event(struct perf_event *parent_event, local64_set(&hwc->period_left, sample_period); } - child_event->ctx = child_ctx; child_event->overflow_handler = parent_event->overflow_handler; child_event->overflow_handler_context = parent_event->overflow_handler_context; From 892fcde9941d16fd3346baba16961341c332a608 Mon Sep 17 00:00:00 2001 From: Jason Andryuk Date: Mon, 31 Mar 2025 13:29:12 -0400 Subject: [PATCH 542/606] xen: Change xen-acpi-processor dom0 dependency [ Upstream commit 0f2946bb172632e122d4033e0b03f85230a29510 ] xen-acpi-processor functions under a PVH dom0 with only a xen_initial_domain() runtime check. Change the Kconfig dependency from PV dom0 to generic dom0 to reflect that. Suggested-by: Jan Beulich Signed-off-by: Jason Andryuk Reviewed-by: Juergen Gross Tested-by: Jan Beulich Signed-off-by: Juergen Gross Message-ID: <20250331172913.51240-1-jason.andryuk@amd.com> Signed-off-by: Sasha Levin --- drivers/xen/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index d43153fec18e..af5c214b2206 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig @@ -278,7 +278,7 @@ config XEN_PRIVCMD_IRQFD config XEN_ACPI_PROCESSOR tristate "Xen ACPI processor" - depends on XEN && XEN_PV_DOM0 && X86 && ACPI_PROCESSOR && CPU_FREQ + depends on XEN && XEN_DOM0 && X86 && ACPI_PROCESSOR && CPU_FREQ default m help This ACPI processor uploads Power Management information to the Xen From fe063491e90d0e1907fab577ad3d3da7e2efe9ff Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 3 Apr 2025 09:19:29 +0200 Subject: [PATCH 543/606] nvme: requeue namespace scan on missed AENs [ Upstream commit 9546ad1a9bda7362492114f5866b95b0ac4a100e ] Scanning for namespaces can take some time, so if the target is reconfigured while the scan is running we may miss a Attached Namespace Attribute Changed AEN. Check if the NVME_AER_NOTICE_NS_CHANGED bit is set once the scan has finished, and requeue scanning to pick up any missed change. Signed-off-by: Hannes Reinecke Reviewed-by: Keith Busch Signed-off-by: Christoph Hellwig Signed-off-by: Sasha Levin --- drivers/nvme/host/core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index f00665ad0c11..e36c6fcab1ee 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -3972,6 +3972,10 @@ static void nvme_scan_work(struct work_struct *work) nvme_scan_ns_sequential(ctrl); } mutex_unlock(&ctrl->scan_lock); + + /* Requeue if we have missed AENs */ + if (test_bit(NVME_AER_NOTICE_NS_CHANGED, &ctrl->events)) + nvme_queue_scan(ctrl); } /* From fcf524eaff201d4bcb01e400d68d17a4825c5007 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 1 Apr 2025 08:38:51 -0500 Subject: [PATCH 544/606] ACPI: EC: Set ec_no_wakeup for Lenovo Go S [ Upstream commit b988685388effd648150aab272533f833a2a70f0 ] When AC adapter is unplugged or plugged in EC wakes from HW sleep but APU doesn't enter back into HW sleep. The reason this happens is that, when the APU exits HW sleep, the power rails controlled by the EC will power up the TCON. The TCON has a GPIO that will be toggled at this time. The GPIO is not marked as a wakeup source, but the GPIO controller still has an unserviced interrupt. Unserviced interrupts will block entering HW sleep again. Clearing the GPIO doesn't help as the TCON continues to assert it until it's been initialized by i2c-hid. Fixing this would require TCON F/W changes and it's already broken in the wild on production hardware. To avoid triggering this issue add a quirk to avoid letting EC wake up system at all. The power button still works properly on this system. Reported-by: Antheas Kapenekakis Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3929 Link: https://github.com/bazzite-org/patchwork/commit/95b93b2852718ee1e808c72e6b1836da4a95fc63 Co-developed-by: Antheas Kapenekakis Signed-off-by: Antheas Kapenekakis Signed-off-by: Mario Limonciello Link: https://patch.msgid.link/20250401133858.1892077-1-superm1@kernel.org [ rjw: Changelog edits ] Signed-off-by: Rafael J. Wysocki Signed-off-by: Sasha Levin --- drivers/acpi/ec.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 115994dfefec..77d6af611589 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -2301,6 +2301,34 @@ static const struct dmi_system_id acpi_ec_no_wakeup[] = { DMI_MATCH(DMI_PRODUCT_FAMILY, "103C_5336AN HP ZHAN 66 Pro"), }, }, + /* + * Lenovo Legion Go S; touchscreen blocks HW sleep when woken up from EC + * https://gitlab.freedesktop.org/drm/amd/-/issues/3929 + */ + { + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83L3"), + } + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83N6"), + } + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83Q2"), + } + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83Q3"), + } + }, { }, }; From 4c97ba1b0b98cec6d5759048d3b4509428be12ba Mon Sep 17 00:00:00 2001 From: Jean-Marc Eurin Date: Tue, 1 Apr 2025 17:15:42 -0700 Subject: [PATCH 545/606] ACPI PPTT: Fix coding mistakes in a couple of sizeof() calls [ Upstream commit 7ab4f0e37a0f4207e742a8de69be03984db6ebf0 ] The end of table checks should be done with the structure size, but 2 of the 3 similar calls use the pointer size. Signed-off-by: Jean-Marc Eurin Link: https://patch.msgid.link/20250402001542.2600671-1-jmeurin@google.com [ rjw: Subject edits ] Signed-off-by: Rafael J. Wysocki Signed-off-by: Sasha Levin --- drivers/acpi/pptt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c index a35dd0e41c27..f73ce6e13065 100644 --- a/drivers/acpi/pptt.c +++ b/drivers/acpi/pptt.c @@ -229,7 +229,7 @@ static int acpi_pptt_leaf_node(struct acpi_table_header *table_hdr, node_entry = ACPI_PTR_DIFF(node, table_hdr); entry = ACPI_ADD_PTR(struct acpi_subtable_header, table_hdr, sizeof(struct acpi_table_pptt)); - proc_sz = sizeof(struct acpi_pptt_processor *); + proc_sz = sizeof(struct acpi_pptt_processor); while ((unsigned long)entry + proc_sz < table_end) { cpu_node = (struct acpi_pptt_processor *)entry; @@ -270,7 +270,7 @@ static struct acpi_pptt_processor *acpi_find_processor_node(struct acpi_table_he table_end = (unsigned long)table_hdr + table_hdr->length; entry = ACPI_ADD_PTR(struct acpi_subtable_header, table_hdr, sizeof(struct acpi_table_pptt)); - proc_sz = sizeof(struct acpi_pptt_processor *); + proc_sz = sizeof(struct acpi_pptt_processor); /* find the processor structure associated with this cpuid */ while ((unsigned long)entry + proc_sz < table_end) { From 60ed102378a31f423e19b16f03439b60be489b37 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 3 Apr 2025 09:19:30 +0200 Subject: [PATCH 546/606] nvme: re-read ANA log page after ns scan completes [ Upstream commit 62baf70c327444338c34703c71aa8cc8e4189bd6 ] When scanning for new namespaces we might have missed an ANA AEN. The NVMe base spec (NVMe Base Specification v2.1, Figure 151 'Asynchonous Event Information - Notice': Asymmetric Namespace Access Change) states: A controller shall not send this even if an Attached Namespace Attribute Changed asynchronous event [...] is sent for the same event. so we need to re-read the ANA log page after we rescanned the namespace list to update the ANA states of the new namespaces. Signed-off-by: Hannes Reinecke Reviewed-by: Keith Busch Signed-off-by: Christoph Hellwig Signed-off-by: Sasha Levin --- drivers/nvme/host/core.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index e36c6fcab1ee..8827614ab8c6 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -3976,6 +3976,11 @@ static void nvme_scan_work(struct work_struct *work) /* Requeue if we have missed AENs */ if (test_bit(NVME_AER_NOTICE_NS_CHANGED, &ctrl->events)) nvme_queue_scan(ctrl); +#ifdef CONFIG_NVME_MULTIPATH + else + /* Re-read the ANA log page to not miss updates */ + queue_work(nvme_wq, &ctrl->ana_work); +#endif } /* From 0cf5fd802452b41c9ac3e96abcb80d12af2d82b6 Mon Sep 17 00:00:00 2001 From: Uday Shankar Date: Fri, 4 Apr 2025 14:06:43 -0600 Subject: [PATCH 547/606] nvme: multipath: fix return value of nvme_available_path [ Upstream commit e3105f54a51554fb1bbf19dcaf93c4411d2d6c8a ] The function returns bool so we should return false, not NULL. No functional changes are expected. Signed-off-by: Uday Shankar Signed-off-by: Christoph Hellwig Signed-off-by: Sasha Levin --- drivers/nvme/host/multipath.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c index 32283301199f..119afdfe4b91 100644 --- a/drivers/nvme/host/multipath.c +++ b/drivers/nvme/host/multipath.c @@ -426,7 +426,7 @@ static bool nvme_available_path(struct nvme_ns_head *head) struct nvme_ns *ns; if (!test_bit(NVME_NSHEAD_DISK_LIVE, &head->flags)) - return NULL; + return false; list_for_each_entry_srcu(ns, &head->list, siblings, srcu_read_lock_held(&head->srcu)) { From 18082da6ce0ef03adc76982ae0d7fb54e5bdb818 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Tue, 8 Apr 2025 00:02:15 -0700 Subject: [PATCH 548/606] objtool: Stop UNRET validation on UD2 [ Upstream commit 9f9cc012c2cbac4833746a0182e06a8eec940d19 ] In preparation for simplifying INSN_SYSCALL, make validate_unret() terminate control flow on UD2 just like validate_branch() already does. Signed-off-by: Josh Poimboeuf Signed-off-by: Ingo Molnar Cc: Linus Torvalds Link: https://lore.kernel.org/r/ce841269e7e28c8b7f32064464a9821034d724ff.1744095216.git.jpoimboe@kernel.org Signed-off-by: Sasha Levin --- tools/objtool/check.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/objtool/check.c b/tools/objtool/check.c index eb6d7025ee49..6d35fe0e4695 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -3949,6 +3949,9 @@ static int validate_unret(struct objtool_file *file, struct instruction *insn) break; } + if (insn->dead_end) + return 0; + if (!next) { WARN_INSN(insn, "teh end!"); return -1; From 4978a798a38d231ee630ef85437009b026e4dc55 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 2 Apr 2025 15:20:01 +0300 Subject: [PATCH 549/606] gpiolib: of: Move Atmel HSMCI quirk up out of the regulator comment [ Upstream commit b8c7a1ac884cc267d1031f8de07f1a689a69fbab ] The regulator comment in of_gpio_set_polarity_by_property() made on top of a couple of the cases, while Atmel HSMCI quirk is not related to that. Make it clear by moving Atmel HSMCI quirk up out of the scope of the regulator comment. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20250402122058.1517393-3-andriy.shevchenko@linux.intel.com Signed-off-by: Bartosz Golaszewski Signed-off-by: Sasha Levin --- drivers/gpio/gpiolib-of.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index cec9e8f29bbd..a0a2a0f75bba 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -247,6 +247,9 @@ static void of_gpio_set_polarity_by_property(const struct device_node *np, { "fsl,imx8qm-fec", "phy-reset-gpios", "phy-reset-active-high" }, { "fsl,s32v234-fec", "phy-reset-gpios", "phy-reset-active-high" }, #endif +#if IS_ENABLED(CONFIG_MMC_ATMELMCI) + { "atmel,hsmci", "cd-gpios", "cd-inverted" }, +#endif #if IS_ENABLED(CONFIG_PCI_IMX6) { "fsl,imx6q-pcie", "reset-gpio", "reset-gpio-active-high" }, { "fsl,imx6sx-pcie", "reset-gpio", "reset-gpio-active-high" }, @@ -272,9 +275,6 @@ static void of_gpio_set_polarity_by_property(const struct device_node *np, #if IS_ENABLED(CONFIG_REGULATOR_GPIO) { "regulator-gpio", "enable-gpio", "enable-active-high" }, { "regulator-gpio", "enable-gpios", "enable-active-high" }, -#endif -#if IS_ENABLED(CONFIG_MMC_ATMELMCI) - { "atmel,hsmci", "cd-gpios", "cd-inverted" }, #endif }; unsigned int i; From 84b52a6cd01202e7f3177ed286e3f0c200bd3bcd Mon Sep 17 00:00:00 2001 From: Qiuxu Zhuo Date: Tue, 11 Mar 2025 16:09:40 +0800 Subject: [PATCH 550/606] selftests/mincore: Allow read-ahead pages to reach the end of the file [ Upstream commit 197c1eaa7ba633a482ed7588eea6fd4aa57e08d4 ] When running the mincore_selftest on a system with an XFS file system, it failed the "check_file_mmap" test case due to the read-ahead pages reaching the end of the file. The failure log is as below: RUN global.check_file_mmap ... mincore_selftest.c:264:check_file_mmap:Expected i (1024) < vec_size (1024) mincore_selftest.c:265:check_file_mmap:Read-ahead pages reached the end of the file check_file_mmap: Test failed FAIL global.check_file_mmap This is because the read-ahead window size of the XFS file system on this machine is 4 MB, which is larger than the size from the #PF address to the end of the file. As a result, all the pages for this file are populated. blockdev --getra /dev/nvme0n1p5 8192 blockdev --getbsz /dev/nvme0n1p5 512 This issue can be fixed by extending the current FILE_SIZE 4MB to a larger number, but it will still fail if the read-ahead window size of the file system is larger enough. Additionally, in the real world, read-ahead pages reaching the end of the file can happen and is an expected behavior. Therefore, allowing read-ahead pages to reach the end of the file is a better choice for the "check_file_mmap" test case. Link: https://lore.kernel.org/r/20250311080940.21413-1-qiuxu.zhuo@intel.com Reported-by: Yi Lai Signed-off-by: Qiuxu Zhuo Signed-off-by: Shuah Khan Signed-off-by: Sasha Levin --- tools/testing/selftests/mincore/mincore_selftest.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/testing/selftests/mincore/mincore_selftest.c b/tools/testing/selftests/mincore/mincore_selftest.c index e949a43a6145..efabfcbe0b49 100644 --- a/tools/testing/selftests/mincore/mincore_selftest.c +++ b/tools/testing/selftests/mincore/mincore_selftest.c @@ -261,9 +261,6 @@ TEST(check_file_mmap) TH_LOG("No read-ahead pages found in memory"); } - EXPECT_LT(i, vec_size) { - TH_LOG("Read-ahead pages reached the end of the file"); - } /* * End of the readahead window. The rest of the pages shouldn't * be in memory. From 19160ed5e5fa7cef24135fe6c1347ce55713d4f1 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Tue, 8 Apr 2025 14:47:31 -0700 Subject: [PATCH 551/606] x86/bugs: Use SBPB in write_ibpb() if applicable [ Upstream commit fc9fd3f98423367c79e0bd85a9515df26dc1b3cc ] write_ibpb() does IBPB, which (among other things) flushes branch type predictions on AMD. If the CPU has SRSO_NO, or if the SRSO mitigation has been disabled, branch type flushing isn't needed, in which case the lighter-weight SBPB can be used. The 'x86_pred_cmd' variable already keeps track of whether IBPB or SBPB should be used. Use that instead of hardcoding IBPB. Signed-off-by: Josh Poimboeuf Signed-off-by: Ingo Molnar Link: https://lore.kernel.org/r/17c5dcd14b29199b75199d67ff7758de9d9a4928.1744148254.git.jpoimboe@kernel.org Signed-off-by: Sasha Levin --- arch/x86/entry/entry.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/entry/entry.S b/arch/x86/entry/entry.S index 2143358d0c4c..78fd2442b49d 100644 --- a/arch/x86/entry/entry.S +++ b/arch/x86/entry/entry.S @@ -16,7 +16,7 @@ SYM_FUNC_START(entry_ibpb) movl $MSR_IA32_PRED_CMD, %ecx - movl $PRED_CMD_IBPB, %eax + movl _ASM_RIP(x86_pred_cmd), %eax xorl %edx, %edx wrmsr From b73c62b1ca432f2406e973d7743b6274af55572e Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Tue, 8 Apr 2025 14:47:33 -0700 Subject: [PATCH 552/606] x86/bugs: Don't fill RSB on VMEXIT with eIBRS+retpoline [ Upstream commit 18bae0dfec15b24ec14ca17dc18603372f5f254f ] eIBRS protects against guest->host RSB underflow/poisoning attacks. Adding retpoline to the mix doesn't change that. Retpoline has a balanced CALL/RET anyway. So the current full RSB filling on VMEXIT with eIBRS+retpoline is overkill. Disable it or do the VMEXIT_LITE mitigation if needed. Suggested-by: Pawan Gupta Signed-off-by: Josh Poimboeuf Signed-off-by: Ingo Molnar Reviewed-by: Pawan Gupta Reviewed-by: Amit Shah Reviewed-by: Nikolay Borisov Cc: Paolo Bonzini Cc: Vitaly Kuznetsov Cc: Sean Christopherson Cc: David Woodhouse Link: https://lore.kernel.org/r/84a1226e5c9e2698eae1b5ade861f1b8bf3677dc.1744148254.git.jpoimboe@kernel.org Signed-off-by: Sasha Levin --- arch/x86/kernel/cpu/bugs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 7df458a6553e..a8fce2ab0f25 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -1600,20 +1600,20 @@ static void __init spectre_v2_determine_rsb_fill_type_at_vmexit(enum spectre_v2_ case SPECTRE_V2_NONE: return; - case SPECTRE_V2_EIBRS_LFENCE: case SPECTRE_V2_EIBRS: + case SPECTRE_V2_EIBRS_LFENCE: + case SPECTRE_V2_EIBRS_RETPOLINE: if (boot_cpu_has_bug(X86_BUG_EIBRS_PBRSB)) { - setup_force_cpu_cap(X86_FEATURE_RSB_VMEXIT_LITE); pr_info("Spectre v2 / PBRSB-eIBRS: Retire a single CALL on VMEXIT\n"); + setup_force_cpu_cap(X86_FEATURE_RSB_VMEXIT_LITE); } return; - case SPECTRE_V2_EIBRS_RETPOLINE: case SPECTRE_V2_RETPOLINE: case SPECTRE_V2_LFENCE: case SPECTRE_V2_IBRS: - setup_force_cpu_cap(X86_FEATURE_RSB_VMEXIT); pr_info("Spectre v2 / SpectreRSB : Filling RSB on VMEXIT\n"); + setup_force_cpu_cap(X86_FEATURE_RSB_VMEXIT); return; } From 0cad1849e903e2cfec4af6e11de8f7135be7d985 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Tue, 8 Apr 2025 14:47:34 -0700 Subject: [PATCH 553/606] x86/bugs: Don't fill RSB on context switch with eIBRS [ Upstream commit 27ce8299bc1ec6df8306073785ff82b30b3cc5ee ] User->user Spectre v2 attacks (including RSB) across context switches are already mitigated by IBPB in cond_mitigation(), if enabled globally or if either the prev or the next task has opted in to protection. RSB filling without IBPB serves no purpose for protecting user space, as indirect branches are still vulnerable. User->kernel RSB attacks are mitigated by eIBRS. In which case the RSB filling on context switch isn't needed, so remove it. Suggested-by: Pawan Gupta Signed-off-by: Josh Poimboeuf Signed-off-by: Ingo Molnar Reviewed-by: Pawan Gupta Reviewed-by: Amit Shah Reviewed-by: Nikolay Borisov Link: https://lore.kernel.org/r/98cdefe42180358efebf78e3b80752850c7a3e1b.1744148254.git.jpoimboe@kernel.org Signed-off-by: Sasha Levin --- arch/x86/kernel/cpu/bugs.c | 24 ++++++++++++------------ arch/x86/mm/tlb.c | 6 +++--- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index a8fce2ab0f25..78545f7e9cc6 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -1574,7 +1574,7 @@ static void __init spec_ctrl_disable_kernel_rrsba(void) rrsba_disabled = true; } -static void __init spectre_v2_determine_rsb_fill_type_at_vmexit(enum spectre_v2_mitigation mode) +static void __init spectre_v2_select_rsb_mitigation(enum spectre_v2_mitigation mode) { /* * Similar to context switches, there are two types of RSB attacks @@ -1598,7 +1598,7 @@ static void __init spectre_v2_determine_rsb_fill_type_at_vmexit(enum spectre_v2_ */ switch (mode) { case SPECTRE_V2_NONE: - return; + break; case SPECTRE_V2_EIBRS: case SPECTRE_V2_EIBRS_LFENCE: @@ -1607,18 +1607,21 @@ static void __init spectre_v2_determine_rsb_fill_type_at_vmexit(enum spectre_v2_ pr_info("Spectre v2 / PBRSB-eIBRS: Retire a single CALL on VMEXIT\n"); setup_force_cpu_cap(X86_FEATURE_RSB_VMEXIT_LITE); } - return; + break; case SPECTRE_V2_RETPOLINE: case SPECTRE_V2_LFENCE: case SPECTRE_V2_IBRS: - pr_info("Spectre v2 / SpectreRSB : Filling RSB on VMEXIT\n"); + pr_info("Spectre v2 / SpectreRSB: Filling RSB on context switch and VMEXIT\n"); + setup_force_cpu_cap(X86_FEATURE_RSB_CTXSW); setup_force_cpu_cap(X86_FEATURE_RSB_VMEXIT); - return; - } + break; - pr_warn_once("Unknown Spectre v2 mode, disabling RSB mitigation at VM exit"); - dump_stack(); + default: + pr_warn_once("Unknown Spectre v2 mode, disabling RSB mitigation\n"); + dump_stack(); + break; + } } /* @@ -1844,10 +1847,7 @@ static void __init spectre_v2_select_mitigation(void) * * FIXME: Is this pointless for retbleed-affected AMD? */ - setup_force_cpu_cap(X86_FEATURE_RSB_CTXSW); - pr_info("Spectre v2 / SpectreRSB mitigation: Filling RSB on context switch\n"); - - spectre_v2_determine_rsb_fill_type_at_vmexit(mode); + spectre_v2_select_rsb_mitigation(mode); /* * Retpoline protects the kernel, but doesn't protect firmware. IBRS diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index df1794a5e38a..4872bb082b19 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -392,9 +392,9 @@ static void cond_mitigation(struct task_struct *next) prev_mm = this_cpu_read(cpu_tlbstate.last_user_mm_spec); /* - * Avoid user/user BTB poisoning by flushing the branch predictor - * when switching between processes. This stops one process from - * doing Spectre-v2 attacks on another. + * Avoid user->user BTB/RSB poisoning by flushing them when switching + * between processes. This stops one process from doing Spectre-v2 + * attacks on another. * * Both, the conditional and the always IBPB mode use the mm * pointer to avoid the IBPB when switching between tasks of the From e45e8f0dd324c0b863bf956456f009d1faede286 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 8 Apr 2025 17:29:09 +0200 Subject: [PATCH 554/606] nvmet-fc: take tgtport reference only once [ Upstream commit b0b26ad0e1943de25ce82a7e5af3574f31b1cf99 ] The reference counting code can be simplified. Instead taking a tgtport refrerence at the beginning of nvmet_fc_alloc_hostport and put it back if not a new hostport object is allocated, only take it when a new hostport object is allocated. Signed-off-by: Daniel Wagner Reviewed-by: Hannes Reinecke Signed-off-by: Christoph Hellwig Signed-off-by: Sasha Levin --- drivers/nvme/target/fc.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/drivers/nvme/target/fc.c b/drivers/nvme/target/fc.c index d40d5a4ea932..68ff9540e2d1 100644 --- a/drivers/nvme/target/fc.c +++ b/drivers/nvme/target/fc.c @@ -1030,33 +1030,24 @@ nvmet_fc_alloc_hostport(struct nvmet_fc_tgtport *tgtport, void *hosthandle) struct nvmet_fc_hostport *newhost, *match = NULL; unsigned long flags; + /* + * Caller holds a reference on tgtport. + */ + /* if LLDD not implemented, leave as NULL */ if (!hosthandle) return NULL; - /* - * take reference for what will be the newly allocated hostport if - * we end up using a new allocation - */ - if (!nvmet_fc_tgtport_get(tgtport)) - return ERR_PTR(-EINVAL); - spin_lock_irqsave(&tgtport->lock, flags); match = nvmet_fc_match_hostport(tgtport, hosthandle); spin_unlock_irqrestore(&tgtport->lock, flags); - if (match) { - /* no new allocation - release reference */ - nvmet_fc_tgtport_put(tgtport); + if (match) return match; - } newhost = kzalloc(sizeof(*newhost), GFP_KERNEL); - if (!newhost) { - /* no new allocation - release reference */ - nvmet_fc_tgtport_put(tgtport); + if (!newhost) return ERR_PTR(-ENOMEM); - } spin_lock_irqsave(&tgtport->lock, flags); match = nvmet_fc_match_hostport(tgtport, hosthandle); @@ -1065,6 +1056,7 @@ nvmet_fc_alloc_hostport(struct nvmet_fc_tgtport *tgtport, void *hosthandle) kfree(newhost); newhost = match; } else { + nvmet_fc_tgtport_get(tgtport); newhost->tgtport = tgtport; newhost->hosthandle = hosthandle; INIT_LIST_HEAD(&newhost->host_list); From f444c139e820f8a09c3c76194e0f061009038659 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 8 Apr 2025 17:29:10 +0200 Subject: [PATCH 555/606] nvmet-fc: put ref when assoc->del_work is already scheduled [ Upstream commit 70289ae5cac4d3a39575405aaf63330486cea030 ] Do not leak the tgtport reference when the work is already scheduled. Signed-off-by: Daniel Wagner Reviewed-by: Hannes Reinecke Signed-off-by: Christoph Hellwig Signed-off-by: Sasha Levin --- drivers/nvme/target/fc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/target/fc.c b/drivers/nvme/target/fc.c index 68ff9540e2d1..570c58d2b5a5 100644 --- a/drivers/nvme/target/fc.c +++ b/drivers/nvme/target/fc.c @@ -1091,7 +1091,8 @@ static void nvmet_fc_schedule_delete_assoc(struct nvmet_fc_tgt_assoc *assoc) { nvmet_fc_tgtport_get(assoc->tgtport); - queue_work(nvmet_wq, &assoc->del_work); + if (!queue_work(nvmet_wq, &assoc->del_work)) + nvmet_fc_tgtport_put(assoc->tgtport); } static struct nvmet_fc_tgt_assoc * From e5208da73954b651ba4d80c0348da58178d716a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Sun, 6 Oct 2024 19:20:13 +0200 Subject: [PATCH 556/606] cifs: Fix encoding of SMB1 Session Setup Kerberos Request in non-UNICODE mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 16cb6b0509b65ac89187e9402e0b7a9ddf1765ef ] Like in UNICODE mode, SMB1 Session Setup Kerberos Request contains oslm and domain strings. Extract common code into ascii_oslm_strings() and ascii_domain_string() functions (similar to unicode variants) and use these functions in non-UNICODE code path in sess_auth_kerberos(). Decision if non-UNICODE or UNICODE mode is used is based on the SMBFLG2_UNICODE flag in Flags2 packed field, and not based on the capabilities of server. Fix this check too. Signed-off-by: Pali Rohár Signed-off-by: Steve French Signed-off-by: Sasha Levin --- fs/smb/client/sess.c | 60 +++++++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/fs/smb/client/sess.c b/fs/smb/client/sess.c index c2a98b273664..f04922eb45d4 100644 --- a/fs/smb/client/sess.c +++ b/fs/smb/client/sess.c @@ -732,6 +732,22 @@ unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp) *pbcc_area = bcc_ptr; } +static void +ascii_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp) +{ + char *bcc_ptr = *pbcc_area; + + strcpy(bcc_ptr, "Linux version "); + bcc_ptr += strlen("Linux version "); + strcpy(bcc_ptr, init_utsname()->release); + bcc_ptr += strlen(init_utsname()->release) + 1; + + strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); + bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; + + *pbcc_area = bcc_ptr; +} + static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses, const struct nls_table *nls_cp) { @@ -756,6 +772,25 @@ static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses, *pbcc_area = bcc_ptr; } +static void ascii_domain_string(char **pbcc_area, struct cifs_ses *ses, + const struct nls_table *nls_cp) +{ + char *bcc_ptr = *pbcc_area; + int len; + + /* copy domain */ + if (ses->domainName != NULL) { + len = strscpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN); + if (WARN_ON_ONCE(len < 0)) + len = CIFS_MAX_DOMAINNAME_LEN - 1; + bcc_ptr += len; + } /* else we send a null domain name so server will default to its own domain */ + *bcc_ptr = 0; + bcc_ptr++; + + *pbcc_area = bcc_ptr; +} + static void unicode_ssetup_strings(char **pbcc_area, struct cifs_ses *ses, const struct nls_table *nls_cp) { @@ -801,25 +836,10 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses, *bcc_ptr = 0; bcc_ptr++; /* account for null termination */ - /* copy domain */ - if (ses->domainName != NULL) { - len = strscpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN); - if (WARN_ON_ONCE(len < 0)) - len = CIFS_MAX_DOMAINNAME_LEN - 1; - bcc_ptr += len; - } /* else we send a null domain name so server will default to its own domain */ - *bcc_ptr = 0; - bcc_ptr++; - /* BB check for overflow here */ - strcpy(bcc_ptr, "Linux version "); - bcc_ptr += strlen("Linux version "); - strcpy(bcc_ptr, init_utsname()->release); - bcc_ptr += strlen(init_utsname()->release) + 1; - - strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); - bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; + ascii_domain_string(&bcc_ptr, ses, nls_cp); + ascii_oslm_strings(&bcc_ptr, nls_cp); *pbcc_area = bcc_ptr; } @@ -1622,7 +1642,7 @@ sess_auth_kerberos(struct sess_data *sess_data) sess_data->iov[1].iov_len = msg->secblob_len; pSMB->req.SecurityBlobLength = cpu_to_le16(sess_data->iov[1].iov_len); - if (ses->capabilities & CAP_UNICODE) { + if (pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) { /* unicode strings must be word aligned */ if (!IS_ALIGNED(sess_data->iov[0].iov_len + sess_data->iov[1].iov_len, 2)) { *bcc_ptr = 0; @@ -1631,8 +1651,8 @@ sess_auth_kerberos(struct sess_data *sess_data) unicode_oslm_strings(&bcc_ptr, sess_data->nls_cp); unicode_domain_string(&bcc_ptr, ses, sess_data->nls_cp); } else { - /* BB: is this right? */ - ascii_ssetup_strings(&bcc_ptr, ses, sess_data->nls_cp); + ascii_oslm_strings(&bcc_ptr, sess_data->nls_cp); + ascii_domain_string(&bcc_ptr, ses, sess_data->nls_cp); } sess_data->iov[2].iov_len = (long) bcc_ptr - From dc18c5b1301a6fede7b26bebf621816f1a3a0fff Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 4 Apr 2025 15:34:29 +0200 Subject: [PATCH 557/606] timekeeping: Add a lockdep override in tick_freeze() [ Upstream commit 92e250c624ea37fde64bfd624fd2556f0d846f18 ] tick_freeze() acquires a raw spinlock (tick_freeze_lock). Later in the callchain (timekeeping_suspend() -> mc146818_avoid_UIP()) the RTC driver acquires a spinlock which becomes a sleeping lock on PREEMPT_RT. Lockdep complains about this lock nesting. Add a lockdep override for this special case and a comment explaining why it is okay. Reported-by: Borislav Petkov Reported-by: Chris Bainbridge Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Link: https://lore.kernel.org/all/20250404133429.pnAzf-eF@linutronix.de Closes: https://lore.kernel.org/all/20250330113202.GAZ-krsjAnurOlTcp-@fat_crate.local/ Closes: https://lore.kernel.org/all/CAP-bSRZ0CWyZZsMtx046YV8L28LhY0fson2g4EqcwRAVN1Jk+Q@mail.gmail.com/ Signed-off-by: Sasha Levin --- kernel/time/tick-common.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index 7f2b17fc8ce4..ecdb8c2b2cab 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c @@ -495,6 +495,7 @@ void tick_resume(void) #ifdef CONFIG_SUSPEND static DEFINE_RAW_SPINLOCK(tick_freeze_lock); +static DEFINE_WAIT_OVERRIDE_MAP(tick_freeze_map, LD_WAIT_SLEEP); static unsigned int tick_freeze_depth; /** @@ -514,9 +515,22 @@ void tick_freeze(void) if (tick_freeze_depth == num_online_cpus()) { trace_suspend_resume(TPS("timekeeping_freeze"), smp_processor_id(), true); + /* + * All other CPUs have their interrupts disabled and are + * suspended to idle. Other tasks have been frozen so there + * is no scheduling happening. This means that there is no + * concurrency in the system at this point. Therefore it is + * okay to acquire a sleeping lock on PREEMPT_RT, such as a + * spinlock, because the lock cannot be held by other CPUs + * or threads and acquiring it cannot block. + * + * Inform lockdep about the situation. + */ + lock_map_acquire_try(&tick_freeze_map); system_state = SYSTEM_SUSPEND; sched_clock_suspend(); timekeeping_suspend(); + lock_map_release(&tick_freeze_map); } else { tick_suspend_local(); } @@ -538,8 +552,16 @@ void tick_unfreeze(void) raw_spin_lock(&tick_freeze_lock); if (tick_freeze_depth == num_online_cpus()) { + /* + * Similar to tick_freeze(). On resumption the first CPU may + * acquire uncontended sleeping locks while other CPUs block on + * tick_freeze_lock. + */ + lock_map_acquire_try(&tick_freeze_map); timekeeping_resume(); sched_clock_resume(); + lock_map_release(&tick_freeze_map); + system_state = SYSTEM_RUNNING; trace_suspend_resume(TPS("timekeeping_freeze"), smp_processor_id(), false); From ea92c93887f500c2298f5c8b135a68929b664d85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Thu, 26 Dec 2024 17:12:09 +0100 Subject: [PATCH 558/606] cifs: Fix querying of WSL CHR and BLK reparse points over SMB1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit ef86ab131d9127dfbfa8f06e12441d05fdfb090b ] When reparse point in SMB1 query_path_info() callback was detected then query also for EA $LXDEV. In this EA are stored device major and minor numbers used by WSL CHR and BLK reparse points. Without major and minor numbers, stat() syscall does not work for char and block devices. Similar code is already in SMB2+ query_path_info() callback function. Signed-off-by: Pali Rohár Signed-off-by: Steve French Signed-off-by: Sasha Levin --- fs/smb/client/smb1ops.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c index bc1bac36c1b2..caa1d852ece4 100644 --- a/fs/smb/client/smb1ops.c +++ b/fs/smb/client/smb1ops.c @@ -597,6 +597,42 @@ static int cifs_query_path_info(const unsigned int xid, CIFSSMBClose(xid, tcon, fid.netfid); } +#ifdef CONFIG_CIFS_XATTR + /* + * For WSL CHR and BLK reparse points it is required to fetch + * EA $LXDEV which contains major and minor device numbers. + */ + if (!rc && data->reparse_point) { + struct smb2_file_full_ea_info *ea; + + ea = (struct smb2_file_full_ea_info *)data->wsl.eas; + rc = CIFSSMBQAllEAs(xid, tcon, full_path, SMB2_WSL_XATTR_DEV, + &ea->ea_data[SMB2_WSL_XATTR_NAME_LEN + 1], + SMB2_WSL_XATTR_DEV_SIZE, cifs_sb); + if (rc == SMB2_WSL_XATTR_DEV_SIZE) { + ea->next_entry_offset = cpu_to_le32(0); + ea->flags = 0; + ea->ea_name_length = SMB2_WSL_XATTR_NAME_LEN; + ea->ea_value_length = cpu_to_le16(SMB2_WSL_XATTR_DEV_SIZE); + memcpy(&ea->ea_data[0], SMB2_WSL_XATTR_DEV, SMB2_WSL_XATTR_NAME_LEN + 1); + data->wsl.eas_len = sizeof(*ea) + SMB2_WSL_XATTR_NAME_LEN + 1 + + SMB2_WSL_XATTR_DEV_SIZE; + rc = 0; + } else if (rc >= 0) { + /* It is an error if EA $LXDEV has wrong size. */ + rc = -EINVAL; + } else { + /* + * In all other cases ignore error if fetching + * of EA $LXDEV failed. It is needed only for + * WSL CHR and BLK reparse points and wsl_to_fattr() + * handle the case when EA is missing. + */ + rc = 0; + } + } +#endif + return rc; } From a8550ac19d46de531b2de784fcaad860fa49aa6e Mon Sep 17 00:00:00 2001 From: Ojaswin Mujoo Date: Fri, 28 Mar 2025 11:54:52 +0530 Subject: [PATCH 559/606] ext4: make block validity check resistent to sb bh corruption [ Upstream commit ccad447a3d331a239477c281533bacb585b54a98 ] Block validity checks need to be skipped in case they are called for journal blocks since they are part of system's protected zone. Currently, this is done by checking inode->ino against sbi->s_es->s_journal_inum, which is a direct read from the ext4 sb buffer head. If someone modifies this underneath us then the s_journal_inum field might get corrupted. To prevent against this, change the check to directly compare the inode with journal->j_inode. **Slight change in behavior**: During journal init path, check_block_validity etc might be called for journal inode when sbi->s_journal is not set yet. In this case we now proceed with ext4_inode_block_valid() instead of returning early. Since systems zones have not been set yet, it is okay to proceed so we can perform basic checks on the blocks. Suggested-by: Baokun Li Reviewed-by: Baokun Li Reviewed-by: Jan Kara Reviewed-by: Zhang Yi Signed-off-by: Ojaswin Mujoo Link: https://patch.msgid.link/0c06bc9ebfcd6ccfed84a36e79147bf45ff5adc1.1743142920.git.ojaswin@linux.ibm.com Signed-off-by: Theodore Ts'o Signed-off-by: Sasha Levin --- fs/ext4/block_validity.c | 5 ++--- fs/ext4/inode.c | 7 ++++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c index 6fe3c941b565..4d6ba140276b 100644 --- a/fs/ext4/block_validity.c +++ b/fs/ext4/block_validity.c @@ -351,10 +351,9 @@ int ext4_check_blockref(const char *function, unsigned int line, { __le32 *bref = p; unsigned int blk; + journal_t *journal = EXT4_SB(inode->i_sb)->s_journal; - if (ext4_has_feature_journal(inode->i_sb) && - (inode->i_ino == - le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum))) + if (journal && inode == journal->j_inode) return 0; while (bref < p+max) { diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index ddfeaf19bff1..f2b60fb0b937 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -378,10 +378,11 @@ static int __check_block_validity(struct inode *inode, const char *func, unsigned int line, struct ext4_map_blocks *map) { - if (ext4_has_feature_journal(inode->i_sb) && - (inode->i_ino == - le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum))) + journal_t *journal = EXT4_SB(inode->i_sb)->s_journal; + + if (journal && inode == journal->j_inode) return 0; + if (!ext4_inode_block_valid(inode, map->m_pblk, map->m_len)) { ext4_error_inode(inode, func, line, map->m_pblk, "lblock %lu mapped to illegal pblock %llu " From fa99f1886e0a6cb086acaa658b54d78ade3a3209 Mon Sep 17 00:00:00 2001 From: Xingui Yang Date: Wed, 12 Mar 2025 17:51:35 +0800 Subject: [PATCH 560/606] scsi: hisi_sas: Fix I/O errors caused by hardware port ID changes [ Upstream commit daff37f00c7506ca322ccfce95d342022f06ec58 ] The hw port ID of phy may change when inserting disks in batches, causing the port ID in hisi_sas_port and itct to be inconsistent with the hardware, resulting in I/O errors. The solution is to set the device state to gone to intercept I/O sent to the device, and then execute linkreset to discard and find the disk to re-update its information. Signed-off-by: Xingui Yang Link: https://lore.kernel.org/r/20250312095135.3048379-3-yangxingui@huawei.com Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin --- drivers/scsi/hisi_sas/hisi_sas_main.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index f78c5f8a49ff..7e64661d215b 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -911,8 +911,28 @@ static void hisi_sas_phyup_work_common(struct work_struct *work, container_of(work, typeof(*phy), works[event]); struct hisi_hba *hisi_hba = phy->hisi_hba; struct asd_sas_phy *sas_phy = &phy->sas_phy; + struct asd_sas_port *sas_port = sas_phy->port; + struct hisi_sas_port *port = phy->port; + struct device *dev = hisi_hba->dev; + struct domain_device *port_dev; int phy_no = sas_phy->id; + if (!test_bit(HISI_SAS_RESETTING_BIT, &hisi_hba->flags) && + sas_port && port && (port->id != phy->port_id)) { + dev_info(dev, "phy%d's hw port id changed from %d to %llu\n", + phy_no, port->id, phy->port_id); + port_dev = sas_port->port_dev; + if (port_dev && !dev_is_expander(port_dev->dev_type)) { + /* + * Set the device state to gone to block + * sending IO to the device. + */ + set_bit(SAS_DEV_GONE, &port_dev->state); + hisi_sas_notify_phy_event(phy, HISI_PHYE_LINK_RESET); + return; + } + } + phy->wait_phyup_cnt = 0; if (phy->identify.target_port_protocols == SAS_PROTOCOL_SSP) hisi_hba->hw->sl_notify_ssp(hisi_hba, phy_no); From 4cdb02e9f96307c709bcfaa86715986f0ea8b2f8 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Wed, 19 Mar 2025 15:30:18 +0000 Subject: [PATCH 561/606] scsi: ufs: exynos: Ensure pre_link() executes before exynos_ufs_phy_init() [ Upstream commit 3d101165e72316775947d71321d97194f03dfef3 ] Ensure clocks are enabled before configuring unipro. Additionally move the pre_link() hook before the exynos_ufs_phy_init() calls. This means the register write sequence more closely resembles the ordering of the downstream driver. Signed-off-by: Peter Griffin Link: https://lore.kernel.org/r/20250319-exynos-ufs-stability-fixes-v2-1-96722cc2ba1b@linaro.org Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin --- drivers/ufs/host/ufs-exynos.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c index d138b66d5e35..f61126189876 100644 --- a/drivers/ufs/host/ufs-exynos.c +++ b/drivers/ufs/host/ufs-exynos.c @@ -990,9 +990,14 @@ static int exynos_ufs_pre_link(struct ufs_hba *hba) exynos_ufs_config_intr(ufs, DFES_DEF_L4_ERRS, UNIPRO_L4); exynos_ufs_set_unipro_pclk_div(ufs); + exynos_ufs_setup_clocks(hba, true, PRE_CHANGE); + /* unipro */ exynos_ufs_config_unipro(ufs); + if (ufs->drv_data->pre_link) + ufs->drv_data->pre_link(ufs); + /* m-phy */ exynos_ufs_phy_init(ufs); if (!(ufs->opts & EXYNOS_UFS_OPT_SKIP_CONFIG_PHY_ATTR)) { @@ -1000,11 +1005,6 @@ static int exynos_ufs_pre_link(struct ufs_hba *hba) exynos_ufs_config_phy_cap_attr(ufs); } - exynos_ufs_setup_clocks(hba, true, PRE_CHANGE); - - if (ufs->drv_data->pre_link) - ufs->drv_data->pre_link(ufs); - return 0; } From a862d24e1fc3ab1b5e5f20878d2898cea346d0ec Mon Sep 17 00:00:00 2001 From: Igor Pylypiv Date: Wed, 19 Mar 2025 23:03:05 +0000 Subject: [PATCH 562/606] scsi: pm80xx: Set phy_attached to zero when device is gone [ Upstream commit f7b705c238d1483f0a766e2b20010f176e5c0fb7 ] When a fatal error occurs, a phy down event may not be received to set phy->phy_attached to zero. Signed-off-by: Igor Pylypiv Signed-off-by: Salomon Dushimirimana Link: https://lore.kernel.org/r/20250319230305.3172920-1-salomondush@google.com Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin --- drivers/scsi/pm8001/pm8001_sas.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index ee2da8e49d4c..a9d6dac41334 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -719,6 +719,7 @@ static void pm8001_dev_gone_notify(struct domain_device *dev) spin_lock_irqsave(&pm8001_ha->lock, flags); } PM8001_CHIP_DISP->dereg_dev_req(pm8001_ha, device_id); + pm8001_ha->phy[pm8001_dev->attached_phy].phy_attached = 0; pm8001_free_dev(pm8001_dev); } else { pm8001_dbg(pm8001_ha, DISC, "Found dev has gone.\n"); From bb7878cca96923cc67d1dd7b6fa0fc76da40a8fc Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Tue, 1 Apr 2025 11:23:03 +0200 Subject: [PATCH 563/606] x86/i8253: Call clockevent_i8253_disable() with interrupts disabled [ Upstream commit 3940f5349b476197fb079c5aa19c9a988de64efb ] There's a lockdep false positive warning related to i8253_lock: WARNING: HARDIRQ-safe -> HARDIRQ-unsafe lock order detected ... systemd-sleep/3324 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire: ffffffffb2c23398 (i8253_lock){+.+.}-{2:2}, at: pcspkr_event+0x3f/0xe0 [pcspkr] ... ... which became HARDIRQ-irq-unsafe at: ... lock_acquire+0xd0/0x2f0 _raw_spin_lock+0x30/0x40 clockevent_i8253_disable+0x1c/0x60 pit_timer_init+0x25/0x50 hpet_time_init+0x46/0x50 x86_late_time_init+0x1b/0x40 start_kernel+0x962/0xa00 x86_64_start_reservations+0x24/0x30 x86_64_start_kernel+0xed/0xf0 common_startup_64+0x13e/0x141 ... Lockdep complains due pit_timer_init() using the lock in an IRQ-unsafe fashion, but it's a false positive, because there is no deadlock possible at that point due to init ordering: at the point where pit_timer_init() is called there is no other possible usage of i8253_lock because the system is still in the very early boot stage with no interrupts. But in any case, pit_timer_init() should disable interrupts before calling clockevent_i8253_disable() out of general principle, and to keep lockdep working even in this scenario. Use scoped_guard() for that, as suggested by Thomas Gleixner. [ mingo: Cleaned up the changelog. ] Suggested-by: Thomas Gleixner Signed-off-by: Fernando Fernandez Mancera Signed-off-by: Ingo Molnar Reviewed-by: Thomas Gleixner Link: https://lore.kernel.org/r/Z-uwd4Bnn7FcCShX@gmail.com Signed-off-by: Sasha Levin --- arch/x86/kernel/i8253.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c index 80e262bb627f..cb9852ad6098 100644 --- a/arch/x86/kernel/i8253.c +++ b/arch/x86/kernel/i8253.c @@ -46,7 +46,8 @@ bool __init pit_timer_init(void) * VMMs otherwise steal CPU time just to pointlessly waggle * the (masked) IRQ. */ - clockevent_i8253_disable(); + scoped_guard(irq) + clockevent_i8253_disable(); return false; } clockevent_i8253_init(true); From ce7e04d26a3566aefbc603c6bb39067283bc1268 Mon Sep 17 00:00:00 2001 From: Gou Hao Date: Thu, 10 Apr 2025 15:12:36 +0800 Subject: [PATCH 564/606] iomap: skip unnecessary ifs_block_is_uptodate check [ Upstream commit 8e3c15ee0d292c413c66fe10201d1b035a0bea72 ] In iomap_adjust_read_range, i is either the first !uptodate block, or it is past last for the second loop looking for trailing uptodate blocks. Assuming there's no overflow (there's no combination of huge folios and tiny blksize) then yeah, there is no point in retesting that the same block pointed to by i is uptodate since we hold the folio lock so nobody else could have set it uptodate. Signed-off-by: Gou Hao Link: https://lore.kernel.org/20250410071236.16017-1-gouhao@uniontech.com Reviewed-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig Suggested-by: Christoph Hellwig Signed-off-by: Christian Brauner Signed-off-by: Sasha Levin --- fs/iomap/buffered-io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c index e7e6701806ad..7ffdf0d037fa 100644 --- a/fs/iomap/buffered-io.c +++ b/fs/iomap/buffered-io.c @@ -224,7 +224,7 @@ static void iomap_adjust_read_range(struct inode *inode, struct folio *folio, } /* truncate len if we find any trailing uptodate block(s) */ - for ( ; i <= last; i++) { + while (++i <= last) { if (ifs_block_is_uptodate(ifs, i)) { plen -= (last - i + 1) * block_size; last = i - 1; From f0209397ed2c77d0d18ba7beb49f48e63009b3cd Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 14 Apr 2025 14:09:48 +0200 Subject: [PATCH 565/606] riscv: Provide all alternative macros all the time [ Upstream commit fb53a9aa5f5b8bf302f3260a7f1f5a24345ce62a ] We need to provide all six forms of the alternative macros (ALTERNATIVE, ALTERNATIVE_2, _ALTERNATIVE_CFG, _ALTERNATIVE_CFG_2, __ALTERNATIVE_CFG, __ALTERNATIVE_CFG_2) for all four cases derived from the two ifdefs (RISCV_ALTERNATIVE, __ASSEMBLY__) in order to ensure all configs can compile. Define this missing ones and ensure all are defined to consume all parameters passed. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202504130710.3IKz6Ibs-lkp@intel.com/ Signed-off-by: Andrew Jones Tested-by: Alexandre Ghiti Reviewed-by: Alexandre Ghiti Link: https://lore.kernel.org/r/20250414120947.135173-2-ajones@ventanamicro.com Signed-off-by: Alexandre Ghiti Signed-off-by: Sasha Levin --- arch/riscv/include/asm/alternative-macros.h | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/arch/riscv/include/asm/alternative-macros.h b/arch/riscv/include/asm/alternative-macros.h index 721ec275ce57..231d777d936c 100644 --- a/arch/riscv/include/asm/alternative-macros.h +++ b/arch/riscv/include/asm/alternative-macros.h @@ -115,24 +115,19 @@ \old_c .endm -#define _ALTERNATIVE_CFG(old_c, ...) \ - ALTERNATIVE_CFG old_c - -#define _ALTERNATIVE_CFG_2(old_c, ...) \ - ALTERNATIVE_CFG old_c +#define __ALTERNATIVE_CFG(old_c, ...) ALTERNATIVE_CFG old_c +#define __ALTERNATIVE_CFG_2(old_c, ...) ALTERNATIVE_CFG old_c #else /* !__ASSEMBLY__ */ -#define __ALTERNATIVE_CFG(old_c) \ - old_c "\n" - -#define _ALTERNATIVE_CFG(old_c, ...) \ - __ALTERNATIVE_CFG(old_c) - -#define _ALTERNATIVE_CFG_2(old_c, ...) \ - __ALTERNATIVE_CFG(old_c) +#define __ALTERNATIVE_CFG(old_c, ...) old_c "\n" +#define __ALTERNATIVE_CFG_2(old_c, ...) old_c "\n" #endif /* __ASSEMBLY__ */ + +#define _ALTERNATIVE_CFG(old_c, ...) __ALTERNATIVE_CFG(old_c) +#define _ALTERNATIVE_CFG_2(old_c, ...) __ALTERNATIVE_CFG_2(old_c) + #endif /* CONFIG_RISCV_ALTERNATIVE */ /* From 6c2e136ffd056e460528518c902e0f3424b694cc Mon Sep 17 00:00:00 2001 From: Yunlong Xing Date: Mon, 14 Apr 2025 11:01:59 +0800 Subject: [PATCH 566/606] loop: aio inherit the ioprio of original request [ Upstream commit 1fdb8188c3d505452b40cdb365b1bb32be533a8e ] Set cmd->iocb.ki_ioprio to the ioprio of loop device's request. The purpose is to inherit the original request ioprio in the aio flow. Signed-off-by: Yunlong Xing Signed-off-by: Zhiguo Niu Reviewed-by: Christoph Hellwig Link: https://lore.kernel.org/r/20250414030159.501180-1-yunlong.xing@unisoc.com Signed-off-by: Jens Axboe Signed-off-by: Sasha Levin --- drivers/block/loop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 8a6c1146df00..455e2a2b149f 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -441,7 +441,7 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd, cmd->iocb.ki_filp = file; cmd->iocb.ki_complete = lo_rw_aio_complete; cmd->iocb.ki_flags = IOCB_DIRECT; - cmd->iocb.ki_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 0); + cmd->iocb.ki_ioprio = req_get_ioprio(rq); if (rw == ITER_SOURCE) ret = call_write_iter(file, &cmd->iocb, &iter); From 0134e326abc30eca0eef20fcf3235ee0b9ad924e Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Tue, 1 Apr 2025 06:47:49 -0700 Subject: [PATCH 567/606] spi: tegra210-quad: use WARN_ON_ONCE instead of WARN_ON for timeouts [ Upstream commit 41c721fc093938745d116c3a21326a0ee03bb491 ] Some machines with tegra_qspi_combined_seq_xfer hardware issues generate excessive kernel warnings, severely polluting the logs: dmesg | grep -i "WARNING:.*tegra_qspi_transfer_one_message" | wc -l 94451 This patch replaces WARN_ON with WARN_ON_ONCE for timeout conditions to reduce log spam. The subsequent error message still prints on each occurrence, providing sufficient information about the failure, while the stack trace is only needed once for debugging purposes. Signed-off-by: Breno Leitao Link: https://patch.msgid.link/20250401-tegra-v2-1-126c293ec047@debian.org Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- drivers/spi/spi-tegra210-quad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c index d1afa4140e8a..2abb54f9a9ba 100644 --- a/drivers/spi/spi-tegra210-quad.c +++ b/drivers/spi/spi-tegra210-quad.c @@ -1117,7 +1117,7 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, (&tqspi->xfer_completion, QSPI_DMA_TIMEOUT); - if (WARN_ON(ret == 0)) { + if (WARN_ON_ONCE(ret == 0)) { dev_err(tqspi->dev, "QSPI Transfer failed with timeout: %d\n", ret); if (tqspi->is_curr_dma_xfer && From 96ae4c19ed71d7cda8aadb522f3d2dd04ac37cd6 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Tue, 1 Apr 2025 06:47:50 -0700 Subject: [PATCH 568/606] spi: tegra210-quad: add rate limiting and simplify timeout error message [ Upstream commit 21f4314e66ed8d40b2ee24185d1a06a07a512eb1 ] On malfunctioning hardware, timeout error messages can appear thousands of times, creating unnecessary system pressure and log bloat. This patch makes two improvements: 1. Replace dev_err() with dev_err_ratelimited() to prevent log flooding when hardware errors persist 2. Remove the redundant timeout value parameter from the error message, as 'ret' is always zero in this error path These changes reduce logging overhead while maintaining necessary error reporting for debugging purposes. Signed-off-by: Breno Leitao Link: https://patch.msgid.link/20250401-tegra-v2-2-126c293ec047@debian.org Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- drivers/spi/spi-tegra210-quad.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c index 2abb54f9a9ba..e3c236025a7b 100644 --- a/drivers/spi/spi-tegra210-quad.c +++ b/drivers/spi/spi-tegra210-quad.c @@ -1118,8 +1118,8 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, QSPI_DMA_TIMEOUT); if (WARN_ON_ONCE(ret == 0)) { - dev_err(tqspi->dev, "QSPI Transfer failed with timeout: %d\n", - ret); + dev_err_ratelimited(tqspi->dev, + "QSPI Transfer failed with timeout\n"); if (tqspi->is_curr_dma_xfer && (tqspi->cur_direction & DATA_DIR_TX)) dmaengine_terminate_all From aa0cf04b6959adbb54b536307d590d2a350d02d7 Mon Sep 17 00:00:00 2001 From: Mostafa Saleh Date: Tue, 15 Apr 2025 20:33:54 +0000 Subject: [PATCH 569/606] ubsan: Fix panic from test_ubsan_out_of_bounds [ Upstream commit 9b044614be12d78d3a93767708b8d02fb7dfa9b0 ] Running lib_ubsan.ko on arm64 (without CONFIG_UBSAN_TRAP) panics the kernel: [ 31.616546] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: test_ubsan_out_of_bounds+0x158/0x158 [test_ubsan] [ 31.646817] CPU: 3 UID: 0 PID: 179 Comm: insmod Not tainted 6.15.0-rc2 #1 PREEMPT [ 31.648153] Hardware name: linux,dummy-virt (DT) [ 31.648970] Call trace: [ 31.649345] show_stack+0x18/0x24 (C) [ 31.650960] dump_stack_lvl+0x40/0x84 [ 31.651559] dump_stack+0x18/0x24 [ 31.652264] panic+0x138/0x3b4 [ 31.652812] __ktime_get_real_seconds+0x0/0x10 [ 31.653540] test_ubsan_load_invalid_value+0x0/0xa8 [test_ubsan] [ 31.654388] init_module+0x24/0xff4 [test_ubsan] [ 31.655077] do_one_initcall+0xd4/0x280 [ 31.655680] do_init_module+0x58/0x2b4 That happens because the test corrupts other data in the stack: 400: d5384108 mrs x8, sp_el0 404: f9426d08 ldr x8, [x8, #1240] 408: f85f83a9 ldur x9, [x29, #-8] 40c: eb09011f cmp x8, x9 410: 54000301 b.ne 470 // b.any As there is no guarantee the compiler will order the local variables as declared in the module: volatile char above[4] = { }; /* Protect surrounding memory. */ volatile int arr[4]; volatile char below[4] = { }; /* Protect surrounding memory. */ There is another problem where the out-of-bound index is 5 which is larger than the extra surrounding memory for protection. So, use a struct to enforce the ordering, and fix the index to be 4. Also, remove some of the volatiles and rely on OPTIMIZER_HIDE_VAR() Signed-off-by: Mostafa Saleh Link: https://lore.kernel.org/r/20250415203354.4109415-1-smostafa@google.com Signed-off-by: Kees Cook Signed-off-by: Sasha Levin --- lib/test_ubsan.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/test_ubsan.c b/lib/test_ubsan.c index 2062be1f2e80..f90f2b9842ec 100644 --- a/lib/test_ubsan.c +++ b/lib/test_ubsan.c @@ -35,18 +35,22 @@ static void test_ubsan_shift_out_of_bounds(void) static void test_ubsan_out_of_bounds(void) { - volatile int i = 4, j = 5, k = -1; - volatile char above[4] = { }; /* Protect surrounding memory. */ - volatile int arr[4]; - volatile char below[4] = { }; /* Protect surrounding memory. */ + int i = 4, j = 4, k = -1; + volatile struct { + char above[4]; /* Protect surrounding memory. */ + int arr[4]; + char below[4]; /* Protect surrounding memory. */ + } data; - above[0] = below[0]; + OPTIMIZER_HIDE_VAR(i); + OPTIMIZER_HIDE_VAR(j); + OPTIMIZER_HIDE_VAR(k); UBSAN_TEST(CONFIG_UBSAN_BOUNDS, "above"); - arr[j] = i; + data.arr[j] = i; UBSAN_TEST(CONFIG_UBSAN_BOUNDS, "below"); - arr[k] = i; + data.arr[k] = i; } enum ubsan_test_enum { From 41866aa93d2ec8fd6cc24dbe9074c7928bf6a1f6 Mon Sep 17 00:00:00 2001 From: Pi Xiange Date: Mon, 14 Apr 2025 11:28:39 +0800 Subject: [PATCH 570/606] x86/cpu: Add CPU model number for Bartlett Lake CPUs with Raptor Cove cores [ Upstream commit d466304c4322ad391797437cd84cca7ce1660de0 ] Bartlett Lake has a P-core only product with Raptor Cove. [ mingo: Switch around the define as pointed out by Christian Ludloff: Ratpr Cove is the core, Bartlett Lake is the product. Signed-off-by: Pi Xiange Signed-off-by: Ingo Molnar Cc: Christian Ludloff Cc: Peter Zijlstra Cc: Tony Luck Cc: Andrew Cooper Cc: "H. Peter Anvin" Cc: John Ogness Cc: "Ahmed S. Darwish" Cc: x86-cpuid@lists.linux.dev Link: https://lore.kernel.org/r/20250414032839.5368-1-xiange.pi@intel.com Signed-off-by: Sasha Levin --- arch/x86/include/asm/intel-family.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/include/asm/intel-family.h b/arch/x86/include/asm/intel-family.h index f81a851c46dc..652c0137e909 100644 --- a/arch/x86/include/asm/intel-family.h +++ b/arch/x86/include/asm/intel-family.h @@ -159,6 +159,8 @@ #define INTEL_FAM6_GRANITERAPIDS_D 0xAE #define INTEL_GRANITERAPIDS_D IFM(6, 0xAE) +#define INTEL_BARTLETTLAKE IFM(6, 0xD7) /* Raptor Cove */ + /* "Hybrid" Processors (P-Core/E-Core) */ #define INTEL_FAM6_LAKEFIELD 0x8A /* Sunny Cove / Tremont */ From 459098685edf611ef272b300da3376dfa75ade8e Mon Sep 17 00:00:00 2001 From: Meir Elisha Date: Tue, 8 Apr 2025 17:38:08 +0300 Subject: [PATCH 571/606] md/raid1: Add check for missing source disk in process_checks() [ Upstream commit b7c178d9e57c8fd4238ff77263b877f6f16182ba ] During recovery/check operations, the process_checks function loops through available disks to find a 'primary' source with successfully read data. If no suitable source disk is found after checking all possibilities, the 'primary' index will reach conf->raid_disks * 2. Add an explicit check for this condition after the loop. If no source disk was found, print an error message and return early to prevent further processing without a valid primary source. Link: https://lore.kernel.org/linux-raid/20250408143808.1026534-1-meir.elisha@volumez.com Signed-off-by: Meir Elisha Suggested-and-reviewed-by: Yu Kuai Signed-off-by: Yu Kuai Signed-off-by: Sasha Levin --- drivers/md/raid1.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 65309da1dca3..8b25287c89ed 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -2061,14 +2061,9 @@ static int fix_sync_read_error(struct r1bio *r1_bio) if (!rdev_set_badblocks(rdev, sect, s, 0)) abort = 1; } - if (abort) { - conf->recovery_disabled = - mddev->recovery_disabled; - set_bit(MD_RECOVERY_INTR, &mddev->recovery); - md_done_sync(mddev, r1_bio->sectors, 0); - put_buf(r1_bio); + if (abort) return 0; - } + /* Try next page */ sectors -= s; sect += s; @@ -2207,10 +2202,21 @@ static void sync_request_write(struct mddev *mddev, struct r1bio *r1_bio) int disks = conf->raid_disks * 2; struct bio *wbio; - if (!test_bit(R1BIO_Uptodate, &r1_bio->state)) - /* ouch - failed to read all of that. */ - if (!fix_sync_read_error(r1_bio)) + if (!test_bit(R1BIO_Uptodate, &r1_bio->state)) { + /* + * ouch - failed to read all of that. + * No need to fix read error for check/repair + * because all member disks are read. + */ + if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) || + !fix_sync_read_error(r1_bio)) { + conf->recovery_disabled = mddev->recovery_disabled; + set_bit(MD_RECOVERY_INTR, &mddev->recovery); + md_done_sync(mddev, r1_bio->sectors, 0); + put_buf(r1_bio); return; + } + } if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) process_checks(r1_bio); From 2b4479eb462ecb39001b38dfb331fc6028dedac8 Mon Sep 17 00:00:00 2001 From: Tamura Dai Date: Thu, 17 Apr 2025 10:16:05 +0900 Subject: [PATCH 572/606] spi: spi-imx: Add check for spi_imx_setupxfer() [ Upstream commit 951a04ab3a2db4029debfa48d380ef834b93207e ] Add check for the return value of spi_imx_setupxfer(). spi_imx->rx and spi_imx->tx function pointer can be NULL when spi_imx_setupxfer() return error, and make NULL pointer dereference. Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 Call trace: 0x0 spi_imx_pio_transfer+0x50/0xd8 spi_imx_transfer_one+0x18c/0x858 spi_transfer_one_message+0x43c/0x790 __spi_pump_transfer_message+0x238/0x5d4 __spi_sync+0x2b0/0x454 spi_write_then_read+0x11c/0x200 Signed-off-by: Tamura Dai Reviewed-by: Carlos Song Link: https://patch.msgid.link/20250417011700.14436-1-kirinode0@gmail.com Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- drivers/spi/spi-imx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index daa32bde6155..da4442954375 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1614,10 +1614,13 @@ static int spi_imx_transfer_one(struct spi_controller *controller, struct spi_device *spi, struct spi_transfer *transfer) { + int ret; struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller); unsigned long hz_per_byte, byte_limit; - spi_imx_setupxfer(spi, transfer); + ret = spi_imx_setupxfer(spi, transfer); + if (ret < 0) + return ret; transfer->effective_speed_hz = spi_imx->spi_bus_clk; /* flush rxfifo before transfer */ From 0fd13033d4e7fcf3fe2a36e1c7dcef8a06795988 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 9 Oct 2024 18:04:40 +0200 Subject: [PATCH 573/606] x86/pvh: Call C code via the kernel virtual mapping commit e8fbc0d9cab6c1ee6403f42c0991b0c1d5dbc092 upstream. Calling C code via a different mapping than it was linked at is problematic, because the compiler assumes that RIP-relative and absolute symbol references are interchangeable. GCC in particular may use RIP-relative per-CPU variable references even when not using -fpic. So call xen_prepare_pvh() via its kernel virtual mapping on x86_64, so that those RIP-relative references produce the correct values. This matches the pre-existing behavior for i386, which also invokes xen_prepare_pvh() via the kernel virtual mapping before invoking startup_32 with paging disabled again. Fixes: 7243b93345f7 ("xen/pvh: Bootstrap PVH guest") Tested-by: Jason Andryuk Reviewed-by: Jason Andryuk Signed-off-by: Ard Biesheuvel Message-ID: <20241009160438.3884381-8-ardb+git@google.com> Signed-off-by: Juergen Gross [ Stable context update ] Signed-off-by: Jason Andryuk Signed-off-by: Greg Kroah-Hartman --- arch/x86/platform/pvh/head.S | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/x86/platform/pvh/head.S b/arch/x86/platform/pvh/head.S index c4365a05ab83..fc46b4dfbd74 100644 --- a/arch/x86/platform/pvh/head.S +++ b/arch/x86/platform/pvh/head.S @@ -100,7 +100,12 @@ SYM_CODE_START_LOCAL(pvh_start_xen) xor %edx, %edx wrmsr - call xen_prepare_pvh + /* Call xen_prepare_pvh() via the kernel virtual mapping */ + leaq xen_prepare_pvh(%rip), %rax + subq phys_base(%rip), %rax + addq $__START_KERNEL_map, %rax + ANNOTATE_RETPOLINE_SAFE + call *%rax /* startup_64 expects boot_params in %rsi. */ mov $_pa(pvh_bootparams), %rsi From d29c2d53357fd35f24b7acba594725a5be6404d7 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 10 Mar 2025 22:24:14 -0700 Subject: [PATCH 574/606] Revert "drivers: core: synchronize really_probe() and dev_uevent()" commit dc1771f718548f7d4b93991b174c6e7b5e1ba410 upstream. This reverts commit c0a40097f0bc81deafc15f9195d1fb54595cd6d0. Probing a device can take arbitrary long time. In the field we observed that, for example, probing a bad micro-SD cards in an external USB card reader (or maybe cards were good but cables were flaky) sometimes takes longer than 2 minutes due to multiple retries at various levels of the stack. We can not block uevent_show() method for that long because udev is reading that attribute very often and that blocks udev and interferes with booting of the system. The change that introduced locking was concerned with dev_uevent() racing with unbinding the driver. However we can handle it without locking (which will be done in subsequent patch). There was also claim that synchronization with probe() is needed to properly load USB drivers, however this is a red herring: the change adding the lock was introduced in May of last year and USB loading and probing worked properly for many years before that. Revert the harmful locking. Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov Reviewed-by: Masami Hiramatsu (Google) Link: https://lore.kernel.org/r/20250311052417.1846985-1-dmitry.torokhov@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 8e2caa9eb5cd..197af212ef7e 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -2672,11 +2672,8 @@ static ssize_t uevent_show(struct device *dev, struct device_attribute *attr, if (!env) return -ENOMEM; - /* Synchronize with really_probe() */ - device_lock(dev); /* let the kset specific function add its keys */ retval = kset->uevent_ops->uevent(&dev->kobj, env); - device_unlock(dev); if (retval) goto out; From a55111066205090aec18e1e999155a5dd15f4394 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 10 Mar 2025 22:24:15 -0700 Subject: [PATCH 575/606] driver core: introduce device_set_driver() helper commit 04d3e5461c1f5cf8eec964ab64948ebed826e95e upstream. In preparation to closing a race when reading driver pointer in dev_uevent() code, instead of setting device->driver pointer directly introduce device_set_driver() helper. Signed-off-by: Dmitry Torokhov Reviewed-by: Masami Hiramatsu (Google) Link: https://lore.kernel.org/r/20250311052417.1846985-2-dmitry.torokhov@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 6 ++++++ drivers/base/core.c | 2 +- drivers/base/dd.c | 6 +++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/base/base.h b/drivers/base/base.h index a8e3d8165232..7ac16589af3c 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -179,6 +179,12 @@ int driver_add_groups(struct device_driver *drv, const struct attribute_group ** void driver_remove_groups(struct device_driver *drv, const struct attribute_group **groups); void device_driver_detach(struct device *dev); +static inline void device_set_driver(struct device *dev, const struct device_driver *drv) +{ + // FIXME - this cast should not be needed "soon" + dev->driver = (struct device_driver *)drv; +} + int devres_release_all(struct device *dev); void device_block_probing(void); void device_unblock_probing(void); diff --git a/drivers/base/core.c b/drivers/base/core.c index 197af212ef7e..a5b2db9720a4 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -3688,7 +3688,7 @@ done: device_pm_remove(dev); dpm_sysfs_remove(dev); DPMError: - dev->driver = NULL; + device_set_driver(dev, NULL); bus_remove_device(dev); BusError: device_remove_attrs(dev); diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 0c3725c3eefa..7e2fb159bb89 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -550,7 +550,7 @@ static void device_unbind_cleanup(struct device *dev) arch_teardown_dma_ops(dev); kfree(dev->dma_range_map); dev->dma_range_map = NULL; - dev->driver = NULL; + device_set_driver(dev, NULL); dev_set_drvdata(dev, NULL); if (dev->pm_domain && dev->pm_domain->dismiss) dev->pm_domain->dismiss(dev); @@ -629,7 +629,7 @@ static int really_probe(struct device *dev, struct device_driver *drv) } re_probe: - dev->driver = drv; + device_set_driver(dev, drv); /* If using pinctrl, bind pins now before probing */ ret = pinctrl_bind_pins(dev); @@ -1014,7 +1014,7 @@ static int __device_attach(struct device *dev, bool allow_async) if (ret == 0) ret = 1; else { - dev->driver = NULL; + device_set_driver(dev, NULL); ret = 0; } } else { From abe56be73eb10a677d16066f65ff9d30251f5eee Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 10 Mar 2025 22:24:16 -0700 Subject: [PATCH 576/606] driver core: fix potential NULL pointer dereference in dev_uevent() commit 18daa52418e7e4629ed1703b64777294209d2622 upstream. If userspace reads "uevent" device attribute at the same time as another threads unbinds the device from its driver, change to dev->driver from a valid pointer to NULL may result in crash. Fix this by using READ_ONCE() when fetching the pointer, and take bus' drivers klist lock to make sure driver instance will not disappear while we access it. Use WRITE_ONCE() when setting the driver pointer to ensure there is no tearing. Signed-off-by: Dmitry Torokhov Reviewed-by: Masami Hiramatsu (Google) Link: https://lore.kernel.org/r/20250311052417.1846985-3-dmitry.torokhov@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 13 ++++++++++++- drivers/base/bus.c | 2 +- drivers/base/core.c | 33 +++++++++++++++++++++++++++++++-- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/drivers/base/base.h b/drivers/base/base.h index 7ac16589af3c..0b491449b022 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -73,6 +73,7 @@ static inline void subsys_put(struct subsys_private *sp) kset_put(&sp->subsys); } +struct subsys_private *bus_to_subsys(const struct bus_type *bus); struct subsys_private *class_to_subsys(const struct class *class); struct driver_private { @@ -181,8 +182,18 @@ void device_driver_detach(struct device *dev); static inline void device_set_driver(struct device *dev, const struct device_driver *drv) { + /* + * Majority (all?) read accesses to dev->driver happens either + * while holding device lock or in bus/driver code that is only + * invoked when the device is bound to a driver and there is no + * concern of the pointer being changed while it is being read. + * However when reading device's uevent file we read driver pointer + * without taking device lock (so we do not block there for + * arbitrary amount of time). We use WRITE_ONCE() here to prevent + * tearing so that READ_ONCE() can safely be used in uevent code. + */ // FIXME - this cast should not be needed "soon" - dev->driver = (struct device_driver *)drv; + WRITE_ONCE(dev->driver, (struct device_driver *)drv); } int devres_release_all(struct device *dev); diff --git a/drivers/base/bus.c b/drivers/base/bus.c index d4361ad3b433..b97e13a52c33 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -57,7 +57,7 @@ static int __must_check bus_rescan_devices_helper(struct device *dev, * NULL. A call to subsys_put() must be done when finished with the pointer in * order for it to be properly freed. */ -static struct subsys_private *bus_to_subsys(const struct bus_type *bus) +struct subsys_private *bus_to_subsys(const struct bus_type *bus) { struct subsys_private *sp = NULL; struct kobject *kobj; diff --git a/drivers/base/core.c b/drivers/base/core.c index a5b2db9720a4..a192ce5bb8f9 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -2570,6 +2570,35 @@ static const char *dev_uevent_name(const struct kobject *kobj) return NULL; } +/* + * Try filling "DRIVER=" uevent variable for a device. Because this + * function may race with binding and unbinding the device from a driver, + * we need to be careful. Binding is generally safe, at worst we miss the + * fact that the device is already bound to a driver (but the driver + * information that is delivered through uevents is best-effort, it may + * become obsolete as soon as it is generated anyways). Unbinding is more + * risky as driver pointer is transitioning to NULL, so READ_ONCE() should + * be used to make sure we are dealing with the same pointer, and to + * ensure that driver structure is not going to disappear from under us + * we take bus' drivers klist lock. The assumption that only registered + * driver can be bound to a device, and to unregister a driver bus code + * will take the same lock. + */ +static void dev_driver_uevent(const struct device *dev, struct kobj_uevent_env *env) +{ + struct subsys_private *sp = bus_to_subsys(dev->bus); + + if (sp) { + scoped_guard(spinlock, &sp->klist_drivers.k_lock) { + struct device_driver *drv = READ_ONCE(dev->driver); + if (drv) + add_uevent_var(env, "DRIVER=%s", drv->name); + } + + subsys_put(sp); + } +} + static int dev_uevent(const struct kobject *kobj, struct kobj_uevent_env *env) { const struct device *dev = kobj_to_dev(kobj); @@ -2601,8 +2630,8 @@ static int dev_uevent(const struct kobject *kobj, struct kobj_uevent_env *env) if (dev->type && dev->type->name) add_uevent_var(env, "DEVTYPE=%s", dev->type->name); - if (dev->driver) - add_uevent_var(env, "DRIVER=%s", dev->driver->name); + /* Add "DRIVER=%s" variable if the device is bound to a driver */ + dev_driver_uevent(dev, env); /* Add common DT information about the device */ of_device_uevent(dev, env); From c4312c4d244aa58e811ff0297e013124d115e793 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Wed, 23 Apr 2025 15:36:00 +0200 Subject: [PATCH 577/606] vmxnet3: Fix malformed packet sizing in vmxnet3_process_xdp commit 4c2227656d9003f4d77afc76f34dd81b95e4c2c4 upstream. vmxnet3 driver's XDP handling is buggy for packet sizes using ring0 (that is, packet sizes between 128 - 3k bytes). We noticed MTU-related connectivity issues with Cilium's service load- balancing in case of vmxnet3 as NIC underneath. A simple curl to a HTTP backend service where the XDP LB was doing IPIP encap led to overly large packet sizes but only for *some* of the packets (e.g. HTTP GET request) while others (e.g. the prior TCP 3WHS) looked completely fine on the wire. In fact, the pcap recording on the backend node actually revealed that the node with the XDP LB was leaking uninitialized kernel data onto the wire for the affected packets, for example, while the packets should have been 152 bytes their actual size was 1482 bytes, so the remainder after 152 bytes was padded with whatever other data was in that page at the time (e.g. we saw user/payload data from prior processed packets). We only noticed this through an MTU issue, e.g. when the XDP LB node and the backend node both had the same MTU (e.g. 1500) then the curl request got dropped on the backend node's NIC given the packet was too large even though the IPIP-encapped packet normally would never even come close to the MTU limit. Lowering the MTU on the XDP LB (e.g. 1480) allowed to let the curl request succeed (which also indicates that the kernel ignored the padding, and thus the issue wasn't very user-visible). Commit e127ce7699c1 ("vmxnet3: Fix missing reserved tailroom") was too eager to also switch xdp_prepare_buff() from rcd->len to rbi->len. It really needs to stick to rcd->len which is the actual packet length from the descriptor. The latter we also feed into vmxnet3_process_xdp_small(), by the way, and it indicates the correct length needed to initialize the xdp->{data,data_end} parts. For e127ce7699c1 ("vmxnet3: Fix missing reserved tailroom") the relevant part was adapting xdp_init_buff() to address the warning given the xdp_data_hard_end() depends on xdp->frame_sz. With that fixed, traffic on the wire looks good again. Fixes: e127ce7699c1 ("vmxnet3: Fix missing reserved tailroom") Signed-off-by: Daniel Borkmann Tested-by: Andrew Sauber Cc: Anton Protopopov Cc: William Tu Cc: Martin Zaharinov Cc: Ronak Doshi Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250423133600.176689-1-daniel@iogearbox.net Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- drivers/net/vmxnet3/vmxnet3_xdp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/vmxnet3/vmxnet3_xdp.c b/drivers/net/vmxnet3/vmxnet3_xdp.c index 616ecc38d172..5f470499e600 100644 --- a/drivers/net/vmxnet3/vmxnet3_xdp.c +++ b/drivers/net/vmxnet3/vmxnet3_xdp.c @@ -397,7 +397,7 @@ vmxnet3_process_xdp(struct vmxnet3_adapter *adapter, xdp_init_buff(&xdp, PAGE_SIZE, &rq->xdp_rxq); xdp_prepare_buff(&xdp, page_address(page), rq->page_pool->p.offset, - rbi->len, false); + rcd->len, false); xdp_buff_clear_frags_flag(&xdp); xdp_prog = rcu_dereference(rq->adapter->xdp_bpf_prog); From ffe79cc6c71dde5165c6010ab7f7dad635df5b66 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 15 Apr 2025 13:39:01 +0100 Subject: [PATCH 578/606] comedi: jr3_pci: Fix synchronous deletion of timer commit 44d9b3f584c59a606b521e7274e658d5b866c699 upstream. When `jr3_pci_detach()` is called during device removal, it calls `timer_delete_sync()` to stop the timer, but the timer expiry function always reschedules the timer, so the synchronization is ineffective. Call `timer_shutdown_sync()` instead. It does not matter that the timer expiry function pointer is cleared, because the device is being removed. Fixes: 07b509e6584a5 ("Staging: comedi: add jr3_pci driver") Cc: stable Signed-off-by: Ian Abbott Link: https://lore.kernel.org/r/20250415123901.13483-1-abbotti@mev.co.uk Signed-off-by: Greg Kroah-Hartman --- drivers/comedi/drivers/jr3_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/comedi/drivers/jr3_pci.c b/drivers/comedi/drivers/jr3_pci.c index 951c23fa0369..75dce1ff2419 100644 --- a/drivers/comedi/drivers/jr3_pci.c +++ b/drivers/comedi/drivers/jr3_pci.c @@ -758,7 +758,7 @@ static void jr3_pci_detach(struct comedi_device *dev) struct jr3_pci_dev_private *devpriv = dev->private; if (devpriv) - del_timer_sync(&devpriv->timer); + timer_shutdown_sync(&devpriv->timer); comedi_pci_detach(dev); } From 551667f99bcf04fa58594d7d19aef73c861a1200 Mon Sep 17 00:00:00 2001 From: Baokun Li Date: Thu, 13 Feb 2025 19:22:47 +0800 Subject: [PATCH 579/606] ext4: goto right label 'out_mmap_sem' in ext4_setattr() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 7e91ae31e2d264155dfd102101afc2de7bd74a64 upstream. Otherwise, if ext4_inode_attach_jinode() fails, a hung task will happen because filemap_invalidate_unlock() isn't called to unlock mapping->invalidate_lock. Like this: EXT4-fs error (device sda) in ext4_setattr:5557: Out of memory INFO: task fsstress:374 blocked for more than 122 seconds. Not tainted 6.14.0-rc1-next-20250206-xfstests-dirty #726 "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. task:fsstress state:D stack:0 pid:374 tgid:374 ppid:373 task_flags:0x440140 flags:0x00000000 Call Trace: __schedule+0x2c9/0x7f0 schedule+0x27/0xa0 schedule_preempt_disabled+0x15/0x30 rwsem_down_read_slowpath+0x278/0x4c0 down_read+0x59/0xb0 page_cache_ra_unbounded+0x65/0x1b0 filemap_get_pages+0x124/0x3e0 filemap_read+0x114/0x3d0 vfs_read+0x297/0x360 ksys_read+0x6c/0xe0 do_syscall_64+0x4b/0x110 entry_SYSCALL_64_after_hwframe+0x76/0x7e Fixes: c7fc0366c656 ("ext4: partial zero eof block on unaligned inode size extension") Signed-off-by: Baokun Li Reviewed-by: Jan Kara Reviewed-by: Brian Foster Link: https://patch.msgid.link/20250213112247.3168709-1-libaokun@huaweicloud.com Signed-off-by: Theodore Ts'o Signed-off-by: Ricardo Cañuelo Navarro Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index f2b60fb0b937..d3d28e658720 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -5479,7 +5479,7 @@ int ext4_setattr(struct mnt_idmap *idmap, struct dentry *dentry, oldsize & (inode->i_sb->s_blocksize - 1)) { error = ext4_inode_attach_jinode(inode); if (error) - goto err_out; + goto out_mmap_sem; } handle = ext4_journal_start(inode, EXT4_HT_INODE, 3); From bfbd730e100b89bbaef81c0ca7a7d0b7509e7556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Tue, 29 Apr 2025 12:10:47 +0200 Subject: [PATCH 580/606] net: dsa: mv88e6xxx: fix atu_move_port_mask for 6341 family MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 4ae01ec007716986e1a20f1285eb013cbf188830 upstream. The atu_move_port_mask for 6341 family (Topaz) is 0xf, not 0x1f. The PortVec field is 8 bits wide, not 11 as in 6390 family. Fix this. Fixes: e606ca36bbf2 ("net: dsa: mv88e6xxx: rework ATU Remove") Signed-off-by: Marek Behún Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/20250317173250.28780-3-kabel@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- drivers/net/dsa/mv88e6xxx/chip.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index bf93d700802b..be42de54e7df 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -5713,7 +5713,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 3750, - .atu_move_port_mask = 0x1f, + .atu_move_port_mask = 0xf, .g1_irqs = 9, .g2_irqs = 10, .pvt = true, @@ -6174,7 +6174,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .global1_addr = 0x1b, .global2_addr = 0x1c, .age_time_coeff = 3750, - .atu_move_port_mask = 0x1f, + .atu_move_port_mask = 0xf, .g1_irqs = 9, .g2_irqs = 10, .pvt = true, From 13685484072a9fce60b39a21cd6d7c6a547598b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Tue, 29 Apr 2025 12:10:48 +0200 Subject: [PATCH 581/606] net: dsa: mv88e6xxx: enable PVT for 6321 switch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f85c69369854a43af2c5d3b3896da0908d713133 upstream. Commit f36456522168 ("net: dsa: mv88e6xxx: move PVT description in info") did not enable PVT for 6321 switch. Fix it. Fixes: f36456522168 ("net: dsa: mv88e6xxx: move PVT description in info") Signed-off-by: Marek Behún Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/20250317173250.28780-4-kabel@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- drivers/net/dsa/mv88e6xxx/chip.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index be42de54e7df..f8ac209e712e 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -6152,6 +6152,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .g1_irqs = 8, .g2_irqs = 10, .atu_move_port_mask = 0xf, + .pvt = true, .multi_chip = true, .edsa_support = MV88E6XXX_EDSA_SUPPORTED, .ptp_support = true, From cd17c8638d211c92417a73ca3137dc7cd412fe01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Tue, 29 Apr 2025 12:10:49 +0200 Subject: [PATCH 582/606] net: dsa: mv88e6xxx: enable .port_set_policy() for 6320 family MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit a2ef58e2c4aea4de166fc9832eb2b621e88c98d5 upstream. Commit f3a2cd326e44 ("net: dsa: mv88e6xxx: introduce .port_set_policy") did not add the .port_set_policy() method for the 6320 family. Fix it. Fixes: f3a2cd326e44 ("net: dsa: mv88e6xxx: introduce .port_set_policy") Signed-off-by: Marek Behún Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/20250317173250.28780-5-kabel@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- drivers/net/dsa/mv88e6xxx/chip.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index f8ac209e712e..472fe300b196 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -5047,6 +5047,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { .port_set_rgmii_delay = mv88e6320_port_set_rgmii_delay, .port_set_speed_duplex = mv88e6185_port_set_speed_duplex, .port_tag_remap = mv88e6095_port_tag_remap, + .port_set_policy = mv88e6352_port_set_policy, .port_set_frame_mode = mv88e6351_port_set_frame_mode, .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, @@ -5097,6 +5098,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { .port_set_rgmii_delay = mv88e6320_port_set_rgmii_delay, .port_set_speed_duplex = mv88e6185_port_set_speed_duplex, .port_tag_remap = mv88e6095_port_tag_remap, + .port_set_policy = mv88e6352_port_set_policy, .port_set_frame_mode = mv88e6351_port_set_frame_mode, .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, From eee19a8037316ba38f1cdf3825e6a21672131ad6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Tue, 29 Apr 2025 12:10:50 +0200 Subject: [PATCH 583/606] net: dsa: mv88e6xxx: enable STU methods for 6320 family MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 1428a6109b20e356188c3fb027bdb7998cc2fb98 upstream. Commit c050f5e91b47 ("net: dsa: mv88e6xxx: Fill in STU support for all supported chips") introduced STU methods, but did not add them to the 6320 family. Fix it. Fixes: c050f5e91b47 ("net: dsa: mv88e6xxx: Fill in STU support for all supported chips") Signed-off-by: Marek Behún Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/20250317173250.28780-6-kabel@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- drivers/net/dsa/mv88e6xxx/chip.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 472fe300b196..ef52d1ae27d6 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -5074,6 +5074,8 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { .reset = mv88e6352_g1_reset, .vtu_getnext = mv88e6352_g1_vtu_getnext, .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, + .stu_getnext = mv88e6352_g1_stu_getnext, + .stu_loadpurge = mv88e6352_g1_stu_loadpurge, .gpio_ops = &mv88e6352_gpio_ops, .avb_ops = &mv88e6352_avb_ops, .ptp_ops = &mv88e6352_ptp_ops, @@ -5124,6 +5126,8 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { .reset = mv88e6352_g1_reset, .vtu_getnext = mv88e6352_g1_vtu_getnext, .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, + .stu_getnext = mv88e6352_g1_stu_getnext, + .stu_loadpurge = mv88e6352_g1_stu_loadpurge, .gpio_ops = &mv88e6352_gpio_ops, .avb_ops = &mv88e6352_avb_ops, .ptp_ops = &mv88e6352_ptp_ops, @@ -6120,6 +6124,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .internal_phys_offset = 3, .num_gpio = 15, .max_vid = 4095, + .max_sid = 63, .port_base_addr = 0x10, .phy_base_addr = 0x0, .global1_addr = 0x1b, @@ -6146,6 +6151,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .internal_phys_offset = 3, .num_gpio = 15, .max_vid = 4095, + .max_sid = 63, .port_base_addr = 0x10, .phy_base_addr = 0x0, .global1_addr = 0x1b, From 17d41d0f3a2683be946a0e2d134660481a250029 Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Fri, 28 Feb 2025 15:37:02 +0100 Subject: [PATCH 584/606] MIPS: cm: Fix warning if MIPS_CM is disabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit b73c3ccdca95c237750c981054997c71d33e09d7 upstream. Commit e27fbe16af5c ("MIPS: cm: Detect CM quirks from device tree") introduced arch/mips/include/asm/mips-cm.h:119:13: error: ‘mips_cm_update_property’ defined but not used [-Werror=unused-function] Fix this by making empty function implementation inline Fixes: e27fbe16af5c ("MIPS: cm: Detect CM quirks from device tree") Signed-off-by: Thomas Bogendoerfer Signed-off-by: Greg Kroah-Hartman --- arch/mips/include/asm/mips-cm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index 0f31324998c0..8494466740cc 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -104,7 +104,7 @@ static inline bool mips_cm_present(void) #ifdef CONFIG_MIPS_CM extern void mips_cm_update_property(void); #else -static void mips_cm_update_property(void) {} +static inline void mips_cm_update_property(void) {} #endif /** From 26084aa1a1433723dc00fece5464369ce3e29586 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 14 Apr 2025 14:05:09 +0200 Subject: [PATCH 585/606] nvme: fixup scan failure for non-ANA multipath controllers commit 26d7fb4fd4ca1180e2fa96587dea544563b4962a upstream. Commit 62baf70c3274 caused the ANA log page to be re-read, even on controllers that do not support ANA. While this should generally harmless, some controllers hang on the unsupported log page and never finish probing. Fixes: 62baf70c3274 ("nvme: re-read ANA log page after ns scan completes") Signed-off-by: Hannes Reinecke Tested-by: Srikanth Aithal [hch: more detailed commit message] Signed-off-by: Christoph Hellwig Reviewed-by: Sagi Grimberg Signed-off-by: Greg Kroah-Hartman --- drivers/nvme/host/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 8827614ab8c6..c6b0637e61de 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -3977,7 +3977,7 @@ static void nvme_scan_work(struct work_struct *work) if (test_bit(NVME_AER_NOTICE_NS_CHANGED, &ctrl->events)) nvme_queue_scan(ctrl); #ifdef CONFIG_NVME_MULTIPATH - else + else if (ctrl->ana_log_buf) /* Re-read the ANA log page to not miss updates */ queue_work(nvme_wq, &ctrl->ana_work); #endif From 014a761be083020aa3860aa965f4706da658dcea Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Mon, 31 Mar 2025 21:26:37 -0700 Subject: [PATCH 586/606] objtool: Ignore end-of-section jumps for KCOV/GCOV commit 0d7597749f5a3ac67851d3836635d084df15fb66 upstream. When KCOV or GCOV is enabled, dead code can be left behind, in which case objtool silences unreachable and undefined behavior (fallthrough) warnings. Fallthrough warnings, and their variant "end of section" warnings, were silenced with the following commit: 6b023c784204 ("objtool: Silence more KCOV warnings") Another variant of a fallthrough warning is a jump to the end of a function. If that function happens to be at the end of a section, the jump destination doesn't actually exist. Normally that would be a fatal objtool error, but for KCOV/GCOV it's just another undefined behavior fallthrough. Silence it like the others. Fixes the following warning: drivers/iommu/dma-iommu.o: warning: objtool: iommu_dma_sw_msi+0x92: can't find jump dest instruction at .text+0x54d5 Fixes: 6b023c784204 ("objtool: Silence more KCOV warnings") Reported-by: Randy Dunlap Signed-off-by: Josh Poimboeuf Signed-off-by: Ingo Molnar Cc: Linus Torvalds Link: https://lore.kernel.org/r/08fbe7d7e1e20612206f1df253077b94f178d93e.1743481539.git.jpoimboe@kernel.org Closes: https://lore.kernel.org/314f8809-cd59-479b-97d7-49356bf1c8d1@infradead.org/ Signed-off-by: Greg Kroah-Hartman --- tools/objtool/check.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tools/objtool/check.c b/tools/objtool/check.c index 6d35fe0e4695..a1b14378bab0 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -1552,6 +1552,8 @@ static int add_jump_destinations(struct objtool_file *file) unsigned long dest_off; for_each_insn(file, insn) { + struct symbol *func = insn_func(insn); + if (insn->jump_dest) { /* * handle_group_alt() may have previously set @@ -1575,7 +1577,7 @@ static int add_jump_destinations(struct objtool_file *file) } else if (reloc->sym->return_thunk) { add_return_call(file, insn, true); continue; - } else if (insn_func(insn)) { + } else if (func) { /* * External sibling call or internal sibling call with * STT_FUNC reloc. @@ -1608,6 +1610,15 @@ static int add_jump_destinations(struct objtool_file *file) continue; } + /* + * GCOV/KCOV dead code can jump to the end of the + * function/section. + */ + if (file->ignore_unreachables && func && + dest_sec == insn->sec && + dest_off == func->offset + func->len) + continue; + WARN_INSN(insn, "can't find jump dest instruction at %s+0x%lx", dest_sec->name, dest_off); return -1; @@ -1616,8 +1627,7 @@ static int add_jump_destinations(struct objtool_file *file) /* * Cross-function jump. */ - if (insn_func(insn) && insn_func(jump_dest) && - insn_func(insn) != insn_func(jump_dest)) { + if (func && insn_func(jump_dest) && func != insn_func(jump_dest)) { /* * For GCC 8+, create parent/child links for any cold @@ -1634,10 +1644,10 @@ static int add_jump_destinations(struct objtool_file *file) * case where the parent function's only reference to a * subfunction is through a jump table. */ - if (!strstr(insn_func(insn)->name, ".cold") && + if (!strstr(func->name, ".cold") && strstr(insn_func(jump_dest)->name, ".cold")) { - insn_func(insn)->cfunc = insn_func(jump_dest); - insn_func(jump_dest)->pfunc = insn_func(insn); + func->cfunc = insn_func(jump_dest); + insn_func(jump_dest)->pfunc = func; } } From 20bab4eb1c7cebc16fe434fe0f908505a637373e Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Mon, 31 Mar 2025 21:26:36 -0700 Subject: [PATCH 587/606] objtool: Silence more KCOV warnings, part 2 commit 55c78035a1a8dfb05f1472018ce2a651701adb7d upstream. Similar to GCOV, KCOV can leave behind dead code and undefined behavior. Warnings related to those should be ignored. The previous commit: 6b023c784204 ("objtool: Silence more KCOV warnings") ... only did so for CONFIG_CGOV_KERNEL. Also do it for CONFIG_KCOV, but for real this time. Fixes the following warning: vmlinux.o: warning: objtool: synaptics_report_mt_data: unexpected end of section .text.synaptics_report_mt_data Fixes: 6b023c784204 ("objtool: Silence more KCOV warnings") Reported-by: kernel test robot Signed-off-by: Josh Poimboeuf Signed-off-by: Ingo Molnar Cc: Linus Torvalds Link: https://lore.kernel.org/r/a44ba16e194bcbc52c1cef3d3cd9051a62622723.1743481539.git.jpoimboe@kernel.org Closes: https://lore.kernel.org/oe-kbuild-all/202503282236.UhfRsF3B-lkp@intel.com/ Signed-off-by: Greg Kroah-Hartman --- scripts/Makefile.lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 44f20b1b853a..4aecfb0a0ef6 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -268,7 +268,7 @@ objtool-args-$(CONFIG_SLS) += --sls objtool-args-$(CONFIG_STACK_VALIDATION) += --stackval objtool-args-$(CONFIG_HAVE_STATIC_CALL_INLINE) += --static-call objtool-args-$(CONFIG_HAVE_UACCESS_VALIDATION) += --uaccess -objtool-args-$(CONFIG_GCOV_KERNEL) += --no-unreachable +objtool-args-$(or $(CONFIG_GCOV_KERNEL),$(CONFIG_KCOV)) += --no-unreachable objtool-args-$(CONFIG_PREFIX_SYMBOLS) += --prefix=$(CONFIG_FUNCTION_PADDING_BYTES) objtool-args = $(objtool-args-y) \ From 71e4ec9b2abccce5adecb3b354d0d5003f6f88f2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 2 May 2025 07:51:05 +0200 Subject: [PATCH 588/606] Linux 6.6.89 Link: https://lore.kernel.org/r/20250429161059.396852607@linuxfoundation.org Tested-by: Peter Schneider Tested-by: Hardik Garg Tested-by: Miguel Ojeda Tested-by: Shuah Khan Tested-by: Ron Economos Tested-by: Mark Brown Link: https://lore.kernel.org/r/20250501081437.703410892@linuxfoundation.org Tested-by: Jon Hunter Tested-by: Miguel Ojeda Tested-by: Peter Schneider Tested-by: Mark Brown Tested-by: Hardik Garg Tested-by: Linux Kernel Functional Testing Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b1dfe3df7dfc..23e90df5785c 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 6 PATCHLEVEL = 6 -SUBLEVEL = 88 +SUBLEVEL = 89 EXTRAVERSION = NAME = Pinguïn Aangedreven From 112728ca64d7f2ce8fa5ddff0f9f93f063b0e5c7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 5 May 2025 14:03:19 +0000 Subject: [PATCH 589/606] Revert "module: sign with sha512 instead of sha1 by default" This reverts commit 247395cbec421935d7b3ef1a006e7076587b7af1 which is commit f3b93547b91ad849b58eb5ab2dd070950ad7beb3 upstream. It breaks the Android kernel build as BoringSSL can only sign with SHA1 for this Android branch, and we do not want to break the ABI by changing the module signing process in this stable kernel branch. It was only added upstream by Greg to get his ARM64 stable builds to compile properly on the latest version of Fedora, which did NOT like to sign with SHA1, so blame him :) Bug: 161946584 Change-Id: I4901a37dd9ac4bdd54a712331e1288053f0d9fb9 Signed-off-by: Greg Kroah-Hartman --- kernel/module/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/module/Kconfig b/kernel/module/Kconfig index f8459f689f25..ef582840f59b 100644 --- a/kernel/module/Kconfig +++ b/kernel/module/Kconfig @@ -256,7 +256,6 @@ comment "Do not forget to sign required modules with scripts/sign-file" choice prompt "Which hash algorithm should modules be signed with?" depends on MODULE_SIG || IMA_APPRAISE_MODSIG - default MODULE_SIG_SHA512 help This determines which sort of hashing algorithm will be used during signature generation. This algorithm _must_ be built into the kernel From 81a2d01c7e2ceb000886e5f1d9f99d21feabc0f4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 May 2025 06:43:11 +0000 Subject: [PATCH 590/606] Revert "media: vimc: skip .s_stream() for stopped entities" This reverts commit a505075730d23ccc19fc4ac382a0ed73b630c057 which is commit 36cef585e2a31e4ddf33a004b0584a7a572246de upstream. It breaks the Android kernel abi and can be brought back in the future in an abi-safe way if it is really needed. Bug: 161946584 Change-Id: Ia3bf677ea97e0fc92cec646b59246e8cbc5eb5ce Signed-off-by: Greg Kroah-Hartman --- drivers/media/test-drivers/vimc/vimc-streamer.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/media/test-drivers/vimc/vimc-streamer.c b/drivers/media/test-drivers/vimc/vimc-streamer.c index 15d863f97cbf..807551a5143b 100644 --- a/drivers/media/test-drivers/vimc/vimc-streamer.c +++ b/drivers/media/test-drivers/vimc/vimc-streamer.c @@ -59,12 +59,6 @@ static void vimc_streamer_pipeline_terminate(struct vimc_stream *stream) continue; sd = media_entity_to_v4l2_subdev(ved->ent); - /* - * Do not call .s_stream() to stop an already - * stopped/unstarted subdev. - */ - if (!v4l2_subdev_is_streaming(sd)) - continue; v4l2_subdev_call(sd, video, s_stream, 0); } } From 7c63c3455a972e0f5f7db9ad57621ce90dc9d83b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 May 2025 06:43:26 +0000 Subject: [PATCH 591/606] Revert "media: subdev: Add v4l2_subdev_is_streaming()" This reverts commit a64a102e01eba9c09947a39732e9318d44df71f8 which is commit 5f3ce14fae742d1d23061c3122d93edb879ebf53 upstream. It breaks the Android kernel abi and can be brought back in the future in an abi-safe way if it is really needed. Bug: 161946584 Change-Id: I1a6143299ed8fea16154f6ca0c7e223b96846e2e Signed-off-by: Greg Kroah-Hartman --- drivers/media/v4l2-core/v4l2-subdev.c | 25 ------------------------- include/media/v4l2-subdev.h | 13 ------------- 2 files changed, 38 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 5f115438d072..f555fd3c4b76 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -2240,31 +2240,6 @@ void v4l2_subdev_notify_event(struct v4l2_subdev *sd, } EXPORT_SYMBOL_GPL(v4l2_subdev_notify_event); -bool v4l2_subdev_is_streaming(struct v4l2_subdev *sd) -{ - struct v4l2_subdev_state *state; - - if (!v4l2_subdev_has_op(sd, pad, enable_streams)) - return sd->s_stream_enabled; - - if (!(sd->flags & V4L2_SUBDEV_FL_STREAMS)) - return !!sd->enabled_pads; - - state = v4l2_subdev_get_locked_active_state(sd); - - for (unsigned int i = 0; i < state->stream_configs.num_configs; ++i) { - const struct v4l2_subdev_stream_config *cfg; - - cfg = &state->stream_configs.configs[i]; - - if (cfg->enabled) - return true; - } - - return false; -} -EXPORT_SYMBOL_GPL(v4l2_subdev_is_streaming); - int v4l2_subdev_get_privacy_led(struct v4l2_subdev *sd) { #if IS_REACHABLE(CONFIG_LEDS_CLASS) diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index b4fcd0164048..0a8d75b009ea 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -1918,17 +1918,4 @@ extern const struct v4l2_subdev_ops v4l2_subdev_call_wrappers; void v4l2_subdev_notify_event(struct v4l2_subdev *sd, const struct v4l2_event *ev); -/** - * v4l2_subdev_is_streaming() - Returns if the subdevice is streaming - * @sd: The subdevice - * - * v4l2_subdev_is_streaming() tells if the subdevice is currently streaming. - * "Streaming" here means whether .s_stream() or .enable_streams() has been - * successfully called, and the streaming has not yet been disabled. - * - * If the subdevice implements .enable_streams() this function must be called - * while holding the active state lock. - */ -bool v4l2_subdev_is_streaming(struct v4l2_subdev *sd); - #endif /* _V4L2_SUBDEV_H */ From c06018316a529688318d9a937c0d4e927521ac7a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 May 2025 06:43:42 +0000 Subject: [PATCH 592/606] Revert "media: subdev: Improve v4l2_subdev_enable/disable_streams_fallback" This reverts commit 2b3dc697a46580b050e9bc00373a2860a77d67c2 which is commit 61d6c8c896c1ccde350c281817847a32b0c6b83b upstream. It breaks the Android kernel abi and can be brought back in the future in an abi-safe way if it is really needed. Bug: 161946584 Change-Id: I6b03604c6b43baba83e71cc1af61243813370d33 Signed-off-by: Greg Kroah-Hartman --- drivers/media/v4l2-core/v4l2-subdev.c | 68 +++++++++++---------------- include/media/v4l2-subdev.h | 9 ++-- 2 files changed, 33 insertions(+), 44 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index f555fd3c4b76..8bfbe9d5fe3c 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -1925,43 +1925,37 @@ static int v4l2_subdev_enable_streams_fallback(struct v4l2_subdev *sd, u32 pad, u64 streams_mask) { struct device *dev = sd->entity.graph_obj.mdev->dev; + unsigned int i; int ret; /* * The subdev doesn't implement pad-based stream enable, fall back - * to the .s_stream() operation. + * on the .s_stream() operation. This can only be done for subdevs that + * have a single source pad, as sd->enabled_streams is global to the + * subdev. */ if (!(sd->entity.pads[pad].flags & MEDIA_PAD_FL_SOURCE)) return -EOPNOTSUPP; - /* - * .s_stream() means there is no streams support, so the only allowed - * stream is the implicit stream 0. - */ - if (streams_mask != BIT_ULL(0)) - return -EOPNOTSUPP; + for (i = 0; i < sd->entity.num_pads; ++i) { + if (i != pad && sd->entity.pads[i].flags & MEDIA_PAD_FL_SOURCE) + return -EOPNOTSUPP; + } - /* - * We use a 64-bit bitmask for tracking enabled pads, so only subdevices - * with 64 pads or less can be supported. - */ - if (pad >= sizeof(sd->enabled_pads) * BITS_PER_BYTE) - return -EOPNOTSUPP; - - if (sd->enabled_pads & BIT_ULL(pad)) { - dev_dbg(dev, "pad %u already enabled on %s\n", - pad, sd->entity.name); + if (sd->enabled_streams & streams_mask) { + dev_dbg(dev, "set of streams %#llx already enabled on %s:%u\n", + streams_mask, sd->entity.name, pad); return -EALREADY; } - /* Start streaming when the first pad is enabled. */ - if (!sd->enabled_pads) { + /* Start streaming when the first streams are enabled. */ + if (!sd->enabled_streams) { ret = v4l2_subdev_call(sd, video, s_stream, 1); if (ret) return ret; } - sd->enabled_pads |= BIT_ULL(pad); + sd->enabled_streams |= streams_mask; return 0; } @@ -2048,43 +2042,37 @@ static int v4l2_subdev_disable_streams_fallback(struct v4l2_subdev *sd, u32 pad, u64 streams_mask) { struct device *dev = sd->entity.graph_obj.mdev->dev; + unsigned int i; int ret; /* - * If the subdev doesn't implement pad-based stream enable, fall back - * to the .s_stream() operation. + * If the subdev doesn't implement pad-based stream enable, fall back + * on the .s_stream() operation. This can only be done for subdevs that + * have a single source pad, as sd->enabled_streams is global to the + * subdev. */ if (!(sd->entity.pads[pad].flags & MEDIA_PAD_FL_SOURCE)) return -EOPNOTSUPP; - /* - * .s_stream() means there is no streams support, so the only allowed - * stream is the implicit stream 0. - */ - if (streams_mask != BIT_ULL(0)) - return -EOPNOTSUPP; + for (i = 0; i < sd->entity.num_pads; ++i) { + if (i != pad && sd->entity.pads[i].flags & MEDIA_PAD_FL_SOURCE) + return -EOPNOTSUPP; + } - /* - * We use a 64-bit bitmask for tracking enabled pads, so only subdevices - * with 64 pads or less can be supported. - */ - if (pad >= sizeof(sd->enabled_pads) * BITS_PER_BYTE) - return -EOPNOTSUPP; - - if (!(sd->enabled_pads & BIT_ULL(pad))) { - dev_dbg(dev, "pad %u already disabled on %s\n", - pad, sd->entity.name); + if ((sd->enabled_streams & streams_mask) != streams_mask) { + dev_dbg(dev, "set of streams %#llx already disabled on %s:%u\n", + streams_mask, sd->entity.name, pad); return -EALREADY; } /* Stop streaming when the last streams are disabled. */ - if (!(sd->enabled_pads & ~BIT_ULL(pad))) { + if (!(sd->enabled_streams & ~streams_mask)) { ret = v4l2_subdev_call(sd, video, s_stream, 0); if (ret) return ret; } - sd->enabled_pads &= ~BIT_ULL(pad); + sd->enabled_streams &= ~streams_mask; return 0; } diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 0a8d75b009ea..ee570dfbd791 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -1038,9 +1038,10 @@ struct v4l2_subdev_platform_data { * @active_state: Active state for the subdev (NULL for subdevs tracking the * state internally). Initialized by calling * v4l2_subdev_init_finalize(). - * @enabled_pads: Bitmask of enabled pads used by v4l2_subdev_enable_streams() - * and v4l2_subdev_disable_streams() helper functions for - * fallback cases. + * @enabled_streams: Bitmask of enabled streams used by + * v4l2_subdev_enable_streams() and + * v4l2_subdev_disable_streams() helper functions for fallback + * cases. * @s_stream_enabled: Tracks whether streaming has been enabled with s_stream. * This is only for call_s_stream() internal use. * @@ -1090,7 +1091,7 @@ struct v4l2_subdev { * doesn't support it. */ struct v4l2_subdev_state *active_state; - u64 enabled_pads; + u64 enabled_streams; bool s_stream_enabled; }; From 00201c6c4e0c9d9242598d62554a0fe0a60a22f6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 May 2025 06:44:02 +0000 Subject: [PATCH 593/606] Revert "media: subdev: Fix use of sd->enabled_streams in call_s_stream()" This reverts commit beeeea11ee2a09230b3fd4863563d99b7b23c8f0 which is commit 1d7804281df3f09f0a109d00406e859a00bae7ae upstream. It breaks the Android kernel abi and can be brought back in the future in an abi-safe way if it is really needed. Bug: 161946584 Change-Id: Ie24122f982c1655e610fd591fac52366a0e07bdc Signed-off-by: Greg Kroah-Hartman --- drivers/media/v4l2-core/v4l2-subdev.c | 8 ++++++-- include/media/v4l2-subdev.h | 3 --- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 8bfbe9d5fe3c..a32ef739eb44 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -363,8 +363,12 @@ static int call_s_stream(struct v4l2_subdev *sd, int enable) * The .s_stream() operation must never be called to start or stop an * already started or stopped subdev. Catch offenders but don't return * an error yet to avoid regressions. + * + * As .s_stream() is mutually exclusive with the .enable_streams() and + * .disable_streams() operation, we can use the enabled_streams field + * to store the subdev streaming state. */ - if (WARN_ON(sd->s_stream_enabled == !!enable)) + if (WARN_ON(!!sd->enabled_streams == !!enable)) return 0; ret = sd->ops->video->s_stream(sd, enable); @@ -375,7 +379,7 @@ static int call_s_stream(struct v4l2_subdev *sd, int enable) } if (!ret) { - sd->s_stream_enabled = enable; + sd->enabled_streams = enable ? BIT(0) : 0; #if IS_REACHABLE(CONFIG_LEDS_CLASS) if (!IS_ERR_OR_NULL(sd->privacy_led)) { diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index ee570dfbd791..ab2a7ef61d42 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -1042,8 +1042,6 @@ struct v4l2_subdev_platform_data { * v4l2_subdev_enable_streams() and * v4l2_subdev_disable_streams() helper functions for fallback * cases. - * @s_stream_enabled: Tracks whether streaming has been enabled with s_stream. - * This is only for call_s_stream() internal use. * * Each instance of a subdev driver should create this struct, either * stand-alone or embedded in a larger struct. @@ -1092,7 +1090,6 @@ struct v4l2_subdev { */ struct v4l2_subdev_state *active_state; u64 enabled_streams; - bool s_stream_enabled; }; From e7d23a611343fa0356696ddd741631c527e491f6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 7 May 2025 09:06:43 +0000 Subject: [PATCH 594/606] Revert "sched/topology: Consolidate and clean up access to a CPU's max compute capacity" This reverts commit 7fc781ca938fde88b11a75d4678c9a457c221199 which is commit 7bc263840bc3377186cb06b003ac287bb2f18ce2 upstream. It breaks the Android kernel abi and can be brought back in the future in an abi-safe way if it is really needed. Bug: 161946584 Change-Id: I2db630d00cd4c52eac8d7371a99b415b40fd252a Signed-off-by: Greg Kroah-Hartman --- Documentation/scheduler/sched-capacity.rst | 13 ++++++------- kernel/sched/core.c | 2 +- kernel/sched/cpudeadline.c | 2 +- kernel/sched/deadline.c | 4 ++-- kernel/sched/fair.c | 16 +++++++++------- kernel/sched/rt.c | 2 +- kernel/sched/sched.h | 6 ++++++ kernel/sched/topology.c | 7 ++----- 8 files changed, 28 insertions(+), 24 deletions(-) diff --git a/Documentation/scheduler/sched-capacity.rst b/Documentation/scheduler/sched-capacity.rst index de414b33dd2a..e2c1cf743158 100644 --- a/Documentation/scheduler/sched-capacity.rst +++ b/Documentation/scheduler/sched-capacity.rst @@ -39,15 +39,14 @@ per Hz, leading to:: ------------------- Two different capacity values are used within the scheduler. A CPU's -``original capacity`` is its maximum attainable capacity, i.e. its maximum -attainable performance level. This original capacity is returned by -the function arch_scale_cpu_capacity(). A CPU's ``capacity`` is its ``original -capacity`` to which some loss of available performance (e.g. time spent -handling IRQs) is subtracted. +``capacity_orig`` is its maximum attainable capacity, i.e. its maximum +attainable performance level. A CPU's ``capacity`` is its ``capacity_orig`` to +which some loss of available performance (e.g. time spent handling IRQs) is +subtracted. Note that a CPU's ``capacity`` is solely intended to be used by the CFS class, -while ``original capacity`` is class-agnostic. The rest of this document will use -the term ``capacity`` interchangeably with ``original capacity`` for the sake of +while ``capacity_orig`` is class-agnostic. The rest of this document will use +the term ``capacity`` interchangeably with ``capacity_orig`` for the sake of brevity. 1.3 Platform examples diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 2b2542a63de8..f6ed2a5a5e2f 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -10269,7 +10269,7 @@ void __init sched_init(void) #ifdef CONFIG_SMP rq->sd = NULL; rq->rd = NULL; - rq->cpu_capacity = SCHED_CAPACITY_SCALE; + rq->cpu_capacity = rq->cpu_capacity_orig = SCHED_CAPACITY_SCALE; rq->balance_callback = &balance_push_callback; rq->active_balance = 0; rq->next_balance = jiffies; diff --git a/kernel/sched/cpudeadline.c b/kernel/sched/cpudeadline.c index 95baa12a1029..57c92d751bcd 100644 --- a/kernel/sched/cpudeadline.c +++ b/kernel/sched/cpudeadline.c @@ -131,7 +131,7 @@ int cpudl_find(struct cpudl *cp, struct task_struct *p, if (!dl_task_fits_capacity(p, cpu)) { cpumask_clear_cpu(cpu, later_mask); - cap = arch_scale_cpu_capacity(cpu); + cap = capacity_orig_of(cpu); if (cap > max_cap || (cpu == task_cpu(p) && cap == max_cap)) { diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index fd2312607bd9..ca41ecd36ec2 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -132,7 +132,7 @@ static inline unsigned long __dl_bw_capacity(const struct cpumask *mask) int i; for_each_cpu_and(i, mask, cpu_active_mask) - cap += arch_scale_cpu_capacity(i); + cap += capacity_orig_of(i); return cap; } @@ -144,7 +144,7 @@ static inline unsigned long __dl_bw_capacity(const struct cpumask *mask) static inline unsigned long dl_bw_capacity(int i) { if (!sched_asym_cpucap_active() && - arch_scale_cpu_capacity(i) == SCHED_CAPACITY_SCALE) { + capacity_orig_of(i) == SCHED_CAPACITY_SCALE) { return dl_bw_cpus(i) << SCHED_CAPACITY_SHIFT; } else { RCU_LOCKDEP_WARN(!rcu_read_lock_sched_held(), diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 6f8cedcd492b..35ffd5b504b2 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -4991,14 +4991,14 @@ static inline int util_fits_cpu(unsigned long util, return fits; /* - * We must use arch_scale_cpu_capacity() for comparing against uclamp_min and + * We must use capacity_orig_of() for comparing against uclamp_min and * uclamp_max. We only care about capacity pressure (by using * capacity_of()) for comparing against the real util. * * If a task is boosted to 1024 for example, we don't want a tiny * pressure to skew the check whether it fits a CPU or not. * - * Similarly if a task is capped to arch_scale_cpu_capacity(little_cpu), it + * Similarly if a task is capped to capacity_orig_of(little_cpu), it * should fit a little cpu even if there's some pressure. * * Only exception is for thermal pressure since it has a direct impact @@ -5010,7 +5010,7 @@ static inline int util_fits_cpu(unsigned long util, * For uclamp_max, we can tolerate a drop in performance level as the * goal is to cap the task. So it's okay if it's getting less. */ - capacity_orig = arch_scale_cpu_capacity(cpu); + capacity_orig = capacity_orig_of(cpu); capacity_orig_thermal = capacity_orig - arch_scale_thermal_pressure(cpu); /* @@ -7536,7 +7536,7 @@ select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target) * Look for the CPU with best capacity. */ else if (fits < 0) - cpu_cap = arch_scale_cpu_capacity(cpu) - thermal_load_avg(cpu_rq(cpu)); + cpu_cap = capacity_orig_of(cpu) - thermal_load_avg(cpu_rq(cpu)); /* * First, select CPU which fits better (-1 being better than 0). @@ -7778,7 +7778,7 @@ cpu_util(int cpu, struct task_struct *p, int dst_cpu, int boost) util = max(util, util_est); } - return min(util, arch_scale_cpu_capacity(cpu)); + return min(util, capacity_orig_of(cpu)); } unsigned long cpu_util_cfs(int cpu) @@ -9626,6 +9626,8 @@ static void update_cpu_capacity(struct sched_domain *sd, int cpu) unsigned long capacity = scale_rt_capacity(cpu); struct sched_group *sdg = sd->groups; + cpu_rq(cpu)->cpu_capacity_orig = arch_scale_cpu_capacity(cpu); + if (!capacity) capacity = 1; @@ -9702,7 +9704,7 @@ static inline int check_cpu_capacity(struct rq *rq, struct sched_domain *sd) { return ((rq->cpu_capacity * sd->imbalance_pct) < - (arch_scale_cpu_capacity(cpu_of(rq)) * 100)); + (rq->cpu_capacity_orig * 100)); } /* @@ -9713,7 +9715,7 @@ check_cpu_capacity(struct rq *rq, struct sched_domain *sd) static inline int check_misfit_status(struct rq *rq, struct sched_domain *sd) { return rq->misfit_task_load && - (arch_scale_cpu_capacity(rq->cpu) < rq->rd->max_cpu_capacity || + (rq->cpu_capacity_orig < rq->rd->max_cpu_capacity || check_cpu_capacity(rq, sd)); } diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 427f4afe6eba..e70cac66d270 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -521,7 +521,7 @@ static inline bool rt_task_fits_capacity(struct task_struct *p, int cpu) min_cap = uclamp_eff_value(p, UCLAMP_MIN); max_cap = uclamp_eff_value(p, UCLAMP_MAX); - cpu_cap = arch_scale_cpu_capacity(cpu); + cpu_cap = capacity_orig_of(cpu); return cpu_cap >= min(min_cap, max_cap); } diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 37e40a701917..581fc21cf34a 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1076,6 +1076,7 @@ struct rq { struct sched_domain __rcu *sd; unsigned long cpu_capacity; + unsigned long cpu_capacity_orig; struct balance_callback *balance_callback; @@ -3029,6 +3030,11 @@ static inline void cpufreq_update_util(struct rq *rq, unsigned int flags) {} #endif #ifdef CONFIG_SMP +static inline unsigned long capacity_orig_of(int cpu) +{ + return cpu_rq(cpu)->cpu_capacity_orig; +} + /** * enum cpu_util_type - CPU utilization type * @FREQUENCY_UTIL: Utilization used to select frequency diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c index b2d81e8a6c96..eb36532d6eb4 100644 --- a/kernel/sched/topology.c +++ b/kernel/sched/topology.c @@ -2478,15 +2478,12 @@ build_sched_domains(const struct cpumask *cpu_map, struct sched_domain_attr *att /* Attach the domains */ rcu_read_lock(); for_each_cpu(i, cpu_map) { - unsigned long capacity; - rq = cpu_rq(i); sd = *per_cpu_ptr(d.sd, i); - capacity = arch_scale_cpu_capacity(i); /* Use READ_ONCE()/WRITE_ONCE() to avoid load/store tearing: */ - if (capacity > READ_ONCE(d.rd->max_cpu_capacity)) - WRITE_ONCE(d.rd->max_cpu_capacity, capacity); + if (rq->cpu_capacity_orig > READ_ONCE(d.rd->max_cpu_capacity)) + WRITE_ONCE(d.rd->max_cpu_capacity, rq->cpu_capacity_orig); cpu_attach_domain(sd, d.rd, i); } From 6fc7e6988884e20913095d147b919c665f51e9d5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 6 May 2025 06:38:56 +0000 Subject: [PATCH 595/606] ANDROID: GKI: fix up crc issue in crypto_get_default_null_skcipher() In commit 1b66a5920b7f ("crypto: null - Use spin lock instead of mutex"), the .h files get shuffled around a bit, which causes a CRC mismatch in crypto_get_default_null_skcipher(). Put them back to the way they were if we are calculating crcs, to keep the build clean. Bug: 161946584 Fixes: 1b66a5920b7f ("crypto: null - Use spin lock instead of mutex") Change-Id: I7d1490944efbbd3bdc99e4116014b5f32ab3d708 Signed-off-by: Greg Kroah-Hartman --- crypto/crypto_null.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crypto/crypto_null.c b/crypto/crypto_null.c index 337867028653..3170e2fdcfd3 100644 --- a/crypto/crypto_null.c +++ b/crypto/crypto_null.c @@ -17,7 +17,11 @@ #include #include #include +#ifdef __GENKSYMS__ // CRC fix for e307c54ac819 ("crypto: null - Use spin lock instead of mutex") +#include +#else #include +#endif #include static DEFINE_SPINLOCK(crypto_default_null_skcipher_lock); From 290f5d0002fb7b1ce6a1e1bf6241438bb676693f Mon Sep 17 00:00:00 2001 From: Fuad Tabba Date: Wed, 7 May 2025 12:40:11 +0100 Subject: [PATCH 596/606] ANDROID: KVM: arm64: Move kvm_hyp_handle_fpsimd_host() to switch.h Move kvm_hyp_handle_fpsimd_host() to the shared switch header, instead of having separate implementations in the vhe/nvhe switch.c files. Subsequent patches will remove all specific implementations from switch.c and include switch.h in other files. Bug: 411040189 Change-Id: I07f1d92f96b072435ded5f0b84a446df4e6a81ab Signed-off-by: Fuad Tabba --- arch/arm64/include/asm/kvm_hyp.h | 3 +++ arch/arm64/kvm/hyp/include/hyp/switch.h | 26 ++++++++++++++++++++++++- arch/arm64/kvm/hyp/nvhe/switch.c | 25 ------------------------ arch/arm64/kvm/hyp/vhe/switch.c | 5 ----- 4 files changed, 28 insertions(+), 31 deletions(-) diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h index 171e654b07d8..37b7728511c7 100644 --- a/arch/arm64/include/asm/kvm_hyp.h +++ b/arch/arm64/include/asm/kvm_hyp.h @@ -142,6 +142,9 @@ void __hyp_exit(void); #ifdef __KVM_NVHE_HYPERVISOR__ struct user_fpsimd_state *get_host_fpsimd_state(struct kvm_vcpu *vcpu); struct kvm_host_sve_state *get_host_sve_state(struct kvm_vcpu *vcpu); +#else +#define get_host_fpsimd_state(vcpu) (vcpu)->arch.host_fpsimd_state +#define get_host_sve_state(vcpu) NULL #endif extern u64 kvm_nvhe_sym(id_aa64pfr0_el1_sys_val); diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h index 92b43c9d7a60..19b411e69d62 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -303,7 +304,30 @@ static inline void __hyp_sve_restore_guest(struct kvm_vcpu *vcpu) sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1ULL, SYS_ZCR_EL2); } -static void kvm_hyp_handle_fpsimd_host(struct kvm_vcpu *vcpu); +static void kvm_hyp_handle_fpsimd_host(struct kvm_vcpu *vcpu) +{ + /* + * Non-protected kvm relies on the host restoring its sve state. + * Protected kvm restores the host's sve state as not to reveal that + * fpsimd was used by a guest nor leak upper sve bits. + */ + if (unlikely(is_protected_kvm_enabled() && system_supports_sve())) { + struct kvm_host_sve_state *sve_state = get_host_sve_state(vcpu); + u64 zcr_el2 = sve_vq_from_vl(kvm_host_sve_max_vl) - 1; + + sve_state->zcr_el1 = read_sysreg_el1(SYS_ZCR); + sve_cond_update_zcr_vq(zcr_el2, SYS_ZCR_EL2); + __sve_save_state(sve_state->sve_regs + + sve_ffr_offset(kvm_host_sve_max_vl), + &sve_state->fpsr); + + /* Still trap SVE since it's handled by hyp in pKVM. */ + if (!vcpu_has_sve(vcpu)) + sysreg_clear_set(cptr_el2, 0, CPTR_EL2_TZ); + } else { + __fpsimd_save_state(get_host_fpsimd_state(vcpu)); + } +} static void __deactivate_fpsimd_traps(struct kvm_vcpu *vcpu); diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c index 8d0ad38e2a51..3f63fc22f1e0 100644 --- a/arch/arm64/kvm/hyp/nvhe/switch.c +++ b/arch/arm64/kvm/hyp/nvhe/switch.c @@ -262,31 +262,6 @@ static bool kvm_handle_pvm_sys64(struct kvm_vcpu *vcpu, u64 *exit_code) kvm_handle_pvm_sysreg(vcpu, exit_code)); } -static void kvm_hyp_handle_fpsimd_host(struct kvm_vcpu *vcpu) -{ - /* - * Non-protected kvm relies on the host restoring its sve state. - * Protected kvm restores the host's sve state as not to reveal that - * fpsimd was used by a guest nor leak upper sve bits. - */ - if (unlikely(is_protected_kvm_enabled() && system_supports_sve())) { - struct kvm_host_sve_state *sve_state = get_host_sve_state(vcpu); - u64 zcr_el2 = sve_vq_from_vl(kvm_host_sve_max_vl) - 1; - - sve_state->zcr_el1 = read_sysreg_el1(SYS_ZCR); - sve_cond_update_zcr_vq(zcr_el2, SYS_ZCR_EL2); - __sve_save_state(sve_state->sve_regs + - sve_ffr_offset(kvm_host_sve_max_vl), - &sve_state->fpsr); - - /* Still trap SVE since it's handled by hyp in pKVM. */ - if (!vcpu_has_sve(vcpu)) - sysreg_clear_set(cptr_el2, 0, CPTR_EL2_TZ); - } else { - __fpsimd_save_state(get_host_fpsimd_state(vcpu)); - } -} - static const exit_handler_fn hyp_exit_handlers[] = { [0 ... ESR_ELx_EC_MAX] = NULL, [ESR_ELx_EC_CP15_32] = kvm_hyp_handle_cp15_32, diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c index 5ca78a5dcc8b..74eff5280c91 100644 --- a/arch/arm64/kvm/hyp/vhe/switch.c +++ b/arch/arm64/kvm/hyp/vhe/switch.c @@ -173,11 +173,6 @@ static void __deactivate_fpsimd_traps(struct kvm_vcpu *vcpu) sysreg_clear_set(cpacr_el1, 0, reg); } -static void kvm_hyp_handle_fpsimd_host(struct kvm_vcpu *vcpu) -{ - __fpsimd_save_state(vcpu->arch.host_fpsimd_state); -} - static const exit_handler_fn hyp_exit_handlers[] = { [0 ... ESR_ELx_EC_MAX] = NULL, [ESR_ELx_EC_CP15_32] = kvm_hyp_handle_cp15_32, From 051c5c53b0b13f24e640dbb090913e9eb3141cf0 Mon Sep 17 00:00:00 2001 From: Fuad Tabba Date: Thu, 1 May 2025 13:21:50 +0100 Subject: [PATCH 597/606] ANDROID: KVM: arm64: Move __deactivate_fpsimd_traps() to switch.h Move __deactivate_fpsimd_traps() to the shared switch header, instead of having separate implementations in the vhe/nvhe switch.c files. Subsequent patches will remove all specific implementations from switch.c and include switch.h in other files. Bug: 411040189 Change-Id: I42c545e939b230366fbd9ad8e41a614193169bce Signed-off-by: Fuad Tabba --- arch/arm64/kvm/hyp/include/hyp/switch.h | 21 ++++++++++++++++++++- arch/arm64/kvm/hyp/nvhe/switch.c | 21 --------------------- arch/arm64/kvm/hyp/vhe/switch.c | 10 ---------- 3 files changed, 20 insertions(+), 32 deletions(-) diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h index 19b411e69d62..212bf2983128 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -329,7 +329,26 @@ static void kvm_hyp_handle_fpsimd_host(struct kvm_vcpu *vcpu) } } -static void __deactivate_fpsimd_traps(struct kvm_vcpu *vcpu); +static void __deactivate_fpsimd_traps(struct kvm_vcpu *vcpu) +{ + u64 reg; + bool trap_sve = vcpu_has_sve(vcpu) || + (is_protected_kvm_enabled() && system_supports_sve()); + + if (has_vhe() || has_hvhe()) { + reg = CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN; + if (trap_sve) + reg |= CPACR_EL1_ZEN_EL0EN | CPACR_EL1_ZEN_EL1EN; + + sysreg_clear_set(cpacr_el1, 0, reg); + } else { + reg = CPTR_EL2_TFP; + if (trap_sve) + reg |= CPTR_EL2_TZ; + + sysreg_clear_set(cptr_el2, reg, 0); + } +} /* * We trap the first access to the FP/SIMD to save the host context and diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c index 3f63fc22f1e0..60516f9a364b 100644 --- a/arch/arm64/kvm/hyp/nvhe/switch.c +++ b/arch/arm64/kvm/hyp/nvhe/switch.c @@ -171,27 +171,6 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu) write_sysreg(__kvm_hyp_host_vector, vbar_el2); } -static void __deactivate_fpsimd_traps(struct kvm_vcpu *vcpu) -{ - u64 reg; - bool trap_sve = vcpu_has_sve(vcpu) || - (is_protected_kvm_enabled() && system_supports_sve()); - - if (has_hvhe()) { - reg = CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN; - if (trap_sve) - reg |= CPACR_EL1_ZEN_EL0EN | CPACR_EL1_ZEN_EL1EN; - - sysreg_clear_set(cpacr_el1, 0, reg); - } else { - reg = CPTR_EL2_TFP; - if (trap_sve) - reg |= CPTR_EL2_TZ; - - sysreg_clear_set(cptr_el2, reg, 0); - } -} - /* Save VGICv3 state on non-VHE systems */ static void __hyp_vgic_save_state(struct kvm_vcpu *vcpu) { diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c index 74eff5280c91..49b178886395 100644 --- a/arch/arm64/kvm/hyp/vhe/switch.c +++ b/arch/arm64/kvm/hyp/vhe/switch.c @@ -163,16 +163,6 @@ void deactivate_traps_vhe_put(struct kvm_vcpu *vcpu) local_irq_restore(flags); } -static void __deactivate_fpsimd_traps(struct kvm_vcpu *vcpu) -{ - u64 reg = CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN; - - if (vcpu_has_sve(vcpu)) - reg |= CPACR_EL1_ZEN_EL0EN | CPACR_EL1_ZEN_EL1EN; - - sysreg_clear_set(cpacr_el1, 0, reg); -} - static const exit_handler_fn hyp_exit_handlers[] = { [0 ... ESR_ELx_EC_MAX] = NULL, [ESR_ELx_EC_CP15_32] = kvm_hyp_handle_cp15_32, From a8408e37cec1bb0267f6b2b15214d44dddbea7ec Mon Sep 17 00:00:00 2001 From: Fuad Tabba Date: Thu, 1 May 2025 10:21:31 +0100 Subject: [PATCH 598/606] ANDROID: KVM: arm64: Eagerly restore host FPSIMD/SVE state in pKVM Eagerly restore the host fpsimd/sve state after every vcpu run in protected mode if the fpsimd/sve unit was used by the guest, instead of setting fpsimd/simd traps and restoring if the host triggers them. Note that the behavior with this patch is the existing behavior in Android 16 (except for restoring ZCL_EL2, which is being fixed in conjunction with this patch there as well). Bug: 411040189 Change-Id: I5702590331093937c1cd0d08ac754c634054c7f7 Signed-off-by: Fuad Tabba --- arch/arm64/kvm/hyp/nvhe/hyp-main.c | 101 ++++++++++++----------------- 1 file changed, 41 insertions(+), 60 deletions(-) diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c index 5c6015656abe..91447b108ec6 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -65,6 +65,8 @@ static inline void hyp_reqs_smccc_encode(unsigned long ret, struct kvm_cpu_conte void __kvm_hyp_host_forward_smc(struct kvm_cpu_context *host_ctxt); +static void fpsimd_host_restore(struct kvm_vcpu *vcpu); + static bool (*default_host_smc_handler)(struct user_pt_regs *regs); static bool (*default_trap_handler)(struct user_pt_regs *regs); static bool (*unmask_serror)(void); @@ -671,6 +673,8 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu) hyp_entry_exit_handler_fn ec_handler; u8 esr_ec; + hyp_vcpu->vcpu.arch.fp_state = FP_STATE_HOST_OWNED; + /* * If we deal with a non-protected guest and the state is potentially * dirty (from a host perspective), copy the state back into the hyp @@ -761,6 +765,9 @@ static void sync_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu, u32 exit_reason) else host_vcpu->arch.iflags = hyp_vcpu->vcpu.arch.iflags; + if (hyp_vcpu->vcpu.arch.fp_state != FP_STATE_HOST_OWNED) + fpsimd_host_restore(&hyp_vcpu->vcpu); + hyp_vcpu->exit_code = exit_reason; } @@ -788,32 +795,37 @@ static void __hyp_sve_restore_host(struct kvm_vcpu *vcpu) sve_cond_update_zcr_vq(ZCR_ELx_LEN_MASK, SYS_ZCR_EL2); } -static void fpsimd_host_restore(void) +static void fpsimd_host_restore(struct kvm_vcpu *vcpu) { - if (has_hvhe()) - sysreg_clear_set(cpacr_el1, 0, - (CPACR_EL1_ZEN_EL1EN | CPACR_EL1_ZEN_EL0EN | - CPACR_EL1_FPEN_EL1EN | CPACR_EL1_FPEN_EL0EN)); - else - sysreg_clear_set(cptr_el2, CPTR_EL2_TZ | CPTR_EL2_TFP, 0); + u64 reg; + bool trap_sve = system_supports_sve(); + + if (has_hvhe()) { + reg = CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN; + if (trap_sve) + reg |= CPACR_EL1_ZEN_EL0EN | CPACR_EL1_ZEN_EL1EN; + + sysreg_clear_set(cpacr_el1, 0, reg); + } else { + reg = CPTR_EL2_TFP; + if (trap_sve) + reg |= CPTR_EL2_TZ; + + sysreg_clear_set(cptr_el2, reg, 0); + } isb(); - if (unlikely(is_protected_kvm_enabled())) { - struct pkvm_hyp_vcpu *hyp_vcpu = pkvm_get_loaded_hyp_vcpu(); - struct kvm_vcpu *vcpu = &hyp_vcpu->vcpu; + if (vcpu_has_sve(vcpu)) + __hyp_sve_save_guest(vcpu); + else + __fpsimd_save_state(&vcpu->arch.ctxt.fp_regs); - if (vcpu_has_sve(vcpu)) - __hyp_sve_save_guest(vcpu); - else - __fpsimd_save_state(&vcpu->arch.ctxt.fp_regs); + if (system_supports_sve()) + __hyp_sve_restore_host(vcpu); + else + __fpsimd_restore_state(get_host_fpsimd_state(vcpu)); - if (system_supports_sve()) - __hyp_sve_restore_host(vcpu); - else - __fpsimd_restore_state(get_host_fpsimd_state(vcpu)); - - hyp_vcpu->vcpu.arch.fp_state = FP_STATE_HOST_OWNED; - } + vcpu->arch.fp_state = FP_STATE_HOST_OWNED; } static void handle___pkvm_vcpu_load(struct kvm_cpu_context *host_ctxt) @@ -844,8 +856,6 @@ static void handle___pkvm_vcpu_load(struct kvm_cpu_context *host_ctxt) *last_ran = hyp_vcpu->vcpu.vcpu_id; } - hyp_vcpu->vcpu.arch.fp_state = FP_STATE_HOST_OWNED; - if (pkvm_hyp_vcpu_is_protected(hyp_vcpu)) { /* Propagate WFx trapping flags, trap ptrauth */ hyp_vcpu->vcpu.arch.hcr_el2 &= ~(HCR_TWE | HCR_TWI | @@ -865,9 +875,6 @@ static void handle___pkvm_vcpu_put(struct kvm_cpu_context *host_ctxt) if (hyp_vcpu) { struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu; - if (hyp_vcpu->vcpu.arch.fp_state == FP_STATE_GUEST_OWNED) - fpsimd_host_restore(); - if (!pkvm_hyp_vcpu_is_protected(hyp_vcpu) && !vcpu_get_flag(host_vcpu, PKVM_HOST_STATE_DIRTY)) { __sync_hyp_vcpu(hyp_vcpu); @@ -888,9 +895,6 @@ static void handle___pkvm_vcpu_sync_state(struct kvm_cpu_context *host_ctxt) if (!hyp_vcpu || pkvm_hyp_vcpu_is_protected(hyp_vcpu)) return; - if (hyp_vcpu->vcpu.arch.fp_state == FP_STATE_GUEST_OWNED) - fpsimd_host_restore(); - __sync_hyp_vcpu(hyp_vcpu); } @@ -961,31 +965,8 @@ static void handle___kvm_vcpu_run(struct kvm_cpu_context *host_ctxt) goto out; flush_hyp_vcpu(hyp_vcpu); - ret = __kvm_vcpu_run(&hyp_vcpu->vcpu); - sync_hyp_vcpu(hyp_vcpu, ret); - - if (hyp_vcpu->vcpu.arch.fp_state == FP_STATE_GUEST_OWNED) { - /* - * The guest has used the FP, trap all accesses - * from the host (both FP and SVE). - */ - u64 reg; - if (has_hvhe()) { - reg = CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN; - if (system_supports_sve()) - reg |= CPACR_EL1_ZEN_EL0EN | CPACR_EL1_ZEN_EL1EN; - - sysreg_clear_set(cpacr_el1, reg, 0); - } else { - reg = CPTR_EL2_TFP; - if (system_supports_sve()) - reg |= CPTR_EL2_TZ; - - sysreg_clear_set(cptr_el2, 0, reg); - } - } } else { /* The host is fully trusted, run its vCPU directly. */ ret = __kvm_vcpu_run(host_vcpu); @@ -1730,13 +1711,8 @@ inval: static void handle_host_smc(struct kvm_cpu_context *host_ctxt) { DECLARE_REG(u64, func_id, host_ctxt, 0); - struct pkvm_hyp_vcpu *hyp_vcpu; bool handled; - hyp_vcpu = pkvm_get_loaded_hyp_vcpu(); - if (hyp_vcpu && hyp_vcpu->vcpu.arch.fp_state == FP_STATE_GUEST_OWNED) - fpsimd_host_restore(); - func_id &= ~ARM_SMCCC_CALL_HINTS; handled = kvm_host_psci_handler(host_ctxt, func_id); @@ -1769,10 +1745,15 @@ void handle_trap(struct kvm_cpu_context *host_ctxt) case ESR_ELx_EC_SMC64: handle_host_smc(host_ctxt); break; - case ESR_ELx_EC_FP_ASIMD: case ESR_ELx_EC_SVE: - case ESR_ELx_EC_SME: - fpsimd_host_restore(); + BUG_ON(is_protected_kvm_enabled()); + if (has_hvhe()) + sysreg_clear_set(cpacr_el1, 0, (CPACR_EL1_ZEN_EL1EN | + CPACR_EL1_ZEN_EL0EN)); + else + sysreg_clear_set(cptr_el2, CPTR_EL2_TZ, 0); + isb(); + sve_cond_update_zcr_vq(ZCR_ELx_LEN_MASK, SYS_ZCR_EL2); break; case ESR_ELx_EC_IABT_LOW: case ESR_ELx_EC_DABT_LOW: From db6c8d3397d21d26d7facef0d27c7d39496754dd Mon Sep 17 00:00:00 2001 From: Fuad Tabba Date: Mon, 16 Dec 2024 10:50:52 +0000 Subject: [PATCH 599/606] BACKPORT: KVM: arm64: Calculate cptr_el2 traps on activating traps [ Upstream commit 2fd5b4b0e7b440602455b79977bfa64dea101e6c ] Similar to VHE, calculate the value of cptr_el2 from scratch on activate traps. This removes the need to store cptr_el2 in every vcpu structure. Moreover, some traps, such as whether the guest owns the fp registers, need to be set on every vcpu run. [tabba@ Kept cptr_el2 as to not break the KMI.] Bug: 411040189 Reported-by: James Clark Fixes: 5294afdbf45a ("KVM: arm64: Exclude FP ownership from kvm_vcpu_arch") Change-Id: Iba65e9bb65d8498007423dc5b137dedc602359de Signed-off-by: Fuad Tabba Link: https://lore.kernel.org/r/20241216105057.579031-13-tabba@google.com Signed-off-by: Marc Zyngier Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- arch/arm64/include/asm/kvm_host.h | 2 ++ arch/arm64/kvm/arm.c | 1 - arch/arm64/kvm/hyp/nvhe/pkvm.c | 43 +---------------------- arch/arm64/kvm/hyp/nvhe/switch.c | 58 +++++++++++++++++++------------ 4 files changed, 38 insertions(+), 66 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 45213376303b..9a87186fb1d3 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -587,6 +587,8 @@ struct kvm_vcpu_arch { /* Values of trap registers for the guest. */ u64 hcr_el2; u64 mdcr_el2; + + /* DO NOT USE: Removed upstream. Kept to not break the KMI. */ u64 cptr_el2; /* Values of trap registers for the host before guest entry. */ diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 91702c1dd968..79d9a0cbeb4c 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -1433,7 +1433,6 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu, } vcpu_reset_hcr(vcpu); - vcpu->arch.cptr_el2 = kvm_get_reset_cptr_el2(vcpu); /* * Handle the "start in power-off" case. diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c index 517e4be5af84..3728b1c50502 100644 --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c @@ -82,8 +82,6 @@ static void pvm_init_traps_aa64pfr0(struct kvm_vcpu *vcpu) const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64PFR0_EL1); u64 hcr_set = HCR_RW; u64 hcr_clear = 0; - u64 cptr_set = 0; - u64 cptr_clear = 0; /* Protected KVM does not support AArch32 guests. */ BUILD_BUG_ON(FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL0), @@ -111,23 +109,11 @@ static void pvm_init_traps_aa64pfr0(struct kvm_vcpu *vcpu) } /* Trap AMU */ - if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_AMU), feature_ids)) { + if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_AMU), feature_ids)) hcr_clear |= HCR_AMVOFFEN; - cptr_set |= CPTR_EL2_TAM; - } - - /* Trap SVE */ - if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_SVE), feature_ids)) { - if (has_hvhe()) - cptr_clear |= CPACR_EL1_ZEN_EL0EN | CPACR_EL1_ZEN_EL1EN; - else - cptr_set |= CPTR_EL2_TZ; - } vcpu->arch.hcr_el2 |= hcr_set; vcpu->arch.hcr_el2 &= ~hcr_clear; - vcpu->arch.cptr_el2 |= cptr_set; - vcpu->arch.cptr_el2 &= ~cptr_clear; } /* @@ -138,8 +124,6 @@ static void pvm_init_traps_aa64pfr1(struct kvm_vcpu *vcpu) const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64PFR1_EL1); u64 hcr_set = 0; u64 hcr_clear = 0; - u64 cptr_set = 0; - u64 cptr_clear = 0; /* Memory Tagging: Trap and Treat as Untagged if not supported. */ if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE), feature_ids)) { @@ -147,17 +131,8 @@ static void pvm_init_traps_aa64pfr1(struct kvm_vcpu *vcpu) hcr_clear |= HCR_DCT | HCR_ATA; } - /* No SME supprot in KVM. */ - BUG_ON(FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_SME), feature_ids)); - if (has_hvhe()) - cptr_clear |= CPACR_EL1_SMEN_EL1EN | CPACR_EL1_SMEN_EL0EN; - else - cptr_set |= CPTR_EL2_TSM; - vcpu->arch.hcr_el2 |= hcr_set; vcpu->arch.hcr_el2 &= ~hcr_clear; - vcpu->arch.cptr_el2 |= cptr_set; - vcpu->arch.cptr_el2 &= ~cptr_clear; } /* @@ -168,7 +143,6 @@ static void pvm_init_traps_aa64dfr0(struct kvm_vcpu *vcpu) const u64 feature_ids = pvm_read_id_reg(vcpu, SYS_ID_AA64DFR0_EL1); u64 mdcr_set = 0; u64 mdcr_clear = 0; - u64 cptr_set = 0; /* Trap/constrain PMU */ if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMUVer), feature_ids)) { @@ -195,21 +169,12 @@ static void pvm_init_traps_aa64dfr0(struct kvm_vcpu *vcpu) if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceFilt), feature_ids)) mdcr_set |= MDCR_EL2_TTRF; - /* Trap Trace */ - if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_TraceVer), feature_ids)) { - if (has_hvhe()) - cptr_set |= CPACR_EL1_TTA; - else - cptr_set |= CPTR_EL2_TTA; - } - /* Trap External Trace */ if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_ExtTrcBuff), feature_ids)) mdcr_clear |= MDCR_EL2_E2TB_MASK << MDCR_EL2_E2TB_SHIFT; vcpu->arch.mdcr_el2 |= mdcr_set; vcpu->arch.mdcr_el2 &= ~mdcr_clear; - vcpu->arch.cptr_el2 |= cptr_set; } /* @@ -267,11 +232,6 @@ static void pvm_init_trap_regs(struct kvm_vcpu *vcpu) if (cpus_have_const_cap(ARM64_MISMATCHED_CACHE_TYPE)) vcpu->arch.hcr_el2 |= HCR_TID2; - - if (!has_hvhe()) { - vcpu->arch.cptr_el2 |= CPTR_NVHE_EL2_RES1; - vcpu->arch.cptr_el2 &= ~(CPTR_NVHE_EL2_RES0); - } } /* @@ -279,7 +239,6 @@ static void pvm_init_trap_regs(struct kvm_vcpu *vcpu) */ static void pkvm_vcpu_init_traps(struct pkvm_hyp_vcpu *hyp_vcpu) { - hyp_vcpu->vcpu.arch.cptr_el2 = kvm_get_reset_cptr_el2(&hyp_vcpu->vcpu); hyp_vcpu->vcpu.arch.mdcr_el2 = 0; if (!pkvm_hyp_vcpu_is_protected(hyp_vcpu)) { diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c index 60516f9a364b..f403c168536a 100644 --- a/arch/arm64/kvm/hyp/nvhe/switch.c +++ b/arch/arm64/kvm/hyp/nvhe/switch.c @@ -83,12 +83,45 @@ static void __deactivate_pvm_traps_hfgxtr(struct kvm_vcpu *vcpu) write_sysreg_s(ctxt_sys_reg(hctxt, HAFGRTR_EL2), SYS_HAFGRTR_EL2); } +static void __activate_cptr_traps(struct kvm_vcpu *vcpu) +{ + u64 val = CPTR_EL2_TAM; /* Same bit irrespective of E2H */ + + if (has_hvhe()) { + val |= CPACR_ELx_TTA; + + if (vcpu->arch.fp_state == FP_STATE_GUEST_OWNED) { + val |= CPACR_ELx_FPEN; + if (vcpu_has_sve(vcpu)) + val |= CPACR_ELx_ZEN; + } + } else { + val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1; + + /* + * Always trap SME since it's not supported in KVM. + * TSM is RES1 if SME isn't implemented. + */ + val |= CPTR_EL2_TSM; + + if (!vcpu_has_sve(vcpu) || vcpu->arch.fp_state != FP_STATE_GUEST_OWNED) + val |= CPTR_EL2_TZ; + + if (vcpu->arch.fp_state != FP_STATE_GUEST_OWNED) + val |= CPTR_EL2_TFP; + } + + if (vcpu->arch.fp_state != FP_STATE_GUEST_OWNED) + __activate_traps_fpsimd32(vcpu); + + kvm_write_cptr_el2(val); +} + static void __activate_traps(struct kvm_vcpu *vcpu) { - u64 val; - ___activate_traps(vcpu); __activate_traps_common(vcpu); + __activate_cptr_traps(vcpu); if (unlikely(vcpu_is_protected(vcpu))) { __activate_pvm_fine_grain_traps(vcpu); @@ -97,27 +130,6 @@ static void __activate_traps(struct kvm_vcpu *vcpu) __activate_traps_hfgxtr(vcpu); } - val = vcpu->arch.cptr_el2; - val |= CPTR_EL2_TAM; /* Same bit irrespective of E2H */ - val |= has_hvhe() ? CPACR_EL1_TTA : CPTR_EL2_TTA; - if (cpus_have_final_cap(ARM64_SME)) { - if (has_hvhe()) - val &= ~(CPACR_EL1_SMEN_EL1EN | CPACR_EL1_SMEN_EL0EN); - else - val |= CPTR_EL2_TSM; - } - - if (vcpu->arch.fp_state != FP_STATE_GUEST_OWNED) { - if (has_hvhe()) - val &= ~(CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN | - CPACR_EL1_ZEN_EL0EN | CPACR_EL1_ZEN_EL1EN); - else - val |= CPTR_EL2_TFP | CPTR_EL2_TZ; - - __activate_traps_fpsimd32(vcpu); - } - - kvm_write_cptr_el2(val); write_sysreg(__this_cpu_read(kvm_hyp_vector), vbar_el2); if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) { From 1775aac0bd9a47c9691c51bb3b50f310a8f16dcb Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Mon, 10 Feb 2025 19:52:19 +0000 Subject: [PATCH 600/606] BACKPORT: KVM: arm64: Unconditionally save+flush host FPSIMD/SVE/SME state [ Upstream commit fbc7e61195e23f744814e78524b73b59faa54ab4 ] There are several problems with the way hyp code lazily saves the host's FPSIMD/SVE state, including: * Host SVE being discarded unexpectedly due to inconsistent configuration of TIF_SVE and CPACR_ELx.ZEN. This has been seen to result in QEMU crashes where SVE is used by memmove(), as reported by Eric Auger: https://issues.redhat.com/browse/RHEL-68997 * Host SVE state is discarded *after* modification by ptrace, which was an unintentional ptrace ABI change introduced with lazy discarding of SVE state. * The host FPMR value can be discarded when running a non-protected VM, where FPMR support is not exposed to a VM, and that VM uses FPSIMD/SVE. In these cases the hyp code does not save the host's FPMR before unbinding the host's FPSIMD/SVE/SME state, leaving a stale value in memory. Avoid these by eagerly saving and "flushing" the host's FPSIMD/SVE/SME state when loading a vCPU such that KVM does not need to save any of the host's FPSIMD/SVE/SME state. For clarity, fpsimd_kvm_prepare() is removed and the necessary call to fpsimd_save_and_flush_cpu_state() is placed in kvm_arch_vcpu_load_fp(). As 'fpsimd_state' and 'fpmr_ptr' should not be used, they are set to NULL; all uses of these will be removed in subsequent patches. Historical problems go back at least as far as v5.17, e.g. erroneous assumptions about TIF_SVE being clear in commit: 8383741ab2e773a9 ("KVM: arm64: Get rid of host SVE tracking/saving") ... and so this eager save+flush probably needs to be backported to ALL stable trees. Bug: 411040189 Fixes: 93ae6b01bafee8fa ("KVM: arm64: Discard any SVE state when entering KVM guests") Fixes: 8c845e2731041f0f ("arm64/sve: Leave SVE enabled on syscall if we don't context switch") Fixes: ef3be86021c3bdf3 ("KVM: arm64: Add save/restore support for FPMR") Reported-by: Eric Auger Reported-by: Wilco Dijkstra Reviewed-by: Mark Brown Tested-by: Mark Brown Tested-by: Eric Auger Acked-by: Will Deacon Cc: Catalin Marinas Cc: Florian Weimer Cc: Fuad Tabba Cc: Jeremy Linton Cc: Marc Zyngier Cc: Oliver Upton Cc: Paolo Bonzini Change-Id: I2c230b8db86f5c68ebf24f06d1e4787da284c80d Signed-off-by: Mark Rutland Reviewed-by: Oliver Upton Link: https://lore.kernel.org/r/20250210195226.1215254-2-mark.rutland@arm.com Signed-off-by: Marc Zyngier [ Mark: Handle vcpu/host flag conflict ] Signed-off-by: Mark Rutland Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Fuad Tabba --- arch/arm64/kernel/fpsimd.c | 25 ------------------------- arch/arm64/kvm/fpsimd.c | 31 ++++++++----------------------- 2 files changed, 8 insertions(+), 48 deletions(-) diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index 0137d987631e..bd4f6c6ee0f3 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -1707,31 +1707,6 @@ void fpsimd_signal_preserve_current_state(void) sve_to_fpsimd(current); } -/* - * Called by KVM when entering the guest. - */ -void fpsimd_kvm_prepare(void) -{ - if (!system_supports_sve()) - return; - - /* - * KVM does not save host SVE state since we can only enter - * the guest from a syscall so the ABI means that only the - * non-saved SVE state needs to be saved. If we have left - * SVE enabled for performance reasons then update the task - * state to be FPSIMD only. - */ - get_cpu_fpsimd_context(); - - if (test_and_clear_thread_flag(TIF_SVE)) { - sve_to_fpsimd(current); - current->thread.fp_type = FP_STATE_FPSIMD; - } - - put_cpu_fpsimd_context(); -} - /* * Associate current's FPSIMD context with this cpu * The caller must have ownership of the cpu FPSIMD context before calling diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c index 847b8be81587..f1d39cb92a41 100644 --- a/arch/arm64/kvm/fpsimd.c +++ b/arch/arm64/kvm/fpsimd.c @@ -56,14 +56,16 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu) if (!system_supports_fpsimd()) return; - fpsimd_kvm_prepare(); - /* - * We will check TIF_FOREIGN_FPSTATE just before entering the - * guest in kvm_arch_vcpu_ctxflush_fp() and override this to - * FP_STATE_FREE if the flag set. + * Ensure that any host FPSIMD/SVE/SME state is saved and unbound such + * that the host kernel is responsible for restoring this state upon + * return to userspace, and the hyp code doesn't need to save anything. + * + * When the host may use SME, fpsimd_save_and_flush_cpu_state() ensures + * that PSTATE.{SM,ZA} == {0,0}. */ - vcpu->arch.fp_state = FP_STATE_HOST_OWNED; + fpsimd_save_and_flush_cpu_state(); + vcpu->arch.fp_state = FP_STATE_FREE; vcpu_clear_flag(vcpu, HOST_SVE_ENABLED); if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN) @@ -73,23 +75,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu) vcpu_clear_flag(vcpu, HOST_SME_ENABLED); if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN) vcpu_set_flag(vcpu, HOST_SME_ENABLED); - - /* - * If PSTATE.SM is enabled then save any pending FP - * state and disable PSTATE.SM. If we leave PSTATE.SM - * enabled and the guest does not enable SME via - * CPACR_EL1.SMEN then operations that should be valid - * may generate SME traps from EL1 to EL1 which we - * can't intercept and which would confuse the guest. - * - * Do the same for PSTATE.ZA in the case where there - * is state in the registers which has not already - * been saved, this is very unlikely to happen. - */ - if (read_sysreg_s(SYS_SVCR) & (SVCR_SM_MASK | SVCR_ZA_MASK)) { - vcpu->arch.fp_state = FP_STATE_FREE; - fpsimd_save_and_flush_cpu_state(); - } } /* From 1e88a51e5dee10f300613fb12587c09cd63377c6 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Mon, 10 Feb 2025 19:52:20 +0000 Subject: [PATCH 601/606] BACKPORT: KVM: arm64: Remove host FPSIMD saving for non-protected KVM [ Upstream commit 8eca7f6d5100b6997df4f532090bc3f7e0203bef ] Now that the host eagerly saves its own FPSIMD/SVE/SME state, non-protected KVM never needs to save the host FPSIMD/SVE/SME state, and the code to do this is never used. Protected KVM still needs to save/restore the host FPSIMD/SVE state to avoid leaking guest state to the host (and to avoid revealing to the host whether the guest used FPSIMD/SVE/SME), and that code needs to be retained. Remove the unused code and data structures. To avoid the need for a stub copy of kvm_hyp_save_fpsimd_host() in the VHE hyp code, the nVHE/hVHE version is moved into the shared switch header, where it is only invoked when KVM is in protected mode. [tabba@ Kept user_fpsimd_state as to not break the KMI.] Bug: 411040189 Change-Id: I0088db7c5f75c9331956867040b8eb69976aabf8 Signed-off-by: Mark Rutland Reviewed-by: Mark Brown Tested-by: Mark Brown Acked-by: Will Deacon Cc: Catalin Marinas Cc: Fuad Tabba Cc: Marc Zyngier Cc: Oliver Upton Reviewed-by: Oliver Upton Link: https://lore.kernel.org/r/20250210195226.1215254-3-mark.rutland@arm.com Signed-off-by: Marc Zyngier Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Fuad Tabba --- arch/arm64/include/asm/kvm_host.h | 3 ++- arch/arm64/include/asm/kvm_hyp.h | 2 +- arch/arm64/kvm/fpsimd.c | 2 -- arch/arm64/kvm/hyp/include/hyp/switch.h | 4 ++-- arch/arm64/kvm/hyp/nvhe/pkvm.c | 3 --- 5 files changed, 5 insertions(+), 9 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 9a87186fb1d3..a9dfdf9e3dde 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -639,7 +639,8 @@ struct kvm_vcpu_arch { struct kvm_guest_debug_arch vcpu_debug_state; struct kvm_guest_debug_arch external_debug_state; - struct user_fpsimd_state *host_fpsimd_state; /* hyp VA */ + /* DO NOT USE: Removed upstream. Kept to not break the KMI. */ + struct user_fpsimd_state *host_fpsimd_state; struct { /* {Break,watch}point registers */ diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h index 37b7728511c7..25f7006a8a8c 100644 --- a/arch/arm64/include/asm/kvm_hyp.h +++ b/arch/arm64/include/asm/kvm_hyp.h @@ -143,7 +143,7 @@ void __hyp_exit(void); struct user_fpsimd_state *get_host_fpsimd_state(struct kvm_vcpu *vcpu); struct kvm_host_sve_state *get_host_sve_state(struct kvm_vcpu *vcpu); #else -#define get_host_fpsimd_state(vcpu) (vcpu)->arch.host_fpsimd_state +#define get_host_fpsimd_state(vcpu) NULL #define get_host_sve_state(vcpu) NULL #endif diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c index f1d39cb92a41..1a44e57b5745 100644 --- a/arch/arm64/kvm/fpsimd.c +++ b/arch/arm64/kvm/fpsimd.c @@ -37,8 +37,6 @@ int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu) if (ret) return ret; - vcpu->arch.host_fpsimd_state = kern_hyp_va(fpsimd); - return 0; } diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h index 212bf2983128..28b5f0ebc280 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -311,7 +311,7 @@ static void kvm_hyp_handle_fpsimd_host(struct kvm_vcpu *vcpu) * Protected kvm restores the host's sve state as not to reveal that * fpsimd was used by a guest nor leak upper sve bits. */ - if (unlikely(is_protected_kvm_enabled() && system_supports_sve())) { + if (system_supports_sve()) { struct kvm_host_sve_state *sve_state = get_host_sve_state(vcpu); u64 zcr_el2 = sve_vq_from_vl(kvm_host_sve_max_vl) - 1; @@ -386,7 +386,7 @@ static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code) isb(); /* Write out the host state if it's in the registers */ - if (vcpu->arch.fp_state == FP_STATE_HOST_OWNED) + if (is_protected_kvm_enabled() && vcpu->arch.fp_state == FP_STATE_HOST_OWNED) kvm_hyp_handle_fpsimd_host(vcpu); /* Restore the guest state */ diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c index 3728b1c50502..fa4c40b0a172 100644 --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c @@ -60,9 +60,6 @@ static void *__get_host_fpsimd_bytes(void) struct user_fpsimd_state *get_host_fpsimd_state(struct kvm_vcpu *vcpu) { - if (likely(!is_protected_kvm_enabled())) - return vcpu->arch.host_fpsimd_state; - WARN_ON(system_supports_sve()); return __get_host_fpsimd_bytes(); } From 0af026605a02391512e7b8e8e4a5ea087f7c08bd Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Mon, 10 Feb 2025 19:52:21 +0000 Subject: [PATCH 602/606] BACKPORT: KVM: arm64: Remove VHE host restore of CPACR_EL1.ZEN [ Upstream commit 459f059be702056d91537b99a129994aa6ccdd35 ] When KVM is in VHE mode, the host kernel tries to save and restore the configuration of CPACR_EL1.ZEN (i.e. CPTR_EL2.ZEN when HCR_EL2.E2H=1) across kvm_arch_vcpu_load_fp() and kvm_arch_vcpu_put_fp(), since the configuration may be clobbered by hyp when running a vCPU. This logic is currently redundant. The VHE hyp code unconditionally configures CPTR_EL2.ZEN to 0b01 when returning to the host, permitting host kernel usage of SVE. Now that the host eagerly saves and unbinds its own FPSIMD/SVE/SME state, there's no need to save/restore the state of the EL0 SVE trap. The kernel can safely save/restore state without trapping, as described above, and will restore userspace state (including trap controls) before returning to userspace. Remove the redundant logic. Bug: 411040189 Change-Id: I43bf5587223aae54caf9389eb3de17f155043d96 Signed-off-by: Mark Rutland Reviewed-by: Mark Brown Tested-by: Mark Brown Acked-by: Will Deacon Cc: Catalin Marinas Cc: Fuad Tabba Cc: Marc Zyngier Cc: Oliver Upton Reviewed-by: Oliver Upton Link: https://lore.kernel.org/r/20250210195226.1215254-4-mark.rutland@arm.com Signed-off-by: Marc Zyngier [Rework for refactoring of where the flags are stored -- broonie] Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Fuad Tabba --- arch/arm64/include/asm/kvm_host.h | 2 -- arch/arm64/kvm/fpsimd.c | 16 ---------------- 2 files changed, 18 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index a9dfdf9e3dde..888bc463b07b 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -849,8 +849,6 @@ struct kvm_vcpu_arch { /* pKVM host vcpu state is dirty, needs resync (nVHE-only) */ #define PKVM_HOST_STATE_DIRTY __vcpu_single_flag(iflags, BIT(7)) -/* SVE enabled for host EL0 */ -#define HOST_SVE_ENABLED __vcpu_single_flag(sflags, BIT(0)) /* SME enabled for EL0 */ #define HOST_SME_ENABLED __vcpu_single_flag(sflags, BIT(1)) /* Physical CPU not in supported_cpus */ diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c index 1a44e57b5745..513b94733fde 100644 --- a/arch/arm64/kvm/fpsimd.c +++ b/arch/arm64/kvm/fpsimd.c @@ -65,10 +65,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu) fpsimd_save_and_flush_cpu_state(); vcpu->arch.fp_state = FP_STATE_FREE; - vcpu_clear_flag(vcpu, HOST_SVE_ENABLED); - if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN) - vcpu_set_flag(vcpu, HOST_SVE_ENABLED); - if (system_supports_sme()) { vcpu_clear_flag(vcpu, HOST_SME_ENABLED); if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN) @@ -184,18 +180,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) } fpsimd_save_and_flush_cpu_state(); - } else if (has_vhe() && system_supports_sve()) { - /* - * The FPSIMD/SVE state in the CPU has not been touched, and we - * have SVE (and VHE): CPACR_EL1 (alias CPTR_EL2) has been - * reset by kvm_reset_cptr_el2() in the Hyp code, disabling SVE - * for EL0. To avoid spurious traps, restore the trap state - * seen by kvm_arch_vcpu_load_fp(): - */ - if (vcpu_get_flag(vcpu, HOST_SVE_ENABLED)) - sysreg_clear_set(CPACR_EL1, 0, CPACR_EL1_ZEN_EL0EN); - else - sysreg_clear_set(CPACR_EL1, CPACR_EL1_ZEN_EL0EN, 0); } local_irq_restore(flags); From 2af7cb2232cbd25228e506518a55a1325af18e94 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Mon, 10 Feb 2025 19:52:22 +0000 Subject: [PATCH 603/606] BACKPORT: KVM: arm64: Remove VHE host restore of CPACR_EL1.SMEN [ Upstream commit 407a99c4654e8ea65393f412c421a55cac539f5b ] When KVM is in VHE mode, the host kernel tries to save and restore the configuration of CPACR_EL1.SMEN (i.e. CPTR_EL2.SMEN when HCR_EL2.E2H=1) across kvm_arch_vcpu_load_fp() and kvm_arch_vcpu_put_fp(), since the configuration may be clobbered by hyp when running a vCPU. This logic has historically been broken, and is currently redundant. This logic was originally introduced in commit: 861262ab86270206 ("KVM: arm64: Handle SME host state when running guests") At the time, the VHE hyp code would reset CPTR_EL2.SMEN to 0b00 when returning to the host, trapping host access to SME state. Unfortunately, this was unsafe as the host could take a softirq before calling kvm_arch_vcpu_put_fp(), and if a softirq handler were to use kernel mode NEON the resulting attempt to save the live FPSIMD/SVE/SME state would result in a fatal trap. That issue was limited to VHE mode. For nVHE/hVHE modes, KVM always saved/restored the host kernel's CPACR_EL1 value, and configured CPTR_EL2.TSM to 0b0, ensuring that host usage of SME would not be trapped. The issue above was incidentally fixed by commit: 375110ab51dec5dc ("KVM: arm64: Fix resetting SME trap values on reset for (h)VHE") That commit changed the VHE hyp code to configure CPTR_EL2.SMEN to 0b01 when returning to the host, permitting host kernel usage of SME, avoiding the issue described above. At the time, this was not identified as a fix for commit 861262ab86270206. Now that the host eagerly saves and unbinds its own FPSIMD/SVE/SME state, there's no need to save/restore the state of the EL0 SME trap. The kernel can safely save/restore state without trapping, as described above, and will restore userspace state (including trap controls) before returning to userspace. Remove the redundant logic. Bug: 411040189 Change-Id: Ia2fbb22a21da8e63f0a3b9a76d47ee2c987e2fa5 Signed-off-by: Mark Rutland Reviewed-by: Mark Brown Tested-by: Mark Brown Acked-by: Will Deacon Cc: Catalin Marinas Cc: Fuad Tabba Cc: Marc Zyngier Cc: Oliver Upton Reviewed-by: Oliver Upton Link: https://lore.kernel.org/r/20250210195226.1215254-5-mark.rutland@arm.com Signed-off-by: Marc Zyngier [Update for rework of flags storage -- broonie] Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Fuad Tabba --- arch/arm64/include/asm/kvm_host.h | 2 -- arch/arm64/kvm/fpsimd.c | 30 ------------------------------ 2 files changed, 32 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 888bc463b07b..7336137bf221 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -849,8 +849,6 @@ struct kvm_vcpu_arch { /* pKVM host vcpu state is dirty, needs resync (nVHE-only) */ #define PKVM_HOST_STATE_DIRTY __vcpu_single_flag(iflags, BIT(7)) -/* SME enabled for EL0 */ -#define HOST_SME_ENABLED __vcpu_single_flag(sflags, BIT(1)) /* Physical CPU not in supported_cpus */ #define ON_UNSUPPORTED_CPU __vcpu_single_flag(sflags, BIT(2)) /* WFIT instruction trapped */ diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c index 513b94733fde..0c0cfb6dcc17 100644 --- a/arch/arm64/kvm/fpsimd.c +++ b/arch/arm64/kvm/fpsimd.c @@ -64,19 +64,6 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu) */ fpsimd_save_and_flush_cpu_state(); vcpu->arch.fp_state = FP_STATE_FREE; - - if (system_supports_sme()) { - vcpu_clear_flag(vcpu, HOST_SME_ENABLED); - if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN) - vcpu_set_flag(vcpu, HOST_SME_ENABLED); - } - - /* - * If normal guests gain this support, maintain this behavior - * for pKVM guests, which don't support SME. - */ - BUG_ON(is_protected_kvm_enabled() && system_supports_sme() && - read_sysreg_s(SYS_SVCR)); } /* @@ -141,23 +128,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) local_irq_save(flags); - /* - * If we have VHE then the Hyp code will reset CPACR_EL1 to - * the default value and we need to reenable SME. - */ - if (has_vhe() && system_supports_sme()) { - /* Also restore EL0 state seen on entry */ - if (vcpu_get_flag(vcpu, HOST_SME_ENABLED)) - sysreg_clear_set(CPACR_EL1, 0, - CPACR_EL1_SMEN_EL0EN | - CPACR_EL1_SMEN_EL1EN); - else - sysreg_clear_set(CPACR_EL1, - CPACR_EL1_SMEN_EL0EN, - CPACR_EL1_SMEN_EL1EN); - isb(); - } - if (vcpu->arch.fp_state == FP_STATE_GUEST_OWNED) { if (vcpu_has_sve(vcpu)) { __vcpu_sys_reg(vcpu, ZCR_EL1) = read_sysreg_el1(SYS_ZCR); From 2179040e7bc4a277503fa92e6b3e6dc51fe1110c Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Mon, 10 Feb 2025 19:52:24 +0000 Subject: [PATCH 604/606] BACKPORT: KVM: arm64: Refactor exit handlers [ Upstream commit 9b66195063c5a145843547b1d692bd189be85287 ] The hyp exit handling logic is largely shared between VHE and nVHE/hVHE, with common logic in arch/arm64/kvm/hyp/include/hyp/switch.h. The code in the header depends on function definitions provided by arch/arm64/kvm/hyp/vhe/switch.c and arch/arm64/kvm/hyp/nvhe/switch.c when they include the header. This is an unusual header dependency, and prevents the use of arch/arm64/kvm/hyp/include/hyp/switch.h in other files as this would result in compiler warnings regarding missing definitions, e.g. | In file included from arch/arm64/kvm/hyp/nvhe/hyp-main.c:8: | ./arch/arm64/kvm/hyp/include/hyp/switch.h:733:31: warning: 'kvm_get_exit_handler_array' used but never defined | 733 | static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu); | | ^~~~~~~~~~~~~~~~~~~~~~~~~~ | ./arch/arm64/kvm/hyp/include/hyp/switch.h:735:13: warning: 'early_exit_filter' used but never defined | 735 | static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code); | | ^~~~~~~~~~~~~~~~~ Refactor the logic such that the header doesn't depend on anything from the C files. There should be no functional change as a result of this patch. Bug: 411040189 Change-Id: I4e58bad80763afd73fd03f9653ed4e66dfe97255 Signed-off-by: Mark Rutland Reviewed-by: Mark Brown Tested-by: Mark Brown Acked-by: Will Deacon Cc: Catalin Marinas Cc: Fuad Tabba Cc: Marc Zyngier Cc: Oliver Upton Reviewed-by: Oliver Upton Link: https://lore.kernel.org/r/20250210195226.1215254-7-mark.rutland@arm.com Signed-off-by: Marc Zyngier Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Fuad Tabba --- arch/arm64/kvm/hyp/include/hyp/switch.h | 30 +++++------------------- arch/arm64/kvm/hyp/nvhe/switch.c | 31 ++++++++++++++----------- arch/arm64/kvm/hyp/vhe/switch.c | 9 ++++--- 3 files changed, 28 insertions(+), 42 deletions(-) diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h index 28b5f0ebc280..88dbd8cc940b 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -660,23 +660,16 @@ static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code) typedef bool (*exit_handler_fn)(struct kvm_vcpu *, u64 *); -static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu); - -static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code); - /* * Allow the hypervisor to handle the exit with an exit handler if it has one. * * Returns true if the hypervisor handled the exit, and control should go back * to the guest, or false if it hasn't. */ -static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code) +static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code, + const exit_handler_fn *handlers) { - const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu); - exit_handler_fn fn; - - fn = handlers[kvm_vcpu_trap_get_class(vcpu)]; - + exit_handler_fn fn = handlers[kvm_vcpu_trap_get_class(vcpu)]; if (fn) return fn(vcpu, exit_code); @@ -706,20 +699,9 @@ static inline void synchronize_vcpu_pstate(struct kvm_vcpu *vcpu, u64 *exit_code * the guest, false when we should restore the host state and return to the * main run loop. */ -static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) +static inline bool __fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code, + const exit_handler_fn *handlers) { - /* - * Save PSTATE early so that we can evaluate the vcpu mode - * early on. - */ - synchronize_vcpu_pstate(vcpu, exit_code); - - /* - * Check whether we want to repaint the state one way or - * another. - */ - early_exit_filter(vcpu, exit_code); - if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ) vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR); @@ -749,7 +731,7 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) goto exit; /* Check if there's an exit handler and allow it to handle the exit. */ - if (kvm_hyp_handle_exit(vcpu, exit_code)) + if (kvm_hyp_handle_exit(vcpu, exit_code, handlers)) goto guest; exit: /* Return to the host kernel and handle the exit */ diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c index f403c168536a..77feeb8b1e84 100644 --- a/arch/arm64/kvm/hyp/nvhe/switch.c +++ b/arch/arm64/kvm/hyp/nvhe/switch.c @@ -288,20 +288,23 @@ static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu) return hyp_exit_handlers; } -/* - * Some guests (e.g., protected VMs) are not be allowed to run in AArch32. - * The ARMv8 architecture does not give the hypervisor a mechanism to prevent a - * guest from dropping to AArch32 EL0 if implemented by the CPU. If the - * hypervisor spots a guest in such a state ensure it is handled, and don't - * trust the host to spot or fix it. The check below is based on the one in - * kvm_arch_vcpu_ioctl_run(). - * - * Returns false if the guest ran in AArch32 when it shouldn't have, and - * thus should exit to the host, or true if a the guest run loop can continue. - */ -static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code) +static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) { - if (unlikely(vcpu_is_protected(vcpu) && vcpu_mode_is_32bit(vcpu))) { + const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu); + struct kvm *kvm = kern_hyp_va(vcpu->kvm); + + synchronize_vcpu_pstate(vcpu, exit_code); + + /* + * Some guests (e.g., protected VMs) are not be allowed to run in + * AArch32. The ARMv8 architecture does not give the hypervisor a + * mechanism to prevent a guest from dropping to AArch32 EL0 if + * implemented by the CPU. If the hypervisor spots a guest in such a + * state ensure it is handled, and don't trust the host to spot or fix + * it. The check below is based on the one in + * kvm_arch_vcpu_ioctl_run(). + */ + if (kvm_vm_is_protected(kvm) && vcpu_mode_is_32bit(vcpu)) { /* * As we have caught the guest red-handed, decide that it isn't * fit for purpose anymore by making the vcpu invalid. The VMM @@ -313,6 +316,8 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code) *exit_code &= BIT(ARM_EXIT_WITH_SERROR_BIT); *exit_code |= ARM_EXCEPTION_IL; } + + return __fixup_guest_exit(vcpu, exit_code, handlers); } /* Switch to the guest for legacy non-VHE systems */ diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c index 49b178886395..036235b37fa4 100644 --- a/arch/arm64/kvm/hyp/vhe/switch.c +++ b/arch/arm64/kvm/hyp/vhe/switch.c @@ -175,13 +175,10 @@ static const exit_handler_fn hyp_exit_handlers[] = { [ESR_ELx_EC_PAC] = kvm_hyp_handle_ptrauth, }; -static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu) +static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) { - return hyp_exit_handlers; -} + synchronize_vcpu_pstate(vcpu, exit_code); -static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code) -{ /* * If we were in HYP context on entry, adjust the PSTATE view * so that the usual helpers work correctly. @@ -201,6 +198,8 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code) *vcpu_cpsr(vcpu) &= ~(PSR_MODE_MASK | PSR_MODE32_BIT); *vcpu_cpsr(vcpu) |= mode; } + + return __fixup_guest_exit(vcpu, exit_code, hyp_exit_handlers); } /* Switch to the guest for VHE systems running in EL2 */ From 2bdae59ccfe2d1419d2c737c4bdfccbd62071323 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Mon, 10 Feb 2025 19:52:25 +0000 Subject: [PATCH 605/606] BACKPORT: KVM: arm64: Mark some header functions as inline [ Upstream commit f9dd00de1e53a47763dfad601635d18542c3836d ] The shared hyp switch header has a number of static functions which might not be used by all files that include the header, and when unused they will provoke compiler warnings, e.g. | In file included from arch/arm64/kvm/hyp/nvhe/hyp-main.c:8: | ./arch/arm64/kvm/hyp/include/hyp/switch.h:703:13: warning: 'kvm_hyp_handle_dabt_low' defined but not used [-Wunused-function] | 703 | static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code) | | ^~~~~~~~~~~~~~~~~~~~~~~ | ./arch/arm64/kvm/hyp/include/hyp/switch.h:682:13: warning: 'kvm_hyp_handle_cp15_32' defined but not used [-Wunused-function] | 682 | static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code) | | ^~~~~~~~~~~~~~~~~~~~~~ | ./arch/arm64/kvm/hyp/include/hyp/switch.h:662:13: warning: 'kvm_hyp_handle_sysreg' defined but not used [-Wunused-function] | 662 | static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code) | | ^~~~~~~~~~~~~~~~~~~~~ | ./arch/arm64/kvm/hyp/include/hyp/switch.h:458:13: warning: 'kvm_hyp_handle_fpsimd' defined but not used [-Wunused-function] | 458 | static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code) | | ^~~~~~~~~~~~~~~~~~~~~ | ./arch/arm64/kvm/hyp/include/hyp/switch.h:329:13: warning: 'kvm_hyp_handle_mops' defined but not used [-Wunused-function] | 329 | static bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code) | | ^~~~~~~~~~~~~~~~~~~ Mark these functions as 'inline' to suppress this warning. This shouldn't result in any functional change. At the same time, avoid the use of __alias() in the header and alias kvm_hyp_handle_iabt_low() and kvm_hyp_handle_watchpt_low() to kvm_hyp_handle_memory_fault() using CPP, matching the style in the rest of the kernel. For consistency, kvm_hyp_handle_memory_fault() is also marked as 'inline'. Bug: 411040189 Change-Id: I5766401542afda440f737c1fee1810a73e89e86d Signed-off-by: Mark Rutland Reviewed-by: Mark Brown Tested-by: Mark Brown Acked-by: Will Deacon Cc: Catalin Marinas Cc: Fuad Tabba Cc: Marc Zyngier Cc: Oliver Upton Reviewed-by: Oliver Upton Link: https://lore.kernel.org/r/20250210195226.1215254-8-mark.rutland@arm.com Signed-off-by: Marc Zyngier Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Fuad Tabba --- arch/arm64/kvm/hyp/include/hyp/switch.h | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h index 88dbd8cc940b..68961a185661 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -356,7 +356,7 @@ static void __deactivate_fpsimd_traps(struct kvm_vcpu *vcpu) * If FP/SIMD is not implemented, handle the trap and inject an undefined * instruction exception to the guest. Similarly for trapped SVE accesses. */ -static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code) +static inline bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code) { bool sve_guest; u8 esr_ec; @@ -586,7 +586,7 @@ static bool handle_ampere1_tcr(struct kvm_vcpu *vcpu) return true; } -static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code) +static inline bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code) { if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM) && handle_tx2_tvm(vcpu)) @@ -609,7 +609,7 @@ static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code) return false; } -static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code) +static inline bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code) { if (static_branch_unlikely(&vgic_v3_cpuif_trap) && __vgic_v3_perform_cpuif_access(vcpu) == 1) @@ -618,19 +618,18 @@ static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code) return false; } -static bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu, u64 *exit_code) +static inline bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu, + u64 *exit_code) { if (!__populate_fault_info(vcpu)) return true; return false; } -static bool kvm_hyp_handle_iabt_low(struct kvm_vcpu *vcpu, u64 *exit_code) - __alias(kvm_hyp_handle_memory_fault); -static bool kvm_hyp_handle_watchpt_low(struct kvm_vcpu *vcpu, u64 *exit_code) - __alias(kvm_hyp_handle_memory_fault); +#define kvm_hyp_handle_iabt_low kvm_hyp_handle_memory_fault +#define kvm_hyp_handle_watchpt_low kvm_hyp_handle_memory_fault -static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code) +static inline bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code) { if (kvm_hyp_handle_memory_fault(vcpu, exit_code)) return true; From 65999c7d05eccec53506a00d53f85575b230ab51 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Mon, 10 Feb 2025 19:52:26 +0000 Subject: [PATCH 606/606] BACKPORT: KVM: arm64: Eagerly switch ZCR_EL{1,2} [ Upstream commit 59419f10045bc955d2229819c7cf7a8b0b9c5b59 ] In non-protected KVM modes, while the guest FPSIMD/SVE/SME state is live on the CPU, the host's active SVE VL may differ from the guest's maximum SVE VL: * For VHE hosts, when a VM uses NV, ZCR_EL2 contains a value constrained by the guest hypervisor, which may be less than or equal to that guest's maximum VL. Note: in this case the value of ZCR_EL1 is immaterial due to E2H. * For nVHE/hVHE hosts, ZCR_EL1 contains a value written by the guest, which may be less than or greater than the guest's maximum VL. Note: in this case hyp code traps host SVE usage and lazily restores ZCR_EL2 to the host's maximum VL, which may be greater than the guest's maximum VL. This can be the case between exiting a guest and kvm_arch_vcpu_put_fp(). If a softirq is taken during this period and the softirq handler tries to use kernel-mode NEON, then the kernel will fail to save the guest's FPSIMD/SVE state, and will pend a SIGKILL for the current thread. This happens because kvm_arch_vcpu_ctxsync_fp() binds the guest's live FPSIMD/SVE state with the guest's maximum SVE VL, and fpsimd_save_user_state() verifies that the live SVE VL is as expected before attempting to save the register state: | if (WARN_ON(sve_get_vl() != vl)) { | force_signal_inject(SIGKILL, SI_KERNEL, 0, 0); | return; | } Fix this and make this a bit easier to reason about by always eagerly switching ZCR_EL{1,2} at hyp during guest<->host transitions. With this happening, there's no need to trap host SVE usage, and the nVHE/nVHE __deactivate_cptr_traps() logic can be simplified to enable host access to all present FPSIMD/SVE/SME features. In protected nVHE/hVHE modes, the host's state is always saved/restored by hyp, and the guest's state is saved prior to exit to the host, so from the host's PoV the guest never has live FPSIMD/SVE/SME state, and the host's ZCR_EL1 is never clobbered by hyp. [tabba@: remove disabling fpsimd/sve traps on fpsimd_host_restore() in protected mode, since it's redundant with the complete disabling of fpsimd/sve traps in switch.c __deactivate_traps().] Bug: 411040189 Fixes: 8c8010d69c132273 ("KVM: arm64: Save/restore SVE state for nVHE") Fixes: 2e3cf82063a00ea0 ("KVM: arm64: nv: Ensure correct VL is loaded before saving SVE state") Change-Id: Ifecd5024230fadd0b73755587950ba651b94dae0 Signed-off-by: Mark Rutland Reviewed-by: Mark Brown Tested-by: Mark Brown Cc: Catalin Marinas Cc: Fuad Tabba Cc: Marc Zyngier Cc: Oliver Upton Cc: Will Deacon Reviewed-by: Oliver Upton Link: https://lore.kernel.org/r/20250210195226.1215254-9-mark.rutland@arm.com Signed-off-by: Marc Zyngier [ v6.6 lacks pKVM saving of host SVE state, pull in discovery of maximum host VL separately -- broonie ] Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman Signed-off-by: Fuad Tabba --- arch/arm64/kvm/fpsimd.c | 30 +++++--------- arch/arm64/kvm/hyp/entry.S | 5 +++ arch/arm64/kvm/hyp/include/hyp/switch.h | 55 +++++++++++++++++++++++++ arch/arm64/kvm/hyp/nvhe/hyp-main.c | 31 ++------------ arch/arm64/kvm/hyp/nvhe/switch.c | 33 +++++++++++++-- arch/arm64/kvm/hyp/vhe/switch.c | 4 ++ arch/arm64/kvm/reset.c | 1 + 7 files changed, 107 insertions(+), 52 deletions(-) diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c index 0c0cfb6dcc17..c4282c7c90f7 100644 --- a/arch/arm64/kvm/fpsimd.c +++ b/arch/arm64/kvm/fpsimd.c @@ -129,26 +129,16 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) local_irq_save(flags); if (vcpu->arch.fp_state == FP_STATE_GUEST_OWNED) { - if (vcpu_has_sve(vcpu)) { - __vcpu_sys_reg(vcpu, ZCR_EL1) = read_sysreg_el1(SYS_ZCR); - - /* - * Restore the VL that was saved when bound to the CPU, - * which is the maximum VL for the guest. Because - * the layout of the data when saving the sve state - * depends on the VL, we need to use a consistent VL. - * Note that this means that at guest exit ZCR_EL1 is - * not necessarily the same as on guest entry. - * - * Flushing the cpu state sets the TIF_FOREIGN_FPSTATE - * bit for the context, which lets the kernel restore - * the sve state, including ZCR_EL1 later. - */ - if (!has_vhe()) - sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1, - SYS_ZCR_EL1); - } - + /* + * Flush (save and invalidate) the fpsimd/sve state so that if + * the host tries to use fpsimd/sve, it's not using stale data + * from the guest. + * + * Flushing the state sets the TIF_FOREIGN_FPSTATE bit for the + * context unconditionally, in both nVHE and VHE. This allows + * the kernel to restore the fpsimd/sve state, including ZCR_EL1 + * when needed. + */ fpsimd_save_and_flush_cpu_state(); } diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S index 4433a234aa9b..9f4e8d68ab50 100644 --- a/arch/arm64/kvm/hyp/entry.S +++ b/arch/arm64/kvm/hyp/entry.S @@ -44,6 +44,11 @@ alternative_if ARM64_HAS_RAS_EXTN alternative_else_nop_endif mrs x1, isr_el1 cbz x1, 1f + + // Ensure that __guest_enter() always provides a context + // synchronization event so that callers don't need ISBs for anything + // that would usually be synchonized by the ERET. + isb mov x0, #ARM_EXCEPTION_IRQ ret diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h index 68961a185661..92bf61f15c31 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -350,6 +350,61 @@ static void __deactivate_fpsimd_traps(struct kvm_vcpu *vcpu) } } +static inline void fpsimd_lazy_switch_to_guest(struct kvm_vcpu *vcpu) +{ + u64 zcr_el1, zcr_el2; + + if (vcpu->arch.fp_state != FP_STATE_GUEST_OWNED) + return; + + if (vcpu_has_sve(vcpu)) { + zcr_el2 = vcpu_sve_max_vq(vcpu) - 1; + + write_sysreg_el2(zcr_el2, SYS_ZCR); + + zcr_el1 = __vcpu_sys_reg(vcpu, ZCR_EL1); + write_sysreg_el1(zcr_el1, SYS_ZCR); + } +} + +static inline void fpsimd_lazy_switch_to_host(struct kvm_vcpu *vcpu) +{ + u64 zcr_el1, zcr_el2; + + if (vcpu->arch.fp_state != FP_STATE_GUEST_OWNED) + return; + + /* + * When the guest owns the FP regs, we know that guest+hyp traps for + * any FPSIMD/SVE/SME features exposed to the guest have been disabled + * by either fpsimd_lazy_switch_to_guest() or kvm_hyp_handle_fpsimd() + * prior to __guest_entry(). As __guest_entry() guarantees a context + * synchronization event, we don't need an ISB here to avoid taking + * traps for anything that was exposed to the guest. + */ + if (vcpu_has_sve(vcpu)) { + zcr_el1 = read_sysreg_el1(SYS_ZCR); + __vcpu_sys_reg(vcpu, ZCR_EL1) = zcr_el1; + + /* + * The guest's state is always saved using the guest's max VL. + * Ensure that the host has the guest's max VL active such that + * the host can save the guest's state lazily, but don't + * artificially restrict the host to the guest's max VL. + */ + if (has_vhe()) { + zcr_el2 = vcpu_sve_max_vq(vcpu) - 1; + write_sysreg_el2(zcr_el2, SYS_ZCR); + } else { + zcr_el2 = sve_vq_from_vl(kvm_host_sve_max_vl) - 1; + write_sysreg_el2(zcr_el2, SYS_ZCR); + + zcr_el1 = vcpu_sve_max_vq(vcpu) - 1; + write_sysreg_el1(zcr_el1, SYS_ZCR); + } + } +} + /* * We trap the first access to the FP/SIMD to save the host context and * restore the guest context lazily. diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c index 91447b108ec6..e8c484dcc769 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -797,24 +798,6 @@ static void __hyp_sve_restore_host(struct kvm_vcpu *vcpu) static void fpsimd_host_restore(struct kvm_vcpu *vcpu) { - u64 reg; - bool trap_sve = system_supports_sve(); - - if (has_hvhe()) { - reg = CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN; - if (trap_sve) - reg |= CPACR_EL1_ZEN_EL0EN | CPACR_EL1_ZEN_EL1EN; - - sysreg_clear_set(cpacr_el1, 0, reg); - } else { - reg = CPTR_EL2_TFP; - if (trap_sve) - reg |= CPTR_EL2_TZ; - - sysreg_clear_set(cptr_el2, reg, 0); - } - isb(); - if (vcpu_has_sve(vcpu)) __hyp_sve_save_guest(vcpu); else @@ -969,7 +952,9 @@ static void handle___kvm_vcpu_run(struct kvm_cpu_context *host_ctxt) sync_hyp_vcpu(hyp_vcpu, ret); } else { /* The host is fully trusted, run its vCPU directly. */ + fpsimd_lazy_switch_to_guest(host_vcpu); ret = __kvm_vcpu_run(host_vcpu); + fpsimd_lazy_switch_to_host(host_vcpu); } out: cpu_reg(host_ctxt, 1) = ret; @@ -1745,16 +1730,6 @@ void handle_trap(struct kvm_cpu_context *host_ctxt) case ESR_ELx_EC_SMC64: handle_host_smc(host_ctxt); break; - case ESR_ELx_EC_SVE: - BUG_ON(is_protected_kvm_enabled()); - if (has_hvhe()) - sysreg_clear_set(cpacr_el1, 0, (CPACR_EL1_ZEN_EL1EN | - CPACR_EL1_ZEN_EL0EN)); - else - sysreg_clear_set(cptr_el2, CPTR_EL2_TZ, 0); - isb(); - sve_cond_update_zcr_vq(ZCR_ELx_LEN_MASK, SYS_ZCR_EL2); - break; case ESR_ELx_EC_IABT_LOW: case ESR_ELx_EC_DABT_LOW: handle_host_mem_abort(host_ctxt); diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c index 77feeb8b1e84..f68352c741fb 100644 --- a/arch/arm64/kvm/hyp/nvhe/switch.c +++ b/arch/arm64/kvm/hyp/nvhe/switch.c @@ -87,6 +87,9 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu) { u64 val = CPTR_EL2_TAM; /* Same bit irrespective of E2H */ + if (vcpu->arch.fp_state != FP_STATE_GUEST_OWNED) + __activate_traps_fpsimd32(vcpu); + if (has_hvhe()) { val |= CPACR_ELx_TTA; @@ -95,6 +98,8 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu) if (vcpu_has_sve(vcpu)) val |= CPACR_ELx_ZEN; } + + write_sysreg(val, cpacr_el1); } else { val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1; @@ -109,12 +114,32 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu) if (vcpu->arch.fp_state != FP_STATE_GUEST_OWNED) val |= CPTR_EL2_TFP; + + write_sysreg(val, cptr_el2); } +} - if (vcpu->arch.fp_state != FP_STATE_GUEST_OWNED) - __activate_traps_fpsimd32(vcpu); +static void __deactivate_cptr_traps(struct kvm_vcpu *vcpu) +{ + if (has_hvhe()) { + u64 val = CPACR_ELx_FPEN; - kvm_write_cptr_el2(val); + if (cpus_have_final_cap(ARM64_SVE)) + val |= CPACR_ELx_ZEN; + if (cpus_have_final_cap(ARM64_SME)) + val |= CPACR_ELx_SMEN; + + write_sysreg(val, cpacr_el1); + } else { + u64 val = CPTR_NVHE_EL2_RES1; + + if (!cpus_have_final_cap(ARM64_SVE)) + val |= CPTR_EL2_TZ; + if (!cpus_have_final_cap(ARM64_SME)) + val |= CPTR_EL2_TSM; + + write_sysreg(val, cptr_el2); + } } static void __activate_traps(struct kvm_vcpu *vcpu) @@ -179,7 +204,7 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu) write_sysreg(this_cpu_ptr(&kvm_init_params)->hcr_el2, hcr_el2); - kvm_reset_cptr_el2(vcpu); + __deactivate_cptr_traps(vcpu); write_sysreg(__kvm_hyp_host_vector, vbar_el2); } diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c index 036235b37fa4..e9460ed489fc 100644 --- a/arch/arm64/kvm/hyp/vhe/switch.c +++ b/arch/arm64/kvm/hyp/vhe/switch.c @@ -215,6 +215,8 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu) sysreg_save_host_state_vhe(host_ctxt); + fpsimd_lazy_switch_to_guest(vcpu); + /* * ARM erratum 1165522 requires us to configure both stage 1 and * stage 2 translation for the guest context before we clear @@ -250,6 +252,8 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu) __deactivate_traps(vcpu); + fpsimd_lazy_switch_to_host(vcpu); + sysreg_restore_host_state_vhe(host_ctxt); if (vcpu->arch.fp_state == FP_STATE_GUEST_OWNED) diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index 6482da1974f9..059b703b9c56 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -41,6 +41,7 @@ int __init kvm_arm_init_sve(void) if (system_supports_sve()) { kvm_sve_max_vl = sve_max_virtualisable_vl(); kvm_host_sve_max_vl = sve_max_vl(); + kvm_nvhe_sym(kvm_host_sve_max_vl) = kvm_host_sve_max_vl; /* * The get_sve_reg()/set_sve_reg() ioctl interface will need