From: Sasha Levin Date: Tue, 8 Jul 2025 00:37:07 +0000 (-0400) Subject: Fixes for 5.4 X-Git-Tag: v5.15.187~44 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=069c64649d02a1168fceec6f03e88fc6d59b3cbc;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.4 Signed-off-by: Sasha Levin --- diff --git a/queue-5.4/btrfs-propagate-last_unlink_trans-earlier-when-doing.patch b/queue-5.4/btrfs-propagate-last_unlink_trans-earlier-when-doing.patch new file mode 100644 index 0000000000..06bfb97f92 --- /dev/null +++ b/queue-5.4/btrfs-propagate-last_unlink_trans-earlier-when-doing.patch @@ -0,0 +1,101 @@ +From b5b0080afd41226565fd9fea428c47a10fcadab5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Jun 2025 15:54:05 +0100 +Subject: btrfs: propagate last_unlink_trans earlier when doing a rmdir + +From: Filipe Manana + +[ Upstream commit c466e33e729a0ee017d10d919cba18f503853c60 ] + +In case the removed directory had a snapshot that was deleted, we are +propagating its inode's last_unlink_trans to the parent directory after +we removed the entry from the parent directory. This leaves a small race +window where someone can log the parent directory after we removed the +entry and before we updated last_unlink_trans, and as a result if we ever +try to replay such a log tree, we will fail since we will attempt to +remove a snapshot during log replay, which is currently not possible and +results in the log replay (and mount) to fail. This is the type of failure +described in commit 1ec9a1ae1e30 ("Btrfs: fix unreplayable log after +snapshot delete + parent dir fsync"). + +So fix this by propagating the last_unlink_trans to the parent directory +before we remove the entry from it. + +Fixes: 44f714dae50a ("Btrfs: improve performance on fsync against new inode after rename/unlink") +Reviewed-by: Johannes Thumshirn +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/inode.c | 36 ++++++++++++++++++------------------ + 1 file changed, 18 insertions(+), 18 deletions(-) + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 004894e6dd23b..8f92f998dc37b 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -4747,7 +4747,6 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) + int err = 0; + struct btrfs_root *root = BTRFS_I(dir)->root; + struct btrfs_trans_handle *trans; +- u64 last_unlink_trans; + + if (inode->i_size > BTRFS_EMPTY_DIR_SIZE) + return -ENOTEMPTY; +@@ -4758,6 +4757,23 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) + if (IS_ERR(trans)) + return PTR_ERR(trans); + ++ /* ++ * Propagate the last_unlink_trans value of the deleted dir to its ++ * parent directory. This is to prevent an unrecoverable log tree in the ++ * case we do something like this: ++ * 1) create dir foo ++ * 2) create snapshot under dir foo ++ * 3) delete the snapshot ++ * 4) rmdir foo ++ * 5) mkdir foo ++ * 6) fsync foo or some file inside foo ++ * ++ * This is because we can't unlink other roots when replaying the dir ++ * deletes for directory foo. ++ */ ++ if (BTRFS_I(inode)->last_unlink_trans >= trans->transid) ++ BTRFS_I(dir)->last_unlink_trans = BTRFS_I(inode)->last_unlink_trans; ++ + if (unlikely(btrfs_ino(BTRFS_I(inode)) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) { + err = btrfs_unlink_subvol(trans, dir, dentry); + goto out; +@@ -4767,28 +4783,12 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) + if (err) + goto out; + +- last_unlink_trans = BTRFS_I(inode)->last_unlink_trans; +- + /* now the directory is empty */ + err = btrfs_unlink_inode(trans, root, BTRFS_I(dir), + BTRFS_I(d_inode(dentry)), dentry->d_name.name, + dentry->d_name.len); +- if (!err) { ++ if (!err) + btrfs_i_size_write(BTRFS_I(inode), 0); +- /* +- * Propagate the last_unlink_trans value of the deleted dir to +- * its parent directory. This is to prevent an unrecoverable +- * log tree in the case we do something like this: +- * 1) create dir foo +- * 2) create snapshot under dir foo +- * 3) delete the snapshot +- * 4) rmdir foo +- * 5) mkdir foo +- * 6) fsync foo or some file inside foo +- */ +- if (last_unlink_trans >= trans->transid) +- BTRFS_I(dir)->last_unlink_trans = last_unlink_trans; +- } + out: + btrfs_end_transaction(trans); + btrfs_btree_balance_dirty(root->fs_info); +-- +2.39.5 + diff --git a/queue-5.4/btrfs-use-btrfs_record_snapshot_destroy-during-rmdir.patch b/queue-5.4/btrfs-use-btrfs_record_snapshot_destroy-during-rmdir.patch new file mode 100644 index 0000000000..64cff8a59d --- /dev/null +++ b/queue-5.4/btrfs-use-btrfs_record_snapshot_destroy-during-rmdir.patch @@ -0,0 +1,46 @@ +From ba242ed8393f2280ab522477c6a1f592f1656f7e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Jun 2025 16:37:01 +0100 +Subject: btrfs: use btrfs_record_snapshot_destroy() during rmdir + +From: Filipe Manana + +[ Upstream commit 157501b0469969fc1ba53add5049575aadd79d80 ] + +We are setting the parent directory's last_unlink_trans directly which +may result in a concurrent task starting to log the directory not see the +update and therefore can log the directory after we removed a child +directory which had a snapshot within instead of falling back to a +transaction commit. Replaying such a log tree would result in a mount +failure since we can't currently delete snapshots (and subvolumes) during +log replay. This is the type of failure described in commit 1ec9a1ae1e30 +("Btrfs: fix unreplayable log after snapshot delete + parent dir fsync"). + +Fix this by using btrfs_record_snapshot_destroy() which updates the +last_unlink_trans field while holding the inode's log_mutex lock. + +Fixes: 44f714dae50a ("Btrfs: improve performance on fsync against new inode after rename/unlink") +Reviewed-by: Johannes Thumshirn +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + 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 8f92f998dc37b..757111e529948 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -4772,7 +4772,7 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) + * deletes for directory foo. + */ + if (BTRFS_I(inode)->last_unlink_trans >= trans->transid) +- BTRFS_I(dir)->last_unlink_trans = BTRFS_I(inode)->last_unlink_trans; ++ btrfs_record_snapshot_destroy(trans, BTRFS_I(dir)); + + if (unlikely(btrfs_ino(BTRFS_I(inode)) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) { + err = btrfs_unlink_subvol(trans, dir, dentry); +-- +2.39.5 + diff --git a/queue-5.4/dpaa2-eth-fix-xdp_rxq_info-leak.patch b/queue-5.4/dpaa2-eth-fix-xdp_rxq_info-leak.patch new file mode 100644 index 0000000000..6a5c64b33e --- /dev/null +++ b/queue-5.4/dpaa2-eth-fix-xdp_rxq_info-leak.patch @@ -0,0 +1,101 @@ +From 00ca559bcab1795ccf4b13849d8c2a6084b17733 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 26 Jun 2025 21:30:03 +0800 +Subject: dpaa2-eth: fix xdp_rxq_info leak + +From: Fushuai Wang + +[ Upstream commit 2def09ead4ad5907988b655d1e1454003aaf8297 ] + +The driver registered xdp_rxq_info structures via xdp_rxq_info_reg() +but failed to properly unregister them in error paths and during +removal. + +Fixes: d678be1dc1ec ("dpaa2-eth: add XDP_REDIRECT support") +Signed-off-by: Fushuai Wang +Reviewed-by: Simon Horman +Reviewed-by: Ioana Ciornei +Link: https://patch.msgid.link/20250626133003.80136-1-wangfushuai@baidu.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../net/ethernet/freescale/dpaa2/dpaa2-eth.c | 26 +++++++++++++++++-- + 1 file changed, 24 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +index 5f5766b1f3b70..8649578b54c1e 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +@@ -2725,6 +2725,7 @@ static int setup_rx_flow(struct dpaa2_eth_priv *priv, + MEM_TYPE_PAGE_ORDER0, NULL); + if (err) { + dev_err(dev, "xdp_rxq_info_reg_mem_model failed\n"); ++ xdp_rxq_info_unreg(&fq->channel->xdp_rxq); + return err; + } + +@@ -3153,17 +3154,25 @@ static int bind_dpni(struct dpaa2_eth_priv *priv) + return -EINVAL; + } + if (err) +- return err; ++ goto out; + } + + err = dpni_get_qdid(priv->mc_io, 0, priv->mc_token, + DPNI_QUEUE_TX, &priv->tx_qdid); + if (err) { + dev_err(dev, "dpni_get_qdid() failed\n"); +- return err; ++ goto out; + } + + return 0; ++ ++out: ++ while (i--) { ++ if (priv->fq[i].type == DPAA2_RX_FQ && ++ xdp_rxq_info_is_reg(&priv->fq[i].channel->xdp_rxq)) ++ xdp_rxq_info_unreg(&priv->fq[i].channel->xdp_rxq); ++ } ++ return err; + } + + /* Allocate rings for storing incoming frame descriptors */ +@@ -3445,6 +3454,17 @@ static void del_ch_napi(struct dpaa2_eth_priv *priv) + } + } + ++static void dpaa2_eth_free_rx_xdp_rxq(struct dpaa2_eth_priv *priv) ++{ ++ int i; ++ ++ for (i = 0; i < priv->num_fqs; i++) { ++ if (priv->fq[i].type == DPAA2_RX_FQ && ++ xdp_rxq_info_is_reg(&priv->fq[i].channel->xdp_rxq)) ++ xdp_rxq_info_unreg(&priv->fq[i].channel->xdp_rxq); ++ } ++} ++ + static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev) + { + struct device *dev; +@@ -3574,6 +3594,7 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev) + free_percpu(priv->percpu_stats); + err_alloc_percpu_stats: + del_ch_napi(priv); ++ dpaa2_eth_free_rx_xdp_rxq(priv); + err_bind: + free_dpbp(priv); + err_dpbp_setup: +@@ -3614,6 +3635,7 @@ static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev) + free_percpu(priv->percpu_extras); + + del_ch_napi(priv); ++ dpaa2_eth_free_rx_xdp_rxq(priv); + free_dpbp(priv); + free_dpio(priv); + free_dpni(priv); +-- +2.39.5 + diff --git a/queue-5.4/drm-i915-gt-fix-timeline-left-held-on-vma-alloc-erro.patch b/queue-5.4/drm-i915-gt-fix-timeline-left-held-on-vma-alloc-erro.patch new file mode 100644 index 0000000000..0a61441626 --- /dev/null +++ b/queue-5.4/drm-i915-gt-fix-timeline-left-held-on-vma-alloc-erro.patch @@ -0,0 +1,128 @@ +From e28d3bc0b711d597f53375f498e97fd13e7db4ff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Jul 2025 16:34:40 -0400 +Subject: drm/i915/gt: Fix timeline left held on VMA alloc error + +From: Janusz Krzysztofik + +[ Upstream commit a5aa7bc1fca78c7fa127d9e33aa94a0c9066c1d6 ] + +The following error has been reported sporadically by CI when a test +unbinds the i915 driver on a ring submission platform: + +<4> [239.330153] ------------[ cut here ]------------ +<4> [239.330166] i915 0000:00:02.0: [drm] drm_WARN_ON(dev_priv->mm.shrink_count) +<4> [239.330196] WARNING: CPU: 1 PID: 18570 at drivers/gpu/drm/i915/i915_gem.c:1309 i915_gem_cleanup_early+0x13e/0x150 [i915] +... +<4> [239.330640] RIP: 0010:i915_gem_cleanup_early+0x13e/0x150 [i915] +... +<4> [239.330942] Call Trace: +<4> [239.330944] +<4> [239.330949] i915_driver_late_release+0x2b/0xa0 [i915] +<4> [239.331202] i915_driver_release+0x86/0xa0 [i915] +<4> [239.331482] devm_drm_dev_init_release+0x61/0x90 +<4> [239.331494] devm_action_release+0x15/0x30 +<4> [239.331504] release_nodes+0x3d/0x120 +<4> [239.331517] devres_release_all+0x96/0xd0 +<4> [239.331533] device_unbind_cleanup+0x12/0x80 +<4> [239.331543] device_release_driver_internal+0x23a/0x280 +<4> [239.331550] ? bus_find_device+0xa5/0xe0 +<4> [239.331563] device_driver_detach+0x14/0x20 +... +<4> [357.719679] ---[ end trace 0000000000000000 ]--- + +If the test also unloads the i915 module then that's followed with: + +<3> [357.787478] ============================================================================= +<3> [357.788006] BUG i915_vma (Tainted: G U W N ): Objects remaining on __kmem_cache_shutdown() +<3> [357.788031] ----------------------------------------------------------------------------- +<3> [357.788204] Object 0xffff888109e7f480 @offset=29824 +<3> [357.788670] Allocated in i915_vma_instance+0xee/0xc10 [i915] age=292729 cpu=4 pid=2244 +<4> [357.788994] i915_vma_instance+0xee/0xc10 [i915] +<4> [357.789290] init_status_page+0x7b/0x420 [i915] +<4> [357.789532] intel_engines_init+0x1d8/0x980 [i915] +<4> [357.789772] intel_gt_init+0x175/0x450 [i915] +<4> [357.790014] i915_gem_init+0x113/0x340 [i915] +<4> [357.790281] i915_driver_probe+0x847/0xed0 [i915] +<4> [357.790504] i915_pci_probe+0xe6/0x220 [i915] +... + +Closer analysis of CI results history has revealed a dependency of the +error on a few IGT tests, namely: +- igt@api_intel_allocator@fork-simple-stress-signal, +- igt@api_intel_allocator@two-level-inception-interruptible, +- igt@gem_linear_blits@interruptible, +- igt@prime_mmap_coherency@ioctl-errors, +which invisibly trigger the issue, then exhibited with first driver unbind +attempt. + +All of the above tests perform actions which are actively interrupted with +signals. Further debugging has allowed to narrow that scope down to +DRM_IOCTL_I915_GEM_EXECBUFFER2, and ring_context_alloc(), specific to ring +submission, in particular. + +If successful then that function, or its execlists or GuC submission +equivalent, is supposed to be called only once per GEM context engine, +followed by raise of a flag that prevents the function from being called +again. The function is expected to unwind its internal errors itself, so +it may be safely called once more after it returns an error. + +In case of ring submission, the function first gets a reference to the +engine's legacy timeline and then allocates a VMA. If the VMA allocation +fails, e.g. when i915_vma_instance() called from inside is interrupted +with a signal, then ring_context_alloc() fails, leaving the timeline held +referenced. On next I915_GEM_EXECBUFFER2 IOCTL, another reference to the +timeline is got, and only that last one is put on successful completion. +As a consequence, the legacy timeline, with its underlying engine status +page's VMA object, is still held and not released on driver unbind. + +Get the legacy timeline only after successful allocation of the context +engine's VMA. + +v2: Add a note on other submission methods (Krzysztof Karas): + Both execlists and GuC submission use lrc_alloc() which seems free + from a similar issue. + +Fixes: 75d0a7f31eec ("drm/i915: Lift timeline into intel_context") +Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12061 +Cc: Chris Wilson +Cc: Matthew Auld +Cc: Krzysztof Karas +Reviewed-by: Sebastian Brzezinka +Reviewed-by: Krzysztof Niemiec +Signed-off-by: Janusz Krzysztofik +Reviewed-by: Nitin Gote +Reviewed-by: Andi Shyti +Signed-off-by: Andi Shyti +Link: https://lore.kernel.org/r/20250611104352.1014011-2-janusz.krzysztofik@linux.intel.com +(cherry picked from commit cc43422b3cc79eacff4c5a8ba0d224688ca9dd4f) +Signed-off-by: Joonas Lahtinen +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/gt/intel_ringbuffer.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/i915/gt/intel_ringbuffer.c b/drivers/gpu/drm/i915/gt/intel_ringbuffer.c +index 125f7bb67bee9..57593600a8cc4 100644 +--- a/drivers/gpu/drm/i915/gt/intel_ringbuffer.c ++++ b/drivers/gpu/drm/i915/gt/intel_ringbuffer.c +@@ -1475,7 +1475,6 @@ static int ring_context_alloc(struct intel_context *ce) + /* One ringbuffer to rule them all */ + GEM_BUG_ON(!engine->legacy.ring); + ce->ring = engine->legacy.ring; +- ce->timeline = intel_timeline_get(engine->legacy.timeline); + + GEM_BUG_ON(ce->state); + if (engine->context_size) { +@@ -1488,6 +1487,8 @@ static int ring_context_alloc(struct intel_context *ce) + ce->state = vma; + } + ++ ce->timeline = intel_timeline_get(engine->legacy.timeline); ++ + return 0; + } + +-- +2.39.5 + diff --git a/queue-5.4/drm-i915-selftests-change-mock_request-to-return-err.patch b/queue-5.4/drm-i915-selftests-change-mock_request-to-return-err.patch new file mode 100644 index 0000000000..e043d6100d --- /dev/null +++ b/queue-5.4/drm-i915-selftests-change-mock_request-to-return-err.patch @@ -0,0 +1,108 @@ +From bfa4b38596bb334b283536ec937345e9c40a885c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Jun 2025 10:21:58 -0500 +Subject: drm/i915/selftests: Change mock_request() to return error pointers + +From: Dan Carpenter + +[ Upstream commit caa7c7a76b78ce41d347003f84975125383e6b59 ] + +There was an error pointer vs NULL bug in __igt_breadcrumbs_smoketest(). +The __mock_request_alloc() function implements the +smoketest->request_alloc() function pointer. It was supposed to return +error pointers, but it propogates the NULL return from mock_request() +so in the event of a failure, it would lead to a NULL pointer +dereference. + +To fix this, change the mock_request() function to return error pointers +and update all the callers to expect that. + +Fixes: 52c0fdb25c7c ("drm/i915: Replace global breadcrumbs with per-context interrupt tracking") +Signed-off-by: Dan Carpenter +Reviewed-by: Rodrigo Vivi +Link: https://lore.kernel.org/r/685c1417.050a0220.696f5.5c05@mx.google.com +Signed-off-by: Rodrigo Vivi +(cherry picked from commit 778fa8ad5f0f23397d045c7ebca048ce8def1c43) +Signed-off-by: Joonas Lahtinen +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/selftests/i915_request.c | 20 ++++++++++--------- + drivers/gpu/drm/i915/selftests/mock_request.c | 2 +- + 2 files changed, 12 insertions(+), 10 deletions(-) + +diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c +index b3688543ed7d0..6ee24f2061616 100644 +--- a/drivers/gpu/drm/i915/selftests/i915_request.c ++++ b/drivers/gpu/drm/i915/selftests/i915_request.c +@@ -47,8 +47,10 @@ static int igt_add_request(void *arg) + + mutex_lock(&i915->drm.struct_mutex); + request = mock_request(i915->engine[RCS0]->kernel_context, HZ / 10); +- if (!request) ++ if (IS_ERR(request)) { ++ err = PTR_ERR(request); + goto out_unlock; ++ } + + i915_request_add(request); + +@@ -69,8 +71,8 @@ static int igt_wait_request(void *arg) + + mutex_lock(&i915->drm.struct_mutex); + request = mock_request(i915->engine[RCS0]->kernel_context, T); +- if (!request) { +- err = -ENOMEM; ++ if (IS_ERR(request)) { ++ err = PTR_ERR(request); + goto out_unlock; + } + i915_request_get(request); +@@ -142,8 +144,8 @@ static int igt_fence_wait(void *arg) + + mutex_lock(&i915->drm.struct_mutex); + request = mock_request(i915->engine[RCS0]->kernel_context, T); +- if (!request) { +- err = -ENOMEM; ++ if (IS_ERR(request)) { ++ err = PTR_ERR(request); + goto out_locked; + } + +@@ -203,8 +205,8 @@ static int igt_request_rewind(void *arg) + GEM_BUG_ON(IS_ERR(ce)); + request = mock_request(ce, 2 * HZ); + intel_context_put(ce); +- if (!request) { +- err = -ENOMEM; ++ if (IS_ERR(request)) { ++ err = PTR_ERR(request); + goto err_context_0; + } + +@@ -216,8 +218,8 @@ static int igt_request_rewind(void *arg) + GEM_BUG_ON(IS_ERR(ce)); + vip = mock_request(ce, 0); + intel_context_put(ce); +- if (!vip) { +- err = -ENOMEM; ++ if (IS_ERR(vip)) { ++ err = PTR_ERR(vip); + goto err_context_1; + } + +diff --git a/drivers/gpu/drm/i915/selftests/mock_request.c b/drivers/gpu/drm/i915/selftests/mock_request.c +index 09f747228dff5..1b0cf073e9643 100644 +--- a/drivers/gpu/drm/i915/selftests/mock_request.c ++++ b/drivers/gpu/drm/i915/selftests/mock_request.c +@@ -35,7 +35,7 @@ mock_request(struct intel_context *ce, unsigned long delay) + /* NB the i915->requests slab cache is enlarged to fit mock_request */ + request = intel_context_create_request(ce); + if (IS_ERR(request)) +- return NULL; ++ return request; + + request->mock.delay = delay; + return request; +-- +2.39.5 + diff --git a/queue-5.4/drm-v3d-disable-interrupts-before-resetting-the-gpu.patch b/queue-5.4/drm-v3d-disable-interrupts-before-resetting-the-gpu.patch new file mode 100644 index 0000000000..baa0532513 --- /dev/null +++ b/queue-5.4/drm-v3d-disable-interrupts-before-resetting-the-gpu.patch @@ -0,0 +1,215 @@ +From b54c9bdf8f1e7d98a0a931c9eb2a610099117ea7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 28 Jun 2025 19:42:42 -0300 +Subject: drm/v3d: Disable interrupts before resetting the GPU +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Maíra Canal + +[ Upstream commit 226862f50a7a88e4e4de9abbf36c64d19acd6fd0 ] + +Currently, an interrupt can be triggered during a GPU reset, which can +lead to GPU hangs and NULL pointer dereference in an interrupt context +as shown in the following trace: + + [ 314.035040] Unable to handle kernel NULL pointer dereference at virtual address 00000000000000c0 + [ 314.043822] Mem abort info: + [ 314.046606] ESR = 0x0000000096000005 + [ 314.050347] EC = 0x25: DABT (current EL), IL = 32 bits + [ 314.055651] SET = 0, FnV = 0 + [ 314.058695] EA = 0, S1PTW = 0 + [ 314.061826] FSC = 0x05: level 1 translation fault + [ 314.066694] Data abort info: + [ 314.069564] ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000 + [ 314.075039] CM = 0, WnR = 0, TnD = 0, TagAccess = 0 + [ 314.080080] GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 + [ 314.085382] user pgtable: 4k pages, 39-bit VAs, pgdp=0000000102728000 + [ 314.091814] [00000000000000c0] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000 + [ 314.100511] Internal error: Oops: 0000000096000005 [#1] PREEMPT SMP + [ 314.106770] Modules linked in: v3d i2c_brcmstb vc4 snd_soc_hdmi_codec gpu_sched drm_shmem_helper drm_display_helper cec drm_dma_helper drm_kms_helper drm drm_panel_orientation_quirks snd_soc_core snd_compress snd_pcm_dmaengine snd_pcm snd_timer snd backlight + [ 314.129654] CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 6.12.25+rpt-rpi-v8 #1 Debian 1:6.12.25-1+rpt1 + [ 314.139388] Hardware name: Raspberry Pi 4 Model B Rev 1.4 (DT) + [ 314.145211] pstate: 600000c5 (nZCv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--) + [ 314.152165] pc : v3d_irq+0xec/0x2e0 [v3d] + [ 314.156187] lr : v3d_irq+0xe0/0x2e0 [v3d] + [ 314.160198] sp : ffffffc080003ea0 + [ 314.163502] x29: ffffffc080003ea0 x28: ffffffec1f184980 x27: 021202b000000000 + [ 314.170633] x26: ffffffec1f17f630 x25: ffffff8101372000 x24: ffffffec1f17d9f0 + [ 314.177764] x23: 000000000000002a x22: 000000000000002a x21: ffffff8103252000 + [ 314.184895] x20: 0000000000000001 x19: 00000000deadbeef x18: 0000000000000000 + [ 314.192026] x17: ffffff94e51d2000 x16: ffffffec1dac3cb0 x15: c306000000000000 + [ 314.199156] x14: 0000000000000000 x13: b2fc982e03cc5168 x12: 0000000000000001 + [ 314.206286] x11: ffffff8103f8bcc0 x10: ffffffec1f196868 x9 : ffffffec1dac3874 + [ 314.213416] x8 : 0000000000000000 x7 : 0000000000042a3a x6 : ffffff810017a180 + [ 314.220547] x5 : ffffffec1ebad400 x4 : ffffffec1ebad320 x3 : 00000000000bebeb + [ 314.227677] x2 : 0000000000000000 x1 : 0000000000000000 x0 : 0000000000000000 + [ 314.234807] Call trace: + [ 314.237243] v3d_irq+0xec/0x2e0 [v3d] + [ 314.240906] __handle_irq_event_percpu+0x58/0x218 + [ 314.245609] handle_irq_event+0x54/0xb8 + [ 314.249439] handle_fasteoi_irq+0xac/0x240 + [ 314.253527] handle_irq_desc+0x48/0x68 + [ 314.257269] generic_handle_domain_irq+0x24/0x38 + [ 314.261879] gic_handle_irq+0x48/0xd8 + [ 314.265533] call_on_irq_stack+0x24/0x58 + [ 314.269448] do_interrupt_handler+0x88/0x98 + [ 314.273624] el1_interrupt+0x34/0x68 + [ 314.277193] el1h_64_irq_handler+0x18/0x28 + [ 314.281281] el1h_64_irq+0x64/0x68 + [ 314.284673] default_idle_call+0x3c/0x168 + [ 314.288675] do_idle+0x1fc/0x230 + [ 314.291895] cpu_startup_entry+0x3c/0x50 + [ 314.295810] rest_init+0xe4/0xf0 + [ 314.299030] start_kernel+0x5e8/0x790 + [ 314.302684] __primary_switched+0x80/0x90 + [ 314.306691] Code: 940029eb 360ffc13 f9442ea0 52800001 (f9406017) + [ 314.312775] ---[ end trace 0000000000000000 ]--- + [ 314.317384] Kernel panic - not syncing: Oops: Fatal exception in interrupt + [ 314.324249] SMP: stopping secondary CPUs + [ 314.328167] Kernel Offset: 0x2b9da00000 from 0xffffffc080000000 + [ 314.334076] PHYS_OFFSET: 0x0 + [ 314.336946] CPU features: 0x08,00002013,c0200000,0200421b + [ 314.342337] Memory Limit: none + [ 314.345382] ---[ end Kernel panic - not syncing: Oops: Fatal exception in interrupt ]--- + +Before resetting the GPU, it's necessary to disable all interrupts and +deal with any interrupt handler still in-flight. Otherwise, the GPU might +reset with jobs still running, or yet, an interrupt could be handled +during the reset. + +Cc: stable@vger.kernel.org +Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+") +Reviewed-by: Juan A. Suarez +Reviewed-by: Iago Toral Quiroga +Link: https://lore.kernel.org/r/20250628224243.47599-1-mcanal@igalia.com +Signed-off-by: Maíra Canal +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/v3d/v3d_drv.h | 9 +++++++++ + drivers/gpu/drm/v3d/v3d_gem.c | 2 ++ + drivers/gpu/drm/v3d/v3d_irq.c | 36 +++++++++++++++++++++++++++-------- + 3 files changed, 39 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h +index 9a35c555ec522..6236e0446b307 100644 +--- a/drivers/gpu/drm/v3d/v3d_drv.h ++++ b/drivers/gpu/drm/v3d/v3d_drv.h +@@ -38,6 +38,12 @@ struct v3d_queue_state { + u64 emit_seqno; + }; + ++enum v3d_irq { ++ V3D_CORE_IRQ, ++ V3D_HUB_IRQ, ++ V3D_MAX_IRQS, ++}; ++ + struct v3d_dev { + struct drm_device drm; + +@@ -49,6 +55,9 @@ struct v3d_dev { + + struct device *dev; + struct platform_device *pdev; ++ ++ int irq[V3D_MAX_IRQS]; ++ + void __iomem *hub_regs; + void __iomem *core_regs[3]; + void __iomem *bridge_regs; +diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c +index 1609a85429cef..d994e3ce20d25 100644 +--- a/drivers/gpu/drm/v3d/v3d_gem.c ++++ b/drivers/gpu/drm/v3d/v3d_gem.c +@@ -120,6 +120,8 @@ v3d_reset(struct v3d_dev *v3d) + if (false) + v3d_idle_axi(v3d, 0); + ++ v3d_irq_disable(v3d); ++ + v3d_idle_gca(v3d); + v3d_reset_v3d(v3d); + +diff --git a/drivers/gpu/drm/v3d/v3d_irq.c b/drivers/gpu/drm/v3d/v3d_irq.c +index 41705436a7488..f0a9310cefc11 100644 +--- a/drivers/gpu/drm/v3d/v3d_irq.c ++++ b/drivers/gpu/drm/v3d/v3d_irq.c +@@ -218,7 +218,7 @@ v3d_hub_irq(int irq, void *arg) + int + v3d_irq_init(struct v3d_dev *v3d) + { +- int irq1, ret, core; ++ int irq, ret, core; + + INIT_WORK(&v3d->overflow_mem_work, v3d_overflow_mem_work); + +@@ -229,16 +229,24 @@ v3d_irq_init(struct v3d_dev *v3d) + V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS); + V3D_WRITE(V3D_HUB_INT_CLR, V3D_HUB_IRQS); + +- irq1 = platform_get_irq(v3d->pdev, 1); +- if (irq1 == -EPROBE_DEFER) +- return irq1; +- if (irq1 > 0) { +- ret = devm_request_irq(v3d->dev, irq1, ++ irq = platform_get_irq(v3d->pdev, 1); ++ if (irq == -EPROBE_DEFER) ++ return irq; ++ if (irq > 0) { ++ v3d->irq[V3D_CORE_IRQ] = irq; ++ ++ ret = devm_request_irq(v3d->dev, v3d->irq[V3D_CORE_IRQ], + v3d_irq, IRQF_SHARED, + "v3d_core0", v3d); + if (ret) + goto fail; +- ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0), ++ ++ irq = platform_get_irq(v3d->pdev, 0); ++ if (irq < 0) ++ return irq; ++ v3d->irq[V3D_HUB_IRQ] = irq; ++ ++ ret = devm_request_irq(v3d->dev, v3d->irq[V3D_HUB_IRQ], + v3d_hub_irq, IRQF_SHARED, + "v3d_hub", v3d); + if (ret) +@@ -246,7 +254,12 @@ v3d_irq_init(struct v3d_dev *v3d) + } else { + v3d->single_irq_line = true; + +- ret = devm_request_irq(v3d->dev, platform_get_irq(v3d->pdev, 0), ++ irq = platform_get_irq(v3d->pdev, 0); ++ if (irq < 0) ++ return irq; ++ v3d->irq[V3D_CORE_IRQ] = irq; ++ ++ ret = devm_request_irq(v3d->dev, v3d->irq[V3D_CORE_IRQ], + v3d_irq, IRQF_SHARED, + "v3d", v3d); + if (ret) +@@ -281,12 +294,19 @@ void + v3d_irq_disable(struct v3d_dev *v3d) + { + int core; ++ int i; + + /* Disable all interrupts. */ + for (core = 0; core < v3d->cores; core++) + V3D_CORE_WRITE(core, V3D_CTL_INT_MSK_SET, ~0); + V3D_WRITE(V3D_HUB_INT_MSK_SET, ~0); + ++ /* Finish any interrupt handler still in flight. */ ++ for (i = 0; i < V3D_MAX_IRQS; i++) { ++ if (v3d->irq[i]) ++ synchronize_irq(v3d->irq[i]); ++ } ++ + /* Clear any pending interrupts we might have left. */ + for (core = 0; core < v3d->cores; core++) + V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS); +-- +2.39.5 + diff --git a/queue-5.4/ethernet-atl1-add-missing-dma-mapping-error-checks-a.patch b/queue-5.4/ethernet-atl1-add-missing-dma-mapping-error-checks-a.patch new file mode 100644 index 0000000000..fa005f8a95 --- /dev/null +++ b/queue-5.4/ethernet-atl1-add-missing-dma-mapping-error-checks-a.patch @@ -0,0 +1,212 @@ +From b1d19973f3984f2b546bc4c93180aabfbff69a50 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Jul 2025 15:36:37 -0400 +Subject: ethernet: atl1: Add missing DMA mapping error checks and count errors + +From: Thomas Fourier + +[ Upstream commit d72411d20905180cdc452c553be17481b24463d2 ] + +The `dma_map_XXX()` functions can fail and must be checked using +`dma_mapping_error()`. This patch adds proper error handling for all +DMA mapping calls. + +In `atl1_alloc_rx_buffers()`, if DMA mapping fails, the buffer is +deallocated and marked accordingly. + +In `atl1_tx_map()`, previously mapped buffers are unmapped and the +packet is dropped on failure. + +If `atl1_xmit_frame()` drops the packet, increment the tx_error counter. + +Fixes: f3cc28c79760 ("Add Attansic L1 ethernet driver.") +Signed-off-by: Thomas Fourier +Link: https://patch.msgid.link/20250625141629.114984-2-fourier.thomas@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/atheros/atlx/atl1.c | 78 +++++++++++++++++------- + 1 file changed, 56 insertions(+), 22 deletions(-) + +diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c +index b498fd6a47d0b..3e80b9659e3b4 100644 +--- a/drivers/net/ethernet/atheros/atlx/atl1.c ++++ b/drivers/net/ethernet/atheros/atlx/atl1.c +@@ -1863,14 +1863,21 @@ static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter) + break; + } + +- buffer_info->alloced = 1; +- buffer_info->skb = skb; +- buffer_info->length = (u16) adapter->rx_buffer_len; + page = virt_to_page(skb->data); + offset = offset_in_page(skb->data); + buffer_info->dma = pci_map_page(pdev, page, offset, + adapter->rx_buffer_len, + PCI_DMA_FROMDEVICE); ++ if (pci_dma_mapping_error(pdev, buffer_info->dma)) { ++ kfree_skb(skb); ++ adapter->soft_stats.rx_dropped++; ++ break; ++ } ++ ++ buffer_info->alloced = 1; ++ buffer_info->skb = skb; ++ buffer_info->length = (u16)adapter->rx_buffer_len; ++ + rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma); + rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len); + rfd_desc->coalese = 0; +@@ -2182,8 +2189,8 @@ static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb, + return 0; + } + +-static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, +- struct tx_packet_desc *ptpd) ++static bool atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, ++ struct tx_packet_desc *ptpd) + { + struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; + struct atl1_buffer *buffer_info; +@@ -2193,6 +2200,7 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, + unsigned int nr_frags; + unsigned int f; + int retval; ++ u16 first_mapped; + u16 next_to_use; + u16 data_len; + u8 hdr_len; +@@ -2200,6 +2208,7 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, + buf_len -= skb->data_len; + nr_frags = skb_shinfo(skb)->nr_frags; + next_to_use = atomic_read(&tpd_ring->next_to_use); ++ first_mapped = next_to_use; + buffer_info = &tpd_ring->buffer_info[next_to_use]; + BUG_ON(buffer_info->skb); + /* put skb in last TPD */ +@@ -2215,6 +2224,8 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, + buffer_info->dma = pci_map_page(adapter->pdev, page, + offset, hdr_len, + PCI_DMA_TODEVICE); ++ if (pci_dma_mapping_error(adapter->pdev, buffer_info->dma)) ++ goto dma_err; + + if (++next_to_use == tpd_ring->count) + next_to_use = 0; +@@ -2240,6 +2251,9 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, + buffer_info->dma = pci_map_page(adapter->pdev, + page, offset, buffer_info->length, + PCI_DMA_TODEVICE); ++ if (pci_dma_mapping_error(adapter->pdev, ++ buffer_info->dma)) ++ goto dma_err; + if (++next_to_use == tpd_ring->count) + next_to_use = 0; + } +@@ -2251,6 +2265,8 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, + offset = offset_in_page(skb->data); + buffer_info->dma = pci_map_page(adapter->pdev, page, + offset, buf_len, PCI_DMA_TODEVICE); ++ if (pci_dma_mapping_error(adapter->pdev, buffer_info->dma)) ++ goto dma_err; + if (++next_to_use == tpd_ring->count) + next_to_use = 0; + } +@@ -2274,6 +2290,9 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, + buffer_info->dma = skb_frag_dma_map(&adapter->pdev->dev, + frag, i * ATL1_MAX_TX_BUF_LEN, + buffer_info->length, DMA_TO_DEVICE); ++ if (dma_mapping_error(&adapter->pdev->dev, ++ buffer_info->dma)) ++ goto dma_err; + + if (++next_to_use == tpd_ring->count) + next_to_use = 0; +@@ -2282,6 +2301,22 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, + + /* last tpd's buffer-info */ + buffer_info->skb = skb; ++ ++ return true; ++ ++ dma_err: ++ while (first_mapped != next_to_use) { ++ buffer_info = &tpd_ring->buffer_info[first_mapped]; ++ pci_unmap_page(adapter->pdev, ++ buffer_info->dma, ++ buffer_info->length, ++ PCI_DMA_TODEVICE); ++ buffer_info->dma = 0; ++ ++ if (++first_mapped == tpd_ring->count) ++ first_mapped = 0; ++ } ++ return false; + } + + static void atl1_tx_queue(struct atl1_adapter *adapter, u16 count, +@@ -2352,10 +2387,8 @@ static netdev_tx_t atl1_xmit_frame(struct sk_buff *skb, + + len = skb_headlen(skb); + +- if (unlikely(skb->len <= 0)) { +- dev_kfree_skb_any(skb); +- return NETDEV_TX_OK; +- } ++ if (unlikely(skb->len <= 0)) ++ goto drop_packet; + + nr_frags = skb_shinfo(skb)->nr_frags; + for (f = 0; f < nr_frags; f++) { +@@ -2369,10 +2402,8 @@ static netdev_tx_t atl1_xmit_frame(struct sk_buff *skb, + if (skb->protocol == htons(ETH_P_IP)) { + proto_hdr_len = (skb_transport_offset(skb) + + tcp_hdrlen(skb)); +- if (unlikely(proto_hdr_len > len)) { +- dev_kfree_skb_any(skb); +- return NETDEV_TX_OK; +- } ++ if (unlikely(proto_hdr_len > len)) ++ goto drop_packet; + /* need additional TPD ? */ + if (proto_hdr_len != len) + count += (len - proto_hdr_len + +@@ -2404,23 +2435,26 @@ static netdev_tx_t atl1_xmit_frame(struct sk_buff *skb, + } + + tso = atl1_tso(adapter, skb, ptpd); +- if (tso < 0) { +- dev_kfree_skb_any(skb); +- return NETDEV_TX_OK; +- } ++ if (tso < 0) ++ goto drop_packet; + + if (!tso) { + ret_val = atl1_tx_csum(adapter, skb, ptpd); +- if (ret_val < 0) { +- dev_kfree_skb_any(skb); +- return NETDEV_TX_OK; +- } ++ if (ret_val < 0) ++ goto drop_packet; + } + +- atl1_tx_map(adapter, skb, ptpd); ++ if (!atl1_tx_map(adapter, skb, ptpd)) ++ goto drop_packet; ++ + atl1_tx_queue(adapter, count, ptpd); + atl1_update_mailbox(adapter); + return NETDEV_TX_OK; ++ ++drop_packet: ++ adapter->soft_stats.tx_errors++; ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; + } + + static int atl1_rings_clean(struct napi_struct *napi, int budget) +-- +2.39.5 + diff --git a/queue-5.4/mmc-mediatek-use-data-instead-of-mrq-parameter-from-.patch b/queue-5.4/mmc-mediatek-use-data-instead-of-mrq-parameter-from-.patch new file mode 100644 index 0000000000..f89e5bf59e --- /dev/null +++ b/queue-5.4/mmc-mediatek-use-data-instead-of-mrq-parameter-from-.patch @@ -0,0 +1,99 @@ +From a2bf9900524f9a46f956bf0c25551181b92a0f65 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 May 2021 18:09:00 +0800 +Subject: mmc: mediatek: use data instead of mrq parameter from + msdc_{un}prepare_data() + +From: Yue Hu + +[ Upstream commit 151071351bb6f3d1861e99a22c4cebadf81911a0 ] + +We already have 'mrq->data' before calling these two functions, no +need to find it again via 'mrq->data' internally. Also remove local +data variable accordingly. + +Signed-off-by: Yue Hu +Link: https://lore.kernel.org/r/20210517100900.1620-1-zbestahu@gmail.com +Signed-off-by: Ulf Hansson +Stable-dep-of: f5de469990f1 ("mtk-sd: Prevent memory corruption from DMA map failure") +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/mtk-sd.c | 20 ++++++++------------ + 1 file changed, 8 insertions(+), 12 deletions(-) + +diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c +index c87227bf6e68f..5d330f2a3faae 100644 +--- a/drivers/mmc/host/mtk-sd.c ++++ b/drivers/mmc/host/mtk-sd.c +@@ -676,10 +676,8 @@ static inline void msdc_dma_setup(struct msdc_host *host, struct msdc_dma *dma, + writel(lower_32_bits(dma->gpd_addr), host->base + MSDC_DMA_SA); + } + +-static void msdc_prepare_data(struct msdc_host *host, struct mmc_request *mrq) ++static void msdc_prepare_data(struct msdc_host *host, struct mmc_data *data) + { +- struct mmc_data *data = mrq->data; +- + if (!(data->host_cookie & MSDC_PREPARE_FLAG)) { + data->sg_count = dma_map_sg(host->dev, data->sg, data->sg_len, + mmc_get_dma_dir(data)); +@@ -688,10 +686,8 @@ static void msdc_prepare_data(struct msdc_host *host, struct mmc_request *mrq) + } + } + +-static void msdc_unprepare_data(struct msdc_host *host, struct mmc_request *mrq) ++static void msdc_unprepare_data(struct msdc_host *host, struct mmc_data *data) + { +- struct mmc_data *data = mrq->data; +- + if (data->host_cookie & MSDC_ASYNC_FLAG) + return; + +@@ -1034,7 +1030,7 @@ static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq) + + msdc_track_cmd_data(host, mrq->cmd, mrq->data); + if (mrq->data) +- msdc_unprepare_data(host, mrq); ++ msdc_unprepare_data(host, mrq->data); + if (host->error) + msdc_reset_hw(host); + mmc_request_done(host->mmc, mrq); +@@ -1203,7 +1199,7 @@ static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request *mrq) + host->mrq = mrq; + + if (mrq->data) +- msdc_prepare_data(host, mrq); ++ msdc_prepare_data(host, mrq->data); + + /* if SBC is required, we have HW option and SW option. + * if HW option is enabled, and SBC does not have "special" flags, +@@ -1224,7 +1220,7 @@ static void msdc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq) + if (!data) + return; + +- msdc_prepare_data(host, mrq); ++ msdc_prepare_data(host, data); + data->host_cookie |= MSDC_ASYNC_FLAG; + } + +@@ -1232,14 +1228,14 @@ static void msdc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, + int err) + { + struct msdc_host *host = mmc_priv(mmc); +- struct mmc_data *data; ++ struct mmc_data *data = mrq->data; + +- data = mrq->data; + if (!data) + return; ++ + if (data->host_cookie) { + data->host_cookie &= ~MSDC_ASYNC_FLAG; +- msdc_unprepare_data(host, mrq); ++ msdc_unprepare_data(host, data); + } + } + +-- +2.39.5 + diff --git a/queue-5.4/mtk-sd-prevent-memory-corruption-from-dma-map-failur.patch b/queue-5.4/mtk-sd-prevent-memory-corruption-from-dma-map-failur.patch new file mode 100644 index 0000000000..d65d6d10e9 --- /dev/null +++ b/queue-5.4/mtk-sd-prevent-memory-corruption-from-dma-map-failur.patch @@ -0,0 +1,65 @@ +From 0e23de9e9b7c2acc50b47d687f0ce859931cd1f3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Jun 2025 20:26:10 +0900 +Subject: mtk-sd: Prevent memory corruption from DMA map failure + +From: Masami Hiramatsu (Google) + +[ Upstream commit f5de469990f19569627ea0dd56536ff5a13beaa3 ] + +If msdc_prepare_data() fails to map the DMA region, the request is +not prepared for data receiving, but msdc_start_data() proceeds +the DMA with previous setting. +Since this will lead a memory corruption, we have to stop the +request operation soon after the msdc_prepare_data() fails to +prepare it. + +Signed-off-by: Masami Hiramatsu (Google) +Fixes: 208489032bdd ("mmc: mediatek: Add Mediatek MMC driver") +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/174972756982.3337526.6755001617701603082.stgit@mhiramat.tok.corp.google.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/mtk-sd.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c +index 5d330f2a3faae..dbe3478cc2308 100644 +--- a/drivers/mmc/host/mtk-sd.c ++++ b/drivers/mmc/host/mtk-sd.c +@@ -686,6 +686,11 @@ static void msdc_prepare_data(struct msdc_host *host, struct mmc_data *data) + } + } + ++static bool msdc_data_prepared(struct mmc_data *data) ++{ ++ return data->host_cookie & MSDC_PREPARE_FLAG; ++} ++ + static void msdc_unprepare_data(struct msdc_host *host, struct mmc_data *data) + { + if (data->host_cookie & MSDC_ASYNC_FLAG) +@@ -1198,8 +1203,18 @@ static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request *mrq) + WARN_ON(host->mrq); + host->mrq = mrq; + +- if (mrq->data) ++ if (mrq->data) { + msdc_prepare_data(host, mrq->data); ++ if (!msdc_data_prepared(mrq->data)) { ++ /* ++ * Failed to prepare DMA area, fail fast before ++ * starting any commands. ++ */ ++ mrq->cmd->error = -ENOSPC; ++ mmc_request_done(mmc_from_priv(host), mrq); ++ return; ++ } ++ } + + /* if SBC is required, we have HW option and SW option. + * if HW option is enabled, and SBC does not have "special" flags, +-- +2.39.5 + diff --git a/queue-5.4/mtk-sd-reset-host-mrq-on-prepare_data-error.patch b/queue-5.4/mtk-sd-reset-host-mrq-on-prepare_data-error.patch new file mode 100644 index 0000000000..b89679281f --- /dev/null +++ b/queue-5.4/mtk-sd-reset-host-mrq-on-prepare_data-error.patch @@ -0,0 +1,38 @@ +From 76c5280b6298db6cd847ad54d9dfa4678edd59b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Jun 2025 14:20:37 +0900 +Subject: mtk-sd: reset host->mrq on prepare_data() error + +From: Sergey Senozhatsky + +[ Upstream commit ec54c0a20709ed6e56f40a8d59eee725c31a916b ] + +Do not leave host with dangling ->mrq pointer if we hit +the msdc_prepare_data() error out path. + +Signed-off-by: Sergey Senozhatsky +Reviewed-by: Masami Hiramatsu (Google) +Fixes: f5de469990f1 ("mtk-sd: Prevent memory corruption from DMA map failure") +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20250625052106.584905-1-senozhatsky@chromium.org +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/mtk-sd.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c +index dbe3478cc2308..c374cf40d9558 100644 +--- a/drivers/mmc/host/mtk-sd.c ++++ b/drivers/mmc/host/mtk-sd.c +@@ -1206,6 +1206,7 @@ static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request *mrq) + if (mrq->data) { + msdc_prepare_data(host, mrq->data); + if (!msdc_data_prepared(mrq->data)) { ++ host->mrq = NULL; + /* + * Failed to prepare DMA area, fail fast before + * starting any commands. +-- +2.39.5 + diff --git a/queue-5.4/net-rose-fix-fall-through-warnings-for-clang.patch b/queue-5.4/net-rose-fix-fall-through-warnings-for-clang.patch new file mode 100644 index 0000000000..b751c4e3bf --- /dev/null +++ b/queue-5.4/net-rose-fix-fall-through-warnings-for-clang.patch @@ -0,0 +1,45 @@ +From 7ffee67421a44f9fa817276735db02d570e8cb00 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Mar 2021 23:43:45 -0600 +Subject: net: rose: Fix fall-through warnings for Clang + +From: Gustavo A. R. Silva + +[ Upstream commit 90d181ca488f466904ea59dd5c836f766b69c71b ] + +In preparation to enable -Wimplicit-fallthrough for Clang, fix multiple +warnings by explicitly adding multiple break statements instead of +letting the code fall through to the next case. + +Link: https://github.com/KSPP/linux/issues/115 +Signed-off-by: Gustavo A. R. Silva +Signed-off-by: David S. Miller +Stable-dep-of: 34a500caf48c ("rose: fix dangling neighbour pointers in rose_rt_device_down()") +Signed-off-by: Sasha Levin +--- + net/rose/rose_route.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c +index 64d441d3b6533..49a0e7d5a7684 100644 +--- a/net/rose/rose_route.c ++++ b/net/rose/rose_route.c +@@ -347,6 +347,7 @@ static int rose_del_node(struct rose_route_struct *rose_route, + case 1: + rose_node->neighbour[1] = + rose_node->neighbour[2]; ++ break; + case 2: + break; + } +@@ -508,6 +509,7 @@ void rose_rt_device_down(struct net_device *dev) + /* fall through */ + case 1: + t->neighbour[1] = t->neighbour[2]; ++ break; + case 2: + break; + } +-- +2.39.5 + diff --git a/queue-5.4/rdma-core-create-and-destroy-counters-in-the-ib_core.patch b/queue-5.4/rdma-core-create-and-destroy-counters-in-the-ib_core.patch new file mode 100644 index 0000000000..9b53409322 --- /dev/null +++ b/queue-5.4/rdma-core-create-and-destroy-counters-in-the-ib_core.patch @@ -0,0 +1,155 @@ +From 56d9c5edc309bc75c77af09d8187da5d431169b7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Jun 2020 13:18:52 +0300 +Subject: RDMA/core: Create and destroy counters in the ib_core + +From: Leon Romanovsky + +[ Upstream commit 3b023e1b680a56e84c22d43486875a5aa4c78afe ] + +Move allocation and destruction of counters under ib_core responsibility + +Link: https://lore.kernel.org/r/20200630101855.368895-2-leon@kernel.org +Signed-off-by: Leon Romanovsky +Signed-off-by: Jason Gunthorpe +Stable-dep-of: acd245b1e33f ("RDMA/mlx5: Fix CC counters query for MPV") +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/device.c | 1 + + .../core/uverbs_std_types_counters.c | 17 ++++++++-------- + drivers/infiniband/hw/mlx5/main.c | 20 ++++++------------- + include/rdma/ib_verbs.h | 7 ++++--- + 4 files changed, 20 insertions(+), 25 deletions(-) + +diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c +index c46d68e6ccd0e..cf3c0d6928ac2 100644 +--- a/drivers/infiniband/core/device.c ++++ b/drivers/infiniband/core/device.c +@@ -2683,6 +2683,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops) + SET_DEVICE_OP(dev_ops, unmap_fmr); + + SET_OBJ_SIZE(dev_ops, ib_ah); ++ SET_OBJ_SIZE(dev_ops, ib_counters); + SET_OBJ_SIZE(dev_ops, ib_cq); + SET_OBJ_SIZE(dev_ops, ib_pd); + SET_OBJ_SIZE(dev_ops, ib_srq); +diff --git a/drivers/infiniband/core/uverbs_std_types_counters.c b/drivers/infiniband/core/uverbs_std_types_counters.c +index 35e41c5ca1bb1..95b66ce4943b4 100644 +--- a/drivers/infiniband/core/uverbs_std_types_counters.c ++++ b/drivers/infiniband/core/uverbs_std_types_counters.c +@@ -46,7 +46,9 @@ static int uverbs_free_counters(struct ib_uobject *uobject, + if (ret) + return ret; + +- return counters->device->ops.destroy_counters(counters); ++ counters->device->ops.destroy_counters(counters); ++ kfree(counters); ++ return 0; + } + + static int UVERBS_HANDLER(UVERBS_METHOD_COUNTERS_CREATE)( +@@ -66,20 +68,19 @@ static int UVERBS_HANDLER(UVERBS_METHOD_COUNTERS_CREATE)( + if (!ib_dev->ops.create_counters) + return -EOPNOTSUPP; + +- counters = ib_dev->ops.create_counters(ib_dev, attrs); +- if (IS_ERR(counters)) { +- ret = PTR_ERR(counters); +- goto err_create_counters; +- } ++ counters = rdma_zalloc_drv_obj(ib_dev, ib_counters); ++ if (!counters) ++ return -ENOMEM; + + counters->device = ib_dev; + counters->uobject = uobj; + uobj->object = counters; + atomic_set(&counters->usecnt, 0); + +- return 0; ++ ret = ib_dev->ops.create_counters(counters, attrs); ++ if (ret) ++ kfree(counters); + +-err_create_counters: + return ret; + } + +diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c +index fb5a1b4abcbce..d30c37688bdac 100644 +--- a/drivers/infiniband/hw/mlx5/main.c ++++ b/drivers/infiniband/hw/mlx5/main.c +@@ -6113,7 +6113,7 @@ static int mlx5_ib_read_counters(struct ib_counters *counters, + return ret; + } + +-static int mlx5_ib_destroy_counters(struct ib_counters *counters) ++static void mlx5_ib_destroy_counters(struct ib_counters *counters) + { + struct mlx5_ib_mcounters *mcounters = to_mcounters(counters); + +@@ -6121,24 +6121,15 @@ static int mlx5_ib_destroy_counters(struct ib_counters *counters) + if (mcounters->hw_cntrs_hndl) + mlx5_fc_destroy(to_mdev(counters->device)->mdev, + mcounters->hw_cntrs_hndl); +- +- kfree(mcounters); +- +- return 0; + } + +-static struct ib_counters *mlx5_ib_create_counters(struct ib_device *device, +- struct uverbs_attr_bundle *attrs) ++static int mlx5_ib_create_counters(struct ib_counters *counters, ++ struct uverbs_attr_bundle *attrs) + { +- struct mlx5_ib_mcounters *mcounters; +- +- mcounters = kzalloc(sizeof(*mcounters), GFP_KERNEL); +- if (!mcounters) +- return ERR_PTR(-ENOMEM); ++ struct mlx5_ib_mcounters *mcounters = to_mcounters(counters); + + mutex_init(&mcounters->mcntrs_mutex); +- +- return &mcounters->ibcntrs; ++ return 0; + } + + static void mlx5_ib_stage_init_cleanup(struct mlx5_ib_dev *dev) +@@ -6296,6 +6287,7 @@ static const struct ib_device_ops mlx5_ib_dev_ops = { + .resize_cq = mlx5_ib_resize_cq, + + INIT_RDMA_OBJ_SIZE(ib_ah, mlx5_ib_ah, ibah), ++ INIT_RDMA_OBJ_SIZE(ib_counters, mlx5_ib_mcounters, ibcntrs), + INIT_RDMA_OBJ_SIZE(ib_cq, mlx5_ib_cq, ibcq), + INIT_RDMA_OBJ_SIZE(ib_pd, mlx5_ib_pd, ibpd), + INIT_RDMA_OBJ_SIZE(ib_srq, mlx5_ib_srq, ibsrq), +diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h +index 30d50528d710e..7e5df8218689e 100644 +--- a/include/rdma/ib_verbs.h ++++ b/include/rdma/ib_verbs.h +@@ -2468,9 +2468,9 @@ struct ib_device_ops { + struct ib_mr *(*reg_dm_mr)(struct ib_pd *pd, struct ib_dm *dm, + struct ib_dm_mr_attr *attr, + struct uverbs_attr_bundle *attrs); +- struct ib_counters *(*create_counters)( +- struct ib_device *device, struct uverbs_attr_bundle *attrs); +- int (*destroy_counters)(struct ib_counters *counters); ++ int (*create_counters)(struct ib_counters *counters, ++ struct uverbs_attr_bundle *attrs); ++ void (*destroy_counters)(struct ib_counters *counters); + int (*read_counters)(struct ib_counters *counters, + struct ib_counters_read_attr *counters_read_attr, + struct uverbs_attr_bundle *attrs); +@@ -2563,6 +2563,7 @@ struct ib_device_ops { + int (*counter_update_stats)(struct rdma_counter *counter); + + DECLARE_RDMA_OBJ_SIZE(ib_ah); ++ DECLARE_RDMA_OBJ_SIZE(ib_counters); + DECLARE_RDMA_OBJ_SIZE(ib_cq); + DECLARE_RDMA_OBJ_SIZE(ib_pd); + DECLARE_RDMA_OBJ_SIZE(ib_srq); +-- +2.39.5 + diff --git a/queue-5.4/rdma-mlx5-fix-cc-counters-query-for-mpv.patch b/queue-5.4/rdma-mlx5-fix-cc-counters-query-for-mpv.patch new file mode 100644 index 0000000000..06b7553a34 --- /dev/null +++ b/queue-5.4/rdma-mlx5-fix-cc-counters-query-for-mpv.patch @@ -0,0 +1,38 @@ +From 64c22bf56f778761e08433f77cb36d7d6e5dd8d3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 Jun 2025 12:14:53 +0300 +Subject: RDMA/mlx5: Fix CC counters query for MPV + +From: Patrisious Haddad + +[ Upstream commit acd245b1e33fc4b9d0f2e3372021d632f7ee0652 ] + +In case, CC counters are querying for the second port use the correct +core device for the query instead of always using the master core device. + +Fixes: aac4492ef23a ("IB/mlx5: Update counter implementation for dual port RoCE") +Signed-off-by: Patrisious Haddad +Reviewed-by: Michael Guralnik +Link: https://patch.msgid.link/9cace74dcf106116118bebfa9146d40d4166c6b0.1750064969.git.leon@kernel.org +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/mlx5/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c +index d30c37688bdac..1b880b555412f 100644 +--- a/drivers/infiniband/hw/mlx5/main.c ++++ b/drivers/infiniband/hw/mlx5/main.c +@@ -5615,7 +5615,7 @@ static int mlx5_ib_get_hw_stats(struct ib_device *ibdev, + */ + goto done; + } +- ret = mlx5_lag_query_cong_counters(dev->mdev, ++ ret = mlx5_lag_query_cong_counters(mdev, + stats->value + + cnts->num_q_counters, + cnts->num_cong_counters, +-- +2.39.5 + diff --git a/queue-5.4/regulator-gpio-add-input_supply-support-in-gpio_regu.patch b/queue-5.4/regulator-gpio-add-input_supply-support-in-gpio_regu.patch new file mode 100644 index 0000000000..486555a004 --- /dev/null +++ b/queue-5.4/regulator-gpio-add-input_supply-support-in-gpio_regu.patch @@ -0,0 +1,82 @@ +From 9923fa832a03d1167d05c95e14cf932ea0a0693b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Sep 2022 15:25:25 +0200 +Subject: regulator: gpio: Add input_supply support in gpio_regulator_config + +From: Jerome Neanne + +[ Upstream commit adfdfcbdbd32b356323a3db6d3a683270051a7e6 ] + +This is simillar as fixed-regulator. +Used to extract regulator parent from the device tree. + +Without that property used, the parent regulator can be shut down (if not an always on). +Thus leading to inappropriate behavior: +On am62-SP-SK this fix is required to avoid tps65219 ldo1 (SDMMC rail) to be shut down after boot completion. + +Signed-off-by: Jerome Neanne +Link: https://lore.kernel.org/r/20220929132526.29427-2-jneanne@baylibre.com +Signed-off-by: Mark Brown +Stable-dep-of: c9764fd88bc7 ("regulator: gpio: Fix the out-of-bounds access to drvdata::gpiods") +Signed-off-by: Sasha Levin +--- + drivers/regulator/gpio-regulator.c | 15 +++++++++++++++ + include/linux/regulator/gpio-regulator.h | 2 ++ + 2 files changed, 17 insertions(+) + +diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c +index 110ee6fe76c4c..e84fc9d724486 100644 +--- a/drivers/regulator/gpio-regulator.c ++++ b/drivers/regulator/gpio-regulator.c +@@ -213,6 +213,9 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np, + regtype); + } + ++ if (of_find_property(np, "vin-supply", NULL)) ++ config->input_supply = "vin"; ++ + return config; + } + +@@ -252,6 +255,18 @@ static int gpio_regulator_probe(struct platform_device *pdev) + + drvdata->gpiods = devm_kzalloc(dev, sizeof(struct gpio_desc *), + GFP_KERNEL); ++ ++ if (config->input_supply) { ++ drvdata->desc.supply_name = devm_kstrdup(&pdev->dev, ++ config->input_supply, ++ GFP_KERNEL); ++ if (!drvdata->desc.supply_name) { ++ dev_err(&pdev->dev, ++ "Failed to allocate input supply\n"); ++ return -ENOMEM; ++ } ++ } ++ + if (!drvdata->gpiods) + return -ENOMEM; + for (i = 0; i < config->ngpios; i++) { +diff --git a/include/linux/regulator/gpio-regulator.h b/include/linux/regulator/gpio-regulator.h +index fdeb312cdabdf..c223e50ff9f78 100644 +--- a/include/linux/regulator/gpio-regulator.h ++++ b/include/linux/regulator/gpio-regulator.h +@@ -42,6 +42,7 @@ struct gpio_regulator_state { + /** + * struct gpio_regulator_config - config structure + * @supply_name: Name of the regulator supply ++ * @input_supply: Name of the input regulator supply + * @enabled_at_boot: Whether regulator has been enabled at + * boot or not. 1 = Yes, 0 = No + * This is used to keep the regulator at +@@ -62,6 +63,7 @@ struct gpio_regulator_state { + */ + struct gpio_regulator_config { + const char *supply_name; ++ const char *input_supply; + + unsigned enabled_at_boot:1; + unsigned startup_delay; +-- +2.39.5 + diff --git a/queue-5.4/regulator-gpio-fix-the-out-of-bounds-access-to-drvda.patch b/queue-5.4/regulator-gpio-fix-the-out-of-bounds-access-to-drvda.patch new file mode 100644 index 0000000000..56641cee2d --- /dev/null +++ b/queue-5.4/regulator-gpio-fix-the-out-of-bounds-access-to-drvda.patch @@ -0,0 +1,57 @@ +From 38cb1e125f550de00968d1ff6567a9c212258f2b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 3 Jul 2025 16:05:49 +0530 +Subject: regulator: gpio: Fix the out-of-bounds access to drvdata::gpiods + +From: Manivannan Sadhasivam + +[ Upstream commit c9764fd88bc744592b0604ccb6b6fc1a5f76b4e3 ] + +drvdata::gpiods is supposed to hold an array of 'gpio_desc' pointers. But +the memory is allocated for only one pointer. This will lead to +out-of-bounds access later in the code if 'config::ngpios' is > 1. So +fix the code to allocate enough memory to hold 'config::ngpios' of GPIO +descriptors. + +While at it, also move the check for memory allocation failure to be below +the allocation to make it more readable. + +Cc: stable@vger.kernel.org # 5.0 +Fixes: d6cd33ad7102 ("regulator: gpio: Convert to use descriptors") +Signed-off-by: Manivannan Sadhasivam +Link: https://patch.msgid.link/20250703103549.16558-1-mani@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/regulator/gpio-regulator.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c +index e84fc9d724486..50fcb5fce11ac 100644 +--- a/drivers/regulator/gpio-regulator.c ++++ b/drivers/regulator/gpio-regulator.c +@@ -253,8 +253,10 @@ static int gpio_regulator_probe(struct platform_device *pdev) + return -ENOMEM; + } + +- drvdata->gpiods = devm_kzalloc(dev, sizeof(struct gpio_desc *), +- GFP_KERNEL); ++ drvdata->gpiods = devm_kcalloc(dev, config->ngpios, ++ sizeof(struct gpio_desc *), GFP_KERNEL); ++ if (!drvdata->gpiods) ++ return -ENOMEM; + + if (config->input_supply) { + drvdata->desc.supply_name = devm_kstrdup(&pdev->dev, +@@ -267,8 +269,6 @@ static int gpio_regulator_probe(struct platform_device *pdev) + } + } + +- if (!drvdata->gpiods) +- return -ENOMEM; + for (i = 0; i < config->ngpios; i++) { + drvdata->gpiods[i] = devm_gpiod_get_index(dev, + NULL, +-- +2.39.5 + diff --git a/queue-5.4/rose-fix-dangling-neighbour-pointers-in-rose_rt_devi.patch b/queue-5.4/rose-fix-dangling-neighbour-pointers-in-rose_rt_devi.patch new file mode 100644 index 0000000000..b51145e992 --- /dev/null +++ b/queue-5.4/rose-fix-dangling-neighbour-pointers-in-rose_rt_devi.patch @@ -0,0 +1,84 @@ +From f90d07a55ef0d5708821a79f92642cc76cf772c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 29 Jun 2025 12:06:31 +0900 +Subject: rose: fix dangling neighbour pointers in rose_rt_device_down() + +From: Kohei Enju + +[ Upstream commit 34a500caf48c47d5171f4aa1f237da39b07c6157 ] + +There are two bugs in rose_rt_device_down() that can cause +use-after-free: + +1. The loop bound `t->count` is modified within the loop, which can + cause the loop to terminate early and miss some entries. + +2. When removing an entry from the neighbour array, the subsequent entries + are moved up to fill the gap, but the loop index `i` is still + incremented, causing the next entry to be skipped. + +For example, if a node has three neighbours (A, A, B) with count=3 and A +is being removed, the second A is not checked. + + i=0: (A, A, B) -> (A, B) with count=2 + ^ checked + i=1: (A, B) -> (A, B) with count=2 + ^ checked (B, not A!) + i=2: (doesn't occur because i < count is false) + +This leaves the second A in the array with count=2, but the rose_neigh +structure has been freed. Code that accesses these entries assumes that +the first `count` entries are valid pointers, causing a use-after-free +when it accesses the dangling pointer. + +Fix both issues by iterating over the array in reverse order with a fixed +loop bound. This ensures that all entries are examined and that the removal +of an entry doesn't affect subsequent iterations. + +Reported-by: syzbot+e04e2c007ba2c80476cb@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=e04e2c007ba2c80476cb +Tested-by: syzbot+e04e2c007ba2c80476cb@syzkaller.appspotmail.com +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Kohei Enju +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250629030833.6680-1-enjuk@amazon.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/rose/rose_route.c | 15 ++++----------- + 1 file changed, 4 insertions(+), 11 deletions(-) + +diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c +index 49a0e7d5a7684..91855d11ad15d 100644 +--- a/net/rose/rose_route.c ++++ b/net/rose/rose_route.c +@@ -497,22 +497,15 @@ void rose_rt_device_down(struct net_device *dev) + t = rose_node; + rose_node = rose_node->next; + +- for (i = 0; i < t->count; i++) { ++ for (i = t->count - 1; i >= 0; i--) { + if (t->neighbour[i] != s) + continue; + + t->count--; + +- switch (i) { +- case 0: +- t->neighbour[0] = t->neighbour[1]; +- /* fall through */ +- case 1: +- t->neighbour[1] = t->neighbour[2]; +- break; +- case 2: +- break; +- } ++ memmove(&t->neighbour[i], &t->neighbour[i + 1], ++ sizeof(t->neighbour[0]) * ++ (t->count - i)); + } + + if (t->count <= 0) +-- +2.39.5 + diff --git a/queue-5.4/scsi-ufs-core-fix-spelling-of-a-sysfs-attribute-name.patch b/queue-5.4/scsi-ufs-core-fix-spelling-of-a-sysfs-attribute-name.patch new file mode 100644 index 0000000000..7e4ffd441d --- /dev/null +++ b/queue-5.4/scsi-ufs-core-fix-spelling-of-a-sysfs-attribute-name.patch @@ -0,0 +1,60 @@ +From e9a5b2054b5b9c5574cfe3925df3e5c7b867fd0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Jul 2025 13:26:05 -0400 +Subject: scsi: ufs: core: Fix spelling of a sysfs attribute name + +From: Bart Van Assche + +[ Upstream commit 021f243627ead17eb6500170256d3d9be787dad8 ] + +Change "resourse" into "resource" in the name of a sysfs attribute. + +Fixes: d829fc8a1058 ("scsi: ufs: sysfs: unit descriptor") +Signed-off-by: Bart Van Assche +Link: https://lore.kernel.org/r/20250624181658.336035-1-bvanassche@acm.org +Reviewed-by: Avri Altman +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + Documentation/ABI/testing/sysfs-driver-ufs | 2 +- + drivers/scsi/ufs/ufs-sysfs.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs +index 016724ec26d5a..7318565d68f58 100644 +--- a/Documentation/ABI/testing/sysfs-driver-ufs ++++ b/Documentation/ABI/testing/sysfs-driver-ufs +@@ -589,7 +589,7 @@ Description: This file shows the thin provisioning type. This is one of + about the descriptor could be found at UFS specifications 2.1. + The file is read only. + +-What: /sys/class/scsi_device/*/device/unit_descriptor/physical_memory_resourse_count ++What: /sys/class/scsi_device/*/device/unit_descriptor/physical_memory_resource_count + Date: February 2018 + Contact: Stanislav Nijnikov + Description: This file shows the total physical memory resources. This is +diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c +index ad2abc96c0f19..97e3857bda32a 100644 +--- a/drivers/scsi/ufs/ufs-sysfs.c ++++ b/drivers/scsi/ufs/ufs-sysfs.c +@@ -753,7 +753,7 @@ UFS_UNIT_DESC_PARAM(logical_block_size, _LOGICAL_BLK_SIZE, 1); + UFS_UNIT_DESC_PARAM(logical_block_count, _LOGICAL_BLK_COUNT, 8); + UFS_UNIT_DESC_PARAM(erase_block_size, _ERASE_BLK_SIZE, 4); + UFS_UNIT_DESC_PARAM(provisioning_type, _PROVISIONING_TYPE, 1); +-UFS_UNIT_DESC_PARAM(physical_memory_resourse_count, _PHY_MEM_RSRC_CNT, 8); ++UFS_UNIT_DESC_PARAM(physical_memory_resource_count, _PHY_MEM_RSRC_CNT, 8); + UFS_UNIT_DESC_PARAM(context_capabilities, _CTX_CAPABILITIES, 2); + UFS_UNIT_DESC_PARAM(large_unit_granularity, _LARGE_UNIT_SIZE_M1, 1); + +@@ -768,7 +768,7 @@ static struct attribute *ufs_sysfs_unit_descriptor[] = { + &dev_attr_logical_block_count.attr, + &dev_attr_erase_block_size.attr, + &dev_attr_provisioning_type.attr, +- &dev_attr_physical_memory_resourse_count.attr, ++ &dev_attr_physical_memory_resource_count.attr, + &dev_attr_context_capabilities.attr, + &dev_attr_large_unit_granularity.attr, + NULL, +-- +2.39.5 + diff --git a/queue-5.4/series b/queue-5.4/series index cbfc746d49..f147e70664 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -82,3 +82,23 @@ wifi-mac80211-drop-invalid-source-address-ocb-frames.patch wifi-ath6kl-remove-warn-on-bad-firmware-input.patch acpica-refuse-to-evaluate-a-method-if-arguments-are-.patch rcu-return-early-if-callback-is-not-specified.patch +regulator-gpio-add-input_supply-support-in-gpio_regu.patch +regulator-gpio-fix-the-out-of-bounds-access-to-drvda.patch +mmc-mediatek-use-data-instead-of-mrq-parameter-from-.patch +mtk-sd-prevent-memory-corruption-from-dma-map-failur.patch +mtk-sd-reset-host-mrq-on-prepare_data-error.patch +drm-v3d-disable-interrupts-before-resetting-the-gpu.patch +scsi-ufs-core-fix-spelling-of-a-sysfs-attribute-name.patch +rdma-core-create-and-destroy-counters-in-the-ib_core.patch +rdma-mlx5-fix-cc-counters-query-for-mpv.patch +btrfs-propagate-last_unlink_trans-earlier-when-doing.patch +btrfs-use-btrfs_record_snapshot_destroy-during-rmdir.patch +ethernet-atl1-add-missing-dma-mapping-error-checks-a.patch +dpaa2-eth-fix-xdp_rxq_info-leak.patch +spi-spi-fsl-dspi-rename-fifo_-read-write-and-tx-cmd-.patch +spi-spi-fsl-dspi-fix-interrupt-less-dma-mode-taking-.patch +spi-spi-fsl-dspi-clear-completion-counter-before-ini.patch +drm-i915-selftests-change-mock_request-to-return-err.patch +drm-i915-gt-fix-timeline-left-held-on-vma-alloc-erro.patch +net-rose-fix-fall-through-warnings-for-clang.patch +rose-fix-dangling-neighbour-pointers-in-rose_rt_devi.patch diff --git a/queue-5.4/spi-spi-fsl-dspi-clear-completion-counter-before-ini.patch b/queue-5.4/spi-spi-fsl-dspi-clear-completion-counter-before-ini.patch new file mode 100644 index 0000000000..bd5f3a912e --- /dev/null +++ b/queue-5.4/spi-spi-fsl-dspi-clear-completion-counter-before-ini.patch @@ -0,0 +1,76 @@ +From 68dd4394618b2e589d92093de5735d73786a9f91 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 27 Jun 2025 11:21:37 +0100 +Subject: spi: spi-fsl-dspi: Clear completion counter before initiating + transfer + +From: James Clark + +[ Upstream commit fa60c094c19b97e103d653f528f8d9c178b6a5f5 ] + +In target mode, extra interrupts can be received between the end of a +transfer and halting the module if the host continues sending more data. +If the interrupt from this occurs after the reinit_completion() then the +completion counter is left at a non-zero value. The next unrelated +transfer initiated by userspace will then complete immediately without +waiting for the interrupt or writing to the RX buffer. + +Fix it by resetting the counter before the transfer so that lingering +values are cleared. This is done after clearing the FIFOs and the +status register but before the transfer is initiated, so no interrupts +should be received at this point resulting in other race conditions. + +Fixes: 4f5ee75ea171 ("spi: spi-fsl-dspi: Replace interruptible wait queue with a simple completion") +Signed-off-by: James Clark +Reviewed-by: Frank Li +Link: https://patch.msgid.link/20250627-james-nxp-spi-dma-v4-1-178dba20c120@linaro.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-fsl-dspi.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c +index 7b62ecbe36321..de203b9e3f1b8 100644 +--- a/drivers/spi/spi-fsl-dspi.c ++++ b/drivers/spi/spi-fsl-dspi.c +@@ -773,10 +773,28 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr, + trans_mode = dspi->devtype_data->trans_mode; + switch (trans_mode) { + case DSPI_EOQ_MODE: ++ /* ++ * Reinitialize the completion before transferring data ++ * to avoid the case where it might remain in the done ++ * state due to a spurious interrupt from a previous ++ * transfer. This could falsely signal that the current ++ * transfer has completed. ++ */ ++ if (dspi->irq) ++ reinit_completion(&dspi->xfer_done); + regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_EOQFE); + dspi_eoq_write(dspi); + break; + case DSPI_TCFQ_MODE: ++ /* ++ * Reinitialize the completion before transferring data ++ * to avoid the case where it might remain in the done ++ * state due to a spurious interrupt from a previous ++ * transfer. This could falsely signal that the current ++ * transfer has completed. ++ */ ++ if (dspi->irq) ++ reinit_completion(&dspi->xfer_done); + regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_TCFQE); + dspi_tcfq_write(dspi); + break; +@@ -796,7 +814,6 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr, + if (trans_mode != DSPI_DMA_MODE) { + if (dspi->irq) { + wait_for_completion(&dspi->xfer_done); +- reinit_completion(&dspi->xfer_done); + } else { + do { + status = dspi_poll(dspi); +-- +2.39.5 + diff --git a/queue-5.4/spi-spi-fsl-dspi-fix-interrupt-less-dma-mode-taking-.patch b/queue-5.4/spi-spi-fsl-dspi-fix-interrupt-less-dma-mode-taking-.patch new file mode 100644 index 0000000000..0ce7bc262c --- /dev/null +++ b/queue-5.4/spi-spi-fsl-dspi-fix-interrupt-less-dma-mode-taking-.patch @@ -0,0 +1,58 @@ +From 0b574ccdc589a8565ae3cb62f5d745caad16eb8e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Mar 2020 02:15:59 +0200 +Subject: spi: spi-fsl-dspi: Fix interrupt-less DMA mode taking an XSPI code + path + +From: Vladimir Oltean + +[ Upstream commit 826b3a6a34619b934cdc33eeb961fcb99ce92c09 ] + +Interrupts are not necessary for DMA functionality, since the completion +event is provided by the DMA driver. + +But if the driver fails to request the IRQ defined in the device tree, +it will call dspi_poll which would make the driver hang waiting for data +to become available in the RX FIFO. + +Fixes: c55be3059159 ("spi: spi-fsl-dspi: Use poll mode in case the platform IRQ is missing") +Signed-off-by: Vladimir Oltean +Tested-by: Michael Walle +Link: https://lore.kernel.org/r/20200318001603.9650-9-olteanv@gmail.com +Signed-off-by: Mark Brown +Stable-dep-of: fa60c094c19b ("spi: spi-fsl-dspi: Clear completion counter before initiating transfer") +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-fsl-dspi.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c +index 99d048acca29e..7b62ecbe36321 100644 +--- a/drivers/spi/spi-fsl-dspi.c ++++ b/drivers/spi/spi-fsl-dspi.c +@@ -793,13 +793,15 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr, + goto out; + } + +- if (!dspi->irq) { +- do { +- status = dspi_poll(dspi); +- } while (status == -EINPROGRESS); +- } else if (trans_mode != DSPI_DMA_MODE) { +- wait_for_completion(&dspi->xfer_done); +- reinit_completion(&dspi->xfer_done); ++ if (trans_mode != DSPI_DMA_MODE) { ++ if (dspi->irq) { ++ wait_for_completion(&dspi->xfer_done); ++ reinit_completion(&dspi->xfer_done); ++ } else { ++ do { ++ status = dspi_poll(dspi); ++ } while (status == -EINPROGRESS); ++ } + } + + if (transfer->delay_usecs) +-- +2.39.5 + diff --git a/queue-5.4/spi-spi-fsl-dspi-rename-fifo_-read-write-and-tx-cmd-.patch b/queue-5.4/spi-spi-fsl-dspi-rename-fifo_-read-write-and-tx-cmd-.patch new file mode 100644 index 0000000000..75ded4dc8a --- /dev/null +++ b/queue-5.4/spi-spi-fsl-dspi-rename-fifo_-read-write-and-tx-cmd-.patch @@ -0,0 +1,103 @@ +From 7a610fd3047fc09790529a751ba45c7d0f9b2d24 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Mar 2020 00:00:37 +0200 +Subject: spi: spi-fsl-dspi: Rename fifo_{read,write} and {tx,cmd}_fifo_write + +From: Vladimir Oltean + +[ Upstream commit 547248fbed23f3cd2f6a5937b44fad60993640c4 ] + +These function names are very generic and it is easy to get confused. +Rename them after the hardware register that they are accessing. + +Signed-off-by: Vladimir Oltean +Link: https://lore.kernel.org/r/20200304220044.11193-6-olteanv@gmail.com +Signed-off-by: Mark Brown +Stable-dep-of: fa60c094c19b ("spi: spi-fsl-dspi: Clear completion counter before initiating transfer") +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-fsl-dspi.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c +index 1d94fc89602f2..99d048acca29e 100644 +--- a/drivers/spi/spi-fsl-dspi.c ++++ b/drivers/spi/spi-fsl-dspi.c +@@ -560,12 +560,12 @@ static void ns_delay_scale(char *psc, char *sc, int delay_ns, + } + } + +-static void fifo_write(struct fsl_dspi *dspi) ++static void dspi_pushr_write(struct fsl_dspi *dspi) + { + regmap_write(dspi->regmap, SPI_PUSHR, dspi_pop_tx_pushr(dspi)); + } + +-static void cmd_fifo_write(struct fsl_dspi *dspi) ++static void dspi_pushr_cmd_write(struct fsl_dspi *dspi) + { + u16 cmd = dspi->tx_cmd; + +@@ -574,7 +574,7 @@ static void cmd_fifo_write(struct fsl_dspi *dspi) + regmap_write(dspi->regmap_pushr, PUSHR_CMD, cmd); + } + +-static void tx_fifo_write(struct fsl_dspi *dspi, u16 txdata) ++static void dspi_pushr_txdata_write(struct fsl_dspi *dspi, u16 txdata) + { + regmap_write(dspi->regmap_pushr, PUSHR_TX, txdata); + } +@@ -590,18 +590,18 @@ static void dspi_tcfq_write(struct fsl_dspi *dspi) + */ + u32 data = dspi_pop_tx(dspi); + +- cmd_fifo_write(dspi); +- tx_fifo_write(dspi, data & 0xFFFF); +- tx_fifo_write(dspi, data >> 16); ++ dspi_pushr_cmd_write(dspi); ++ dspi_pushr_txdata_write(dspi, data & 0xFFFF); ++ dspi_pushr_txdata_write(dspi, data >> 16); + } else { + /* Write one entry to both TX FIFO and CMD FIFO + * simultaneously. + */ +- fifo_write(dspi); ++ dspi_pushr_write(dspi); + } + } + +-static u32 fifo_read(struct fsl_dspi *dspi) ++static u32 dspi_popr_read(struct fsl_dspi *dspi) + { + u32 rxdata = 0; + +@@ -611,7 +611,7 @@ static u32 fifo_read(struct fsl_dspi *dspi) + + static void dspi_tcfq_read(struct fsl_dspi *dspi) + { +- dspi_push_rx(dspi, fifo_read(dspi)); ++ dspi_push_rx(dspi, dspi_popr_read(dspi)); + } + + static void dspi_eoq_write(struct fsl_dspi *dspi) +@@ -629,7 +629,7 @@ static void dspi_eoq_write(struct fsl_dspi *dspi) + if (fifo_size == (DSPI_FIFO_SIZE - 1)) + dspi->tx_cmd |= SPI_PUSHR_CMD_CTCNT; + /* Write combined TX FIFO and CMD FIFO entry */ +- fifo_write(dspi); ++ dspi_pushr_write(dspi); + } + } + +@@ -639,7 +639,7 @@ static void dspi_eoq_read(struct fsl_dspi *dspi) + + /* Read one FIFO entry and push to rx buffer */ + while ((dspi->rx < dspi->rx_end) && fifo_size--) +- dspi_push_rx(dspi, fifo_read(dspi)); ++ dspi_push_rx(dspi, dspi_popr_read(dspi)); + } + + static int dspi_rxtx(struct fsl_dspi *dspi) +-- +2.39.5 +