]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
7.0-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 15 Jun 2026 15:53:04 +0000 (17:53 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 15 Jun 2026 15:53:04 +0000 (17:53 +0200)
added patches:
drm-gem-try-to-fix-change_handle-ioctl-attempt-4.patch
drm-i915-fix-color-blob-reference-handling-in-intel_plane_state.patch
mm-cma-fix-reserved-page-leak-on-activation-failure.patch
mm-cma_debug-fix-invalid-accesses-for-inactive-cma-areas.patch
mm-damon-lru_sort-handle-ctx-allocation-failure.patch
mm-damon-reclaim-handle-ctx-allocation-failure.patch
mm-huge_memory-use-correct-flags-for-device-private-pmd-entry.patch
mm-hugetlb-avoid-false-positive-lockdep-assertion.patch
mm-hugetlb-restore-reservation-on-error-in-hugetlb-folio-copy-paths.patch
mm-list_lru-drain-before-clearing-xarray-entry-on-reparent.patch
mm-mincore-handle-non-swap-entries-before-config_swap-guard.patch
mmc-core-fix-host-controller-programming-for-fixed-driver-type.patch
mmc-dw_mmc-rockchip-add-missing-private-data-for-very-old-controllers.patch
mmc-litex_mmc-set-mandatory-idle-clocks-before-cmd0.patch
mmc-renesas_sdhi-add-of-entry-for-rz-g2h-soc.patch
mmc-sdhci-add-signal-voltage-switch-in-sdhci_resume_host.patch
mmc-sdhci-of-dwcmshc-fix-reset-clk-and-sdio-support-for-eswin-eic7700.patch
pmdomain-imx-fix-of-node-refcount.patch
pmdomain-ti_sci-add-wakeup-constraint-to-parent-devices-of-wakeup-source.patch
rtase-avoid-sleeping-in-get_stats64.patch
rtase-reset-tx-subqueue-when-clearing-tx-ring.patch
rxrpc-fix-the-ack-parser-to-extract-the-sack-table-for-parsing.patch
sctp-diag-reject-stale-associations-in-dump_one-path.patch
sctp-stream-fully-roll-back-denied-add-stream-state.patch
slimbus-qcom-ngd-ctrl-avoid-abba-on-tx_lock-ctrl-lock.patch
slimbus-qcom-ngd-ctrl-balance-pm_runtime-enablement-for-ngd.patch
slimbus-qcom-ngd-ctrl-correct-pdr-and-ssr-cleanup-ownership.patch
slimbus-qcom-ngd-ctrl-fix-of-node-refcount.patch
slimbus-qcom-ngd-ctrl-fix-probe-error-path-ordering.patch
slimbus-qcom-ngd-ctrl-fix-up-platform_driver-registration.patch
slimbus-qcom-ngd-ctrl-initialize-controller-resources-in-controller.patch
slimbus-qcom-ngd-ctrl-register-callbacks-after-creating-the-ngd.patch
thunderbolt-bound-root-directory-content-to-block-size.patch
thunderbolt-clamp-xdomain-response-data-copy-to-allocation-size.patch
thunderbolt-limit-xdomain-response-copy-to-actual-frame-size.patch
thunderbolt-reject-zero-length-property-entries-in-validator.patch
thunderbolt-validate-xdomain-request-packet-size-before-type-cast.patch

38 files changed:
queue-7.0/drm-gem-try-to-fix-change_handle-ioctl-attempt-4.patch [new file with mode: 0644]
queue-7.0/drm-i915-fix-color-blob-reference-handling-in-intel_plane_state.patch [new file with mode: 0644]
queue-7.0/mm-cma-fix-reserved-page-leak-on-activation-failure.patch [new file with mode: 0644]
queue-7.0/mm-cma_debug-fix-invalid-accesses-for-inactive-cma-areas.patch [new file with mode: 0644]
queue-7.0/mm-damon-lru_sort-handle-ctx-allocation-failure.patch [new file with mode: 0644]
queue-7.0/mm-damon-reclaim-handle-ctx-allocation-failure.patch [new file with mode: 0644]
queue-7.0/mm-huge_memory-use-correct-flags-for-device-private-pmd-entry.patch [new file with mode: 0644]
queue-7.0/mm-hugetlb-avoid-false-positive-lockdep-assertion.patch [new file with mode: 0644]
queue-7.0/mm-hugetlb-restore-reservation-on-error-in-hugetlb-folio-copy-paths.patch [new file with mode: 0644]
queue-7.0/mm-list_lru-drain-before-clearing-xarray-entry-on-reparent.patch [new file with mode: 0644]
queue-7.0/mm-mincore-handle-non-swap-entries-before-config_swap-guard.patch [new file with mode: 0644]
queue-7.0/mmc-core-fix-host-controller-programming-for-fixed-driver-type.patch [new file with mode: 0644]
queue-7.0/mmc-dw_mmc-rockchip-add-missing-private-data-for-very-old-controllers.patch [new file with mode: 0644]
queue-7.0/mmc-litex_mmc-set-mandatory-idle-clocks-before-cmd0.patch [new file with mode: 0644]
queue-7.0/mmc-renesas_sdhi-add-of-entry-for-rz-g2h-soc.patch [new file with mode: 0644]
queue-7.0/mmc-sdhci-add-signal-voltage-switch-in-sdhci_resume_host.patch [new file with mode: 0644]
queue-7.0/mmc-sdhci-of-dwcmshc-fix-reset-clk-and-sdio-support-for-eswin-eic7700.patch [new file with mode: 0644]
queue-7.0/pmdomain-imx-fix-of-node-refcount.patch [new file with mode: 0644]
queue-7.0/pmdomain-ti_sci-add-wakeup-constraint-to-parent-devices-of-wakeup-source.patch [new file with mode: 0644]
queue-7.0/rtase-avoid-sleeping-in-get_stats64.patch [new file with mode: 0644]
queue-7.0/rtase-reset-tx-subqueue-when-clearing-tx-ring.patch [new file with mode: 0644]
queue-7.0/rxrpc-fix-the-ack-parser-to-extract-the-sack-table-for-parsing.patch [new file with mode: 0644]
queue-7.0/sctp-diag-reject-stale-associations-in-dump_one-path.patch [new file with mode: 0644]
queue-7.0/sctp-stream-fully-roll-back-denied-add-stream-state.patch [new file with mode: 0644]
queue-7.0/series
queue-7.0/slimbus-qcom-ngd-ctrl-avoid-abba-on-tx_lock-ctrl-lock.patch [new file with mode: 0644]
queue-7.0/slimbus-qcom-ngd-ctrl-balance-pm_runtime-enablement-for-ngd.patch [new file with mode: 0644]
queue-7.0/slimbus-qcom-ngd-ctrl-correct-pdr-and-ssr-cleanup-ownership.patch [new file with mode: 0644]
queue-7.0/slimbus-qcom-ngd-ctrl-fix-of-node-refcount.patch [new file with mode: 0644]
queue-7.0/slimbus-qcom-ngd-ctrl-fix-probe-error-path-ordering.patch [new file with mode: 0644]
queue-7.0/slimbus-qcom-ngd-ctrl-fix-up-platform_driver-registration.patch [new file with mode: 0644]
queue-7.0/slimbus-qcom-ngd-ctrl-initialize-controller-resources-in-controller.patch [new file with mode: 0644]
queue-7.0/slimbus-qcom-ngd-ctrl-register-callbacks-after-creating-the-ngd.patch [new file with mode: 0644]
queue-7.0/thunderbolt-bound-root-directory-content-to-block-size.patch [new file with mode: 0644]
queue-7.0/thunderbolt-clamp-xdomain-response-data-copy-to-allocation-size.patch [new file with mode: 0644]
queue-7.0/thunderbolt-limit-xdomain-response-copy-to-actual-frame-size.patch [new file with mode: 0644]
queue-7.0/thunderbolt-reject-zero-length-property-entries-in-validator.patch [new file with mode: 0644]
queue-7.0/thunderbolt-validate-xdomain-request-packet-size-before-type-cast.patch [new file with mode: 0644]

diff --git a/queue-7.0/drm-gem-try-to-fix-change_handle-ioctl-attempt-4.patch b/queue-7.0/drm-gem-try-to-fix-change_handle-ioctl-attempt-4.patch
new file mode 100644 (file)
index 0000000..a41c0f1
--- /dev/null
@@ -0,0 +1,228 @@
+From 1a4f03d22fb655e5f192244fb2c87d8066fcfca2 Mon Sep 17 00:00:00 2001
+From: Simona Vetter <simona.vetter@ffwll.ch>
+Date: Thu, 4 Jun 2026 21:44:37 +0200
+Subject: drm/gem: Try to fix change_handle ioctl, attempt 4
+
+From: Simona Vetter <simona.vetter@ffwll.ch>
+
+commit 1a4f03d22fb655e5f192244fb2c87d8066fcfca2 upstream.
+
+[airlied: just added some comments on how to reenable]
+On-list because the cat is out of the bag and we're clearly not good
+enough to figure this out in private. The story thus far:
+
+5e28b7b94408 ("drm: Set old handle to NULL before prime swap in
+change_handle") tried to fix a race condition between the gem_close and
+gem_change_handle ioctls, but got a few things wrong:
+
+- There's a confusion with the local variable handle, which is actually
+  the new handle, and so the two-stage trick was actually applied to the
+  wrong idr slot. 7164d78559b0 ("drm/gem: fix race between
+  change_handle and handle_delete") tried to fix that by adding yet
+  another code block, but forgot to add the error handling. Which meant
+  we now have two paths, both kinda wrong.
+
+- dc366607c41c ("drm: Replace old pointer to new idr") tried to apply
+  another fix, but inconsistently, again because of the handle confusion
+  - this would be the right fix (kinda, somewhat, it's a mess) if we'd
+  do the two-stage approach for the new handle. Except that wasn't the
+  intent of the original fix.
+
+We also didn't have an igt merged for the original ioctl, which is a big
+no-go. This was attempted to address off-list in the original bugfix,
+and amd QA people claimed the bug was fixed now. Very clearly that's not
+the case. Here's my attempt to sort this out:
+
+- Rename the local variable to new_handle, the old aliasing with
+  args->handle is just too dangerously confusing.
+
+- Merge the gem obj lookup with the two-stage idr_replace so that we
+  avoid getting ourselves confused there.
+
+- This means we don't have a surplus temporary reference anymore, only
+  an inherited from the idr. A concurrent gem_close on the new_handle
+  could steal that. Fix that with the same two-stage approach
+  create_tail uses. This is a bit overkill as documented in the comment,
+  but I also don't trust my ability to understand this all correctly, so
+  go with the established pattern we have from other ioctls instead for
+  maximum paranoia.
+
+- Adjust error paths. I've tried to make the error and success paths
+  common, because they are identical except for which handle is removed
+  and on which we call idr_replace to (re)install the object again. But
+  that made things messier to read, so I've left it at the more verbose
+  version, which unfortunately hides the symmetry in the entire code
+  flow a bit.
+
+- While at it, also replace the 7 space indent with 1 tab.
+
+And finally, because I flat out don't trust my abilities here at all
+anymore:
+
+- Disable the ioctl until we have the igt situation and everything else
+  sorted out on-list and with full consensus.
+
+v2:
+
+Sashiko noticed that I didn't handle the error path for idr_replace
+correctly, it must be checked with IS_ERR_OR_NULL like in
+gem_handle_delete. So yeah, definitely should just the existing paths
+1:1 because this is endless amounts of tricky.
+
+Also add the Fixes: line for the original ioctl, I forgot that too.
+
+Reported-by: DARKNAVY (@DarkNavyOrg) <vr@darknavy.com>
+Signed-off-by: Simona Vetter <simona.vetter@ffwll.ch>
+Fixes: dc366607c41c ("drm: Replace old pointer to new idr")
+Cc: syzbot+d7c9eed171647e421013@syzkaller.appspotmail.com
+Cc: stable@vger.kernel.org
+Cc: Edward Adam Davis <eadavis@qq.com>
+Cc: Dave Airlie <airlied@redhat.com>
+Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+Cc: Maxime Ripard <mripard@kernel.org>
+Cc: Thomas Zimmermann <tzimmermann@suse.de>
+Fixes: 5e28b7b94408 ("drm: Set old handle to NULL before prime swap in change_handle")
+Cc: David Francis <David.Francis@amd.com>
+Cc: Puttimet Thammasaeng <pwn8official@gmail.com>
+Cc: Christian Koenig <Christian.Koenig@amd.com>
+Fixes: 7164d78559b0 ("drm/gem: fix race between change_handle and handle_delete")
+Cc: Zhenghang Xiao <kipreyyy@gmail.com>
+Fixes: 5e28b7b94408 ("drm: Set old handle to NULL before prime swap in change_handle")
+Reviewed-by: David Francis <David.Francis@amd.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Link: https://patch.msgid.link/20260604194437.1725314-1-simona.vetter@ffwll.ch
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/drm_gem.c   |   73 ++++++++++++++++++++------------------------
+ drivers/gpu/drm/drm_ioctl.c |    3 +
+ 2 files changed, 36 insertions(+), 40 deletions(-)
+
+--- a/drivers/gpu/drm/drm_gem.c
++++ b/drivers/gpu/drm/drm_gem.c
+@@ -997,12 +997,25 @@ err:
+       return ret;
+ }
++/*
++ * This ioctl is disabled for security reasons but also it failed
++ * to follow process in terms of adding testing in igt and verifying
++ * all the corner cases which made fixing security bugs in it even
++ * harder than necessary.
++ *
++ * To re-enable this ioctl
++ * 1. land working IGT tests in igt-gpu-tools that cover
++ *    all corner cases and race conditions.
++ * 2. handle idr_preload
++ * 3. handle == 0
++ * 4. handle == new_handle semantics definition.
++ */
+ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv)
+ {
+       struct drm_gem_change_handle *args = data;
+-      struct drm_gem_object *obj, *idrobj;
+-      int handle, ret;
++      struct drm_gem_object *obj;
++      int new_handle, ret;
+       if (!drm_core_check_feature(dev, DRIVER_GEM))
+               return -EOPNOTSUPP;
+@@ -1010,52 +1023,36 @@ int drm_gem_change_handle_ioctl(struct d
+       /* idr_alloc() limitation. */
+       if (args->new_handle > INT_MAX)
+               return -EINVAL;
+-      handle = args->new_handle;
++      new_handle = args->new_handle;
+-      obj = drm_gem_object_lookup(file_priv, args->handle);
+-      if (!obj)
+-              return -ENOENT;
+-
+-      if (args->handle == handle) {
+-              ret = 0;
+-              goto out;
+-      }
++      if (args->handle == new_handle)
++              return 0;
+       mutex_lock(&file_priv->prime.lock);
+-
+       spin_lock(&file_priv->table_lock);
+-
+-       /* When create_tail allocs an obj idr, it needs to first alloc as NULL,
+-      * then later replace with the correct object. This is not necessary
+-      * here, because the only operations that could race are drm_prime
+-      * bookkeeping, and we hold the prime lock.
+-      */
+-      ret = idr_alloc(&file_priv->object_idr, obj, handle, handle + 1,
++      ret = idr_alloc(&file_priv->object_idr, NULL, new_handle, new_handle + 1,
+                       GFP_NOWAIT);
+-       if (ret < 0) {
+-             spin_unlock(&file_priv->table_lock);
+-             goto out_unlock;
+-       }
+-
+-       idrobj = idr_replace(&file_priv->object_idr, NULL, handle);
+-       if (idrobj != obj) {
+-             idr_replace(&file_priv->object_idr, idrobj, handle);
+-             idr_remove(&file_priv->object_idr, args->new_handle);
+-             spin_unlock(&file_priv->table_lock);
+-             ret = -ENOENT;
+-             goto out_unlock;
+-       }
++      if (ret < 0) {
++              spin_unlock(&file_priv->table_lock);
++              goto out_unlock;
++      }
+-      idr_replace(&file_priv->object_idr, NULL, args->handle);
++      obj = idr_replace(&file_priv->object_idr, NULL, args->handle);
++      if (IS_ERR_OR_NULL(obj)) {
++              idr_remove(&file_priv->object_idr, new_handle);
++              spin_unlock(&file_priv->table_lock);
++              ret = -ENOENT;
++              goto out_unlock;
++      }
+       spin_unlock(&file_priv->table_lock);
+       if (obj->dma_buf) {
+               ret = drm_prime_add_buf_handle(&file_priv->prime, obj->dma_buf,
+-                                             handle);
++                                             new_handle);
+               if (ret < 0) {
+                       spin_lock(&file_priv->table_lock);
+-                      idr_remove(&file_priv->object_idr, handle);
++                      idr_remove(&file_priv->object_idr, new_handle);
+                       idr_replace(&file_priv->object_idr, obj, args->handle);
+                       spin_unlock(&file_priv->table_lock);
+                       goto out_unlock;
+@@ -1068,14 +1065,12 @@ int drm_gem_change_handle_ioctl(struct d
+       spin_lock(&file_priv->table_lock);
+       idr_remove(&file_priv->object_idr, args->handle);
+-      idrobj = idr_replace(&file_priv->object_idr, obj, handle);
++      obj = idr_replace(&file_priv->object_idr, obj, new_handle);
+       spin_unlock(&file_priv->table_lock);
+-      WARN_ON(idrobj != NULL);
++      WARN_ON(obj != NULL);
+ out_unlock:
+       mutex_unlock(&file_priv->prime.lock);
+-out:
+-      drm_gem_object_put(obj);
+       return ret;
+ }
+--- a/drivers/gpu/drm/drm_ioctl.c
++++ b/drivers/gpu/drm/drm_ioctl.c
+@@ -660,7 +660,8 @@ static const struct drm_ioctl_desc drm_i
+       DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH),
+-      DRM_IOCTL_DEF(DRM_IOCTL_GEM_CHANGE_HANDLE, drm_gem_change_handle_ioctl, DRM_RENDER_ALLOW),
++      /* see drm_gem.c:drm_gem_change_handle_ioctl for why this is invalid */
++      DRM_IOCTL_DEF(DRM_IOCTL_GEM_CHANGE_HANDLE, drm_invalid_op, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, 0),
diff --git a/queue-7.0/drm-i915-fix-color-blob-reference-handling-in-intel_plane_state.patch b/queue-7.0/drm-i915-fix-color-blob-reference-handling-in-intel_plane_state.patch
new file mode 100644 (file)
index 0000000..c767aa5
--- /dev/null
@@ -0,0 +1,82 @@
+From 26eb7c0a7ab09d83eec833db6a5a2bc60b9d4d9a Mon Sep 17 00:00:00 2001
+From: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>
+Date: Mon, 1 Jun 2026 13:59:53 +0530
+Subject: drm/i915: Fix color blob reference handling in intel_plane_state
+
+From: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>
+
+commit 26eb7c0a7ab09d83eec833db6a5a2bc60b9d4d9a upstream.
+
+Take proper references for hw color blobs (degamma_lut, gamma_lut,
+ctm, lut_3d) in intel_plane_duplicate_state() and drop them in
+intel_plane_destroy_state().
+
+v2:
+- handle blobs in hw state clear
+
+Cc: <stable@vger.kernel.org> #v6.19+
+Fixes: 3b7476e786c2 ("drm/i915/color: Add framework to program PRE/POST CSC LUT")
+Fixes: a78f1b6baf4d ("drm/i915/color: Add framework to program CSC")
+Fixes: 65db7a1f9cf7 ("drm/i915/color: Add 3D LUT to color pipeline")
+Reviewed-by: Pranay Samala <pranay.samala@intel.com> #v1
+Reviewed-by: Uma Shankar <uma.shankar@intel.com>
+Signed-off-by: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>
+Signed-off-by: Uma Shankar <uma.shankar@intel.com>
+Link: https://patch.msgid.link/20260601082953.128539-4-chaitanya.kumar.borah@intel.com
+(cherry picked from commit c6eea1925154b6697fe22b217faab9bb30635e6b)
+Signed-off-by: Tvrtko Ursulin <tursulin@ursulin.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/display/intel_plane.c |   27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+--- a/drivers/gpu/drm/i915/display/intel_plane.c
++++ b/drivers/gpu/drm/i915/display/intel_plane.c
+@@ -144,6 +144,15 @@ intel_plane_duplicate_state(struct drm_p
+       if (intel_state->hw.fb)
+               drm_framebuffer_get(intel_state->hw.fb);
++      if (intel_state->hw.degamma_lut)
++              drm_property_blob_get(intel_state->hw.degamma_lut);
++      if (intel_state->hw.gamma_lut)
++              drm_property_blob_get(intel_state->hw.gamma_lut);
++      if (intel_state->hw.ctm)
++              drm_property_blob_get(intel_state->hw.ctm);
++      if (intel_state->hw.lut_3d)
++              drm_property_blob_get(intel_state->hw.lut_3d);
++
+       return &intel_state->uapi;
+ }
+@@ -167,6 +176,16 @@ intel_plane_destroy_state(struct drm_pla
+       __drm_atomic_helper_plane_destroy_state(&plane_state->uapi);
+       if (plane_state->hw.fb)
+               drm_framebuffer_put(plane_state->hw.fb);
++
++      if (plane_state->hw.degamma_lut)
++              drm_property_blob_put(plane_state->hw.degamma_lut);
++      if (plane_state->hw.gamma_lut)
++              drm_property_blob_put(plane_state->hw.gamma_lut);
++      if (plane_state->hw.ctm)
++              drm_property_blob_put(plane_state->hw.ctm);
++      if (plane_state->hw.lut_3d)
++              drm_property_blob_put(plane_state->hw.lut_3d);
++
+       kfree(plane_state);
+ }
+@@ -317,6 +336,14 @@ static void intel_plane_clear_hw_state(s
+ {
+       if (plane_state->hw.fb)
+               drm_framebuffer_put(plane_state->hw.fb);
++      if (plane_state->hw.degamma_lut)
++              drm_property_blob_put(plane_state->hw.degamma_lut);
++      if (plane_state->hw.gamma_lut)
++              drm_property_blob_put(plane_state->hw.gamma_lut);
++      if (plane_state->hw.ctm)
++              drm_property_blob_put(plane_state->hw.ctm);
++      if (plane_state->hw.lut_3d)
++              drm_property_blob_put(plane_state->hw.lut_3d);
+       memset(&plane_state->hw, 0, sizeof(plane_state->hw));
+ }
diff --git a/queue-7.0/mm-cma-fix-reserved-page-leak-on-activation-failure.patch b/queue-7.0/mm-cma-fix-reserved-page-leak-on-activation-failure.patch
new file mode 100644 (file)
index 0000000..a616859
--- /dev/null
@@ -0,0 +1,68 @@
+From 00739e4dd46dde2b39dd9dd19a27e3c8af4ca0d0 Mon Sep 17 00:00:00 2001
+From: Muchun Song <songmuchun@bytedance.com>
+Date: Sat, 23 May 2026 14:01:23 +0800
+Subject: mm/cma: fix reserved page leak on activation failure
+
+From: Muchun Song <songmuchun@bytedance.com>
+
+commit 00739e4dd46dde2b39dd9dd19a27e3c8af4ca0d0 upstream.
+
+If cma_activate_area() fails after allocating only part of the range
+bitmaps, the cleanup path still has to release the reserved pages when
+CMA_RESERVE_PAGES_ON_ERROR is clear.
+
+That is still worth doing even in this __init path.  A bitmap_zalloc()
+failure does not necessarily mean the system cannot make further progress:
+freeing the reserved CMA pages can return a substantial amount of memory
+to the buddy allocator and may relieve the temporary memory shortage that
+caused the allocation failure in the first place.
+
+However, the cleanup path currently uses the bitmap-freeing bound for page
+release as well.  That is only correct for ranges whose bitmap allocation
+already succeeded.  The failed range and all later ranges still keep their
+reserved pages, so a partial bitmap allocation failure can permanently
+leak them.
+
+Fix this by releasing reserved pages for all ranges.  Use the saved
+early_pfn[] value for ranges whose bitmap allocation already succeeded and
+for the failed range, and use cmr->early_pfn for later ranges whose bitmap
+allocation was never attempted.
+
+Link: https://lore.kernel.org/20260523060123.2207992-1-songmuchun@bytedance.com
+Fixes: c009da4258f9 ("mm, cma: support multiple contiguous ranges, if requested")
+Signed-off-by: Muchun Song <songmuchun@bytedance.com>
+Reviewed-by: Oscar Salvador (SUSE) <osalvador@kernel.org>
+Acked-by: Usama Arif <usama.arif@linux.dev>
+Cc: David Hildenbrand <david@kernel.org>
+Cc: Frank van der Linden <fvdl@google.com>
+Cc: Liam R. Howlett <liam@infradead.org>
+Cc: Lorenzo Stoakes <ljs@kernel.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/cma.c |    7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/mm/cma.c
++++ b/mm/cma.c
+@@ -187,10 +187,13 @@ cleanup:
+       /* Expose all pages to the buddy, they are useless for CMA. */
+       if (!test_bit(CMA_RESERVE_PAGES_ON_ERROR, &cma->flags)) {
+-              for (r = 0; r < allocrange; r++) {
++              for (r = 0; r < cma->nranges; r++) {
++                      unsigned long start_pfn;
++
+                       cmr = &cma->ranges[r];
++                      start_pfn = r <= allocrange ? early_pfn[r] : cmr->early_pfn;
+                       end_pfn = cmr->base_pfn + cmr->count;
+-                      for (pfn = early_pfn[r]; pfn < end_pfn; pfn++)
++                      for (pfn = start_pfn; pfn < end_pfn; pfn++)
+                               free_reserved_page(pfn_to_page(pfn));
+               }
+       }
diff --git a/queue-7.0/mm-cma_debug-fix-invalid-accesses-for-inactive-cma-areas.patch b/queue-7.0/mm-cma_debug-fix-invalid-accesses-for-inactive-cma-areas.patch
new file mode 100644 (file)
index 0000000..bb791f9
--- /dev/null
@@ -0,0 +1,62 @@
+From c0ca59beb5252ea2bd4fdaef009d003dedc2030e Mon Sep 17 00:00:00 2001
+From: Muchun Song <songmuchun@bytedance.com>
+Date: Wed, 20 May 2026 14:10:25 +0800
+Subject: mm/cma_debug: fix invalid accesses for inactive CMA areas
+
+From: Muchun Song <songmuchun@bytedance.com>
+
+commit c0ca59beb5252ea2bd4fdaef009d003dedc2030e upstream.
+
+cma_activate_area() can fail after allocating range bitmaps.  Its cleanup
+path frees those bitmaps, but only clears cma->count and
+cma->available_count.  It leaves cma->nranges and each range's count in
+place, so cma_debugfs_init() can still register debugfs files for an area
+that never activated successfully.
+
+That exposes two problems.  Reading the bitmap file can make debugfs walk
+a freed range bitmap and trigger an invalid memory access.  Reading
+maxchunk can also take cma->lock even though that lock is initialized only
+on the successful activation path.
+
+Fix this by creating debugfs entries only for CMA areas that reached
+CMA_ACTIVATED.
+
+c009da4258f9 introduced the invalid access to bitmap file.  2e32b947606d
+introduced the invalid access to cma->lock.  This change applies to both
+issues.  So I added two Fixes tags.
+
+Link: https://lore.kernel.org/20260520061025.3971821-1-songmuchun@bytedance.com
+Fixes: c009da4258f9 ("mm, cma: support multiple contiguous ranges, if requested")
+Fixes: 2e32b947606d ("mm: cma: add functions to get region pages counters")
+Signed-off-by: Muchun Song <songmuchun@bytedance.com>
+Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
+Acked-by: Oscar Salvador (SUSE) <osalvador@kernel.org>
+Acked-by: David Hildenbrand (Arm) <david@kernel.org>
+Cc: Dmitry Safonov <0x7f454c46@gmail.com>
+Cc: Frank van der Linden <fvdl@google.com>
+Cc: Liam R. Howlett <liam@infradead.org>
+Cc: Lorenzo Stoakes <ljs@kernel.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Michal Nazarewicz <mina86@mina86.com>
+Cc: Stefan Strogin <stefan.strogin@gmail.com>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/cma_debug.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/mm/cma_debug.c
++++ b/mm/cma_debug.c
+@@ -205,7 +205,8 @@ static int __init cma_debugfs_init(void)
+       cma_debugfs_root = debugfs_create_dir("cma", NULL);
+       for (i = 0; i < cma_area_count; i++)
+-              cma_debugfs_add_one(&cma_areas[i], cma_debugfs_root);
++              if (test_bit(CMA_ACTIVATED, &cma_areas[i].flags))
++                      cma_debugfs_add_one(&cma_areas[i], cma_debugfs_root);
+       return 0;
+ }
diff --git a/queue-7.0/mm-damon-lru_sort-handle-ctx-allocation-failure.patch b/queue-7.0/mm-damon-lru_sort-handle-ctx-allocation-failure.patch
new file mode 100644 (file)
index 0000000..01111d8
--- /dev/null
@@ -0,0 +1,39 @@
+From ab04340b5ae5d52c1d46b750538febcde9d889e7 Mon Sep 17 00:00:00 2001
+From: SeongJae Park <sj@kernel.org>
+Date: Thu, 28 May 2026 17:01:03 -0700
+Subject: mm/damon/lru_sort: handle ctx allocation failure
+
+From: SeongJae Park <sj@kernel.org>
+
+commit ab04340b5ae5d52c1d46b750538febcde9d889e7 upstream.
+
+DAMON_LRU_SORT allocates the damon_ctx object for its kdamond in its init
+function.  damon_lru_sort_enabled_store() wrongly assumes the allocation
+will always succeed once tried.  If the damon_ctx allocation was failed,
+therefore, code execution reaches to damon_commit_ctx() while 'ctx' is
+NULL.  As a result, it dereferences the NULL 'ctx' pointer.  Avoid the
+NULL dereference by returning -ENOMEM if 'ctx' is NULL.
+
+Link: https://lore.kernel.org/20260529000104.7006-3-sj@kernel.org
+Fixes: c4a8e662c839 ("mm/damon/lru_sort: use damon_initialized()")
+Signed-off-by: SeongJae Park <sj@kernel.org>
+Cc: <stable@vger.kernel.org> # 6.18.x
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/damon/lru_sort.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/mm/damon/lru_sort.c
++++ b/mm/damon/lru_sort.c
+@@ -442,6 +442,10 @@ static int damon_lru_sort_enabled_store(
+       if (!damon_initialized())
+               return 0;
++      /* damon_modules_new_paddr_ctx_target() in the init function failed. */
++      if (!ctx)
++              return -ENOMEM;
++
+       return damon_lru_sort_turn(enabled);
+ }
diff --git a/queue-7.0/mm-damon-reclaim-handle-ctx-allocation-failure.patch b/queue-7.0/mm-damon-reclaim-handle-ctx-allocation-failure.patch
new file mode 100644 (file)
index 0000000..aca75cc
--- /dev/null
@@ -0,0 +1,53 @@
+From 7e2ed8a29427af534bf2cb9b8bc51762b8b6e654 Mon Sep 17 00:00:00 2001
+From: SeongJae Park <sj@kernel.org>
+Date: Thu, 28 May 2026 17:01:02 -0700
+Subject: mm/damon/reclaim: handle ctx allocation failure
+
+From: SeongJae Park <sj@kernel.org>
+
+commit 7e2ed8a29427af534bf2cb9b8bc51762b8b6e654 upstream.
+
+Patch series "mm/damon/{reclaim,lru_sort}: handle ctx allocation failures".
+
+DAMON_RECLAIM and DAMON_LRU_SORT could dereference NULL pointers if their
+damon_ctx object allocations fail.  The bugs are expected to happen
+infrequently because the allocations are arguably too small to fail on
+common setups.  But theoretically they are possible and the consequences
+are bad.  Fix those.
+
+The issues were discovered [1] by Sashiko.
+
+
+This patch (of 2):
+
+DAMON_RECLAIM allocates the damon_ctx object for its kdamond in its init
+function.  damon_reclaim_enabled_store() wrongly assumes the allocation
+will always succeed once tried.  If the damon_ctx allocation was failed,
+therefore, code execution reaches to damon_commit_ctx() while 'ctx' is
+NULL.  As a result, it dereferences the NULL 'ctx' pointer.  Avoid the
+NULL dereference by returning -ENOMEM if 'ctx' is NULL.
+
+Link: https://lore.kernel.org/20260529000104.7006-2-sj@kernel.org
+Link: https://lore.kernel.org/20260419014800.877-1-sj@kernel.org [1]
+Fixes: 3f7a914ab9a5 ("mm/damon/reclaim: use damon_initialized()")
+Signed-off-by: SeongJae Park <sj@kernel.org>
+Cc: <stable@vger.kernel.org> # 6.18.x
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/damon/reclaim.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/mm/damon/reclaim.c
++++ b/mm/damon/reclaim.c
+@@ -344,6 +344,10 @@ static int damon_reclaim_enabled_store(c
+       if (!damon_initialized())
+               return 0;
++      /* damon_modules_new_paddr_ctx_target() in the init function failed. */
++      if (!ctx)
++              return -ENOMEM;
++
+       return damon_reclaim_turn(enabled);
+ }
diff --git a/queue-7.0/mm-huge_memory-use-correct-flags-for-device-private-pmd-entry.patch b/queue-7.0/mm-huge_memory-use-correct-flags-for-device-private-pmd-entry.patch
new file mode 100644 (file)
index 0000000..3027155
--- /dev/null
@@ -0,0 +1,179 @@
+From 43e7f189769c512c843184a8a5892ac779a6bd90 Mon Sep 17 00:00:00 2001
+From: Lorenzo Stoakes <ljs@kernel.org>
+Date: Mon, 1 Jun 2026 09:30:44 +0100
+Subject: mm/huge_memory: use correct flags for device private PMD entry
+
+From: Lorenzo Stoakes <ljs@kernel.org>
+
+commit 43e7f189769c512c843184a8a5892ac779a6bd90 upstream.
+
+Commit 65edfda6f3f2 ("mm/rmap: extend rmap and migration support
+device-private entries") updated set_pmd_migration_entry() to use
+pmdp_huge_get_and_clear() in the softleaf case, but made no further
+adjustments to the function itself.
+
+Therefore this function continues to incorrectly use pmd_write(),
+pmd_soft_dirty() and pmd_uffd_wp() to determine whether the installed
+migration entry should be marked writable, softdirty or uffd-wp
+respectively.
+
+Whilst all are incorrect, the most problematic of these is pmd_write(), as
+this can lead to corrupted rmap state.
+
+On x86-64 _PAGE_SWP_SOFT_DIRTY is aliased to _PAGE_RW.  So calling
+pmd_write() on a softleaf will return the softdirty state encoded in the
+entry, assuming CONFIG_MEM_SOFT_DIRTY was enabled.
+
+This was observed when running the hmm.hmm_device_private.anon_write_child
+selftest:
+
+1. The test faults in a range then migrates it such that a device-private
+   THP range is established.
+
+2. The parent then migrates it to a device-private writable PMD entry whose
+   folio is entirely AnonExclusive with entire_mapcount=1, softdirty set
+   (accidentally correct write state).
+
+3. The parent forks and the PMD entries are set to device-private read only
+   entries, entire_mapcount=2, softdirty still set.
+
+4. [BUG] The child writes to the range then migrates to RAM - intending to
+   install non-writable migration entries - but replacing parent and child
+   PMD mappings with WRITABLE entries due to misinterpreting the softdirty
+   bit.
+
+5. In remove_migration_pmd(), if !softleaf_is_migration_read(entry) we
+   set the RMAP_EXCLUSIVE flag when calling folio_add_anon_rmap_pmd() for
+   both parent and child, which are therefore AnonExclusive.
+
+6. [SPLAT] Child sets migrated folio entire_mapcount=1, parent sets
+   entire_mapcount=2 and we end up with an AnonExclusive folio with
+   entire_mapcount=2! Assert fires in __folio_add_anon_rmap():
+
+               VM_WARN_ON_FOLIO(folio_test_large(folio) &&
+                                folio_entire_mapcount(folio) > 1 &&
+                                PageAnonExclusive(cur_page), folio)
+
+This patch fixes the issue by correctly referencing the softleaf entry
+fields for writable, softdirty and uffd-wp in set_pmd_migration_entry().
+
+It also only updates A/D flags if the entry is present as these are
+otherwise not meaningful for a softleaf entry.
+
+This patch also flips the if (!present) { ...  } else { ...  } logic in
+set_pmd_migration_entry() so it is easier to understand, and adds some
+comments to make things clearer.
+
+I was able to bisect this to commit 775465fd26a3 ("lib/test_hmm: add zone
+device private THP test infrastructure") which first exposes this bug as
+it was the commit that permitted test_hmm to generate the test.
+
+However commit 65edfda6f3f2 ("mm/rmap: extend rmap and migration support
+device-private entries") is the commit that actually enabled this
+behaviour.
+
+Link: https://lore.kernel.org/20260601083044.57132-1-ljs@kernel.org
+Fixes: 65edfda6f3f2 ("mm/rmap: extend rmap and migration support device-private entries")
+Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
+Acked-by: David Hildenbrand (Arm) <david@kernel.org>
+Reviewed-by: Dev Jain <dev.jain@arm.com>
+Reviewed-by: Balbir Singh <balbirs@nvidia.com>
+Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
+Reviewed-by: Oscar Salvador (SUSE) <osalvador@kernel.org>
+Reviewed-by: Barry Song <baohua@kernel.org>
+Reviewed-by: Lance Yang <lance.yang@linux.dev>
+Reviewed-by: Zi Yan <ziy@nvidia.com>
+Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
+Cc: Liam R. Howlett <liam@infradead.org>
+Cc: Nico Pache <npache@redhat.com>
+Cc: Ryan Roberts <ryan.roberts@arm.com>
+Cc: SeongJae Park <sj@kernel.org>
+Cc: Wei Yang <richard.weiyang@gmail.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/huge_memory.c |   45 +++++++++++++++++++++++++++++++++------------
+ 1 file changed, 33 insertions(+), 12 deletions(-)
+
+--- a/mm/huge_memory.c
++++ b/mm/huge_memory.c
+@@ -4873,7 +4873,7 @@ int set_pmd_migration_entry(struct page_
+       struct vm_area_struct *vma = pvmw->vma;
+       struct mm_struct *mm = vma->vm_mm;
+       unsigned long address = pvmw->address;
+-      bool anon_exclusive;
++      bool anon_exclusive, present, writable, softdirty, uffd_wp;
+       pmd_t pmdval;
+       swp_entry_t entry;
+       pmd_t pmdswp;
+@@ -4881,12 +4881,26 @@ int set_pmd_migration_entry(struct page_
+       if (!(pvmw->pmd && !pvmw->pte))
+               return 0;
+-      flush_cache_range(vma, address, address + HPAGE_PMD_SIZE);
+-      if (unlikely(!pmd_present(*pvmw->pmd)))
+-              pmdval = pmdp_huge_get_and_clear(vma->vm_mm, address, pvmw->pmd);
+-      else
++      present = pmd_present(*pvmw->pmd);
++      if (likely(present)) {
++              flush_cache_range(vma, address, address + HPAGE_PMD_SIZE);
++
+               pmdval = pmdp_invalidate(vma, address, pvmw->pmd);
++              writable = pmd_write(pmdval);
++              softdirty = pmd_soft_dirty(pmdval);
++              uffd_wp = pmd_uffd_wp(pmdval);
++      } else {
++              softleaf_t old_entry;
++
++              pmdval = pmdp_huge_get_and_clear(vma->vm_mm, address, pvmw->pmd);
++              old_entry = softleaf_from_pmd(pmdval);
++
++              writable = softleaf_is_device_private_write(old_entry);
++              softdirty = pmd_swp_soft_dirty(pmdval);
++              uffd_wp = pmd_swp_uffd_wp(pmdval);
++      }
++
+       /* See folio_try_share_anon_rmap_pmd(): invalidate PMD first. */
+       anon_exclusive = folio_test_anon(folio) && PageAnonExclusive(page);
+       if (anon_exclusive && folio_try_share_anon_rmap_pmd(folio, page)) {
+@@ -4894,24 +4908,31 @@ int set_pmd_migration_entry(struct page_
+               return -EBUSY;
+       }
+-      if (pmd_dirty(pmdval))
+-              folio_mark_dirty(folio);
+-      if (pmd_write(pmdval))
++      /* Determine type of migration entry. */
++      if (writable)
+               entry = make_writable_migration_entry(page_to_pfn(page));
+       else if (anon_exclusive)
+               entry = make_readable_exclusive_migration_entry(page_to_pfn(page));
+       else
+               entry = make_readable_migration_entry(page_to_pfn(page));
+-      if (pmd_young(pmdval))
++
++      /* Set A/D bits as necessary. */
++      if (present && pmd_young(pmdval))
+               entry = make_migration_entry_young(entry);
+-      if (pmd_dirty(pmdval))
++      if (present && pmd_dirty(pmdval)) {
++              folio_mark_dirty(folio);
+               entry = make_migration_entry_dirty(entry);
++      }
++
++      /* Set PMD. */
+       pmdswp = swp_entry_to_pmd(entry);
+-      if (pmd_soft_dirty(pmdval))
++      if (softdirty)
+               pmdswp = pmd_swp_mksoft_dirty(pmdswp);
+-      if (pmd_uffd_wp(pmdval))
++      if (uffd_wp)
+               pmdswp = pmd_swp_mkuffd_wp(pmdswp);
+       set_pmd_at(mm, address, pvmw->pmd, pmdswp);
++
++      /* Migration entry installed: cleanup rmap, folio. */
+       folio_remove_rmap_pmd(folio, page, vma);
+       folio_put(folio);
+       trace_set_migration_pmd(address, pmd_val(pmdswp));
diff --git a/queue-7.0/mm-hugetlb-avoid-false-positive-lockdep-assertion.patch b/queue-7.0/mm-hugetlb-avoid-false-positive-lockdep-assertion.patch
new file mode 100644 (file)
index 0000000..531de0e
--- /dev/null
@@ -0,0 +1,249 @@
+From b4aea43cd37afad714b5684fe9fdfcb0e78dba26 Mon Sep 17 00:00:00 2001
+From: Lorenzo Stoakes <ljs@kernel.org>
+Date: Wed, 13 May 2026 09:56:58 +0100
+Subject: mm/hugetlb: avoid false positive lockdep assertion
+
+From: Lorenzo Stoakes <ljs@kernel.org>
+
+commit b4aea43cd37afad714b5684fe9fdfcb0e78dba26 upstream.
+
+Commit 081056dc00a2 ("mm/hugetlb: unshare page tables during VMA split,
+not before") changed the locking model around hugetlbfs PMD unsharing on
+VMA split, but did not update the function which asserts the locks,
+hugetlb_vma_assert_locked().
+
+This function asserts that either the hugetlb VMA lock is held (if a
+shared mapping) or that the reservation map lock is held (if private).
+
+If you get an unfortunate race between something which results in one of
+these locks being released and a hugetlb VMA split and you have
+CONFIG_LOCKDEP enabled, you can therefore see a false positive assertion
+arise when there is in fact no issue.
+
+Since this change introduced a new take_locks parameter to
+hugetlb_unshare_pmds(), which, when set to false, indicates that locking
+is sufficient, simply pass this to the unsharing logic and predicate the
+lock assertions on this.
+
+This is safe, as we already asserted the file rmap lock and the VMA write
+lock prior to this (implying exclusive mmap write lock), so we cannot be
+raced by either rmap or page fault page table walkers which the asserted
+locks are intended to protect against (we don't mind GUP-fast).
+
+Separate out huge_pmd_unshare() into __huge_pmd_unshare() to add a
+check_locks parameter, and update hugetlb_unshare_pmds() to pass this
+parameter to it.
+
+This leaves all other callers of huge_pmd_unshare() still correctly
+asserting the locks.
+
+The below reproducer will trigger the assert in a kernel with
+CONFIG_LOCKDEP enabled by racing process teardown (which will release the
+hugetlb lock) against a hugetlb split.
+
+void execute_one(void)
+{
+       void *ptr;
+       pid_t pid;
+
+       /*
+        * Create a hugetlb mapping spanning a PUD entry.
+        *
+        * We force the hugetlb page allocation with populate and
+        * noreserve.
+        *
+        * |---------------------|
+        * |                     |
+        * |---------------------|
+        * 0                 PUD boundary
+        */
+       ptr = mmap(0, PUD_SIZE, PROT_READ | PROT_WRITE,
+                  MAP_FIXED | MAP_SHARED | MAP_ANON |
+                  MAP_NORESERVE | MAP_HUGETLB | MAP_POPULATE,
+                  -1, 0);
+       if (ptr == MAP_FAILED) {
+               perror("mmap");
+               exit(EXIT_FAILURE);
+       }
+
+       /*
+        * Fork but with a bogus stack pointer so we try to execute code in
+        * a non-VM_EXEC VMA, causing segfault + teardown via exit_mmap().
+        *
+        * The clone will cause PMD page table sharing between the
+        * processes first via:
+        * copy_process() -> ... -> huge_pte_alloc() -> huge_pmd_share()
+        *
+        * Then tear down and release the hugetlb 'VMA' lock via:
+        * exit_mmap() -> ... -> vma_close() -> hugetlb_vma_lock_free()
+        */
+       pid = syscall(__NR_clone, 0, 2 * PMD_SIZE, 0, 0, 0);
+       if (pid < 0) {
+               perror("clone");
+               exit(EXIT_FAILURE);
+       } if (pid == 0) {
+               /* Pop stack... */
+               return;
+       }
+
+       /*
+        * We are the parent process.
+        *
+        * Race the child process's teardown with a PMD unshare.
+        *
+        * We do this by triggering:
+        *
+        * __split_vma() -> hugetlb_split() -> hugetlb_unshare_pmds()
+        *
+        * Which, importantly, doesn't hold the hugetlb VMA lock (nor can
+        * it), meaning we assert in hugetlb_vma_assert_locked().
+        *
+        *            .
+        * |----------.----------|
+        * |          .          |
+        * |----------.----------|
+        * 0          .     PUD boundary
+        */
+       mmap(0, PUD_SIZE / 2, PROT_READ | PROT_WRITE,
+            MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
+}
+
+int main(void)
+{
+       int i;
+
+       /* Kick off fork children. */
+       for (i = 0; i < NUM_FORKS; i++) {
+               pid_t pid = fork();
+
+               if (pid < 0) {
+                       perror("fork");
+                       exit(EXIT_FAILURE);
+               }
+
+               /* Fork children do their work and exit. */
+               if (!pid) {
+                       int j;
+
+                       for (j = 0; j < NUM_ITERS; j++)
+                               execute_one();
+                       return EXIT_SUCCESS;
+               }
+       }
+
+       /* If we succeeded, wait on children. */
+       for (i = 0; i < NUM_FORKS; i++)
+               wait(NULL);
+
+       return EXIT_SUCCESS;
+}
+
+[ljs@kernel.org: account for the !CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING case]
+  Link: https://lore.kernel.org/agWZsPGYid08uU6O@lucifer
+Link: https://lore.kernel.org/20260513085658.45264-1-ljs@kernel.org
+Fixes: 081056dc00a2 ("mm/hugetlb: unshare page tables during VMA split, not before")
+Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
+Acked-by: David Hildenbrand (Arm) <david@kernel.org>
+Acked-by: Oscar Salvador <osalvador@suse.de>
+Cc: Jann Horn <jannh@google.com>
+Cc: Muchun Song <muchun.song@linux.dev>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/hugetlb.c |   56 +++++++++++++++++++++++++++++++++++++-------------------
+ 1 file changed, 37 insertions(+), 19 deletions(-)
+
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -118,6 +118,9 @@ static int hugetlb_acct_memory(struct hs
+ static void hugetlb_vma_lock_free(struct vm_area_struct *vma);
+ static void hugetlb_vma_lock_alloc(struct vm_area_struct *vma);
+ static void __hugetlb_vma_unlock_write_free(struct vm_area_struct *vma);
++static int __huge_pmd_unshare(struct mmu_gather *tlb,
++              struct vm_area_struct *vma, unsigned long addr, pte_t *ptep,
++              bool check_locks);
+ static void hugetlb_unshare_pmds(struct vm_area_struct *vma,
+               unsigned long start, unsigned long end, bool take_locks);
+ static struct resv_map *vma_resv_map(struct vm_area_struct *vma);
+@@ -6910,6 +6913,31 @@ out:
+       return pte;
+ }
++static int __huge_pmd_unshare(struct mmu_gather *tlb,
++              struct vm_area_struct *vma, unsigned long addr, pte_t *ptep,
++              bool check_locks)
++{
++      unsigned long sz = huge_page_size(hstate_vma(vma));
++      struct mm_struct *mm = vma->vm_mm;
++      pgd_t *pgd = pgd_offset(mm, addr);
++      p4d_t *p4d = p4d_offset(pgd, addr);
++      pud_t *pud = pud_offset(p4d, addr);
++
++      if (sz != PMD_SIZE)
++              return 0;
++      if (!ptdesc_pmd_is_shared(virt_to_ptdesc(ptep)))
++              return 0;
++      i_mmap_assert_write_locked(vma->vm_file->f_mapping);
++      if (check_locks)
++              hugetlb_vma_assert_locked(vma);
++      pud_clear(pud);
++
++      tlb_unshare_pmd_ptdesc(tlb, virt_to_ptdesc(ptep), addr);
++
++      mm_dec_nr_pmds(mm);
++      return 1;
++}
++
+ /**
+  * huge_pmd_unshare - Unmap a pmd table if it is shared by multiple users
+  * @tlb: the current mmu_gather.
+@@ -6929,24 +6957,7 @@ out:
+ int huge_pmd_unshare(struct mmu_gather *tlb, struct vm_area_struct *vma,
+               unsigned long addr, pte_t *ptep)
+ {
+-      unsigned long sz = huge_page_size(hstate_vma(vma));
+-      struct mm_struct *mm = vma->vm_mm;
+-      pgd_t *pgd = pgd_offset(mm, addr);
+-      p4d_t *p4d = p4d_offset(pgd, addr);
+-      pud_t *pud = pud_offset(p4d, addr);
+-
+-      if (sz != PMD_SIZE)
+-              return 0;
+-      if (!ptdesc_pmd_is_shared(virt_to_ptdesc(ptep)))
+-              return 0;
+-      i_mmap_assert_write_locked(vma->vm_file->f_mapping);
+-      hugetlb_vma_assert_locked(vma);
+-      pud_clear(pud);
+-
+-      tlb_unshare_pmd_ptdesc(tlb, virt_to_ptdesc(ptep), addr);
+-
+-      mm_dec_nr_pmds(mm);
+-      return 1;
++      return __huge_pmd_unshare(tlb, vma, addr, ptep, /*check_locks=*/true);
+ }
+ /*
+@@ -6980,6 +6991,13 @@ pte_t *huge_pmd_share(struct mm_struct *
+       return NULL;
+ }
++static int __huge_pmd_unshare(struct mmu_gather *tlb,
++              struct vm_area_struct *vma, unsigned long addr, pte_t *ptep,
++              bool check_locks)
++{
++      return 0;
++}
++
+ int huge_pmd_unshare(struct mmu_gather *tlb, struct vm_area_struct *vma,
+               unsigned long addr, pte_t *ptep)
+ {
+@@ -7277,7 +7295,7 @@ static void hugetlb_unshare_pmds(struct
+               if (!ptep)
+                       continue;
+               ptl = huge_pte_lock(h, mm, ptep);
+-              huge_pmd_unshare(&tlb, vma, address, ptep);
++              __huge_pmd_unshare(&tlb, vma, address, ptep, take_locks);
+               spin_unlock(ptl);
+       }
+       huge_pmd_unshare_flush(&tlb, vma);
diff --git a/queue-7.0/mm-hugetlb-restore-reservation-on-error-in-hugetlb-folio-copy-paths.patch b/queue-7.0/mm-hugetlb-restore-reservation-on-error-in-hugetlb-folio-copy-paths.patch
new file mode 100644 (file)
index 0000000..f07d087
--- /dev/null
@@ -0,0 +1,68 @@
+From 40c81856e622a9dc59294a90d169ac07ea25b0b0 Mon Sep 17 00:00:00 2001
+From: David Carlier <devnexen@gmail.com>
+Date: Wed, 20 May 2026 05:49:12 +0100
+Subject: mm/hugetlb: restore reservation on error in hugetlb folio copy paths
+
+From: David Carlier <devnexen@gmail.com>
+
+commit 40c81856e622a9dc59294a90d169ac07ea25b0b0 upstream.
+
+Two sites in mm/hugetlb.c allocate a hugetlb folio via
+alloc_hugetlb_folio() (consuming a VMA reservation) and then call
+copy_user_large_folio(), which became int-returning in commit 1cb9dc4b475c
+("mm: hwpoison: support recovery from HugePage copy-on-write faults") and
+can now fail (e.g.  -EHWPOISON on a hwpoisoned source page).  On the
+failure path, folio_put() restores the global hugetlb pool count through
+free_huge_folio(), but the per-VMA reservation map entry is left marked
+consumed:
+
+  - hugetlb_mfill_atomic_pte() resubmission path (UFFDIO_COPY)
+  - copy_hugetlb_page_range() fork-time CoW path when
+    hugetlb_try_dup_anon_rmap() fails (rare: pinned hugetlb anon
+    folio under fork)
+
+User-visible effect: on UFFDIO_COPY into a private hugetlb VMA where the
+resubmission copy fails, the reservation for that address is leaked from
+the VMA's reserve map.  A subsequent fault at the same address takes the
+no-reservation path, and under hugetlb pool pressure the task is SIGBUSed
+at an address it had previously reserved.  The fork-time CoW path leaks
+the same way in the child VMA's reserve map, though it requires the much
+rarer combination of pinned hugetlb anon page + hwpoisoned source.
+
+Add the missing restore_reserve_on_error() call before folio_put() on both
+error paths.
+
+Link: https://lore.kernel.org/20260520044912.6751-1-devnexen@gmail.com
+Fixes: 1cb9dc4b475c ("mm: hwpoison: support recovery from HugePage copy-on-write faults")
+Signed-off-by: David Carlier <devnexen@gmail.com>
+Reviewed-by: Muchun Song <muchun.song@linux.dev>
+Cc: David Hildenbrand <david@kernel.org>
+Cc: Mina Almasry <almasrymina@google.com>
+Cc: Muchun Song <muchun.song@linux.dev>
+Cc: Oscar Salvador <osalvador@suse.de>
+Cc: yuehaibing <yuehaibing@huawei.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/hugetlb.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -4996,6 +4996,7 @@ again:
+                                                           addr, dst_vma);
+                               folio_put(pte_folio);
+                               if (ret) {
++                                      restore_reserve_on_error(h, dst_vma, addr, new_folio);
+                                       folio_put(new_folio);
+                                       break;
+                               }
+@@ -6292,6 +6293,7 @@ int hugetlb_mfill_atomic_pte(pte_t *dst_
+               folio_put(*foliop);
+               *foliop = NULL;
+               if (ret) {
++                      restore_reserve_on_error(h, dst_vma, dst_addr, folio);
+                       folio_put(folio);
+                       goto out;
+               }
diff --git a/queue-7.0/mm-list_lru-drain-before-clearing-xarray-entry-on-reparent.patch b/queue-7.0/mm-list_lru-drain-before-clearing-xarray-entry-on-reparent.patch
new file mode 100644 (file)
index 0000000..4d329ff
--- /dev/null
@@ -0,0 +1,86 @@
+From 98733f3f0becb1ae0701d021c1748e974e5fa55c Mon Sep 17 00:00:00 2001
+From: Shakeel Butt <shakeel.butt@linux.dev>
+Date: Mon, 1 Jun 2026 09:15:01 -0700
+Subject: mm/list_lru: drain before clearing xarray entry on reparent
+
+From: Shakeel Butt <shakeel.butt@linux.dev>
+
+commit 98733f3f0becb1ae0701d021c1748e974e5fa55c upstream.
+
+memcg_reparent_list_lrus() clears the dying memcg's xarray entry with
+xas_store(&xas, NULL) before reparenting its per-node lists into the
+parent.  This opens a window where a concurrent list_lru_del() arriving
+for the dying memcg sees xa_load() == NULL, walks to the parent in
+lock_list_lru_of_memcg(), takes the parent's per-node lock, and calls
+list_del_init() on an item still physically linked on the dying memcg's
+list.
+
+If another in-flight thread holds the dying memcg's per-node lock at the
+same moment (another list_lru_del, or a list_lru_walk_one running an
+isolate callback), both threads modify ->next/->prev pointers on the same
+physical list under different locks.  Adjacent items can corrupt each
+other's links.
+
+Fix it by reversing the order: reparent each per-node list and mark the
+child's list lru dead and then clear the xarray entry.  Any concurrent
+list_lru op that finds the still-set xarray entry either takes the dying
+memcg's per-node lock (synchronizing with the drain) or sees LONG_MIN and
+walks to the parent, where the items now live.
+
+Link: https://lore.kernel.org/20260601161501.1444829-1-shakeel.butt@linux.dev
+Fixes: fb56fdf8b9a2 ("mm/list_lru: split the lock to per-cgroup scope")
+Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev>
+Reported-by: Chris Mason <clm@fb.com>
+Reviewed-by: Kairui Song <kasong@tencent.com>
+Acked-by: Muchun Song <muchun.song@linux.dev>
+Cc: Dave Chinner <david@fromorbit.com>
+Cc: Johannes Weiner <hannes@cmpxchg.org>
+Cc: Roman Gushchin <roman.gushchin@linux.dev>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/list_lru.c |   21 ++++++++++++---------
+ 1 file changed, 12 insertions(+), 9 deletions(-)
+
+--- a/mm/list_lru.c
++++ b/mm/list_lru.c
+@@ -472,26 +472,29 @@ void memcg_reparent_list_lrus(struct mem
+       mutex_lock(&list_lrus_mutex);
+       list_for_each_entry(lru, &memcg_list_lrus, list) {
+               struct list_lru_memcg *mlru;
+-              XA_STATE(xas, &lru->xa, memcg->kmemcg_id);
+               /*
+-               * Lock the Xarray to ensure no on going list_lru_memcg
+-               * allocation and further allocation will see css_is_dying().
++               * css_is_dying() check in memcg_list_lru_alloc() avoids
++               * allocating a new mlru since CSS_DYING is already set for this
++               * memcg a rcu grace period ago.
+                */
+-              xas_lock_irq(&xas);
+-              mlru = xas_store(&xas, NULL);
+-              xas_unlock_irq(&xas);
++              mlru = xa_load(&lru->xa, memcg->kmemcg_id);
+               if (!mlru)
+                       continue;
+               /*
+-               * With Xarray value set to NULL, holding the lru lock below
+-               * prevents list_lru_{add,del,isolate} from touching the lru,
+-               * safe to reparent.
++               * Reparent each per-node list and mark the child dead
++               * (LONG_MIN) before clearing xarray entry otherwise a
++               * concurrent list_lru_del() may corrupt the list if it arrives
++               * after xarray clear but before reparenting as
++               * lock_list_lru_of_memcg will acquire parent's lock while the
++               * item is still on child's list.
+                */
+               for_each_node(i)
+                       memcg_reparent_list_lru_one(lru, i, &mlru->node[i], parent);
++              xa_erase_irq(&lru->xa, memcg->kmemcg_id);
++
+               /*
+                * Here all list_lrus corresponding to the cgroup are guaranteed
+                * to remain empty, we can safely free this lru, any further
diff --git a/queue-7.0/mm-mincore-handle-non-swap-entries-before-config_swap-guard.patch b/queue-7.0/mm-mincore-handle-non-swap-entries-before-config_swap-guard.patch
new file mode 100644 (file)
index 0000000..35ce072
--- /dev/null
@@ -0,0 +1,67 @@
+From 0c25b8734367574e21aeb8468c2e522713134da7 Mon Sep 17 00:00:00 2001
+From: Usama Arif <usama.arif@linux.dev>
+Date: Tue, 2 Jun 2026 10:22:47 -0700
+Subject: mm/mincore: handle non-swap entries before !CONFIG_SWAP guard
+
+From: Usama Arif <usama.arif@linux.dev>
+
+commit 0c25b8734367574e21aeb8468c2e522713134da7 upstream.
+
+mincore_swap() also fields migration/hwpoison entries (and shmem
+swapin-error entries), which can exist on !CONFIG_SWAP builds when
+CONFIG_MIGRATION or CONFIG_MEMORY_FAILURE is enabled.  The
+!IS_ENABLED(CONFIG_SWAP) guard ran before the non-swap-entry early return,
+so mincore_pte_range() can spuriously WARN and report these pages
+nonresident on !CONFIG_SWAP kernels.
+
+Move the guard below the non-swap-entry check so only true swap entries
+trip the WARN, and migration/hwpoison entries take the existing "uptodate
+/ non-shmem" path.
+
+Link: https://lore.kernel.org/20260602172247.279421-1-usama.arif@linux.dev
+Fixes: 1f2052755c15 ("mm/mincore: use a helper for checking the swap cache")
+Signed-off-by: Usama Arif <usama.arif@linux.dev>
+Reviewed-by: Pedro Falcato <pfalcato@suse.de>
+Reviewed-by: Kairui Song <kasong@tencent.com>
+Reviewed-by: Lorenzo Stoakes <ljs@kernel.org>
+Acked-by: Johannes Weiner <hannes@cmpxchg.org>
+Cc: Baoquan He <baoquan.he@linux.dev>
+Cc: Chris Li <chrisl@kernel.org>
+Cc: Jann Horn <jannh@google.com>
+Cc: Liam R. Howlett <liam@infradead.org>
+Cc: Rik van Riel <riel@surriel.com>
+Cc: Shakeel Butt <shakeel.butt@linux.dev>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/mincore.c |   10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/mm/mincore.c
++++ b/mm/mincore.c
+@@ -64,11 +64,6 @@ static unsigned char mincore_swap(swp_en
+       struct folio *folio = NULL;
+       unsigned char present = 0;
+-      if (!IS_ENABLED(CONFIG_SWAP)) {
+-              WARN_ON(1);
+-              return 0;
+-      }
+-
+       /*
+        * Shmem mapping may contain swapin error entries, which are
+        * absent. Page table may contain migration or hwpoison
+@@ -77,6 +72,11 @@ static unsigned char mincore_swap(swp_en
+       if (!softleaf_is_swap(entry))
+               return !shmem;
++      if (!IS_ENABLED(CONFIG_SWAP)) {
++              WARN_ON(1);
++              return 0;
++      }
++
+       /*
+        * Shmem mapping lookup is lockless, so we need to grab the swap
+        * device. mincore page table walk locks the PTL, and the swap
diff --git a/queue-7.0/mmc-core-fix-host-controller-programming-for-fixed-driver-type.patch b/queue-7.0/mmc-core-fix-host-controller-programming-for-fixed-driver-type.patch
new file mode 100644 (file)
index 0000000..8fe7f8c
--- /dev/null
@@ -0,0 +1,46 @@
+From 5a52c5701a67d5176eb1afbf1bdaf7d6dfeec597 Mon Sep 17 00:00:00 2001
+From: Kamal Dasu <kamal.dasu@broadcom.com>
+Date: Thu, 23 Apr 2026 15:18:55 -0400
+Subject: mmc: core: Fix host controller programming for fixed driver type
+
+From: Kamal Dasu <kamal.dasu@broadcom.com>
+
+commit 5a52c5701a67d5176eb1afbf1bdaf7d6dfeec597 upstream.
+
+When using the fixed-emmc-driver-type device tree property, the MMC core
+correctly selects the driver strength for the card but fails to program
+the host controller accordingly. This causes a mismatch where the card
+uses the specified driver type while the host controller defaults to
+Type B (since ios->drv_type remains zero).
+
+Split the driver type programming logic to handle both fixed and dynamic
+driver type selection paths. For fixed driver types, program the host
+controller with the selected drive_strength value. For dynamic selection,
+use the existing drv_type as before.
+
+This ensures both the eMMC device and host controller use matching driver
+strengths, preventing potential signal integrity issues.
+
+Fixes: 6186d06c519e ("mmc: parse new binding for eMMC fixed driver type")
+Signed-off-by: Kamal Dasu <kamal.dasu@broadcom.com>
+Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mmc/core/mmc.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/mmc/core/mmc.c
++++ b/drivers/mmc/core/mmc.c
+@@ -1371,7 +1371,9 @@ static void mmc_select_driver_type(struc
+       card->drive_strength = drive_strength;
+-      if (drv_type)
++      if (fixed_drv_type >= 0 && drive_strength)
++              mmc_set_driver_type(card->host, drive_strength);
++      else if (drv_type)
+               mmc_set_driver_type(card->host, drv_type);
+ }
diff --git a/queue-7.0/mmc-dw_mmc-rockchip-add-missing-private-data-for-very-old-controllers.patch b/queue-7.0/mmc-dw_mmc-rockchip-add-missing-private-data-for-very-old-controllers.patch
new file mode 100644 (file)
index 0000000..b0cd235
--- /dev/null
@@ -0,0 +1,69 @@
+From 1e9a4850afa0ceb63984fb1a9f3e86d0fc4fd18f Mon Sep 17 00:00:00 2001
+From: Heiko Stuebner <heiko@sntech.de>
+Date: Fri, 22 May 2026 20:43:07 +0200
+Subject: mmc: dw_mmc-rockchip: Add missing private data for very old controllers
+
+From: Heiko Stuebner <heiko@sntech.de>
+
+commit 1e9a4850afa0ceb63984fb1a9f3e86d0fc4fd18f upstream.
+
+The really old controllers (rk2928, rk3066, rk3188) do not support UHS
+speeds at all, and thus never handled phase data.
+
+For that reason it never had a parse_dt callback and no driver private
+data at all.
+
+Commit ff6f0286c896 ("mmc: dw_mmc-rockchip: Add memory clock auto-gating
+support") makes the private data sort of mandatory, because the init
+function checks whether phases are configured internally or through the
+clock controller.
+
+This results in the old SoCs then experiencing NULL-pointer dereferences
+when they try to access that private-data struct.
+
+While we could have if (priv) conditionals in all places, it's way less
+cluttery to just give the old types their private-data struct.
+
+Fixes: ff6f0286c896 ("mmc: dw_mmc-rockchip: Add memory clock auto-gating support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Acked-by: Shawn Lin <shawn.lin@rock-chips.com>
+Signed-off-by: Ulf Hansson <ulfh@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mmc/host/dw_mmc-rockchip.c |   17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+--- a/drivers/mmc/host/dw_mmc-rockchip.c
++++ b/drivers/mmc/host/dw_mmc-rockchip.c
+@@ -433,6 +433,22 @@ static int dw_mci_common_parse_dt(struct
+       return 0;
+ }
++static int dw_mci_rk2928_parse_dt(struct dw_mci *host)
++{
++      struct dw_mci_rockchip_priv_data *priv;
++      int err;
++
++      err = dw_mci_common_parse_dt(host);
++      if (err)
++              return err;
++
++      priv = host->priv;
++
++      priv->internal_phase = false;
++
++      return 0;
++}
++
+ static int dw_mci_rk3288_parse_dt(struct dw_mci *host)
+ {
+       struct dw_mci_rockchip_priv_data *priv;
+@@ -506,6 +522,7 @@ static int dw_mci_rockchip_init(struct d
+ static const struct dw_mci_drv_data rk2928_drv_data = {
+       .init                   = dw_mci_rockchip_init,
++      .parse_dt               = dw_mci_rk2928_parse_dt,
+ };
+ static const struct dw_mci_drv_data rk3288_drv_data = {
diff --git a/queue-7.0/mmc-litex_mmc-set-mandatory-idle-clocks-before-cmd0.patch b/queue-7.0/mmc-litex_mmc-set-mandatory-idle-clocks-before-cmd0.patch
new file mode 100644 (file)
index 0000000..e212dd8
--- /dev/null
@@ -0,0 +1,63 @@
+From 99982b743e5ba72bd1f5de0e03e3b96ae70b1e51 Mon Sep 17 00:00:00 2001
+From: Inochi Amaoto <inochiama@gmail.com>
+Date: Thu, 21 May 2026 15:21:21 +0800
+Subject: mmc: litex_mmc: Set mandatory idle clocks before CMD0
+
+From: Inochi Amaoto <inochiama@gmail.com>
+
+commit 99982b743e5ba72bd1f5de0e03e3b96ae70b1e51 upstream.
+
+The litex_mmc driver assumes the card is already probed in the BIOS
+and skip the phy initialization. This will cause the command fail
+like the following when the old card is unplugged and then insert
+a new card:
+
+[   62.923593] litex-mmc f0004000.mmc: Command (cmd 8) error, status -110
+[   62.949717] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
+[   62.976606] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
+[   63.002516] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
+[   63.028442] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
+
+Add required clock settings and initialization for the CMD 0, so it can
+probe the new card.
+
+Fixes: 92e099104729 ("mmc: Add driver for LiteX's LiteSDCard interface")
+Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
+Reviewed-by: Gabriel Somlo <gsomlo@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Ulf Hansson <ulfh@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mmc/host/litex_mmc.c |   14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/drivers/mmc/host/litex_mmc.c
++++ b/drivers/mmc/host/litex_mmc.c
+@@ -69,6 +69,9 @@
+ #define SD_SLEEP_US       5
+ #define SD_TIMEOUT_US 20000
++#define SD_INIT_DELAY_US  1000
++#define SD_INIT_CLK_HZ    400000
++
+ #define SDIRQ_CARD_DETECT    1
+ #define SDIRQ_SD_TO_MEM_DONE 2
+ #define SDIRQ_MEM_TO_SD_DONE 4
+@@ -450,6 +453,17 @@ static void litex_mmc_set_ios(struct mmc
+       struct litex_mmc_host *host = mmc_priv(mmc);
+       /*
++       * The SD specification requires at least 74 idle clocks before CMD0.
++       * These dummy cycles is generated by writing LITEX_PHY_INITIALIZE.
++       */
++      if (ios->chip_select == MMC_CS_HIGH) {
++              litex_mmc_setclk(host, SD_INIT_CLK_HZ);
++              litex_write8(host->sdphy + LITEX_PHY_INITIALIZE, 1);
++              fsleep(SD_INIT_DELAY_US);
++              return;
++      }
++
++      /*
+        * NOTE: Ignore any ios->bus_width updates; they occur right after
+        * the mmc core sends its own acmd6 bus-width change notification,
+        * which is redundant since we snoop on the command flow and inject
diff --git a/queue-7.0/mmc-renesas_sdhi-add-of-entry-for-rz-g2h-soc.patch b/queue-7.0/mmc-renesas_sdhi-add-of-entry-for-rz-g2h-soc.patch
new file mode 100644 (file)
index 0000000..f07a70a
--- /dev/null
@@ -0,0 +1,40 @@
+From f48ee49726ee4ab545fd2dc644f169c0809b19b3 Mon Sep 17 00:00:00 2001
+From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+Date: Tue, 19 May 2026 14:53:40 +0100
+Subject: mmc: renesas_sdhi: Add OF entry for RZ/G2H SoC
+
+From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+
+commit f48ee49726ee4ab545fd2dc644f169c0809b19b3 upstream.
+
+The RZ/G2H (R8A774E1) SoC was previously handled via the generic
+"renesas,rcar-gen3-sdhi" fallback compatible string. However, because
+the SDHI IP on RZ/G2H is identical with the R-Car H3-N (R8A77951), it
+requires the specific quirks and configuration defined in
+`of_r8a7795_compatible` rather than the generic Gen3 data.
+
+Add the explicit "renesas,sdhi-r8a774e1" match entry to map it correctly.
+Note that the DT binding file renesas,sdhi.yaml does not need an update
+as the entry for this SoC is already present.
+
+Fixes: 31941342888d ("arm64: dts: renesas: r8a774e1: Add SDHI nodes")
+Cc: stable@vger.kernel.org
+Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Signed-off-by: Ulf Hansson <ulfh@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mmc/host/renesas_sdhi_internal_dmac.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c
++++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c
+@@ -279,6 +279,7 @@ static const struct renesas_sdhi_of_data
+ static const struct of_device_id renesas_sdhi_internal_dmac_of_match[] = {
+       { .compatible = "renesas,sdhi-r7s9210", .data = &of_rza2_compatible, },
+       { .compatible = "renesas,sdhi-mmc-r8a77470", .data = &of_rcar_gen3_compatible, },
++      { .compatible = "renesas,sdhi-r8a774e1", .data = &of_r8a7795_compatible, },
+       { .compatible = "renesas,sdhi-r8a7795", .data = &of_r8a7795_compatible, },
+       { .compatible = "renesas,sdhi-r8a77961", .data = &of_r8a77961_compatible, },
+       { .compatible = "renesas,sdhi-r8a77965", .data = &of_r8a77965_compatible, },
diff --git a/queue-7.0/mmc-sdhci-add-signal-voltage-switch-in-sdhci_resume_host.patch b/queue-7.0/mmc-sdhci-add-signal-voltage-switch-in-sdhci_resume_host.patch
new file mode 100644 (file)
index 0000000..fbdc5cb
--- /dev/null
@@ -0,0 +1,47 @@
+From f595e8e77a51eee35e331f69321766593a845ef2 Mon Sep 17 00:00:00 2001
+From: Jisheng Zhang <jszhang@kernel.org>
+Date: Sun, 24 May 2026 10:34:55 +0800
+Subject: mmc: sdhci: add signal voltage switch in sdhci_resume_host
+
+From: Jisheng Zhang <jszhang@kernel.org>
+
+commit f595e8e77a51eee35e331f69321766593a845ef2 upstream.
+
+I met one suspend/resume issue with sdr104 capable sdio wifi card (with
+"keep-power-in-suspend" set in DT property):
+After resuming from suspend to ram, the sdio wifi card stops working.
+Further debug shows that although ios shows the sdio card is at sdr104
+mode, the voltage is still at 3V3. This is due to missing the calling
+of ->start_signal_voltage_switch() in sdhci_resume_host().
+
+Fix this issue by adding ->start_signal_voltage_switch() in
+sdhci_resume_host(). This also matches what we do for
+sdhci_runtime_resume_host().
+
+Then the question is: why this issue hasn't reported and fixed for so
+long time. IMHO, several reasons: Some host controllers just kick off
+the runtime resume for system resume, so they benefit from the well
+supported runtime pm code; Some platforms just use the old sdio wifi
+card which doesn't need signal voltage switch at all, the default
+voltage is 3v3 after resuming.
+
+Fixes: 6308d2905bd3 ("mmc: sdhci: add quirk for keeping card power during suspend")
+Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Ulf Hansson <ulfh@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mmc/host/sdhci.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/mmc/host/sdhci.c
++++ b/drivers/mmc/host/sdhci.c
+@@ -3836,6 +3836,7 @@ int sdhci_resume_host(struct sdhci_host
+               host->pwr = 0;
+               host->clock = 0;
+               host->reinit_uhs = true;
++              mmc->ops->start_signal_voltage_switch(mmc, &mmc->ios);
+               mmc->ops->set_ios(mmc, &mmc->ios);
+       } else {
+               sdhci_init(host, (mmc->pm_flags & MMC_PM_KEEP_POWER));
diff --git a/queue-7.0/mmc-sdhci-of-dwcmshc-fix-reset-clk-and-sdio-support-for-eswin-eic7700.patch b/queue-7.0/mmc-sdhci-of-dwcmshc-fix-reset-clk-and-sdio-support-for-eswin-eic7700.patch
new file mode 100644 (file)
index 0000000..8e26ea7
--- /dev/null
@@ -0,0 +1,172 @@
+From 8d4ae34e997062076a9098602eaca43353665bd9 Mon Sep 17 00:00:00 2001
+From: Huan He <hehuan1@eswincomputing.com>
+Date: Sat, 9 May 2026 16:49:07 +0800
+Subject: mmc: sdhci-of-dwcmshc: Fix reset, clk, and SDIO support for Eswin EIC7700
+
+From: Huan He <hehuan1@eswincomputing.com>
+
+commit 8d4ae34e997062076a9098602eaca43353665bd9 upstream.
+
+The EIC7700 code in sdhci-of-dwcmshc uses host->mmc->caps2 to select
+different configuration paths for different card types. The current logic
+distinguishes eMMC and SD, but does not handle SDIO separately.
+
+Update the EIC7700 card-type checks so that eMMC, SD and SDIO are
+distinguished explicitly.
+
+Switch the reset path to dwcmshc_reset() so that pending interrupt state
+is cleared consistently, and use sdhci_enable_clk() so the clock enable
+sequence follows the standard SDHCI flow.
+
+Fixes: 32b2633219d3 ("mmc: sdhci-of-dwcmshc: Add support for Eswin EIC7700")
+Signed-off-by: Huan He <hehuan1@eswincomputing.com>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Ulf Hansson <ulfh@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mmc/host/sdhci-of-dwcmshc.c |   44 ++++++++++++++++++------------------
+ 1 file changed, 22 insertions(+), 22 deletions(-)
+
+--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
+@@ -251,6 +251,7 @@
+ #define PHY_DELAY_CODE_MAX            0x7f
+ #define PHY_DELAY_CODE_EMMC           0x17
+ #define PHY_DELAY_CODE_SD             0x55
++#define PHY_DELAY_CODE_SDIO           0x29
+ enum dwcmshc_rk_type {
+       DWCMSHC_RK3568,
+@@ -1273,10 +1274,7 @@ static void sdhci_eic7700_set_clock(stru
+       clk_set_rate(pltfm_host->clk, clock);
+       clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+-      clk |= SDHCI_CLOCK_INT_EN;
+-      sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+-
+-      dwcmshc_enable_card_clk(host);
++      sdhci_enable_clk(host, clk);
+ }
+ static void sdhci_eic7700_config_phy_delay(struct sdhci_host *host, int delay)
+@@ -1337,7 +1335,7 @@ static void sdhci_eic7700_config_phy(str
+ static void sdhci_eic7700_reset(struct sdhci_host *host, u8 mask)
+ {
+-      sdhci_reset(host, mask);
++      dwcmshc_reset(host, mask);
+       /* after reset all, the phy's config will be clear */
+       if (mask == SDHCI_RESET_ALL)
+@@ -1434,18 +1432,17 @@ static int sdhci_eic7700_phase_code_tuni
+ {
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
+-      u32 sd_caps = MMC_CAP2_NO_MMC | MMC_CAP2_NO_SDIO;
++      u32 emmc_caps = MMC_CAP2_NO_SD | MMC_CAP2_NO_SDIO;
+       int phase_code = -1;
+       int code_range = -1;
+-      bool is_sd = false;
+       int code_min = -1;
+       int code_max = -1;
+       int cmd_error = 0;
++      bool is_emmc;
+       int ret = 0;
+       int i = 0;
+-      if ((host->mmc->caps2 & sd_caps) == sd_caps)
+-              is_sd = true;
++      is_emmc = (host->mmc->caps2 & emmc_caps) == emmc_caps;
+       for (i = 0; i <= MAX_PHASE_CODE; i++) {
+               /* Centered Phase code */
+@@ -1454,8 +1451,8 @@ static int sdhci_eic7700_phase_code_tuni
+               host->ops->reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+               if (ret) {
+-                      /* SD specific range tracking */
+-                      if (is_sd && code_min != -1 && code_max != -1) {
++                      /* SD/SDIO specific range tracking */
++                      if (!is_emmc && code_min != -1 && code_max != -1) {
+                               if (code_max - code_min > code_range) {
+                                       code_range = code_max - code_min;
+                                       phase_code = (code_min + code_max) / 2;
+@@ -1466,17 +1463,17 @@ static int sdhci_eic7700_phase_code_tuni
+                               code_max = -1;
+                       }
+                       /* EMMC breaks after first valid range */
+-                      if (!is_sd && code_min != -1 && code_max != -1)
++                      if (is_emmc && code_min != -1 && code_max != -1)
+                               break;
+               } else {
+                       /* Track valid phase code range */
+                       if (code_min == -1) {
+                               code_min = i;
+-                              if (!is_sd)
++                              if (is_emmc)
+                                       continue;
+                       }
+                       code_max = i;
+-                      if (is_sd && i == MAX_PHASE_CODE) {
++                      if (!is_emmc && i == MAX_PHASE_CODE) {
+                               if (code_max - code_min > code_range) {
+                                       code_range = code_max - code_min;
+                                       phase_code = (code_min + code_max) / 2;
+@@ -1486,19 +1483,19 @@ static int sdhci_eic7700_phase_code_tuni
+       }
+       /* Handle tuning failure case */
+-      if ((is_sd && phase_code == -1) ||
+-          (!is_sd && code_min == -1 && code_max == -1)) {
++      if ((!is_emmc && phase_code == -1) ||
++          (is_emmc && code_min == -1 && code_max == -1)) {
+               pr_err("%s: phase code tuning failed!\n", mmc_hostname(host->mmc));
+               sdhci_writew(host, 0, priv->vendor_specific_area1 + DWCMSHC_AT_STAT);
+               return -EIO;
+       }
+-      if (!is_sd)
++      if (is_emmc)
+               phase_code = (code_min + code_max) / 2;
+       sdhci_writew(host, phase_code, priv->vendor_specific_area1 + DWCMSHC_AT_STAT);
+-      /* SD specific final verification */
+-      if (is_sd) {
++      /* SD/SDIO specific final verification */
++      if (!is_emmc) {
+               ret = mmc_send_tuning(host->mmc, opcode, &cmd_error);
+               host->ops->reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+               if (ret) {
+@@ -1596,9 +1593,9 @@ static void sdhci_eic7700_set_uhs_signal
+ static void sdhci_eic7700_set_uhs_wrapper(struct sdhci_host *host, unsigned int timing)
+ {
+-      u32 sd_caps = MMC_CAP2_NO_MMC | MMC_CAP2_NO_SDIO;
++      u32 emmc_caps = MMC_CAP2_NO_SD | MMC_CAP2_NO_SDIO;
+-      if ((host->mmc->caps2 & sd_caps) == sd_caps)
++      if ((host->mmc->caps2 & emmc_caps) != emmc_caps)
+               sdhci_set_uhs_signaling(host, timing);
+       else
+               sdhci_eic7700_set_uhs_signaling(host, timing);
+@@ -1607,6 +1604,7 @@ static void sdhci_eic7700_set_uhs_wrappe
+ static int eic7700_init(struct device *dev, struct sdhci_host *host, struct dwcmshc_priv *dwc_priv)
+ {
+       u32 emmc_caps = MMC_CAP2_NO_SD | MMC_CAP2_NO_SDIO;
++      u32 sd_caps = MMC_CAP2_NO_MMC | MMC_CAP2_NO_SDIO;
+       unsigned int val, hsp_int_status, hsp_pwr_ctrl;
+       static const char * const clk_ids[] = {"axi"};
+       struct of_phandle_args args;
+@@ -1661,8 +1659,10 @@ static int eic7700_init(struct device *d
+       if ((host->mmc->caps2 & emmc_caps) == emmc_caps)
+               dwc_priv->delay_line = PHY_DELAY_CODE_EMMC;
+-      else
++      else if ((host->mmc->caps2 & sd_caps) == sd_caps)
+               dwc_priv->delay_line = PHY_DELAY_CODE_SD;
++      else
++              dwc_priv->delay_line = PHY_DELAY_CODE_SDIO;
+       if (!of_property_read_u32(dev->of_node, "eswin,drive-impedance-ohms", &val))
+               priv->drive_impedance = eic7700_convert_drive_impedance_ohm(dev, val);
diff --git a/queue-7.0/pmdomain-imx-fix-of-node-refcount.patch b/queue-7.0/pmdomain-imx-fix-of-node-refcount.patch
new file mode 100644 (file)
index 0000000..86e0a53
--- /dev/null
@@ -0,0 +1,34 @@
+From fba0510cd62666951dcc0221527edc0c47ae6599 Mon Sep 17 00:00:00 2001
+From: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Date: Thu, 21 May 2026 10:36:27 +0200
+Subject: pmdomain: imx: fix OF node refcount
+
+From: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+
+commit fba0510cd62666951dcc0221527edc0c47ae6599 upstream.
+
+for_each_child_of_node_scoped() decrements the reference count of the
+nod after each iteration. Assigning it without incrementing the refcount
+to a dynamically allocated platform device will result in a double put
+in platform_device_release(). Add the missing call to of_node_get().
+
+Cc: stable@vger.kernel.org
+Fixes: 3e4d109ee8fc ("pmdomain: imx: gpc: Simplify with scoped for each OF child loop")
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Ulf Hansson <ulfh@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pmdomain/imx/gpc.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pmdomain/imx/gpc.c
++++ b/drivers/pmdomain/imx/gpc.c
+@@ -487,7 +487,7 @@ static int imx_gpc_probe(struct platform
+                       domain->ipg_rate_mhz = ipg_rate_mhz;
+                       pd_pdev->dev.parent = &pdev->dev;
+-                      pd_pdev->dev.of_node = np;
++                      pd_pdev->dev.of_node = of_node_get(np);
+                       pd_pdev->dev.fwnode = of_fwnode_handle(np);
+                       ret = platform_device_add(pd_pdev);
diff --git a/queue-7.0/pmdomain-ti_sci-add-wakeup-constraint-to-parent-devices-of-wakeup-source.patch b/queue-7.0/pmdomain-ti_sci-add-wakeup-constraint-to-parent-devices-of-wakeup-source.patch
new file mode 100644 (file)
index 0000000..ed74a7b
--- /dev/null
@@ -0,0 +1,36 @@
+From 4db207599acfc9d676340daa2dc6b52bfca17db4 Mon Sep 17 00:00:00 2001
+From: Kendall Willis <k-willis@ti.com>
+Date: Wed, 6 May 2026 22:16:45 -0500
+Subject: pmdomain: ti_sci: add wakeup constraint to parent devices of wakeup source
+
+From: Kendall Willis <k-willis@ti.com>
+
+commit 4db207599acfc9d676340daa2dc6b52bfca17db4 upstream.
+
+Set wakeup constraint for any device in a wakeup path. All parent devices
+of a wakeup device should not be turned off during suspend. This ensures
+the wakeup device is kept on while the system is suspended.
+
+Cc: stable@vger.kernel.org
+Fixes: 9d8aa0dd3be4 ("pmdomain: ti_sci: add wakeup constraint management")
+Reported-by: Vitor Soares <vitor.soares@toradex.com>
+Closes: https://lore.kernel.org/linux-pm/c0fe43a2339c802e9ce5900092cd530a2ba17a6b.camel@gmail.com/
+Signed-off-by: Kendall Willis <k-willis@ti.com>
+Reviewed-by: Sebin Francis <sebin.francis@ti.com>
+Signed-off-by: Ulf Hansson <ulfh@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pmdomain/ti/ti_sci_pm_domains.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pmdomain/ti/ti_sci_pm_domains.c
++++ b/drivers/pmdomain/ti/ti_sci_pm_domains.c
+@@ -86,7 +86,7 @@ static inline void ti_sci_pd_set_wkup_co
+       const struct ti_sci_handle *ti_sci = pd->parent->ti_sci;
+       int ret;
+-      if (device_may_wakeup(dev)) {
++      if (device_may_wakeup(dev) || device_wakeup_path(dev)) {
+               /*
+                * If device can wakeup using IO daisy chain wakeups,
+                * we do not want to set a constraint.
diff --git a/queue-7.0/rtase-avoid-sleeping-in-get_stats64.patch b/queue-7.0/rtase-avoid-sleeping-in-get_stats64.patch
new file mode 100644 (file)
index 0000000..0c84b65
--- /dev/null
@@ -0,0 +1,43 @@
+From 9fc237f8d49f06d05f0f8e80361047b718894e81 Mon Sep 17 00:00:00 2001
+From: Justin Lai <justinlai0215@realtek.com>
+Date: Wed, 3 Jun 2026 14:18:16 +0800
+Subject: rtase: Avoid sleeping in get_stats64()
+
+From: Justin Lai <justinlai0215@realtek.com>
+
+commit 9fc237f8d49f06d05f0f8e80361047b718894e81 upstream.
+
+The .ndo_get_stats64 callback must not sleep because it can be
+called when reading /proc/net/dev.
+
+rtase_get_stats64() calls rtase_dump_tally_counter(), which polls
+the tally counter dump bit with read_poll_timeout(). This may
+sleep while waiting for the hardware counter dump to complete.
+
+Use read_poll_timeout_atomic() instead to avoid sleeping in the
+get_stats64() path.
+
+Fixes: 079600489960 ("rtase: Implement net_device_ops")
+Cc: stable@vger.kernel.org
+Signed-off-by: Justin Lai <justinlai0215@realtek.com>
+Link: https://patch.msgid.link/20260603061816.31356-1-justinlai0215@realtek.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/realtek/rtase/rtase_main.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/ethernet/realtek/rtase/rtase_main.c
++++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c
+@@ -1563,8 +1563,9 @@ static void rtase_dump_tally_counter(con
+       rtase_w32(tp, RTASE_DTCCR0, cmd);
+       rtase_w32(tp, RTASE_DTCCR0, cmd | RTASE_COUNTER_DUMP);
+-      err = read_poll_timeout(rtase_r32, val, !(val & RTASE_COUNTER_DUMP),
+-                              10, 250, false, tp, RTASE_DTCCR0);
++      err = read_poll_timeout_atomic(rtase_r32, val,
++                                     !(val & RTASE_COUNTER_DUMP),
++                                     10, 250, false, tp, RTASE_DTCCR0);
+       if (err == -ETIMEDOUT)
+               netdev_err(tp->dev, "error occurred in dump tally counter\n");
diff --git a/queue-7.0/rtase-reset-tx-subqueue-when-clearing-tx-ring.patch b/queue-7.0/rtase-reset-tx-subqueue-when-clearing-tx-ring.patch
new file mode 100644 (file)
index 0000000..45741ee
--- /dev/null
@@ -0,0 +1,41 @@
+From ab1ecaabe74b7d86c38ab2ab44bd56cdcc33645a Mon Sep 17 00:00:00 2001
+From: Justin Lai <justinlai0215@realtek.com>
+Date: Tue, 2 Jun 2026 19:46:59 +0800
+Subject: rtase: Reset TX subqueue when clearing TX ring
+
+From: Justin Lai <justinlai0215@realtek.com>
+
+commit ab1ecaabe74b7d86c38ab2ab44bd56cdcc33645a upstream.
+
+rtase_tx_clear() clears the TX ring and resets the ring indexes.
+However, the TX queue state and BQL accounting are not reset at
+the same time.
+
+This may leave __QUEUE_STATE_STACK_XOFF asserted after
+rtase_sw_reset(), preventing new TX packets from being scheduled.
+
+Reset the TX subqueue when clearing the TX ring so the TX queue
+state and BQL accounting are restored together.
+
+Fixes: 5a2a2f15244c ("rtase: Implement the rtase_down function")
+Cc: stable@vger.kernel.org
+Signed-off-by: Justin Lai <justinlai0215@realtek.com>
+Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com>
+Link: https://patch.msgid.link/20260602114659.12335-1-justinlai0215@realtek.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/realtek/rtase/rtase_main.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/ethernet/realtek/rtase/rtase_main.c
++++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c
+@@ -239,6 +239,8 @@ static void rtase_tx_clear(struct rtase_
+               rtase_tx_clear_range(ring, ring->dirty_idx, RTASE_NUM_DESC);
+               ring->cur_idx = 0;
+               ring->dirty_idx = 0;
++
++              netdev_tx_reset_subqueue(tp->dev, i);
+       }
+ }
diff --git a/queue-7.0/rxrpc-fix-the-ack-parser-to-extract-the-sack-table-for-parsing.patch b/queue-7.0/rxrpc-fix-the-ack-parser-to-extract-the-sack-table-for-parsing.patch
new file mode 100644 (file)
index 0000000..d4f65c7
--- /dev/null
@@ -0,0 +1,100 @@
+From 333b6d5bb9f87827ac2639c737bf9613dbae7253 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Thu, 4 Jun 2026 12:46:00 +0100
+Subject: rxrpc: Fix the ACK parser to extract the SACK table for parsing
+
+From: David Howells <dhowells@redhat.com>
+
+commit 333b6d5bb9f87827ac2639c737bf9613dbae7253 upstream.
+
+Fix modification of the received skbuff in rxrpc_input_soft_acks() and a
+potential incorrect access of the buffer in a fragmented UDP packet (the
+packet would probably have to be deliberately pre-generated as fragmented)
+when AF_RXRPC tries to extract the contents of the SACK table by copying
+out the contents of the SACK table into a buffer before attempting to parse
+
+AF_RXRPC assumes that it can just call skb_condense() and then validly
+access the SACK table from skb->data and that it will be a flat buffer -
+but skb_condense() can silently fail to do anything under some
+circumstances.
+
+Note that whilst rxrpc_input_soft_acks() should be able to parse extended
+ACKs, the rest of AF_RXRPC doesn't currently support that.
+
+Further, there's then no need to call skb_condense() in rxrpc_input_ack(),
+so don't.
+
+Fixes: d57a3a151660 ("rxrpc: Save last ACK's SACK table rather than marking txbufs")
+Reported-by: Michael Bommarito <michael.bommarito@gmail.com>
+Link: https://lore.kernel.org/r/20260513180907.2061972-1-michael.bommarito@gmail.com
+Signed-off-by: David Howells <dhowells@redhat.com>
+cc: Marc Dionne <marc.dionne@auristor.com>
+cc: Jeffrey Altman <jaltman@auristor.com>
+cc: Eric Dumazet <edumazet@google.com>
+cc: "David S. Miller" <davem@davemloft.net>
+cc: Jakub Kicinski <kuba@kernel.org>
+cc: Paolo Abeni <pabeni@redhat.com>
+cc: Simon Horman <horms@kernel.org>
+cc: linux-afs@lists.infradead.org
+cc: netdev@vger.kernel.org
+cc: stable@kernel.org
+Link: https://patch.msgid.link/105362.1780573560@warthog.procyon.org.uk
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/rxrpc/input.c |   26 +++++++++++++++++---------
+ 1 file changed, 17 insertions(+), 9 deletions(-)
+
+--- a/net/rxrpc/input.c
++++ b/net/rxrpc/input.c
+@@ -963,23 +963,34 @@ static void rxrpc_input_soft_acks(struct
+       struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+       struct rxrpc_txqueue *tq = call->tx_queue;
+       unsigned long extracted = ~0UL;
+-      unsigned int nr = 0;
++      unsigned int nr = 0, nsack;
+       rxrpc_seq_t seq = call->acks_hard_ack + 1;
+       rxrpc_seq_t lowest_nak = seq + sp->ack.nr_acks;
+-      u8 *acks = skb->data + sizeof(struct rxrpc_wire_header) + sizeof(struct rxrpc_ackpacket);
++      u8 sack[256] __aligned(sizeof(unsigned long));
++      u8 *acks = sack;
+       _enter("%x,%x,%u", tq->qbase, seq, sp->ack.nr_acks);
+       while (after(seq, tq->qbase + RXRPC_NR_TXQUEUE - 1))
+               tq = tq->next;
++      /* Extract an individual SACK table.  A normal SACK table is up to 255
++       * bytes with 1 ACK flag per byte, but an extended SACK table can be up
++       * to 256 bytes with up to 8 ACK/NACK flags per byte.  The ACK flags go
++       * across all bit 0's then all bit 1's, then all bit 2's, ...
++       */
++      memset(sack, 0, sizeof(sack));
++      nsack = umin(sp->ack.nr_acks, 256);
++      if (skb_copy_bits(skb,
++                        sizeof(struct rxrpc_wire_header) + sizeof(struct rxrpc_ackpacket),
++                        sack, nsack) < 0)
++              return;
++
+       for (unsigned int i = 0; i < sp->ack.nr_acks; i++) {
+               /* Decant ACKs until we hit a txqueue boundary. */
++              if ((i & 255) == 0)
++                      acks = sack;
+               shiftr_adv_rotr(acks, extracted);
+-              if (i == 256) {
+-                      acks -= i;
+-                      i = 0;
+-              }
+               seq++;
+               nr++;
+               if ((seq & RXRPC_TXQ_MASK) != 0)
+@@ -1117,9 +1128,6 @@ static void rxrpc_input_ack(struct rxrpc
+           skb_copy_bits(skb, ioffset, &trailer, sizeof(trailer)) < 0)
+               return rxrpc_proto_abort(call, 0, rxrpc_badmsg_short_ack_trailer);
+-      if (nr_acks > 0)
+-              skb_condense(skb);
+-
+       call->acks_latest_ts = ktime_get_real();
+       call->acks_hard_ack = hard_ack;
+       call->acks_prev_seq = prev_pkt;
diff --git a/queue-7.0/sctp-diag-reject-stale-associations-in-dump_one-path.patch b/queue-7.0/sctp-diag-reject-stale-associations-in-dump_one-path.patch
new file mode 100644 (file)
index 0000000..8b05822
--- /dev/null
@@ -0,0 +1,78 @@
+From 5eba3e48d78edd7551b992cb7ba687019b3a78da Mon Sep 17 00:00:00 2001
+From: Zhao Zhang <zzhan461@ucr.edu>
+Date: Sat, 30 May 2026 23:57:14 +0800
+Subject: sctp: diag: reject stale associations in dump_one path
+
+From: Zhao Zhang <zzhan461@ucr.edu>
+
+commit 5eba3e48d78edd7551b992cb7ba687019b3a78da upstream.
+
+The SCTP exact sock_diag lookup can hold a transport reference, block on
+lock_sock(sk), and then resume after sctp_association_free() has marked
+the association dead and freed its bind address list.
+
+When that happens, inet_assoc_attr_size() and
+inet_diag_msg_sctpasoc_fill() can still dereference association state
+that is no longer valid for reporting. In particular,
+inet_diag_msg_sctpasoc_fill() may read an empty bind-address list as a
+real sctp_sockaddr_entry and trigger an out-of-bounds read from
+unrelated association memory.
+
+Reject the association after taking the socket lock if it has been
+reaped or detached from the endpoint, and report the lookup as stale.
+This keeps the exact dump-one path from formatting torn association
+state.
+
+Fixes: 8f840e47f190 ("sctp: add the sctp_diag.c file")
+Cc: stable@kernel.org
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Signed-off-by: Zhao Zhang <zzhan461@ucr.edu>
+Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/fac6043fa20a2ff68e12958c431836f692c51268.1780113823.git.zzhan461@ucr.edu
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sctp/diag.c |   17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+--- a/net/sctp/diag.c
++++ b/net/sctp/diag.c
+@@ -266,15 +266,15 @@ static int sctp_sock_dump_one(struct sct
+       lock_sock(sk);
+-      rep = nlmsg_new(inet_assoc_attr_size(sk, assoc), GFP_KERNEL);
+-      if (!rep) {
+-              release_sock(sk);
+-              return -ENOMEM;
++      if (ep != assoc->ep || assoc->base.dead) {
++              err = -ESTALE;
++              goto out_unlock;
+       }
+-      if (ep != assoc->ep) {
+-              err = -EAGAIN;
+-              goto out;
++      rep = nlmsg_new(inet_assoc_attr_size(sk, assoc), GFP_KERNEL);
++      if (!rep) {
++              err = -ENOMEM;
++              goto out_unlock;
+       }
+       err = inet_sctp_diag_fill(sk, assoc, rep, req, sk_user_ns(NETLINK_CB(skb).sk),
+@@ -289,8 +289,9 @@ static int sctp_sock_dump_one(struct sct
+       return nlmsg_unicast(sock_net(skb->sk)->diag_nlsk, rep, NETLINK_CB(skb).portid);
+ out:
+-      release_sock(sk);
+       kfree_skb(rep);
++out_unlock:
++      release_sock(sk);
+       return err;
+ }
diff --git a/queue-7.0/sctp-stream-fully-roll-back-denied-add-stream-state.patch b/queue-7.0/sctp-stream-fully-roll-back-denied-add-stream-state.patch
new file mode 100644 (file)
index 0000000..3da2d88
--- /dev/null
@@ -0,0 +1,61 @@
+From a5f8a90ac9f77c678a9781c0a464b635e0d63e49 Mon Sep 17 00:00:00 2001
+From: Wyatt Feng <bronzed_45_vested@icloud.com>
+Date: Fri, 5 Jun 2026 13:53:42 +0800
+Subject: sctp: stream: fully roll back denied add-stream state
+
+From: Wyatt Feng <bronzed_45_vested@icloud.com>
+
+commit a5f8a90ac9f77c678a9781c0a464b635e0d63e49 upstream.
+
+When ADD_OUT_STREAMS is denied, SCTP only shrinks the queued chunks and
+then lowers outcnt. That leaves removed stream metadata behind, so a
+later re-add can reuse a stale ext and hit a null-pointer dereference in
+the scheduler get path.
+
+Fix the rollback by tearing down the removed stream state the same way
+other stream resizes do. Unschedule the current scheduler state, drop
+the removed stream ext state with sctp_stream_outq_migrate(), and then
+reschedule the remaining streams.
+
+This keeps scheduler-private RR/FC/PRIO lists consistent while fully
+rolling back denied outgoing stream additions.
+
+Fixes: 637784ade221 ("sctp: introduce priority based stream scheduler")
+Cc: stable@kernel.org
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Signed-off-by: Wyatt Feng <bronzed_45_vested@icloud.com>
+Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/d78954ecd94954653ee299400e98d74a03a6f7d3.1780603399.git.bronzed_45_vested@icloud.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sctp/stream.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/net/sctp/stream.c
++++ b/net/sctp/stream.c
+@@ -1038,6 +1038,7 @@ struct sctp_chunk *sctp_process_strreset
+                       stsn, rtsn, GFP_ATOMIC);
+       } else if (req->type == SCTP_PARAM_RESET_ADD_OUT_STREAMS) {
+               struct sctp_strreset_addstrm *addstrm;
++              const struct sctp_sched_ops *sched;
+               __u16 number;
+               addstrm = (struct sctp_strreset_addstrm *)req;
+@@ -1048,7 +1049,10 @@ struct sctp_chunk *sctp_process_strreset
+                       for (i = number; i < stream->outcnt; i++)
+                               SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
+               } else {
+-                      sctp_stream_shrink_out(stream, number);
++                      sched = sctp_sched_ops_from_stream(stream);
++                      sched->unsched_all(stream);
++                      sctp_stream_outq_migrate(stream, NULL, number);
++                      sched->sched_all(stream);
+                       stream->outcnt = number;
+               }
index 5e49ab677ec7b6b2bebe88c60247da510324ae74..29d3827388d145de4ce8d7506df451dbb6e7111c 100644 (file)
@@ -295,3 +295,40 @@ nvmem-core-fix-use-after-free-bugs-in-error-paths.patch
 nvmem-layouts-onie-tlv-fix-hang-on-unknown-types.patch
 octeontx2-af-fix-memory-leak-in-rvu_setup_hw_resources.patch
 pinctrl-mcp23s08-read-spi-present-mask-as-u8-not-u32.patch
+mm-cma-fix-reserved-page-leak-on-activation-failure.patch
+mm-cma_debug-fix-invalid-accesses-for-inactive-cma-areas.patch
+mm-damon-lru_sort-handle-ctx-allocation-failure.patch
+mm-damon-reclaim-handle-ctx-allocation-failure.patch
+mm-huge_memory-use-correct-flags-for-device-private-pmd-entry.patch
+mm-hugetlb-avoid-false-positive-lockdep-assertion.patch
+mm-hugetlb-restore-reservation-on-error-in-hugetlb-folio-copy-paths.patch
+mm-list_lru-drain-before-clearing-xarray-entry-on-reparent.patch
+mm-mincore-handle-non-swap-entries-before-config_swap-guard.patch
+mmc-core-fix-host-controller-programming-for-fixed-driver-type.patch
+mmc-dw_mmc-rockchip-add-missing-private-data-for-very-old-controllers.patch
+mmc-litex_mmc-set-mandatory-idle-clocks-before-cmd0.patch
+mmc-renesas_sdhi-add-of-entry-for-rz-g2h-soc.patch
+mmc-sdhci-of-dwcmshc-fix-reset-clk-and-sdio-support-for-eswin-eic7700.patch
+mmc-sdhci-add-signal-voltage-switch-in-sdhci_resume_host.patch
+pmdomain-imx-fix-of-node-refcount.patch
+pmdomain-ti_sci-add-wakeup-constraint-to-parent-devices-of-wakeup-source.patch
+rtase-avoid-sleeping-in-get_stats64.patch
+rtase-reset-tx-subqueue-when-clearing-tx-ring.patch
+rxrpc-fix-the-ack-parser-to-extract-the-sack-table-for-parsing.patch
+sctp-diag-reject-stale-associations-in-dump_one-path.patch
+sctp-stream-fully-roll-back-denied-add-stream-state.patch
+thunderbolt-reject-zero-length-property-entries-in-validator.patch
+thunderbolt-bound-root-directory-content-to-block-size.patch
+thunderbolt-clamp-xdomain-response-data-copy-to-allocation-size.patch
+thunderbolt-validate-xdomain-request-packet-size-before-type-cast.patch
+thunderbolt-limit-xdomain-response-copy-to-actual-frame-size.patch
+slimbus-qcom-ngd-ctrl-fix-of-node-refcount.patch
+slimbus-qcom-ngd-ctrl-fix-up-platform_driver-registration.patch
+slimbus-qcom-ngd-ctrl-fix-probe-error-path-ordering.patch
+slimbus-qcom-ngd-ctrl-register-callbacks-after-creating-the-ngd.patch
+slimbus-qcom-ngd-ctrl-initialize-controller-resources-in-controller.patch
+slimbus-qcom-ngd-ctrl-correct-pdr-and-ssr-cleanup-ownership.patch
+slimbus-qcom-ngd-ctrl-balance-pm_runtime-enablement-for-ngd.patch
+slimbus-qcom-ngd-ctrl-avoid-abba-on-tx_lock-ctrl-lock.patch
+drm-gem-try-to-fix-change_handle-ioctl-attempt-4.patch
+drm-i915-fix-color-blob-reference-handling-in-intel_plane_state.patch
diff --git a/queue-7.0/slimbus-qcom-ngd-ctrl-avoid-abba-on-tx_lock-ctrl-lock.patch b/queue-7.0/slimbus-qcom-ngd-ctrl-avoid-abba-on-tx_lock-ctrl-lock.patch
new file mode 100644 (file)
index 0000000..e62bfa7
--- /dev/null
@@ -0,0 +1,76 @@
+From 55f2ea9ff83cc27a85526b14bc9b32f96a08d6ec Mon Sep 17 00:00:00 2001
+From: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+Date: Sat, 30 May 2026 21:44:21 +0100
+Subject: slimbus: qcom-ngd-ctrl: Avoid ABBA on tx_lock/ctrl->lock
+
+From: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+
+commit 55f2ea9ff83cc27a85526b14bc9b32f96a08d6ec upstream.
+
+During the SSR/PDR down notification the tx_lock is taken with the
+intent to provide synchronization with active DMA transfers.
+
+But during this period qcom_slim_ngd_down() is invoked, which ends up in
+slim_report_absent(), which takes the slim_controller lock. In multiple
+other codepaths these two locks are taken in the opposite order (i.e.
+slim_controller then tx_lock).
+
+The result is a lockdep splat, and a possible deadlock:
+
+  rprocctl/449 is trying to acquire lock:
+  ffff00009793e620 (&ctrl->lock){+.+.}-{4:4}, at: slim_report_absent (drivers/slimbus/core.c:322) slimbus
+
+  but task is already holding lock:
+  ffff00009793fb50 (&ctrl->tx_lock){+.+.}-{4:4}, at: qcom_slim_ngd_ssr_pdr_notify (drivers/slimbus/qcom-ngd-ctrl.c:1475) slim_qcom_ngd_ctrl
+
+  which lock already depends on the new lock.
+
+  Possible unsafe locking scenario:
+
+        CPU0                    CPU1
+        ----                    ----
+   lock(&ctrl->tx_lock);
+                                lock(&ctrl->lock);
+                                lock(&ctrl->tx_lock);
+   lock(&ctrl->lock);
+
+The assumption is that the comment refers to the desire to not call
+qcom_slim_ngd_exit_dma() while we have an ongoing DMA TX transaction.
+But any such transaction is initiated and completed within a single
+qcom_slim_ngd_xfer_msg().
+
+Prior to calling qcom_slim_ngd_exit_dma() the slim_controller is torn
+down, all child devices are notified that the slimbus is gone and the
+child devices are removed.
+
+Stop taking the tx_lock in qcom_slim_ngd_ssr_pdr_notify() to avoid the
+deadlock.
+
+Fixes: a899d324863a ("slimbus: qcom-ngd-ctrl: add Sub System Restart support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+Signed-off-by: Srinivas Kandagatla <srini@kernel.org>
+Link: https://patch.msgid.link/20260530204421.116824-9-srini@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/slimbus/qcom-ngd-ctrl.c |    3 ---
+ 1 file changed, 3 deletions(-)
+
+--- a/drivers/slimbus/qcom-ngd-ctrl.c
++++ b/drivers/slimbus/qcom-ngd-ctrl.c
+@@ -1471,15 +1471,12 @@ static int qcom_slim_ngd_ssr_pdr_notify(
+       switch (action) {
+       case QCOM_SSR_BEFORE_SHUTDOWN:
+       case SERVREG_SERVICE_STATE_DOWN:
+-              /* Make sure the last dma xfer is finished */
+-              mutex_lock(&ctrl->tx_lock);
+               if (ctrl->state != QCOM_SLIM_NGD_CTRL_DOWN) {
+                       pm_runtime_get_noresume(ctrl->ctrl.dev);
+                       ctrl->state = QCOM_SLIM_NGD_CTRL_DOWN;
+                       qcom_slim_ngd_down(ctrl);
+                       qcom_slim_ngd_exit_dma(ctrl);
+               }
+-              mutex_unlock(&ctrl->tx_lock);
+               break;
+       case QCOM_SSR_AFTER_POWERUP:
+       case SERVREG_SERVICE_STATE_UP:
diff --git a/queue-7.0/slimbus-qcom-ngd-ctrl-balance-pm_runtime-enablement-for-ngd.patch b/queue-7.0/slimbus-qcom-ngd-ctrl-balance-pm_runtime-enablement-for-ngd.patch
new file mode 100644 (file)
index 0000000..a146014
--- /dev/null
@@ -0,0 +1,45 @@
+From 6a003446b725c44b9e3ffa111b0effbaa2d43085 Mon Sep 17 00:00:00 2001
+From: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+Date: Sat, 30 May 2026 21:44:20 +0100
+Subject: slimbus: qcom-ngd-ctrl: Balance pm_runtime enablement for NGD
+
+From: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+
+commit 6a003446b725c44b9e3ffa111b0effbaa2d43085 upstream.
+
+The pm_runtime_enable() and pm_runtime_use_autosuspend() calls are
+supposed to be balanced on exit, add these calls.
+
+Fixes: 917809e2280b ("slimbus: ngd: Add qcom SLIMBus NGD driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+Signed-off-by: Srinivas Kandagatla <srini@kernel.org>
+Link: https://patch.msgid.link/20260530204421.116824-8-srini@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/slimbus/qcom-ngd-ctrl.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/slimbus/qcom-ngd-ctrl.c
++++ b/drivers/slimbus/qcom-ngd-ctrl.c
+@@ -1582,8 +1582,11 @@ static int qcom_slim_ngd_probe(struct pl
+       pm_runtime_enable(dev);
+       pm_runtime_get_noresume(dev);
+       ret = qcom_slim_ngd_qmi_svc_event_init(ctrl);
+-      if (ret)
++      if (ret) {
+               dev_err(&pdev->dev, "QMI service registration failed:%d", ret);
++              pm_runtime_dont_use_autosuspend(dev);
++              pm_runtime_disable(dev);
++      }
+       return ret;
+ }
+@@ -1696,6 +1699,7 @@ static void qcom_slim_ngd_remove(struct
+ {
+       struct qcom_slim_ngd_ctrl *ctrl = platform_get_drvdata(pdev);
++      pm_runtime_dont_use_autosuspend(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
+       qcom_slim_ngd_enable(ctrl, false);
+       qcom_slim_ngd_exit_dma(ctrl);
diff --git a/queue-7.0/slimbus-qcom-ngd-ctrl-correct-pdr-and-ssr-cleanup-ownership.patch b/queue-7.0/slimbus-qcom-ngd-ctrl-correct-pdr-and-ssr-cleanup-ownership.patch
new file mode 100644 (file)
index 0000000..49e9314
--- /dev/null
@@ -0,0 +1,49 @@
+From 960b53a3f76fa214c2fc493734ae7b3c5e713bbf Mon Sep 17 00:00:00 2001
+From: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+Date: Sat, 30 May 2026 21:44:17 +0100
+Subject: slimbus: qcom-ngd-ctrl: Correct PDR and SSR cleanup ownership
+
+From: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+
+commit 960b53a3f76fa214c2fc493734ae7b3c5e713bbf upstream.
+
+PDR and SSR callbacks are registred from the controller probe function,
+but currently released from the child device's remove function.
+
+The remove() function should only be unwinding what was done in the
+same device's probe() function.
+
+Fixes: 917809e2280b ("slimbus: ngd: Add qcom SLIMBus NGD driver")
+Cc: stable@vger.kernel.org
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+Reviewed-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
+Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+Signed-off-by: Srinivas Kandagatla <srini@kernel.org>
+Link: https://patch.msgid.link/20260530204421.116824-5-srini@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/slimbus/qcom-ngd-ctrl.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/slimbus/qcom-ngd-ctrl.c
++++ b/drivers/slimbus/qcom-ngd-ctrl.c
+@@ -1684,6 +1684,9 @@ static void qcom_slim_ngd_ctrl_remove(st
+ {
+       struct qcom_slim_ngd_ctrl *ctrl = platform_get_drvdata(pdev);
++      pdr_handle_release(ctrl->pdr);
++      qcom_unregister_ssr_notifier(ctrl->notifier, &ctrl->nb);
++
+       qcom_slim_ngd_unregister(ctrl);
+       destroy_workqueue(ctrl->mwq);
+@@ -1694,8 +1697,6 @@ static void qcom_slim_ngd_remove(struct
+       struct qcom_slim_ngd_ctrl *ctrl = platform_get_drvdata(pdev);
+       pm_runtime_disable(&pdev->dev);
+-      pdr_handle_release(ctrl->pdr);
+-      qcom_unregister_ssr_notifier(ctrl->notifier, &ctrl->nb);
+       qcom_slim_ngd_enable(ctrl, false);
+       qcom_slim_ngd_exit_dma(ctrl);
+       qcom_slim_ngd_qmi_svc_event_deinit(&ctrl->qmi);
diff --git a/queue-7.0/slimbus-qcom-ngd-ctrl-fix-of-node-refcount.patch b/queue-7.0/slimbus-qcom-ngd-ctrl-fix-of-node-refcount.patch
new file mode 100644 (file)
index 0000000..6192404
--- /dev/null
@@ -0,0 +1,39 @@
+From 120134fe75c6b0ae38f14eb8b548ad1e5761f912 Mon Sep 17 00:00:00 2001
+From: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Date: Sat, 30 May 2026 21:44:14 +0100
+Subject: slimbus: qcom-ngd-ctrl: fix OF node refcount
+
+From: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+
+commit 120134fe75c6b0ae38f14eb8b548ad1e5761f912 upstream.
+
+Platform devices created with platform_device_alloc() call
+platform_device_release() when the last reference to the device's
+kobject is dropped. This function calls of_node_put() unconditionally.
+This works fine for devices created with platform_device_register_full()
+but users of the split approach (platform_device_alloc() +
+platform_device_add()) must bump the reference of the of_node they
+assign manually. Add the missing call to of_node_get().
+
+Cc: stable@vger.kernel.org
+Fixes: 917809e2280b ("slimbus: ngd: Add qcom SLIMBus NGD driver")
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Srinivas Kandagatla <srini@kernel.org>
+Link: https://patch.msgid.link/20260530204421.116824-2-srini@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/slimbus/qcom-ngd-ctrl.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/slimbus/qcom-ngd-ctrl.c
++++ b/drivers/slimbus/qcom-ngd-ctrl.c
+@@ -1542,7 +1542,7 @@ static int of_qcom_slim_ngd_register(str
+                       kfree(ngd);
+                       return ret;
+               }
+-              ngd->pdev->dev.of_node = node;
++              ngd->pdev->dev.of_node = of_node_get(node);
+               ctrl->ngd = ngd;
+               ret = platform_device_add(ngd->pdev);
diff --git a/queue-7.0/slimbus-qcom-ngd-ctrl-fix-probe-error-path-ordering.patch b/queue-7.0/slimbus-qcom-ngd-ctrl-fix-probe-error-path-ordering.patch
new file mode 100644 (file)
index 0000000..e731bf5
--- /dev/null
@@ -0,0 +1,55 @@
+From 2c22ff152d380ec3d3af099fa05d0ac5ca9b4c1e Mon Sep 17 00:00:00 2001
+From: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+Date: Sat, 30 May 2026 21:44:16 +0100
+Subject: slimbus: qcom-ngd-ctrl: Fix probe error path ordering
+
+From: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+
+commit 2c22ff152d380ec3d3af099fa05d0ac5ca9b4c1e upstream.
+
+qcom_slim_ngd_ctrl_probe() first registers the SSR callback then
+allocates the PDR context, as such the error path needs to come in
+opposite order to allow us to unroll each step.
+
+Fixes: 16f14551d0df ("slimbus: qcom-ngd: cleanup in probe error path")
+Cc: stable@vger.kernel.org
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+Reviewed-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
+Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+Signed-off-by: Srinivas Kandagatla <srini@kernel.org>
+Link: https://patch.msgid.link/20260530204421.116824-4-srini@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/slimbus/qcom-ngd-ctrl.c |   11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+--- a/drivers/slimbus/qcom-ngd-ctrl.c
++++ b/drivers/slimbus/qcom-ngd-ctrl.c
+@@ -1660,22 +1660,21 @@ static int qcom_slim_ngd_ctrl_probe(stru
+       if (IS_ERR(ctrl->pdr)) {
+               ret = dev_err_probe(dev, PTR_ERR(ctrl->pdr),
+                                   "Failed to init PDR handle\n");
+-              goto err_pdr_alloc;
++              goto err_unregister_ssr;
+       }
+       pds = pdr_add_lookup(ctrl->pdr, "avs/audio", "msm/adsp/audio_pd");
+       if (IS_ERR(pds) && PTR_ERR(pds) != -EALREADY) {
+               ret = dev_err_probe(dev, PTR_ERR(pds), "pdr add lookup failed\n");
+-              goto err_pdr_lookup;
++              goto err_pdr_release;
+       }
+       return of_qcom_slim_ngd_register(dev, ctrl);
+-err_pdr_alloc:
+-      qcom_unregister_ssr_notifier(ctrl->notifier, &ctrl->nb);
+-
+-err_pdr_lookup:
++err_pdr_release:
+       pdr_handle_release(ctrl->pdr);
++err_unregister_ssr:
++      qcom_unregister_ssr_notifier(ctrl->notifier, &ctrl->nb);
+       return ret;
+ }
diff --git a/queue-7.0/slimbus-qcom-ngd-ctrl-fix-up-platform_driver-registration.patch b/queue-7.0/slimbus-qcom-ngd-ctrl-fix-up-platform_driver-registration.patch
new file mode 100644 (file)
index 0000000..df109dc
--- /dev/null
@@ -0,0 +1,94 @@
+From 8663e8334d7b6007f5d8a4e5dd270246f35107a6 Mon Sep 17 00:00:00 2001
+From: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+Date: Sat, 30 May 2026 21:44:15 +0100
+Subject: slimbus: qcom-ngd-ctrl: Fix up platform_driver registration
+
+From: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+
+commit 8663e8334d7b6007f5d8a4e5dd270246f35107a6 upstream.
+
+Device drivers should not invoke platform_driver_register()/unregister()
+in their probe and remove paths. They should further not rely on
+platform_driver_unregister() as their only means of "deleting" their
+child devices.
+
+Introduce a helper to unregister the child device and move the
+platform_driver_register()/unregister() to module_init()/exit().
+
+Fixes: 917809e2280b ("slimbus: ngd: Add qcom SLIMBus NGD driver")
+Cc: stable@vger.kernel.org
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+Reviewed-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
+Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+Signed-off-by: Srinivas Kandagatla <srini@kernel.org>
+Link: https://patch.msgid.link/20260530204421.116824-3-srini@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/slimbus/qcom-ngd-ctrl.c |   36 +++++++++++++++++++++++++++++++++---
+ 1 file changed, 33 insertions(+), 3 deletions(-)
+
+--- a/drivers/slimbus/qcom-ngd-ctrl.c
++++ b/drivers/slimbus/qcom-ngd-ctrl.c
+@@ -1560,6 +1560,13 @@ static int of_qcom_slim_ngd_register(str
+       return -ENODEV;
+ }
++static void qcom_slim_ngd_unregister(struct qcom_slim_ngd_ctrl *ctrl)
++{
++      struct qcom_slim_ngd *ngd = ctrl->ngd;
++
++      platform_device_del(ngd->pdev);
++}
++
+ static int qcom_slim_ngd_probe(struct platform_device *pdev)
+ {
+       struct device *dev = &pdev->dev;
+@@ -1662,7 +1669,6 @@ static int qcom_slim_ngd_ctrl_probe(stru
+               goto err_pdr_lookup;
+       }
+-      platform_driver_register(&qcom_slim_ngd_driver);
+       return of_qcom_slim_ngd_register(dev, ctrl);
+ err_pdr_alloc:
+@@ -1676,7 +1682,9 @@ err_pdr_lookup:
+ static void qcom_slim_ngd_ctrl_remove(struct platform_device *pdev)
+ {
+-      platform_driver_unregister(&qcom_slim_ngd_driver);
++      struct qcom_slim_ngd_ctrl *ctrl = platform_get_drvdata(pdev);
++
++      qcom_slim_ngd_unregister(ctrl);
+ }
+ static void qcom_slim_ngd_remove(struct platform_device *pdev)
+@@ -1752,6 +1760,28 @@ static struct platform_driver qcom_slim_
+       },
+ };
+-module_platform_driver(qcom_slim_ngd_ctrl_driver);
++static int qcom_slim_ngd_init(void)
++{
++      int ret;
++
++      ret = platform_driver_register(&qcom_slim_ngd_driver);
++      if (ret)
++              return ret;
++
++      ret = platform_driver_register(&qcom_slim_ngd_ctrl_driver);
++      if (ret)
++              platform_driver_unregister(&qcom_slim_ngd_driver);
++
++      return ret;
++}
++
++static void qcom_slim_ngd_exit(void)
++{
++      platform_driver_unregister(&qcom_slim_ngd_ctrl_driver);
++      platform_driver_unregister(&qcom_slim_ngd_driver);
++}
++
++module_init(qcom_slim_ngd_init);
++module_exit(qcom_slim_ngd_exit);
+ MODULE_LICENSE("GPL v2");
+ MODULE_DESCRIPTION("Qualcomm SLIMBus NGD controller");
diff --git a/queue-7.0/slimbus-qcom-ngd-ctrl-initialize-controller-resources-in-controller.patch b/queue-7.0/slimbus-qcom-ngd-ctrl-initialize-controller-resources-in-controller.patch
new file mode 100644 (file)
index 0000000..3636e9d
--- /dev/null
@@ -0,0 +1,108 @@
+From 07c564ea5fb859b7381429de935d5df4781947c6 Mon Sep 17 00:00:00 2001
+From: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+Date: Sat, 30 May 2026 21:44:19 +0100
+Subject: slimbus: qcom-ngd-ctrl: Initialize controller resources in controller
+
+From: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+
+commit 07c564ea5fb859b7381429de935d5df4781947c6 upstream.
+
+The work structs and work queue are controller resources, create and
+destroy them in the controller context. Creating them as part of the
+child device's probe path seems to be okay now that the controller's
+probe has been updated, but if for some reason the child does not probe
+successfully a SSR or PDR notification will schedule_work() on an
+uninitialized "ngd_up_work".
+
+Move the initialization of these controller resources to the controller
+probe function to avoid any issues, and to clarify the ownership.
+
+Fixes: 917809e2280b ("slimbus: ngd: Add qcom SLIMBus NGD driver")
+Cc: stable@vger.kernel.org
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
+Reviewed-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
+Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+Signed-off-by: Srinivas Kandagatla <srini@kernel.org>
+Link: https://patch.msgid.link/20260530204421.116824-7-srini@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/slimbus/qcom-ngd-ctrl.c |   38 ++++++++++++++++----------------------
+ 1 file changed, 16 insertions(+), 22 deletions(-)
+
+--- a/drivers/slimbus/qcom-ngd-ctrl.c
++++ b/drivers/slimbus/qcom-ngd-ctrl.c
+@@ -1582,25 +1582,8 @@ static int qcom_slim_ngd_probe(struct pl
+       pm_runtime_enable(dev);
+       pm_runtime_get_noresume(dev);
+       ret = qcom_slim_ngd_qmi_svc_event_init(ctrl);
+-      if (ret) {
++      if (ret)
+               dev_err(&pdev->dev, "QMI service registration failed:%d", ret);
+-              return ret;
+-      }
+-
+-      INIT_WORK(&ctrl->m_work, qcom_slim_ngd_master_worker);
+-      INIT_WORK(&ctrl->ngd_up_work, qcom_slim_ngd_up_worker);
+-      ctrl->mwq = create_singlethread_workqueue("ngd_master");
+-      if (!ctrl->mwq) {
+-              dev_err(&pdev->dev, "Failed to start master worker\n");
+-              ret = -ENOMEM;
+-              goto wq_err;
+-      }
+-
+-      return 0;
+-wq_err:
+-      qcom_slim_ngd_qmi_svc_event_deinit(&ctrl->qmi);
+-      if (ctrl->mwq)
+-              destroy_workqueue(ctrl->mwq);
+       return ret;
+ }
+@@ -1653,9 +1636,18 @@ static int qcom_slim_ngd_ctrl_probe(stru
+       init_completion(&ctrl->qmi.qmi_comp);
+       init_completion(&ctrl->qmi_up);
++      INIT_WORK(&ctrl->m_work, qcom_slim_ngd_master_worker);
++      INIT_WORK(&ctrl->ngd_up_work, qcom_slim_ngd_up_worker);
++
++      ctrl->mwq = create_singlethread_workqueue("ngd_master");
++      if (!ctrl->mwq)
++              return dev_err_probe(dev, -ENOMEM, "Failed to start master worker\n");
++
+       ctrl->pdr = pdr_handle_alloc(slim_pd_status, ctrl);
+-      if (IS_ERR(ctrl->pdr))
+-              return dev_err_probe(dev, PTR_ERR(ctrl->pdr), "Failed to init PDR handle\n");
++      if (IS_ERR(ctrl->pdr)) {
++              ret = dev_err_probe(dev, PTR_ERR(ctrl->pdr), "Failed to init PDR handle\n");
++              goto err_destroy_mwq;
++      }
+       ret = of_qcom_slim_ngd_register(dev, ctrl);
+       if (ret)
+@@ -1682,6 +1674,8 @@ err_unregister_ngd:
+       qcom_slim_ngd_unregister(ctrl);
+ err_pdr_release:
+       pdr_handle_release(ctrl->pdr);
++err_destroy_mwq:
++      destroy_workqueue(ctrl->mwq);
+       return ret;
+ }
+@@ -1691,6 +1685,8 @@ static void qcom_slim_ngd_ctrl_remove(st
+       struct qcom_slim_ngd_ctrl *ctrl = platform_get_drvdata(pdev);
+       qcom_slim_ngd_unregister(ctrl);
++
++      destroy_workqueue(ctrl->mwq);
+ }
+ static void qcom_slim_ngd_remove(struct platform_device *pdev)
+@@ -1703,8 +1699,6 @@ static void qcom_slim_ngd_remove(struct
+       qcom_slim_ngd_enable(ctrl, false);
+       qcom_slim_ngd_exit_dma(ctrl);
+       qcom_slim_ngd_qmi_svc_event_deinit(&ctrl->qmi);
+-      if (ctrl->mwq)
+-              destroy_workqueue(ctrl->mwq);
+       kfree(ctrl->ngd);
+       ctrl->ngd = NULL;
diff --git a/queue-7.0/slimbus-qcom-ngd-ctrl-register-callbacks-after-creating-the-ngd.patch b/queue-7.0/slimbus-qcom-ngd-ctrl-register-callbacks-after-creating-the-ngd.patch
new file mode 100644 (file)
index 0000000..28b12de
--- /dev/null
@@ -0,0 +1,133 @@
+From 2a9d50e9ea406e0c8735938484adc20515ef1b47 Mon Sep 17 00:00:00 2001
+From: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+Date: Sat, 30 May 2026 21:44:18 +0100
+Subject: slimbus: qcom-ngd-ctrl: Register callbacks after creating the ngd
+
+From: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+
+commit 2a9d50e9ea406e0c8735938484adc20515ef1b47 upstream.
+
+When the remoteproc starts in parallel with the NGD driver being probed,
+or the remoteproc is already up when the PDR lookup is being registered,
+or in the theoretical event that we get an interrupt from the hardware,
+these callbacks will operate on uninitialized data. This result in
+issues to boot the affected boards.
+
+One such example can be seen in the following fault, where
+qcom_slim_ngd_ssr_pdr_notify() schedules work on the NULL ngd_up_work.
+
+[   21.858578] ------------[ cut here ]------------
+[   21.858745] WARNING: kernel/workqueue.c:2338 at __queue_work+0x5e0/0x790, CPU#2: kworker/2:2/116
+...
+[   21.859251] Call trace:
+[   21.859255]  __queue_work+0x5e0/0x790 (P)
+[   21.859265]  queue_work_on+0x6c/0xf0
+[   21.859273]  qcom_slim_ngd_ssr_pdr_notify+0x110/0x150 [slim_qcom_ngd_ctrl]
+[   21.859304]  qcom_slim_ngd_ssr_notify+0x24/0x40 [slim_qcom_ngd_ctrl]
+[   21.859318]  notifier_call_chain+0xa4/0x230
+[   21.859329]  srcu_notifier_call_chain+0x64/0xb8
+[   21.859338]  ssr_notify_start+0x40/0x78 [qcom_common]
+[   21.859355]  rproc_start+0x130/0x230
+[   21.859367]  rproc_boot+0x3d4/0x518
+...
+
+Move the enablement of interrupts, and the registration of SSR and PDR
+until after the NGD device has been registered.
+
+This could be further refined by moving initialization to the control
+driver probe and by removing the platform driver model from the picture.
+
+Fixes: 917809e2280b ("slimbus: ngd: Add qcom SLIMBus NGD driver")
+Cc: stable@vger.kernel.org
+Reviewed-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
+Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
+Signed-off-by: Srinivas Kandagatla <srini@kernel.org>
+Link: https://patch.msgid.link/20260530204421.116824-6-srini@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/slimbus/qcom-ngd-ctrl.c |   47 ++++++++++++++++++++++------------------
+ 1 file changed, 27 insertions(+), 20 deletions(-)
+
+--- a/drivers/slimbus/qcom-ngd-ctrl.c
++++ b/drivers/slimbus/qcom-ngd-ctrl.c
+@@ -1609,6 +1609,7 @@ static int qcom_slim_ngd_ctrl_probe(stru
+ {
+       struct device *dev = &pdev->dev;
+       struct qcom_slim_ngd_ctrl *ctrl;
++      int irq;
+       int ret;
+       struct pdr_service *pds;
+@@ -1622,20 +1623,16 @@ static int qcom_slim_ngd_ctrl_probe(stru
+       if (IS_ERR(ctrl->base))
+               return PTR_ERR(ctrl->base);
+-      ret = platform_get_irq(pdev, 0);
+-      if (ret < 0)
+-              return ret;
+-
+-      ret = devm_request_irq(dev, ret, qcom_slim_ngd_interrupt,
+-                             IRQF_TRIGGER_HIGH, "slim-ngd", ctrl);
++      irq = platform_get_irq(pdev, 0);
++      if (irq < 0)
++              return irq;
++
++      ret = devm_request_irq(dev, irq, qcom_slim_ngd_interrupt,
++                             IRQF_TRIGGER_HIGH | IRQF_NO_AUTOEN,
++                             "slim-ngd", ctrl);
+       if (ret)
+               return dev_err_probe(&pdev->dev, ret, "request IRQ failed\n");
+-      ctrl->nb.notifier_call = qcom_slim_ngd_ssr_notify;
+-      ctrl->notifier = qcom_register_ssr_notifier("lpass", &ctrl->nb);
+-      if (IS_ERR(ctrl->notifier))
+-              return PTR_ERR(ctrl->notifier);
+-
+       ctrl->dev = dev;
+       ctrl->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
+       ctrl->framer.superfreq =
+@@ -1657,24 +1654,34 @@ static int qcom_slim_ngd_ctrl_probe(stru
+       init_completion(&ctrl->qmi_up);
+       ctrl->pdr = pdr_handle_alloc(slim_pd_status, ctrl);
+-      if (IS_ERR(ctrl->pdr)) {
+-              ret = dev_err_probe(dev, PTR_ERR(ctrl->pdr),
+-                                  "Failed to init PDR handle\n");
+-              goto err_unregister_ssr;
+-      }
++      if (IS_ERR(ctrl->pdr))
++              return dev_err_probe(dev, PTR_ERR(ctrl->pdr), "Failed to init PDR handle\n");
++
++      ret = of_qcom_slim_ngd_register(dev, ctrl);
++      if (ret)
++              goto err_pdr_release;
+       pds = pdr_add_lookup(ctrl->pdr, "avs/audio", "msm/adsp/audio_pd");
+       if (IS_ERR(pds) && PTR_ERR(pds) != -EALREADY) {
+               ret = dev_err_probe(dev, PTR_ERR(pds), "pdr add lookup failed\n");
+-              goto err_pdr_release;
++              goto err_unregister_ngd;
+       }
+-      return of_qcom_slim_ngd_register(dev, ctrl);
++      ctrl->nb.notifier_call = qcom_slim_ngd_ssr_notify;
++      ctrl->notifier = qcom_register_ssr_notifier("lpass", &ctrl->nb);
++      if (IS_ERR(ctrl->notifier)) {
++              ret = PTR_ERR(ctrl->notifier);
++              goto err_unregister_ngd;
++      }
++
++      enable_irq(irq);
++
++      return 0;
++err_unregister_ngd:
++      qcom_slim_ngd_unregister(ctrl);
+ err_pdr_release:
+       pdr_handle_release(ctrl->pdr);
+-err_unregister_ssr:
+-      qcom_unregister_ssr_notifier(ctrl->notifier, &ctrl->nb);
+       return ret;
+ }
diff --git a/queue-7.0/thunderbolt-bound-root-directory-content-to-block-size.patch b/queue-7.0/thunderbolt-bound-root-directory-content-to-block-size.patch
new file mode 100644 (file)
index 0000000..b8df569
--- /dev/null
@@ -0,0 +1,40 @@
+From 65423079c7420e3dbf9a7aa345c243a3f5752e5d Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Mon, 25 May 2026 05:28:26 -0400
+Subject: thunderbolt: Bound root directory content to block size
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+commit 65423079c7420e3dbf9a7aa345c243a3f5752e5d upstream.
+
+__tb_property_parse_dir() does not check that content_offset +
+content_len fits within block_len for the root directory case.
+When rootdir->length equals or exceeds block_len - 2, the entry
+loop reads past the allocated property block.
+
+Add a bounds check after computing content_offset and content_len
+to reject directories whose content extends past the block.
+
+Fixes: cdae7c07e3e3 ("thunderbolt: Add support for XDomain properties")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4-7
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/thunderbolt/property.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/thunderbolt/property.c
++++ b/drivers/thunderbolt/property.c
+@@ -187,6 +187,10 @@ static struct tb_property_dir *__tb_prop
+       if (is_root) {
+               content_offset = dir_offset + 2;
+               content_len = dir_len;
++              if (content_offset + content_len > block_len) {
++                      tb_property_free_dir(dir);
++                      return NULL;
++              }
+       } else {
+               if (dir_len < 4) {
+                       tb_property_free_dir(dir);
diff --git a/queue-7.0/thunderbolt-clamp-xdomain-response-data-copy-to-allocation-size.patch b/queue-7.0/thunderbolt-clamp-xdomain-response-data-copy-to-allocation-size.patch
new file mode 100644 (file)
index 0000000..3236418
--- /dev/null
@@ -0,0 +1,39 @@
+From 322e93448d908434ae5545660fcbe8f5a7a8e141 Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Mon, 25 May 2026 05:28:27 -0400
+Subject: thunderbolt: Clamp XDomain response data copy to allocation size
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+commit 322e93448d908434ae5545660fcbe8f5a7a8e141 upstream.
+
+tb_xdp_properties_request() derives the per-packet copy length from
+the response header without checking that it fits in the previously
+allocated data buffer.  A malicious peer can set its length field
+larger than the declared data_length, causing memcpy to write past
+the kcalloc allocation.
+
+Clamp the per-packet copy length so that the cumulative offset
+never exceeds data_len.
+
+Fixes: cdae7c07e3e3 ("thunderbolt: Add support for XDomain properties")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4-7
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/thunderbolt/xdomain.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/thunderbolt/xdomain.c
++++ b/drivers/thunderbolt/xdomain.c
+@@ -393,6 +393,8 @@ static int tb_xdp_properties_request(str
+                       }
+               }
++              if (req.offset + len > data_len)
++                      len = data_len - req.offset;
+               memcpy(data + req.offset, res->data, len * 4);
+               req.offset += len;
+       } while (!data_len || req.offset < data_len);
diff --git a/queue-7.0/thunderbolt-limit-xdomain-response-copy-to-actual-frame-size.patch b/queue-7.0/thunderbolt-limit-xdomain-response-copy-to-actual-frame-size.patch
new file mode 100644 (file)
index 0000000..046d0e8
--- /dev/null
@@ -0,0 +1,40 @@
+From 4db2bd2ed4785dbadaeeab9f4e346b21ac5fb8eb Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Mon, 25 May 2026 05:28:29 -0400
+Subject: thunderbolt: Limit XDomain response copy to actual frame size
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+commit 4db2bd2ed4785dbadaeeab9f4e346b21ac5fb8eb upstream.
+
+tb_xdomain_copy() copies req->response_size bytes from the received
+packet buffer regardless of the actual frame size.  When a short
+response arrives, this reads past the valid frame data in the DMA
+pool buffer into stale contents from previous transactions.
+
+Use the minimum of frame size and expected response size for the
+copy length.
+
+Fixes: cdae7c07e3e3 ("thunderbolt: Add support for XDomain properties")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4-7
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/thunderbolt/xdomain.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/thunderbolt/xdomain.c
++++ b/drivers/thunderbolt/xdomain.c
+@@ -123,7 +123,9 @@ static bool tb_xdomain_match(const struc
+ static bool tb_xdomain_copy(struct tb_cfg_request *req,
+                           const struct ctl_pkg *pkg)
+ {
+-      memcpy(req->response, pkg->buffer, req->response_size);
++      size_t len = min_t(size_t, pkg->frame.size, req->response_size);
++
++      memcpy(req->response, pkg->buffer, len);
+       req->result.err = 0;
+       return true;
+ }
diff --git a/queue-7.0/thunderbolt-reject-zero-length-property-entries-in-validator.patch b/queue-7.0/thunderbolt-reject-zero-length-property-entries-in-validator.patch
new file mode 100644 (file)
index 0000000..8fecdf8
--- /dev/null
@@ -0,0 +1,42 @@
+From cff8eb65d1eafe7793e54b4d0cf6bf831644630b Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Mon, 25 May 2026 05:28:25 -0400
+Subject: thunderbolt: Reject zero-length property entries in validator
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+commit cff8eb65d1eafe7793e54b4d0cf6bf831644630b upstream.
+
+tb_property_entry_valid() accepts entries with length == 0 for
+DIRECTORY, DATA, and TEXT types.  A zero-length TEXT entry passes
+validation but causes an underflow in the null-termination logic:
+
+  property->value.text[property->length * 4 - 1] = '\0';
+
+When property->length is 0 this writes to offset -1 relative to
+the allocation.
+
+Reject zero-length entries early in the validator since they have no
+valid representation in the XDomain property protocol.
+
+Fixes: cdae7c07e3e3 ("thunderbolt: Add support for XDomain properties")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4-7
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/thunderbolt/property.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/thunderbolt/property.c
++++ b/drivers/thunderbolt/property.c
+@@ -60,6 +60,8 @@ static bool tb_property_entry_valid(cons
+       case TB_PROPERTY_TYPE_DIRECTORY:
+       case TB_PROPERTY_TYPE_DATA:
+       case TB_PROPERTY_TYPE_TEXT:
++              if (!entry->length)
++                      return false;
+               if (entry->length > block_len)
+                       return false;
+               if (check_add_overflow(entry->value, entry->length, &end) ||
diff --git a/queue-7.0/thunderbolt-validate-xdomain-request-packet-size-before-type-cast.patch b/queue-7.0/thunderbolt-validate-xdomain-request-packet-size-before-type-cast.patch
new file mode 100644 (file)
index 0000000..181bcba
--- /dev/null
@@ -0,0 +1,75 @@
+From a504b9f2797b739e0304d537e8aa4ce883ecce39 Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Mon, 25 May 2026 05:28:28 -0400
+Subject: thunderbolt: Validate XDomain request packet size before type cast
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+commit a504b9f2797b739e0304d537e8aa4ce883ecce39 upstream.
+
+tb_xdp_handle_request() casts the received packet buffer to
+protocol-specific structs without verifying that the allocation
+is large enough for the target type.  A peer can send a minimal
+XDomain packet that passes the generic header length check but is
+shorter than the struct accessed after the cast, causing out-of-
+bounds reads from the kmemdup allocation.
+
+Plumb the packet length through xdomain_request_work and validate
+it against the expected struct size before each cast.
+
+Fixes: 8e1de7042596 ("thunderbolt: Add support for XDomain lane bonding")
+Fixes: cdae7c07e3e3 ("thunderbolt: Add support for XDomain properties")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4-7
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/thunderbolt/xdomain.c |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/thunderbolt/xdomain.c
++++ b/drivers/thunderbolt/xdomain.c
+@@ -55,6 +55,7 @@ static const char * const state_names[]
+ struct xdomain_request_work {
+       struct work_struct work;
+       struct tb_xdp_header *pkg;
++      size_t pkg_len;
+       struct tb *tb;
+ };
+@@ -733,6 +734,7 @@ static void tb_xdp_handle_request(struct
+       struct xdomain_request_work *xw = container_of(work, typeof(*xw), work);
+       const struct tb_xdp_header *pkg = xw->pkg;
+       const struct tb_xdomain_header *xhdr = &pkg->xd_hdr;
++      size_t pkg_len = xw->pkg_len;
+       struct tb *tb = xw->tb;
+       struct tb_ctl *ctl = tb->ctl;
+       struct tb_xdomain *xd;
+@@ -764,7 +766,7 @@ static void tb_xdp_handle_request(struct
+       switch (pkg->type) {
+       case PROPERTIES_REQUEST:
+               tb_dbg(tb, "%llx: received XDomain properties request\n", route);
+-              if (xd) {
++              if (xd && pkg_len >= sizeof(struct tb_xdp_properties)) {
+                       ret = tb_xdp_properties_response(tb, ctl, xd, sequence,
+                               (const struct tb_xdp_properties *)pkg);
+               }
+@@ -818,7 +820,8 @@ static void tb_xdp_handle_request(struct
+               tb_dbg(tb, "%llx: received XDomain link state change request\n",
+                      route);
+-              if (xd && xd->state == XDOMAIN_STATE_BONDING_UUID_HIGH) {
++              if (xd && xd->state == XDOMAIN_STATE_BONDING_UUID_HIGH &&
++                  pkg_len >= sizeof(struct tb_xdp_link_state_change)) {
+                       const struct tb_xdp_link_state_change *lsc =
+                               (const struct tb_xdp_link_state_change *)pkg;
+@@ -870,6 +873,7 @@ tb_xdp_schedule_request(struct tb *tb, c
+               kfree(xw);
+               return false;
+       }
++      xw->pkg_len = size;
+       xw->tb = tb_domain_get(tb);
+       schedule_work(&xw->work);