]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 15 Dec 2024 08:44:22 +0000 (09:44 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 15 Dec 2024 08:44:22 +0000 (09:44 +0100)
added patches:
drm-amd-pm-set-smu-v13.0.7-default-workload-type.patch
drm-amdgpu-fix-uvd-contiguous-cs-mapping-problem.patch
drm-amdgpu-fix-when-the-cleaner-shader-is-emitted.patch
drm-amdkfd-dereference-null-return-value.patch
drm-amdkfd-hard-code-cacheline-size-for-gfx11.patch
drm-amdkfd-hard-code-mall-cacheline-size-for-gfx11-gfx12.patch
drm-amdkfd-pause-autosuspend-when-creating-pdd.patch
drm-i915-color-stop-using-non-posted-dsb-writes-for-legacy-lut.patch
drm-i915-fix-memory-leak-by-correcting-cache-object-name-in-error-handler.patch
drm-i915-fix-null-pointer-dereference-in-capture_engine.patch
drm-xe-call-invalidation_fence_fini-for-pt-inval-fences-in-error-state.patch
iommu-tegra241-cmdqv-do-not-use-smp_processor_id-in-preemptible-context.patch
iommu-vt-d-fix-qi_batch-null-pointer-with-nested-parent-domain.patch
iommu-vt-d-remove-cache-tags-before-disabling-ats.patch
usb-dwc3-imx8mp-fix-software-node-kernel-dump.patch
usb-dwc3-xilinx-make-sure-pipe-clock-is-deselected-in-usb2-only-mode.patch
usb-ehci-hcd-fix-call-balance-of-clocks-handling-routines.patch
usb-gadget-midi2-fix-interpretation-of-is_midi1-bits.patch
usb-gadget-u_serial-fix-the-issue-that-gs_start_io-crashed-due-to-accessing-null-pointer.patch
usb-typec-anx7411-fix-fwnode_handle-reference-leak.patch
usb-typec-anx7411-fix-of-node-reference-leaks-in-anx7411_typec_switch_probe.patch
usb-typec-ucsi-fix-completion-notifications.patch
xfs-don-t-drop-errno-values-when-we-fail-to-ficlone-the-entire-range.patch
xfs-fix-null-bno_hint-handling-in-xfs_rtallocate_rtg.patch
xfs-return-a-64-bit-block-count-from-xfs_btree_count_blocks.patch
xfs-set-xfs_sick_ino_symlink_zapped-explicitly-when-zapping-a-symlink.patch
xfs-update-btree-keys-correctly-when-_insrec-splits-an-inode-root-block.patch

28 files changed:
queue-6.12/drm-amd-pm-set-smu-v13.0.7-default-workload-type.patch [new file with mode: 0644]
queue-6.12/drm-amdgpu-fix-uvd-contiguous-cs-mapping-problem.patch [new file with mode: 0644]
queue-6.12/drm-amdgpu-fix-when-the-cleaner-shader-is-emitted.patch [new file with mode: 0644]
queue-6.12/drm-amdkfd-dereference-null-return-value.patch [new file with mode: 0644]
queue-6.12/drm-amdkfd-hard-code-cacheline-size-for-gfx11.patch [new file with mode: 0644]
queue-6.12/drm-amdkfd-hard-code-mall-cacheline-size-for-gfx11-gfx12.patch [new file with mode: 0644]
queue-6.12/drm-amdkfd-pause-autosuspend-when-creating-pdd.patch [new file with mode: 0644]
queue-6.12/drm-i915-color-stop-using-non-posted-dsb-writes-for-legacy-lut.patch [new file with mode: 0644]
queue-6.12/drm-i915-fix-memory-leak-by-correcting-cache-object-name-in-error-handler.patch [new file with mode: 0644]
queue-6.12/drm-i915-fix-null-pointer-dereference-in-capture_engine.patch [new file with mode: 0644]
queue-6.12/drm-xe-call-invalidation_fence_fini-for-pt-inval-fences-in-error-state.patch [new file with mode: 0644]
queue-6.12/iommu-tegra241-cmdqv-do-not-use-smp_processor_id-in-preemptible-context.patch [new file with mode: 0644]
queue-6.12/iommu-vt-d-fix-qi_batch-null-pointer-with-nested-parent-domain.patch [new file with mode: 0644]
queue-6.12/iommu-vt-d-remove-cache-tags-before-disabling-ats.patch [new file with mode: 0644]
queue-6.12/series
queue-6.12/usb-dwc3-imx8mp-fix-software-node-kernel-dump.patch [new file with mode: 0644]
queue-6.12/usb-dwc3-xilinx-make-sure-pipe-clock-is-deselected-in-usb2-only-mode.patch [new file with mode: 0644]
queue-6.12/usb-ehci-hcd-fix-call-balance-of-clocks-handling-routines.patch [new file with mode: 0644]
queue-6.12/usb-gadget-midi2-fix-interpretation-of-is_midi1-bits.patch [new file with mode: 0644]
queue-6.12/usb-gadget-u_serial-fix-the-issue-that-gs_start_io-crashed-due-to-accessing-null-pointer.patch [new file with mode: 0644]
queue-6.12/usb-typec-anx7411-fix-fwnode_handle-reference-leak.patch [new file with mode: 0644]
queue-6.12/usb-typec-anx7411-fix-of-node-reference-leaks-in-anx7411_typec_switch_probe.patch [new file with mode: 0644]
queue-6.12/usb-typec-ucsi-fix-completion-notifications.patch [new file with mode: 0644]
queue-6.12/xfs-don-t-drop-errno-values-when-we-fail-to-ficlone-the-entire-range.patch [new file with mode: 0644]
queue-6.12/xfs-fix-null-bno_hint-handling-in-xfs_rtallocate_rtg.patch [new file with mode: 0644]
queue-6.12/xfs-return-a-64-bit-block-count-from-xfs_btree_count_blocks.patch [new file with mode: 0644]
queue-6.12/xfs-set-xfs_sick_ino_symlink_zapped-explicitly-when-zapping-a-symlink.patch [new file with mode: 0644]
queue-6.12/xfs-update-btree-keys-correctly-when-_insrec-splits-an-inode-root-block.patch [new file with mode: 0644]

diff --git a/queue-6.12/drm-amd-pm-set-smu-v13.0.7-default-workload-type.patch b/queue-6.12/drm-amd-pm-set-smu-v13.0.7-default-workload-type.patch
new file mode 100644 (file)
index 0000000..745bf63
--- /dev/null
@@ -0,0 +1,37 @@
+From 3912a78cf72eb45f8153a395162b08fef9c5ec3d Mon Sep 17 00:00:00 2001
+From: Kenneth Feng <kenneth.feng@amd.com>
+Date: Wed, 4 Dec 2024 13:22:10 +0530
+Subject: drm/amd/pm: Set SMU v13.0.7 default workload type
+
+From: Kenneth Feng <kenneth.feng@amd.com>
+
+commit 3912a78cf72eb45f8153a395162b08fef9c5ec3d upstream.
+
+Set the default workload type to bootup type on smu v13.0.7.
+This is because of the constraint on smu v13.0.7.
+Gfx activity has an even higher set point on 3D fullscreen
+mode than the one on bootup mode. This causes the 3D fullscreen
+mode's performance is worse than the bootup mode's performance
+for the lightweighted/medium workload. For the high workload,
+the performance is the same between 3D fullscreen mode and bootup
+mode.
+
+v2: set the default workload in ASIC specific file
+
+Signed-off-by: Kenneth Feng <kenneth.feng@amd.com>
+Reviewed-by: Yang Wang <kevinyang.wang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org # 6.11.x
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
+@@ -2717,4 +2717,5 @@ void smu_v13_0_7_set_ppt_funcs(struct sm
+       smu->workload_map = smu_v13_0_7_workload_map;
+       smu->smc_driver_if_version = SMU13_0_7_DRIVER_IF_VERSION;
+       smu_v13_0_set_smu_mailbox_registers(smu);
++      smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+ }
diff --git a/queue-6.12/drm-amdgpu-fix-uvd-contiguous-cs-mapping-problem.patch b/queue-6.12/drm-amdgpu-fix-uvd-contiguous-cs-mapping-problem.patch
new file mode 100644 (file)
index 0000000..af6f948
--- /dev/null
@@ -0,0 +1,82 @@
+From 12f325bcd2411e571dbb500bf6862c812c479735 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Fri, 29 Nov 2024 14:19:21 +0100
+Subject: drm/amdgpu: fix UVD contiguous CS mapping problem
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Christian König <christian.koenig@amd.com>
+
+commit 12f325bcd2411e571dbb500bf6862c812c479735 upstream.
+
+When starting the mpv player, Radeon R9 users are observing
+the below error in dmesg.
+
+[drm:amdgpu_uvd_cs_pass2 [amdgpu]]
+*ERROR* msg/fb buffer ff00f7c000-ff00f7e000 out of 256MB segment!
+
+The patch tries to set the TTM_PL_FLAG_CONTIGUOUS for both user
+flag(AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS) set and not set cases.
+
+v2: Make the TTM_PL_FLAG_CONTIGUOUS mandatory for user BO's.
+v3: revert back to v1, but fix the check instead (chk).
+
+Closes:https://gitlab.freedesktop.org/drm/amd/-/issues/3599
+Closes:https://gitlab.freedesktop.org/drm/amd/-/issues/3501
+Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com>
+Signed-off-by: Christian König <christian.koenig@amd.com>
+Reviewed-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org # 6.10+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c  | 17 +++++++++++------
+ drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c |  2 ++
+ 2 files changed, 13 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+index d891ab779ca7..5df21529b3b1 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+@@ -1801,13 +1801,18 @@ int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser,
+       if (dma_resv_locking_ctx((*bo)->tbo.base.resv) != &parser->exec.ticket)
+               return -EINVAL;
++      /* Make sure VRAM is allocated contigiously */
+       (*bo)->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
+-      amdgpu_bo_placement_from_domain(*bo, (*bo)->allowed_domains);
+-      for (i = 0; i < (*bo)->placement.num_placement; i++)
+-              (*bo)->placements[i].flags |= TTM_PL_FLAG_CONTIGUOUS;
+-      r = ttm_bo_validate(&(*bo)->tbo, &(*bo)->placement, &ctx);
+-      if (r)
+-              return r;
++      if ((*bo)->tbo.resource->mem_type == TTM_PL_VRAM &&
++          !((*bo)->tbo.resource->placement & TTM_PL_FLAG_CONTIGUOUS)) {
++
++              amdgpu_bo_placement_from_domain(*bo, (*bo)->allowed_domains);
++              for (i = 0; i < (*bo)->placement.num_placement; i++)
++                      (*bo)->placements[i].flags |= TTM_PL_FLAG_CONTIGUOUS;
++              r = ttm_bo_validate(&(*bo)->tbo, &(*bo)->placement, &ctx);
++              if (r)
++                      return r;
++      }
+       return amdgpu_ttm_alloc_gart(&(*bo)->tbo);
+ }
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+index 31fd30dcd593..65bb26215e86 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+@@ -551,6 +551,8 @@ static void amdgpu_uvd_force_into_uvd_segment(struct amdgpu_bo *abo)
+       for (i = 0; i < abo->placement.num_placement; ++i) {
+               abo->placements[i].fpfn = 0 >> PAGE_SHIFT;
+               abo->placements[i].lpfn = (256 * 1024 * 1024) >> PAGE_SHIFT;
++              if (abo->placements[i].mem_type == TTM_PL_VRAM)
++                      abo->placements[i].flags |= TTM_PL_FLAG_CONTIGUOUS;
+       }
+ }
+-- 
+2.47.1
+
diff --git a/queue-6.12/drm-amdgpu-fix-when-the-cleaner-shader-is-emitted.patch b/queue-6.12/drm-amdgpu-fix-when-the-cleaner-shader-is-emitted.patch
new file mode 100644 (file)
index 0000000..d116512
--- /dev/null
@@ -0,0 +1,67 @@
+From f4df208177d02f1c90f3644da3a2453080b8c24f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Fri, 6 Dec 2024 14:46:06 +0100
+Subject: drm/amdgpu: fix when the cleaner shader is emitted
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Christian König <christian.koenig@amd.com>
+
+commit f4df208177d02f1c90f3644da3a2453080b8c24f upstream.
+
+Emitting the cleaner shader must come after the check if a VM switch is
+necessary or not.
+
+Otherwise we will emit the cleaner shader every time and not just when it is
+necessary because we switched between applications.
+
+This can otherwise crash on gang submit and probably decreases performance
+quite a bit.
+
+v2: squash in fix from Srini (Alex)
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+Fixes: ee7a846ea27b ("drm/amdgpu: Emit cleaner shader at end of IB submission")
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+index 8d9bf7a0857f..ddd7f05e4db9 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+@@ -674,12 +674,8 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
+       pasid_mapping_needed &= adev->gmc.gmc_funcs->emit_pasid_mapping &&
+               ring->funcs->emit_wreg;
+-      if (adev->gfx.enable_cleaner_shader &&
+-          ring->funcs->emit_cleaner_shader &&
+-          job->enforce_isolation)
+-              ring->funcs->emit_cleaner_shader(ring);
+-
+-      if (!vm_flush_needed && !gds_switch_needed && !need_pipe_sync)
++      if (!vm_flush_needed && !gds_switch_needed && !need_pipe_sync &&
++          !(job->enforce_isolation && !job->vmid))
+               return 0;
+       amdgpu_ring_ib_begin(ring);
+@@ -690,6 +686,11 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
+       if (need_pipe_sync)
+               amdgpu_ring_emit_pipeline_sync(ring);
++      if (adev->gfx.enable_cleaner_shader &&
++          ring->funcs->emit_cleaner_shader &&
++          job->enforce_isolation)
++              ring->funcs->emit_cleaner_shader(ring);
++
+       if (vm_flush_needed) {
+               trace_amdgpu_vm_flush(ring, job->vmid, job->vm_pd_addr);
+               amdgpu_ring_emit_vm_flush(ring, job->vmid, job->vm_pd_addr);
+-- 
+2.47.1
+
diff --git a/queue-6.12/drm-amdkfd-dereference-null-return-value.patch b/queue-6.12/drm-amdkfd-dereference-null-return-value.patch
new file mode 100644 (file)
index 0000000..7030162
--- /dev/null
@@ -0,0 +1,52 @@
+From a592bb19abdc2072875c87da606461bfd7821b08 Mon Sep 17 00:00:00 2001
+From: Andrew Martin <Andrew.Martin@amd.com>
+Date: Tue, 26 Nov 2024 12:10:59 -0500
+Subject: drm/amdkfd: Dereference null return value
+
+From: Andrew Martin <Andrew.Martin@amd.com>
+
+commit a592bb19abdc2072875c87da606461bfd7821b08 upstream.
+
+In the function pqm_uninit there is a call-assignment of "pdd =
+kfd_get_process_device_data" which could be null, and this value was
+later dereferenced without checking.
+
+Fixes: fb91065851cd ("drm/amdkfd: Refactor queue wptr_bo GART mapping")
+Signed-off-by: Andrew Martin <Andrew.Martin@amd.com>
+Reviewed-by: Felix Kuehling <felix.kuehling@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../gpu/drm/amd/amdkfd/kfd_process_queue_manager.c   | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
+index c76db22a1000..59b92d66e958 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
+@@ -212,13 +212,17 @@ static void pqm_clean_queue_resource(struct process_queue_manager *pqm,
+ void pqm_uninit(struct process_queue_manager *pqm)
+ {
+       struct process_queue_node *pqn, *next;
+-      struct kfd_process_device *pdd;
+       list_for_each_entry_safe(pqn, next, &pqm->queues, process_queue_list) {
+               if (pqn->q) {
+-                      pdd = kfd_get_process_device_data(pqn->q->device, pqm->process);
+-                      kfd_queue_unref_bo_vas(pdd, &pqn->q->properties);
+-                      kfd_queue_release_buffers(pdd, &pqn->q->properties);
++                      struct kfd_process_device *pdd = kfd_get_process_device_data(pqn->q->device,
++                                                                                   pqm->process);
++                      if (pdd) {
++                              kfd_queue_unref_bo_vas(pdd, &pqn->q->properties);
++                              kfd_queue_release_buffers(pdd, &pqn->q->properties);
++                      } else {
++                              WARN_ON(!pdd);
++                      }
+                       pqm_clean_queue_resource(pqm, pqn);
+               }
+-- 
+2.47.1
+
diff --git a/queue-6.12/drm-amdkfd-hard-code-cacheline-size-for-gfx11.patch b/queue-6.12/drm-amdkfd-hard-code-cacheline-size-for-gfx11.patch
new file mode 100644 (file)
index 0000000..3cb7650
--- /dev/null
@@ -0,0 +1,103 @@
+From 321048c4a3e375416b51b4093978f9ce2aa4d391 Mon Sep 17 00:00:00 2001
+From: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
+Date: Wed, 27 Nov 2024 14:01:35 -0500
+Subject: drm/amdkfd: hard-code cacheline size for gfx11
+
+From: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
+
+commit 321048c4a3e375416b51b4093978f9ce2aa4d391 upstream.
+
+This information is not available in ip discovery table.
+
+Signed-off-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
+Reviewed-by: David Belanger <david.belanger@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdkfd/kfd_crat.c |   22 ++++++++++++++++++++--
+ 1 file changed, 20 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+@@ -1422,6 +1422,7 @@ err:
+ static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
++                                                 bool cache_line_size_missing,
+                                                  struct kfd_gpu_cache_info *pcache_info)
+ {
+       struct amdgpu_device *adev = kdev->adev;
+@@ -1436,6 +1437,8 @@ static int kfd_fill_gpu_cache_info_from_
+                                       CRAT_CACHE_FLAGS_SIMD_CACHE);
+               pcache_info[i].num_cu_shared = adev->gfx.config.gc_num_tcp_per_wpg / 2;
+               pcache_info[i].cache_line_size = adev->gfx.config.gc_tcp_cache_line_size;
++              if (cache_line_size_missing && !pcache_info[i].cache_line_size)
++                      pcache_info[i].cache_line_size = 128;
+               i++;
+       }
+       /* Scalar L1 Instruction Cache per SQC */
+@@ -1448,6 +1451,8 @@ static int kfd_fill_gpu_cache_info_from_
+                                       CRAT_CACHE_FLAGS_SIMD_CACHE);
+               pcache_info[i].num_cu_shared = adev->gfx.config.gc_num_sqc_per_wgp * 2;
+               pcache_info[i].cache_line_size = adev->gfx.config.gc_instruction_cache_line_size;
++              if (cache_line_size_missing && !pcache_info[i].cache_line_size)
++                      pcache_info[i].cache_line_size = 128;
+               i++;
+       }
+       /* Scalar L1 Data Cache per SQC */
+@@ -1459,6 +1464,8 @@ static int kfd_fill_gpu_cache_info_from_
+                                       CRAT_CACHE_FLAGS_SIMD_CACHE);
+               pcache_info[i].num_cu_shared = adev->gfx.config.gc_num_sqc_per_wgp * 2;
+               pcache_info[i].cache_line_size = adev->gfx.config.gc_scalar_data_cache_line_size;
++              if (cache_line_size_missing && !pcache_info[i].cache_line_size)
++                      pcache_info[i].cache_line_size = 64;
+               i++;
+       }
+       /* GL1 Data Cache per SA */
+@@ -1471,7 +1478,8 @@ static int kfd_fill_gpu_cache_info_from_
+                                       CRAT_CACHE_FLAGS_DATA_CACHE |
+                                       CRAT_CACHE_FLAGS_SIMD_CACHE);
+               pcache_info[i].num_cu_shared = adev->gfx.config.max_cu_per_sh;
+-              pcache_info[i].cache_line_size = 0;
++              if (cache_line_size_missing)
++                      pcache_info[i].cache_line_size = 128;
+               i++;
+       }
+       /* L2 Data Cache per GPU (Total Tex Cache) */
+@@ -1483,6 +1491,8 @@ static int kfd_fill_gpu_cache_info_from_
+                                       CRAT_CACHE_FLAGS_SIMD_CACHE);
+               pcache_info[i].num_cu_shared = adev->gfx.config.max_cu_per_sh;
+               pcache_info[i].cache_line_size = adev->gfx.config.gc_tcc_cache_line_size;
++              if (cache_line_size_missing && !pcache_info[i].cache_line_size)
++                      pcache_info[i].cache_line_size = 128;
+               i++;
+       }
+       /* L3 Data Cache per GPU */
+@@ -1568,6 +1578,7 @@ static int kfd_fill_gpu_cache_info_from_
+ int kfd_get_gpu_cache_info(struct kfd_node *kdev, struct kfd_gpu_cache_info **pcache_info)
+ {
+       int num_of_cache_types = 0;
++      bool cache_line_size_missing = false;
+       switch (kdev->adev->asic_type) {
+       case CHIP_KAVERI:
+@@ -1691,10 +1702,17 @@ int kfd_get_gpu_cache_info(struct kfd_no
+               case IP_VERSION(11, 5, 0):
+               case IP_VERSION(11, 5, 1):
+               case IP_VERSION(11, 5, 2):
++                      /* Cacheline size not available in IP discovery for gc11.
++                       * kfd_fill_gpu_cache_info_from_gfx_config to hard code it
++                       */
++                      cache_line_size_missing = true;
++                      fallthrough;
+               case IP_VERSION(12, 0, 0):
+               case IP_VERSION(12, 0, 1):
+                       num_of_cache_types =
+-                              kfd_fill_gpu_cache_info_from_gfx_config(kdev->kfd, *pcache_info);
++                              kfd_fill_gpu_cache_info_from_gfx_config(kdev->kfd,
++                                                                      cache_line_size_missing,
++                                                                      *pcache_info);
+                       break;
+               default:
+                       *pcache_info = dummy_cache_info;
diff --git a/queue-6.12/drm-amdkfd-hard-code-mall-cacheline-size-for-gfx11-gfx12.patch b/queue-6.12/drm-amdkfd-hard-code-mall-cacheline-size-for-gfx11-gfx12.patch
new file mode 100644 (file)
index 0000000..e96d187
--- /dev/null
@@ -0,0 +1,31 @@
+From d50bf3f0fab636574c163ba8b5863e12b1ed19bd Mon Sep 17 00:00:00 2001
+From: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
+Date: Thu, 28 Nov 2024 11:07:57 -0500
+Subject: drm/amdkfd: hard-code MALL cacheline size for gfx11, gfx12
+
+From: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
+
+commit d50bf3f0fab636574c163ba8b5863e12b1ed19bd upstream.
+
+This information is not available in ip discovery table.
+
+Signed-off-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
+Reviewed-by: David Belanger <david.belanger@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdkfd/kfd_crat.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+@@ -1503,7 +1503,7 @@ static int kfd_fill_gpu_cache_info_from_
+                                       CRAT_CACHE_FLAGS_DATA_CACHE |
+                                       CRAT_CACHE_FLAGS_SIMD_CACHE);
+               pcache_info[i].num_cu_shared = adev->gfx.config.max_cu_per_sh;
+-              pcache_info[i].cache_line_size = 0;
++              pcache_info[i].cache_line_size = 64;
+               i++;
+       }
+       return i;
diff --git a/queue-6.12/drm-amdkfd-pause-autosuspend-when-creating-pdd.patch b/queue-6.12/drm-amdkfd-pause-autosuspend-when-creating-pdd.patch
new file mode 100644 (file)
index 0000000..46d04dd
--- /dev/null
@@ -0,0 +1,105 @@
+From 438b39ac74e2a9dc0a5c9d653b7d8066877e86b1 Mon Sep 17 00:00:00 2001
+From: "Jesse.zhang@amd.com" <Jesse.zhang@amd.com>
+Date: Thu, 5 Dec 2024 17:41:26 +0800
+Subject: drm/amdkfd: pause autosuspend when creating pdd
+
+From: Jesse.zhang@amd.com <Jesse.zhang@amd.com>
+
+commit 438b39ac74e2a9dc0a5c9d653b7d8066877e86b1 upstream.
+
+When using MES creating a pdd will require talking to the GPU to
+setup the relevant context. The code here forgot to wake up the GPU
+in case it was in suspend, this causes KVM to EFAULT for passthrough
+GPU for example. This issue can be masked if the GPU was woken up by
+other things (e.g. opening the KMS node) first and have not yet gone to sleep.
+
+v4: do the allocation of proc_ctx_bo in a lazy fashion
+when the first queue is created in a process (Felix)
+
+Signed-off-by: Jesse Zhang <jesse.zhang@amd.com>
+Reviewed-by: Yunxiang Li <Yunxiang.Li@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c |   15 +++++++++++
+ drivers/gpu/drm/amd/amdkfd/kfd_process.c              |   23 +-----------------
+ 2 files changed, 17 insertions(+), 21 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+@@ -205,6 +205,21 @@ static int add_queue_mes(struct device_q
+       if (!down_read_trylock(&adev->reset_domain->sem))
+               return -EIO;
++      if (!pdd->proc_ctx_cpu_ptr) {
++              r = amdgpu_amdkfd_alloc_gtt_mem(adev,
++                              AMDGPU_MES_PROC_CTX_SIZE,
++                              &pdd->proc_ctx_bo,
++                              &pdd->proc_ctx_gpu_addr,
++                              &pdd->proc_ctx_cpu_ptr,
++                              false);
++              if (r) {
++                      dev_err(adev->dev,
++                              "failed to allocate process context bo\n");
++                      return r;
++              }
++              memset(pdd->proc_ctx_cpu_ptr, 0, AMDGPU_MES_PROC_CTX_SIZE);
++      }
++
+       memset(&queue_input, 0x0, sizeof(struct mes_add_queue_input));
+       queue_input.process_id = qpd->pqm->process->pasid;
+       queue_input.page_table_base_addr =  qpd->page_table_base;
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+@@ -1076,7 +1076,8 @@ static void kfd_process_destroy_pdds(str
+               kfd_free_process_doorbells(pdd->dev->kfd, pdd);
+-              if (pdd->dev->kfd->shared_resources.enable_mes)
++              if (pdd->dev->kfd->shared_resources.enable_mes &&
++                      pdd->proc_ctx_cpu_ptr)
+                       amdgpu_amdkfd_free_gtt_mem(pdd->dev->adev,
+                                                  &pdd->proc_ctx_bo);
+               /*
+@@ -1610,7 +1611,6 @@ struct kfd_process_device *kfd_create_pr
+                                                       struct kfd_process *p)
+ {
+       struct kfd_process_device *pdd = NULL;
+-      int retval = 0;
+       if (WARN_ON_ONCE(p->n_pdds >= MAX_GPU_INSTANCE))
+               return NULL;
+@@ -1634,21 +1634,6 @@ struct kfd_process_device *kfd_create_pr
+       pdd->user_gpu_id = dev->id;
+       atomic64_set(&pdd->evict_duration_counter, 0);
+-      if (dev->kfd->shared_resources.enable_mes) {
+-              retval = amdgpu_amdkfd_alloc_gtt_mem(dev->adev,
+-                                              AMDGPU_MES_PROC_CTX_SIZE,
+-                                              &pdd->proc_ctx_bo,
+-                                              &pdd->proc_ctx_gpu_addr,
+-                                              &pdd->proc_ctx_cpu_ptr,
+-                                              false);
+-              if (retval) {
+-                      dev_err(dev->adev->dev,
+-                              "failed to allocate process context bo\n");
+-                      goto err_free_pdd;
+-              }
+-              memset(pdd->proc_ctx_cpu_ptr, 0, AMDGPU_MES_PROC_CTX_SIZE);
+-      }
+-
+       p->pdds[p->n_pdds++] = pdd;
+       if (kfd_dbg_is_per_vmid_supported(pdd->dev))
+               pdd->spi_dbg_override = pdd->dev->kfd2kgd->disable_debug_trap(
+@@ -1660,10 +1645,6 @@ struct kfd_process_device *kfd_create_pr
+       idr_init(&pdd->alloc_idr);
+       return pdd;
+-
+-err_free_pdd:
+-      kfree(pdd);
+-      return NULL;
+ }
+ /**
diff --git a/queue-6.12/drm-i915-color-stop-using-non-posted-dsb-writes-for-legacy-lut.patch b/queue-6.12/drm-i915-color-stop-using-non-posted-dsb-writes-for-legacy-lut.patch
new file mode 100644 (file)
index 0000000..14fa499
--- /dev/null
@@ -0,0 +1,105 @@
+From cd3da567e2e46b8f75549637b960a83b024d6b6e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com>
+Date: Wed, 20 Nov 2024 18:41:21 +0200
+Subject: drm/i915/color: Stop using non-posted DSB writes for legacy LUT
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ville Syrjälä <ville.syrjala@linux.intel.com>
+
+commit cd3da567e2e46b8f75549637b960a83b024d6b6e upstream.
+
+DSB LUT register writes vs. palette anti-collision logic
+appear to interact in interesting ways:
+- posted DSB writes simply vanish into thin air while
+  anti-collision is active
+- non-posted DSB writes actually get blocked by the anti-collision
+  logic, but unfortunately this ends up hogging the bus for
+  long enough that unrelated parallel CPU MMIO accesses start
+  to disappear instead
+
+Even though we are updating the LUT during vblank we aren't
+immune to the anti-collision logic because it kicks in briefly
+for pipe prefill (initiated at frame start). The safe time
+window for performing the LUT update is thus between the
+undelayed vblank and frame start. Turns out that with low
+enough CDCLK frequency (DSB execution speed depends on CDCLK)
+we can exceed that.
+
+As we are currently using non-posted writes for the legacy LUT
+updates, in which case we can hit the far more severe failure
+mode. The problem is exacerbated by the fact that non-posted
+writes are much slower than posted writes (~4x it seems).
+
+To mititage the problem let's switch to using posted DSB
+writes for legacy LUT updates (which will involve using the
+double write approach to avoid other problems with DSB
+vs. legacy LUT writes). Despite writing each register twice
+this will in fact make the legacy LUT update faster when
+compared to the non-posted write approach, making the
+problem less likely to appear. The failure mode is also
+less severe.
+
+This isn't the 100% solution we need though. That will involve
+estimating how long the LUT update will take, and pushing
+frame start and/or delayed vblank forward to guarantee that
+the update will have finished by the time the pipe prefill
+starts...
+
+Cc: stable@vger.kernel.org
+Fixes: 34d8311f4a1c ("drm/i915/dsb: Re-instate DSB for LUT updates")
+Fixes: 25ea3411bd23 ("drm/i915/dsb: Use non-posted register writes for legacy LUT")
+Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12494
+Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20241120164123.12706-3-ville.syrjala@linux.intel.com
+Reviewed-by: Uma Shankar <uma.shankar@intel.com>
+(cherry picked from commit 2504a316b35d49522f39cf0dc01830d7c36a9be4)
+Signed-off-by: Tvrtko Ursulin <tursulin@ursulin.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/display/intel_color.c |   30 +++++++++++++++++++----------
+ 1 file changed, 20 insertions(+), 10 deletions(-)
+
+--- a/drivers/gpu/drm/i915/display/intel_color.c
++++ b/drivers/gpu/drm/i915/display/intel_color.c
+@@ -1333,19 +1333,29 @@ static void ilk_load_lut_8(const struct
+       lut = blob->data;
+       /*
+-       * DSB fails to correctly load the legacy LUT
+-       * unless we either write each entry twice,
+-       * or use non-posted writes
++       * DSB fails to correctly load the legacy LUT unless
++       * we either write each entry twice when using posted
++       * writes, or we use non-posted writes.
++       *
++       * If palette anti-collision is active during LUT
++       * register writes:
++       * - posted writes simply get dropped and thus the LUT
++       *   contents may not be correctly updated
++       * - non-posted writes are blocked and thus the LUT
++       *   contents are always correct, but simultaneous CPU
++       *   MMIO access will start to fail
++       *
++       * Choose the lesser of two evils and use posted writes.
++       * Using posted writes is also faster, even when having
++       * to write each register twice.
+        */
+-      if (crtc_state->dsb_color_vblank)
+-              intel_dsb_nonpost_start(crtc_state->dsb_color_vblank);
+-
+-      for (i = 0; i < 256; i++)
++      for (i = 0; i < 256; i++) {
+               ilk_lut_write(crtc_state, LGC_PALETTE(pipe, i),
+                             i9xx_lut_8(&lut[i]));
+-
+-      if (crtc_state->dsb_color_vblank)
+-              intel_dsb_nonpost_end(crtc_state->dsb_color_vblank);
++              if (crtc_state->dsb_color_vblank)
++                      ilk_lut_write(crtc_state, LGC_PALETTE(pipe, i),
++                                    i9xx_lut_8(&lut[i]));
++      }
+ }
+ static void ilk_load_lut_10(const struct intel_crtc_state *crtc_state,
diff --git a/queue-6.12/drm-i915-fix-memory-leak-by-correcting-cache-object-name-in-error-handler.patch b/queue-6.12/drm-i915-fix-memory-leak-by-correcting-cache-object-name-in-error-handler.patch
new file mode 100644 (file)
index 0000000..cda1da5
--- /dev/null
@@ -0,0 +1,36 @@
+From 2828e5808bcd5aae7fdcd169cac1efa2701fa2dd Mon Sep 17 00:00:00 2001
+From: Jiasheng Jiang <jiashengjiangcool@outlook.com>
+Date: Wed, 27 Nov 2024 20:10:42 +0000
+Subject: drm/i915: Fix memory leak by correcting cache object name in error handler
+
+From: Jiasheng Jiang <jiashengjiangcool@outlook.com>
+
+commit 2828e5808bcd5aae7fdcd169cac1efa2701fa2dd upstream.
+
+Replace "slab_priorities" with "slab_dependencies" in the error handler
+to avoid memory leak.
+
+Fixes: 32eb6bcfdda9 ("drm/i915: Make request allocation caches global")
+Cc: <stable@vger.kernel.org> # v5.2+
+Signed-off-by: Jiasheng Jiang <jiashengjiangcool@outlook.com>
+Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
+Reviewed-by: Andi Shyti <andi.shyti@linux.intel.com>
+Signed-off-by: Andi Shyti <andi.shyti@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20241127201042.29620-1-jiashengjiangcool@gmail.com
+(cherry picked from commit 9bc5e7dc694d3112bbf0fa4c46ef0fa0f114937a)
+Signed-off-by: Tvrtko Ursulin <tursulin@ursulin.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/i915_scheduler.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i915/i915_scheduler.c
++++ b/drivers/gpu/drm/i915/i915_scheduler.c
+@@ -506,6 +506,6 @@ int __init i915_scheduler_module_init(vo
+       return 0;
+ err_priorities:
+-      kmem_cache_destroy(slab_priorities);
++      kmem_cache_destroy(slab_dependencies);
+       return -ENOMEM;
+ }
diff --git a/queue-6.12/drm-i915-fix-null-pointer-dereference-in-capture_engine.patch b/queue-6.12/drm-i915-fix-null-pointer-dereference-in-capture_engine.patch
new file mode 100644 (file)
index 0000000..3e7214b
--- /dev/null
@@ -0,0 +1,54 @@
+From da0b986256ae9a78b0215214ff44f271bfe237c1 Mon Sep 17 00:00:00 2001
+From: Eugene Kobyak <eugene.kobyak@intel.com>
+Date: Tue, 3 Dec 2024 14:54:06 +0000
+Subject: drm/i915: Fix NULL pointer dereference in capture_engine
+
+From: Eugene Kobyak <eugene.kobyak@intel.com>
+
+commit da0b986256ae9a78b0215214ff44f271bfe237c1 upstream.
+
+When the intel_context structure contains NULL,
+it raises a NULL pointer dereference error in drm_info().
+
+Fixes: e8a3319c31a1 ("drm/i915: Allow error capture without a request")
+Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12309
+Reviewed-by: Andi Shyti <andi.shyti@linux.intel.com>
+Cc: John Harrison <John.C.Harrison@Intel.com>
+Cc: <stable@vger.kernel.org> # v6.3+
+Signed-off-by: Eugene Kobyak <eugene.kobyak@intel.com>
+Signed-off-by: Andi Shyti <andi.shyti@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/xmsgfynkhycw3cf56akp4he2ffg44vuratocsysaowbsnhutzi@augnqbm777at
+(cherry picked from commit 754302a5bc1bd8fd3b7d85c168b0a1af6d4bba4d)
+Signed-off-by: Tvrtko Ursulin <tursulin@ursulin.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/i915_gpu_error.c |   18 +++++++++++++++---
+ 1 file changed, 15 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/i915/i915_gpu_error.c
++++ b/drivers/gpu/drm/i915/i915_gpu_error.c
+@@ -1652,9 +1652,21 @@ capture_engine(struct intel_engine_cs *e
+               return NULL;
+       intel_engine_get_hung_entity(engine, &ce, &rq);
+-      if (rq && !i915_request_started(rq))
+-              drm_info(&engine->gt->i915->drm, "Got hung context on %s with active request %lld:%lld [0x%04X] not yet started\n",
+-                       engine->name, rq->fence.context, rq->fence.seqno, ce->guc_id.id);
++      if (rq && !i915_request_started(rq)) {
++              /*
++               * We want to know also what is the guc_id of the context,
++               * but if we don't have the context reference, then skip
++               * printing it.
++               */
++              if (ce)
++                      drm_info(&engine->gt->i915->drm,
++                               "Got hung context on %s with active request %lld:%lld [0x%04X] not yet started\n",
++                               engine->name, rq->fence.context, rq->fence.seqno, ce->guc_id.id);
++              else
++                      drm_info(&engine->gt->i915->drm,
++                               "Got hung context on %s with active request %lld:%lld not yet started\n",
++                               engine->name, rq->fence.context, rq->fence.seqno);
++      }
+       if (rq) {
+               capture = intel_engine_coredump_add_request(ee, rq, ATOMIC_MAYFAIL);
diff --git a/queue-6.12/drm-xe-call-invalidation_fence_fini-for-pt-inval-fences-in-error-state.patch b/queue-6.12/drm-xe-call-invalidation_fence_fini-for-pt-inval-fences-in-error-state.patch
new file mode 100644 (file)
index 0000000..4a5f7c1
--- /dev/null
@@ -0,0 +1,86 @@
+From cefade70f346160f47cc24776160329e2ee63653 Mon Sep 17 00:00:00 2001
+From: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
+Date: Thu, 5 Dec 2024 17:50:22 -0800
+Subject: drm/xe: Call invalidation_fence_fini for PT inval fences in error state
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
+
+commit cefade70f346160f47cc24776160329e2ee63653 upstream.
+
+Invalidation_fence_init takes a PM reference, which is released in its
+_fini counterpart, so we need to make sure that the latter is called,
+even if the fence is in an error state.
+
+Since we already have a function that calls _fini() and signals the
+fence in the tlb inval code, we can expose that and call it from the PT
+code.
+
+Fixes: f002702290fc ("drm/xe: Hold a PM ref when GT TLB invalidations are inflight")
+Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
+Cc: <stable@vger.kernel.org> # v6.11+
+Cc: Matthew Brost <matthew.brost@intel.com>
+Cc: Nirmoy Das <nirmoy.das@intel.com>
+Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
+Reviewed-by: Matthew Brost <matthew.brost@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20241206015022.1567113-1-daniele.ceraolospurio@intel.com
+(cherry picked from commit 65338639b79ce88aef5263cd518cde570a3c7c8e)
+Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c | 8 ++++++++
+ drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h | 1 +
+ drivers/gpu/drm/xe/xe_pt.c                  | 3 +--
+ 3 files changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
+index 3cb228c773cd..6146d1776bda 100644
+--- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
++++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
+@@ -65,6 +65,14 @@ invalidation_fence_signal(struct xe_device *xe, struct xe_gt_tlb_invalidation_fe
+       __invalidation_fence_signal(xe, fence);
+ }
++void xe_gt_tlb_invalidation_fence_signal(struct xe_gt_tlb_invalidation_fence *fence)
++{
++      if (WARN_ON_ONCE(!fence->gt))
++              return;
++
++      __invalidation_fence_signal(gt_to_xe(fence->gt), fence);
++}
++
+ static void xe_gt_tlb_fence_timeout(struct work_struct *work)
+ {
+       struct xe_gt *gt = container_of(work, struct xe_gt,
+diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
+index f430d5797af7..00b1c6c01e8d 100644
+--- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
++++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
+@@ -28,6 +28,7 @@ int xe_guc_tlb_invalidation_done_handler(struct xe_guc *guc, u32 *msg, u32 len);
+ void xe_gt_tlb_invalidation_fence_init(struct xe_gt *gt,
+                                      struct xe_gt_tlb_invalidation_fence *fence,
+                                      bool stack);
++void xe_gt_tlb_invalidation_fence_signal(struct xe_gt_tlb_invalidation_fence *fence);
+ static inline void
+ xe_gt_tlb_invalidation_fence_wait(struct xe_gt_tlb_invalidation_fence *fence)
+diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
+index f27f579f4d85..797576690356 100644
+--- a/drivers/gpu/drm/xe/xe_pt.c
++++ b/drivers/gpu/drm/xe/xe_pt.c
+@@ -1333,8 +1333,7 @@ static void invalidation_fence_cb(struct dma_fence *fence,
+               queue_work(system_wq, &ifence->work);
+       } else {
+               ifence->base.base.error = ifence->fence->error;
+-              dma_fence_signal(&ifence->base.base);
+-              dma_fence_put(&ifence->base.base);
++              xe_gt_tlb_invalidation_fence_signal(&ifence->base);
+       }
+       dma_fence_put(ifence->fence);
+ }
+-- 
+2.47.1
+
diff --git a/queue-6.12/iommu-tegra241-cmdqv-do-not-use-smp_processor_id-in-preemptible-context.patch b/queue-6.12/iommu-tegra241-cmdqv-do-not-use-smp_processor_id-in-preemptible-context.patch
new file mode 100644 (file)
index 0000000..dcbbf27
--- /dev/null
@@ -0,0 +1,47 @@
+From 1f806218164d1bb93f3db21eaf61254b08acdf03 Mon Sep 17 00:00:00 2001
+From: "Luis Claudio R. Goncalves" <lgoncalv@redhat.com>
+Date: Fri, 6 Dec 2024 10:01:14 -0300
+Subject: iommu/tegra241-cmdqv: do not use smp_processor_id in preemptible context
+
+From: Luis Claudio R. Goncalves <lgoncalv@redhat.com>
+
+commit 1f806218164d1bb93f3db21eaf61254b08acdf03 upstream.
+
+During boot some of the calls to tegra241_cmdqv_get_cmdq() will happen
+in preemptible context. As this function calls smp_processor_id(), if
+CONFIG_DEBUG_PREEMPT is enabled, these calls will trigger a series of
+"BUG: using smp_processor_id() in preemptible" backtraces.
+
+As tegra241_cmdqv_get_cmdq() only calls smp_processor_id() to use the
+CPU number as a factor to balance out traffic on cmdq usage, it is safe
+to use raw_smp_processor_id() here.
+
+Cc: <stable@vger.kernel.org>
+Fixes: 918eb5c856f6 ("iommu/arm-smmu-v3: Add in-kernel support for NVIDIA Tegra241 (Grace) CMDQV")
+Signed-off-by: Luis Claudio R. Goncalves <lgoncalv@redhat.com>
+Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
+Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
+Tested-by: Nicolin Chen <nicolinc@nvidia.com>
+Link: https://lore.kernel.org/r/Z1L1mja3nXzsJ0Pk@uudg.org
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c
+index c8ec74f089f3..6e41ddaa24d6 100644
+--- a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c
++++ b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c
+@@ -339,7 +339,7 @@ tegra241_cmdqv_get_cmdq(struct arm_smmu_device *smmu,
+        * one CPU at a time can enter the process, while the others
+        * will be spinning at the same lock.
+        */
+-      lidx = smp_processor_id() % cmdqv->num_lvcmdqs_per_vintf;
++      lidx = raw_smp_processor_id() % cmdqv->num_lvcmdqs_per_vintf;
+       vcmdq = vintf->lvcmdqs[lidx];
+       if (!vcmdq || !READ_ONCE(vcmdq->enabled))
+               return NULL;
+-- 
+2.47.1
+
diff --git a/queue-6.12/iommu-vt-d-fix-qi_batch-null-pointer-with-nested-parent-domain.patch b/queue-6.12/iommu-vt-d-fix-qi_batch-null-pointer-with-nested-parent-domain.patch
new file mode 100644 (file)
index 0000000..bdab700
--- /dev/null
@@ -0,0 +1,125 @@
+From 74536f91962d5f6af0a42414773ce61e653c10ee Mon Sep 17 00:00:00 2001
+From: Yi Liu <yi.l.liu@intel.com>
+Date: Fri, 13 Dec 2024 09:17:51 +0800
+Subject: iommu/vt-d: Fix qi_batch NULL pointer with nested parent domain
+
+From: Yi Liu <yi.l.liu@intel.com>
+
+commit 74536f91962d5f6af0a42414773ce61e653c10ee upstream.
+
+The qi_batch is allocated when assigning cache tag for a domain. While
+for nested parent domain, it is missed. Hence, when trying to map pages
+to the nested parent, NULL dereference occurred. Also, there is potential
+memleak since there is no lock around domain->qi_batch allocation.
+
+To solve it, add a helper for qi_batch allocation, and call it in both
+the __cache_tag_assign_domain() and __cache_tag_assign_parent_domain().
+
+  BUG: kernel NULL pointer dereference, address: 0000000000000200
+  #PF: supervisor read access in kernel mode
+  #PF: error_code(0x0000) - not-present page
+  PGD 8104795067 P4D 0
+  Oops: Oops: 0000 [#1] PREEMPT SMP NOPTI
+  CPU: 223 UID: 0 PID: 4357 Comm: qemu-system-x86 Not tainted 6.13.0-rc1-00028-g4b50c3c3b998-dirty #2632
+  Call Trace:
+   ? __die+0x24/0x70
+   ? page_fault_oops+0x80/0x150
+   ? do_user_addr_fault+0x63/0x7b0
+   ? exc_page_fault+0x7c/0x220
+   ? asm_exc_page_fault+0x26/0x30
+   ? cache_tag_flush_range_np+0x13c/0x260
+   intel_iommu_iotlb_sync_map+0x1a/0x30
+   iommu_map+0x61/0xf0
+   batch_to_domain+0x188/0x250
+   iopt_area_fill_domains+0x125/0x320
+   ? rcu_is_watching+0x11/0x50
+   iopt_map_pages+0x63/0x100
+   iopt_map_common.isra.0+0xa7/0x190
+   iopt_map_user_pages+0x6a/0x80
+   iommufd_ioas_map+0xcd/0x1d0
+   iommufd_fops_ioctl+0x118/0x1c0
+   __x64_sys_ioctl+0x93/0xc0
+   do_syscall_64+0x71/0x140
+   entry_SYSCALL_64_after_hwframe+0x76/0x7e
+
+Fixes: 705c1cdf1e73 ("iommu/vt-d: Introduce batched cache invalidation")
+Cc: stable@vger.kernel.org
+Co-developed-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Yi Liu <yi.l.liu@intel.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Link: https://lore.kernel.org/r/20241210130322.17175-1-yi.l.liu@intel.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/intel/cache.c | 34 +++++++++++++++++++++++++++-------
+ 1 file changed, 27 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/iommu/intel/cache.c b/drivers/iommu/intel/cache.c
+index e5b89f728ad3..09694cca8752 100644
+--- a/drivers/iommu/intel/cache.c
++++ b/drivers/iommu/intel/cache.c
+@@ -105,12 +105,35 @@ static void cache_tag_unassign(struct dmar_domain *domain, u16 did,
+       spin_unlock_irqrestore(&domain->cache_lock, flags);
+ }
++/* domain->qi_batch will be freed in iommu_free_domain() path. */
++static int domain_qi_batch_alloc(struct dmar_domain *domain)
++{
++      unsigned long flags;
++      int ret = 0;
++
++      spin_lock_irqsave(&domain->cache_lock, flags);
++      if (domain->qi_batch)
++              goto out_unlock;
++
++      domain->qi_batch = kzalloc(sizeof(*domain->qi_batch), GFP_ATOMIC);
++      if (!domain->qi_batch)
++              ret = -ENOMEM;
++out_unlock:
++      spin_unlock_irqrestore(&domain->cache_lock, flags);
++
++      return ret;
++}
++
+ static int __cache_tag_assign_domain(struct dmar_domain *domain, u16 did,
+                                    struct device *dev, ioasid_t pasid)
+ {
+       struct device_domain_info *info = dev_iommu_priv_get(dev);
+       int ret;
++      ret = domain_qi_batch_alloc(domain);
++      if (ret)
++              return ret;
++
+       ret = cache_tag_assign(domain, did, dev, pasid, CACHE_TAG_IOTLB);
+       if (ret || !info->ats_enabled)
+               return ret;
+@@ -139,6 +162,10 @@ static int __cache_tag_assign_parent_domain(struct dmar_domain *domain, u16 did,
+       struct device_domain_info *info = dev_iommu_priv_get(dev);
+       int ret;
++      ret = domain_qi_batch_alloc(domain);
++      if (ret)
++              return ret;
++
+       ret = cache_tag_assign(domain, did, dev, pasid, CACHE_TAG_NESTING_IOTLB);
+       if (ret || !info->ats_enabled)
+               return ret;
+@@ -190,13 +217,6 @@ int cache_tag_assign_domain(struct dmar_domain *domain,
+       u16 did = domain_get_id_for_dev(domain, dev);
+       int ret;
+-      /* domain->qi_bach will be freed in iommu_free_domain() path. */
+-      if (!domain->qi_batch) {
+-              domain->qi_batch = kzalloc(sizeof(*domain->qi_batch), GFP_KERNEL);
+-              if (!domain->qi_batch)
+-                      return -ENOMEM;
+-      }
+-
+       ret = __cache_tag_assign_domain(domain, did, dev, pasid);
+       if (ret || domain->domain.type != IOMMU_DOMAIN_NESTED)
+               return ret;
+-- 
+2.47.1
+
diff --git a/queue-6.12/iommu-vt-d-remove-cache-tags-before-disabling-ats.patch b/queue-6.12/iommu-vt-d-remove-cache-tags-before-disabling-ats.patch
new file mode 100644 (file)
index 0000000..2400938
--- /dev/null
@@ -0,0 +1,72 @@
+From 1f2557e08a617a4b5e92a48a1a9a6f86621def18 Mon Sep 17 00:00:00 2001
+From: Lu Baolu <baolu.lu@linux.intel.com>
+Date: Fri, 13 Dec 2024 09:17:50 +0800
+Subject: iommu/vt-d: Remove cache tags before disabling ATS
+
+From: Lu Baolu <baolu.lu@linux.intel.com>
+
+commit 1f2557e08a617a4b5e92a48a1a9a6f86621def18 upstream.
+
+The current implementation removes cache tags after disabling ATS,
+leading to potential memory leaks and kernel crashes. Specifically,
+CACHE_TAG_DEVTLB type cache tags may still remain in the list even
+after the domain is freed, causing a use-after-free condition.
+
+This issue really shows up when multiple VFs from different PFs
+passed through to a single user-space process via vfio-pci. In such
+cases, the kernel may crash with kernel messages like:
+
+ BUG: kernel NULL pointer dereference, address: 0000000000000014
+ PGD 19036a067 P4D 1940a3067 PUD 136c9b067 PMD 0
+ Oops: Oops: 0000 [#1] PREEMPT SMP NOPTI
+ CPU: 74 UID: 0 PID: 3183 Comm: testCli Not tainted 6.11.9 #2
+ RIP: 0010:cache_tag_flush_range+0x9b/0x250
+ Call Trace:
+  <TASK>
+  ? __die+0x1f/0x60
+  ? page_fault_oops+0x163/0x590
+  ? exc_page_fault+0x72/0x190
+  ? asm_exc_page_fault+0x22/0x30
+  ? cache_tag_flush_range+0x9b/0x250
+  ? cache_tag_flush_range+0x5d/0x250
+  intel_iommu_tlb_sync+0x29/0x40
+  intel_iommu_unmap_pages+0xfe/0x160
+  __iommu_unmap+0xd8/0x1a0
+  vfio_unmap_unpin+0x182/0x340 [vfio_iommu_type1]
+  vfio_remove_dma+0x2a/0xb0 [vfio_iommu_type1]
+  vfio_iommu_type1_ioctl+0xafa/0x18e0 [vfio_iommu_type1]
+
+Move cache_tag_unassign_domain() before iommu_disable_pci_caps() to fix
+it.
+
+Fixes: 3b1d9e2b2d68 ("iommu/vt-d: Add cache tag assignment interface")
+Cc: stable@vger.kernel.org
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Link: https://lore.kernel.org/r/20241129020506.576413-1-baolu.lu@linux.intel.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/intel/iommu.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -3372,6 +3372,9 @@ void device_block_translation(struct dev
+       struct intel_iommu *iommu = info->iommu;
+       unsigned long flags;
++      if (info->domain)
++              cache_tag_unassign_domain(info->domain, dev, IOMMU_NO_PASID);
++
+       iommu_disable_pci_caps(info);
+       if (!dev_is_real_dma_subdevice(dev)) {
+               if (sm_supported(iommu))
+@@ -3388,7 +3391,6 @@ void device_block_translation(struct dev
+       list_del(&info->link);
+       spin_unlock_irqrestore(&info->domain->lock, flags);
+-      cache_tag_unassign_domain(info->domain, dev, IOMMU_NO_PASID);
+       domain_detach_iommu(info->domain, iommu);
+       info->domain = NULL;
+ }
index 930df99310c95f902c3f0db89f77e2f175792b5a..492fd2029a6cb724be3fcd8167effbe8e3691356 100644 (file)
@@ -42,3 +42,30 @@ usb-dwc2-fix-hcd-resume.patch
 usb-dwc2-hcd-fix-getportstatus-setportfeature.patch
 usb-dwc2-fix-hcd-port-connection-race.patch
 scsi-ufs-core-update-compl_time_stamp_local_clock-after-completing-a-cqe.patch
+usb-gadget-midi2-fix-interpretation-of-is_midi1-bits.patch
+usb-ehci-hcd-fix-call-balance-of-clocks-handling-routines.patch
+usb-typec-anx7411-fix-fwnode_handle-reference-leak.patch
+usb-dwc3-imx8mp-fix-software-node-kernel-dump.patch
+usb-typec-anx7411-fix-of-node-reference-leaks-in-anx7411_typec_switch_probe.patch
+usb-gadget-u_serial-fix-the-issue-that-gs_start_io-crashed-due-to-accessing-null-pointer.patch
+usb-typec-ucsi-fix-completion-notifications.patch
+usb-dwc3-xilinx-make-sure-pipe-clock-is-deselected-in-usb2-only-mode.patch
+iommu-tegra241-cmdqv-do-not-use-smp_processor_id-in-preemptible-context.patch
+iommu-vt-d-remove-cache-tags-before-disabling-ats.patch
+iommu-vt-d-fix-qi_batch-null-pointer-with-nested-parent-domain.patch
+drm-xe-call-invalidation_fence_fini-for-pt-inval-fences-in-error-state.patch
+drm-amdkfd-pause-autosuspend-when-creating-pdd.patch
+drm-i915-fix-memory-leak-by-correcting-cache-object-name-in-error-handler.patch
+drm-i915-color-stop-using-non-posted-dsb-writes-for-legacy-lut.patch
+drm-i915-fix-null-pointer-dereference-in-capture_engine.patch
+drm-amdgpu-fix-uvd-contiguous-cs-mapping-problem.patch
+drm-amd-pm-set-smu-v13.0.7-default-workload-type.patch
+drm-amdgpu-fix-when-the-cleaner-shader-is-emitted.patch
+drm-amdkfd-dereference-null-return-value.patch
+drm-amdkfd-hard-code-cacheline-size-for-gfx11.patch
+drm-amdkfd-hard-code-mall-cacheline-size-for-gfx11-gfx12.patch
+xfs-set-xfs_sick_ino_symlink_zapped-explicitly-when-zapping-a-symlink.patch
+xfs-update-btree-keys-correctly-when-_insrec-splits-an-inode-root-block.patch
+xfs-don-t-drop-errno-values-when-we-fail-to-ficlone-the-entire-range.patch
+xfs-return-a-64-bit-block-count-from-xfs_btree_count_blocks.patch
+xfs-fix-null-bno_hint-handling-in-xfs_rtallocate_rtg.patch
diff --git a/queue-6.12/usb-dwc3-imx8mp-fix-software-node-kernel-dump.patch b/queue-6.12/usb-dwc3-imx8mp-fix-software-node-kernel-dump.patch
new file mode 100644 (file)
index 0000000..2cf076f
--- /dev/null
@@ -0,0 +1,128 @@
+From a4faee01179a4d9cbad9ba6be2da8637c68c1438 Mon Sep 17 00:00:00 2001
+From: Xu Yang <xu.yang_2@nxp.com>
+Date: Tue, 26 Nov 2024 11:28:41 +0800
+Subject: usb: dwc3: imx8mp: fix software node kernel dump
+
+From: Xu Yang <xu.yang_2@nxp.com>
+
+commit a4faee01179a4d9cbad9ba6be2da8637c68c1438 upstream.
+
+When unbind and bind the device again, kernel will dump below warning:
+
+[  173.972130] sysfs: cannot create duplicate filename '/devices/platform/soc/4c010010.usb/software_node'
+[  173.981564] CPU: 2 UID: 0 PID: 536 Comm: sh Not tainted 6.12.0-rc6-06344-g2aed7c4a5c56 #144
+[  173.989923] Hardware name: NXP i.MX95 15X15 board (DT)
+[  173.995062] Call trace:
+[  173.997509]  dump_backtrace+0x90/0xe8
+[  174.001196]  show_stack+0x18/0x24
+[  174.004524]  dump_stack_lvl+0x74/0x8c
+[  174.008198]  dump_stack+0x18/0x24
+[  174.011526]  sysfs_warn_dup+0x64/0x80
+[  174.015201]  sysfs_do_create_link_sd+0xf0/0xf8
+[  174.019656]  sysfs_create_link+0x20/0x40
+[  174.023590]  software_node_notify+0x90/0x100
+[  174.027872]  device_create_managed_software_node+0xec/0x108
+...
+
+The '4c010010.usb' device is a platform device created during the initcall
+and is never removed, which causes its associated software node to persist
+indefinitely.
+
+The existing device_create_managed_software_node() does not provide a
+corresponding removal function.
+
+Replace device_create_managed_software_node() with the
+device_add_software_node() and device_remove_software_node() pair to ensure
+proper addition and removal of software nodes, addressing this issue.
+
+Fixes: a9400f1979a0 ("usb: dwc3: imx8mp: add 2 software managed quirk properties for host mode")
+Cc: stable@vger.kernel.org
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
+Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Link: https://lore.kernel.org/r/20241126032841.2458338-1-xu.yang_2@nxp.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/dwc3-imx8mp.c | 30 ++++++++++++++++--------------
+ 1 file changed, 16 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/usb/dwc3/dwc3-imx8mp.c b/drivers/usb/dwc3/dwc3-imx8mp.c
+index 356812cbcd88..3edc5aca76f9 100644
+--- a/drivers/usb/dwc3/dwc3-imx8mp.c
++++ b/drivers/usb/dwc3/dwc3-imx8mp.c
+@@ -129,6 +129,16 @@ static void dwc3_imx8mp_wakeup_disable(struct dwc3_imx8mp *dwc3_imx)
+       writel(val, dwc3_imx->hsio_blk_base + USB_WAKEUP_CTRL);
+ }
++static const struct property_entry dwc3_imx8mp_properties[] = {
++      PROPERTY_ENTRY_BOOL("xhci-missing-cas-quirk"),
++      PROPERTY_ENTRY_BOOL("xhci-skip-phy-init-quirk"),
++      {},
++};
++
++static const struct software_node dwc3_imx8mp_swnode = {
++      .properties = dwc3_imx8mp_properties,
++};
++
+ static irqreturn_t dwc3_imx8mp_interrupt(int irq, void *_dwc3_imx)
+ {
+       struct dwc3_imx8mp      *dwc3_imx = _dwc3_imx;
+@@ -148,17 +158,6 @@ static irqreturn_t dwc3_imx8mp_interrupt(int irq, void *_dwc3_imx)
+       return IRQ_HANDLED;
+ }
+-static int dwc3_imx8mp_set_software_node(struct device *dev)
+-{
+-      struct property_entry props[3] = { 0 };
+-      int prop_idx = 0;
+-
+-      props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-missing-cas-quirk");
+-      props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-skip-phy-init-quirk");
+-
+-      return device_create_managed_software_node(dev, props, NULL);
+-}
+-
+ static int dwc3_imx8mp_probe(struct platform_device *pdev)
+ {
+       struct device           *dev = &pdev->dev;
+@@ -221,17 +220,17 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev)
+       if (err < 0)
+               goto disable_rpm;
+-      err = dwc3_imx8mp_set_software_node(dev);
++      err = device_add_software_node(dev, &dwc3_imx8mp_swnode);
+       if (err) {
+               err = -ENODEV;
+-              dev_err(dev, "failed to create software node\n");
++              dev_err(dev, "failed to add software node\n");
+               goto disable_rpm;
+       }
+       err = of_platform_populate(node, NULL, NULL, dev);
+       if (err) {
+               dev_err(&pdev->dev, "failed to create dwc3 core\n");
+-              goto disable_rpm;
++              goto remove_swnode;
+       }
+       dwc3_imx->dwc3 = of_find_device_by_node(dwc3_np);
+@@ -255,6 +254,8 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev)
+ depopulate:
+       of_platform_depopulate(dev);
++remove_swnode:
++      device_remove_software_node(dev);
+ disable_rpm:
+       pm_runtime_disable(dev);
+       pm_runtime_put_noidle(dev);
+@@ -268,6 +269,7 @@ static void dwc3_imx8mp_remove(struct platform_device *pdev)
+       pm_runtime_get_sync(dev);
+       of_platform_depopulate(dev);
++      device_remove_software_node(dev);
+       pm_runtime_disable(dev);
+       pm_runtime_put_noidle(dev);
+-- 
+2.47.1
+
diff --git a/queue-6.12/usb-dwc3-xilinx-make-sure-pipe-clock-is-deselected-in-usb2-only-mode.patch b/queue-6.12/usb-dwc3-xilinx-make-sure-pipe-clock-is-deselected-in-usb2-only-mode.patch
new file mode 100644 (file)
index 0000000..c78987e
--- /dev/null
@@ -0,0 +1,44 @@
+From a48f744bef9ee74814a9eccb030b02223e48c76c Mon Sep 17 00:00:00 2001
+From: Neal Frager <neal.frager@amd.com>
+Date: Mon, 2 Dec 2024 23:41:51 +0530
+Subject: usb: dwc3: xilinx: make sure pipe clock is deselected in usb2 only mode
+
+From: Neal Frager <neal.frager@amd.com>
+
+commit a48f744bef9ee74814a9eccb030b02223e48c76c upstream.
+
+When the USB3 PHY is not defined in the Linux device tree, there could
+still be a case where there is a USB3 PHY active on the board and enabled
+by the first stage bootloader. If serdes clock is being used then the USB
+will fail to enumerate devices in 2.0 only mode.
+
+To solve this, make sure that the PIPE clock is deselected whenever the
+USB3 PHY is not defined and guarantees that the USB2 only mode will work
+in all cases.
+
+Fixes: 9678f3361afc ("usb: dwc3: xilinx: Skip resets and USB3 register settings for USB2.0 mode")
+Cc: stable@vger.kernel.org
+Signed-off-by: Neal Frager <neal.frager@amd.com>
+Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
+Acked-by: Peter Korsgaard <peter@korsgaard.com>
+Link: https://lore.kernel.org/r/1733163111-1414816-1-git-send-email-radhey.shyam.pandey@amd.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/dwc3-xilinx.c |    5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/dwc3/dwc3-xilinx.c
++++ b/drivers/usb/dwc3/dwc3-xilinx.c
+@@ -121,8 +121,11 @@ static int dwc3_xlnx_init_zynqmp(struct
+        * in use but the usb3-phy entry is missing from the device tree.
+        * Therefore, skip these operations in this case.
+        */
+-      if (!priv_data->usb3_phy)
++      if (!priv_data->usb3_phy) {
++              /* Deselect the PIPE Clock Select bit in FPD PIPE Clock register */
++              writel(PIPE_CLK_DESELECT, priv_data->regs + XLNX_USB_FPD_PIPE_CLK);
+               goto skip_usb3_phy;
++      }
+       crst = devm_reset_control_get_exclusive(dev, "usb_crst");
+       if (IS_ERR(crst)) {
diff --git a/queue-6.12/usb-ehci-hcd-fix-call-balance-of-clocks-handling-routines.patch b/queue-6.12/usb-ehci-hcd-fix-call-balance-of-clocks-handling-routines.patch
new file mode 100644 (file)
index 0000000..805cb9e
--- /dev/null
@@ -0,0 +1,52 @@
+From 97264eaaba0122a5b7e8ddd7bf4ff3ac57c2b170 Mon Sep 17 00:00:00 2001
+From: Vitalii Mordan <mordan@ispras.ru>
+Date: Thu, 21 Nov 2024 14:47:00 +0300
+Subject: usb: ehci-hcd: fix call balance of clocks handling routines
+
+From: Vitalii Mordan <mordan@ispras.ru>
+
+commit 97264eaaba0122a5b7e8ddd7bf4ff3ac57c2b170 upstream.
+
+If the clocks priv->iclk and priv->fclk were not enabled in ehci_hcd_sh_probe,
+they should not be disabled in any path.
+
+Conversely, if they was enabled in ehci_hcd_sh_probe, they must be disabled
+in all error paths to ensure proper cleanup.
+
+Found by Linux Verification Center (linuxtesting.org) with Klever.
+
+Fixes: 63c845522263 ("usb: ehci-hcd: Add support for SuperH EHCI.")
+Cc: stable@vger.kernel.org # ff30bd6a6618: sh: clk: Fix clk_enable() to return 0 on NULL clk
+Signed-off-by: Vitalii Mordan <mordan@ispras.ru>
+Reviewed-by: Alan Stern <stern@rowland.harvard.edu>
+Link: https://lore.kernel.org/r/20241121114700.2100520-1-mordan@ispras.ru
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/ehci-sh.c |    9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/ehci-sh.c
++++ b/drivers/usb/host/ehci-sh.c
+@@ -119,8 +119,12 @@ static int ehci_hcd_sh_probe(struct plat
+       if (IS_ERR(priv->iclk))
+               priv->iclk = NULL;
+-      clk_enable(priv->fclk);
+-      clk_enable(priv->iclk);
++      ret = clk_enable(priv->fclk);
++      if (ret)
++              goto fail_request_resource;
++      ret = clk_enable(priv->iclk);
++      if (ret)
++              goto fail_iclk;
+       ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+       if (ret != 0) {
+@@ -136,6 +140,7 @@ static int ehci_hcd_sh_probe(struct plat
+ fail_add_hcd:
+       clk_disable(priv->iclk);
++fail_iclk:
+       clk_disable(priv->fclk);
+ fail_request_resource:
diff --git a/queue-6.12/usb-gadget-midi2-fix-interpretation-of-is_midi1-bits.patch b/queue-6.12/usb-gadget-midi2-fix-interpretation-of-is_midi1-bits.patch
new file mode 100644 (file)
index 0000000..2610de5
--- /dev/null
@@ -0,0 +1,40 @@
+From 82937056967da052cbc04b4435c13db84192dc52 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 27 Nov 2024 08:02:11 +0100
+Subject: usb: gadget: midi2: Fix interpretation of is_midi1 bits
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 82937056967da052cbc04b4435c13db84192dc52 upstream.
+
+The UMP Function Block info m1.0 field (represented by is_midi1 sysfs
+entry) is an enumeration from 0 to 2, while the midi2 gadget driver
+incorrectly copies it to the corresponding snd_ump_block_info.flags
+bits as-is.  This made the wrong bit flags set when m1.0 = 2.
+
+This patch corrects the wrong interpretation of is_midi1 bits.
+
+Fixes: 29ee7a4dddd5 ("usb: gadget: midi2: Add configfs support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Link: https://lore.kernel.org/r/20241127070213.8232-1-tiwai@suse.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/f_midi2.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/function/f_midi2.c
++++ b/drivers/usb/gadget/function/f_midi2.c
+@@ -1593,7 +1593,11 @@ static int f_midi2_create_card(struct f_
+                       fb->info.midi_ci_version = b->midi_ci_version;
+                       fb->info.ui_hint = reverse_dir(b->ui_hint);
+                       fb->info.sysex8_streams = b->sysex8_streams;
+-                      fb->info.flags |= b->is_midi1;
++                      if (b->is_midi1 < 2)
++                              fb->info.flags |= b->is_midi1;
++                      else
++                              fb->info.flags |= SNDRV_UMP_BLOCK_IS_MIDI1 |
++                                      SNDRV_UMP_BLOCK_IS_LOWSPEED;
+                       strscpy(fb->info.name, ump_fb_name(b),
+                               sizeof(fb->info.name));
+               }
diff --git a/queue-6.12/usb-gadget-u_serial-fix-the-issue-that-gs_start_io-crashed-due-to-accessing-null-pointer.patch b/queue-6.12/usb-gadget-u_serial-fix-the-issue-that-gs_start_io-crashed-due-to-accessing-null-pointer.patch
new file mode 100644 (file)
index 0000000..e262284
--- /dev/null
@@ -0,0 +1,81 @@
+From 4cfbca86f6a8b801f3254e0e3c8f2b1d2d64be2b Mon Sep 17 00:00:00 2001
+From: Lianqin Hu <hulianqin@vivo.com>
+Date: Tue, 3 Dec 2024 12:14:16 +0000
+Subject: usb: gadget: u_serial: Fix the issue that gs_start_io crashed due to accessing null pointer
+
+From: Lianqin Hu <hulianqin@vivo.com>
+
+commit 4cfbca86f6a8b801f3254e0e3c8f2b1d2d64be2b upstream.
+
+Considering that in some extreme cases,
+when u_serial driver is accessed by multiple threads,
+Thread A is executing the open operation and calling the gs_open,
+Thread B is executing the disconnect operation and calling the
+gserial_disconnect function,The port->port_usb pointer will be set to NULL.
+
+E.g.
+    Thread A                                 Thread B
+    gs_open()                                gadget_unbind_driver()
+    gs_start_io()                            composite_disconnect()
+    gs_start_rx()                            gserial_disconnect()
+    ...                                      ...
+    spin_unlock(&port->port_lock)
+    status = usb_ep_queue()                  spin_lock(&port->port_lock)
+    spin_lock(&port->port_lock)              port->port_usb = NULL
+    gs_free_requests(port->port_usb->in)     spin_unlock(&port->port_lock)
+    Crash
+
+This causes thread A to access a null pointer (port->port_usb is null)
+when calling the gs_free_requests function, causing a crash.
+
+If port_usb is NULL, the release request will be skipped as it
+will be done by gserial_disconnect.
+
+So add a null pointer check to gs_start_io before attempting
+to access the value of the pointer port->port_usb.
+
+Call trace:
+ gs_start_io+0x164/0x25c
+ gs_open+0x108/0x13c
+ tty_open+0x314/0x638
+ chrdev_open+0x1b8/0x258
+ do_dentry_open+0x2c4/0x700
+ vfs_open+0x2c/0x3c
+ path_openat+0xa64/0xc60
+ do_filp_open+0xb8/0x164
+ do_sys_openat2+0x84/0xf0
+ __arm64_sys_openat+0x70/0x9c
+ invoke_syscall+0x58/0x114
+ el0_svc_common+0x80/0xe0
+ do_el0_svc+0x1c/0x28
+ el0_svc+0x38/0x68
+
+Fixes: c1dca562be8a ("usb gadget: split out serial core")
+Cc: stable@vger.kernel.org
+Suggested-by: Prashanth K <quic_prashk@quicinc.com>
+Signed-off-by: Lianqin Hu <hulianqin@vivo.com>
+Acked-by: Prashanth K <quic_prashk@quicinc.com>
+Link: https://lore.kernel.org/r/TYUPR06MB62178DC3473F9E1A537DCD02D2362@TYUPR06MB6217.apcprd06.prod.outlook.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/u_serial.c |    9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/gadget/function/u_serial.c
++++ b/drivers/usb/gadget/function/u_serial.c
+@@ -579,9 +579,12 @@ static int gs_start_io(struct gs_port *p
+                * we didn't in gs_start_tx() */
+               tty_wakeup(port->port.tty);
+       } else {
+-              gs_free_requests(ep, head, &port->read_allocated);
+-              gs_free_requests(port->port_usb->in, &port->write_pool,
+-                      &port->write_allocated);
++              /* Free reqs only if we are still connected */
++              if (port->port_usb) {
++                      gs_free_requests(ep, head, &port->read_allocated);
++                      gs_free_requests(port->port_usb->in, &port->write_pool,
++                              &port->write_allocated);
++              }
+               status = -EIO;
+       }
diff --git a/queue-6.12/usb-typec-anx7411-fix-fwnode_handle-reference-leak.patch b/queue-6.12/usb-typec-anx7411-fix-fwnode_handle-reference-leak.patch
new file mode 100644 (file)
index 0000000..8b63f6c
--- /dev/null
@@ -0,0 +1,160 @@
+From 645d56e4cc74e953284809d096532c1955918a28 Mon Sep 17 00:00:00 2001
+From: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp>
+Date: Thu, 21 Nov 2024 11:34:29 +0900
+Subject: usb: typec: anx7411: fix fwnode_handle reference leak
+
+From: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp>
+
+commit 645d56e4cc74e953284809d096532c1955918a28 upstream.
+
+An fwnode_handle and usb_role_switch are obtained with an incremented
+refcount in anx7411_typec_port_probe(), however the refcounts are not
+decremented in the error path. The fwnode_handle is also not decremented
+in the .remove() function. Therefore, call fwnode_handle_put() and
+usb_role_switch_put() accordingly.
+
+Fixes: fe6d8a9c8e64 ("usb: typec: anx7411: Add Analogix PD ANX7411 support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://lore.kernel.org/r/20241121023429.962848-1-joe@pf.is.s.u-tokyo.ac.jp
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/anx7411.c | 47 +++++++++++++++++++++++--------------
+ 1 file changed, 29 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/usb/typec/anx7411.c b/drivers/usb/typec/anx7411.c
+index d1e7c487ddfb..95607efb9f7e 100644
+--- a/drivers/usb/typec/anx7411.c
++++ b/drivers/usb/typec/anx7411.c
+@@ -1021,6 +1021,16 @@ static void anx7411_port_unregister_altmodes(struct typec_altmode **adev)
+               }
+ }
++static void anx7411_port_unregister(struct typec_params *typecp)
++{
++      fwnode_handle_put(typecp->caps.fwnode);
++      anx7411_port_unregister_altmodes(typecp->port_amode);
++      if (typecp->port)
++              typec_unregister_port(typecp->port);
++      if (typecp->role_sw)
++              usb_role_switch_put(typecp->role_sw);
++}
++
+ static int anx7411_usb_mux_set(struct typec_mux_dev *mux,
+                              struct typec_mux_state *state)
+ {
+@@ -1154,34 +1164,34 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
+       ret = fwnode_property_read_string(fwnode, "power-role", &buf);
+       if (ret) {
+               dev_err(dev, "power-role not found: %d\n", ret);
+-              return ret;
++              goto put_fwnode;
+       }
+       ret = typec_find_port_power_role(buf);
+       if (ret < 0)
+-              return ret;
++              goto put_fwnode;
+       cap->type = ret;
+       ret = fwnode_property_read_string(fwnode, "data-role", &buf);
+       if (ret) {
+               dev_err(dev, "data-role not found: %d\n", ret);
+-              return ret;
++              goto put_fwnode;
+       }
+       ret = typec_find_port_data_role(buf);
+       if (ret < 0)
+-              return ret;
++              goto put_fwnode;
+       cap->data = ret;
+       ret = fwnode_property_read_string(fwnode, "try-power-role", &buf);
+       if (ret) {
+               dev_err(dev, "try-power-role not found: %d\n", ret);
+-              return ret;
++              goto put_fwnode;
+       }
+       ret = typec_find_power_role(buf);
+       if (ret < 0)
+-              return ret;
++              goto put_fwnode;
+       cap->prefer_role = ret;
+       /* Get source pdos */
+@@ -1193,7 +1203,7 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
+                                                    typecp->src_pdo_nr);
+               if (ret < 0) {
+                       dev_err(dev, "source cap validate failed: %d\n", ret);
+-                      return -EINVAL;
++                      goto put_fwnode;
+               }
+               typecp->caps_flags |= HAS_SOURCE_CAP;
+@@ -1207,7 +1217,7 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
+                                                    typecp->sink_pdo_nr);
+               if (ret < 0) {
+                       dev_err(dev, "sink cap validate failed: %d\n", ret);
+-                      return -EINVAL;
++                      goto put_fwnode;
+               }
+               for (i = 0; i < typecp->sink_pdo_nr; i++) {
+@@ -1251,13 +1261,21 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
+               ret = PTR_ERR(ctx->typec.port);
+               ctx->typec.port = NULL;
+               dev_err(dev, "Failed to register type c port %d\n", ret);
+-              return ret;
++              goto put_usb_role_switch;
+       }
+       typec_port_register_altmodes(ctx->typec.port, NULL, ctx,
+                                    ctx->typec.port_amode,
+                                    MAX_ALTMODE);
+       return 0;
++
++put_usb_role_switch:
++      if (ctx->typec.role_sw)
++              usb_role_switch_put(ctx->typec.role_sw);
++put_fwnode:
++      fwnode_handle_put(fwnode);
++
++      return ret;
+ }
+ static int anx7411_typec_check_connection(struct anx7411_data *ctx)
+@@ -1523,8 +1541,7 @@ free_wq:
+       destroy_workqueue(plat->workqueue);
+ free_typec_port:
+-      typec_unregister_port(plat->typec.port);
+-      anx7411_port_unregister_altmodes(plat->typec.port_amode);
++      anx7411_port_unregister(&plat->typec);
+ free_typec_switch:
+       anx7411_unregister_switch(plat);
+@@ -1548,17 +1565,11 @@ static void anx7411_i2c_remove(struct i2c_client *client)
+       i2c_unregister_device(plat->spi_client);
+-      if (plat->typec.role_sw)
+-              usb_role_switch_put(plat->typec.role_sw);
+-
+       anx7411_unregister_mux(plat);
+       anx7411_unregister_switch(plat);
+-      if (plat->typec.port)
+-              typec_unregister_port(plat->typec.port);
+-
+-      anx7411_port_unregister_altmodes(plat->typec.port_amode);
++      anx7411_port_unregister(&plat->typec);
+ }
+ static const struct i2c_device_id anx7411_id[] = {
+-- 
+2.47.1
+
diff --git a/queue-6.12/usb-typec-anx7411-fix-of-node-reference-leaks-in-anx7411_typec_switch_probe.patch b/queue-6.12/usb-typec-anx7411-fix-of-node-reference-leaks-in-anx7411_typec_switch_probe.patch
new file mode 100644 (file)
index 0000000..052d4f2
--- /dev/null
@@ -0,0 +1,90 @@
+From ef42b906df5c57d0719b69419df9dfd25f25c161 Mon Sep 17 00:00:00 2001
+From: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp>
+Date: Tue, 26 Nov 2024 10:49:09 +0900
+Subject: usb: typec: anx7411: fix OF node reference leaks in anx7411_typec_switch_probe()
+
+From: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp>
+
+commit ef42b906df5c57d0719b69419df9dfd25f25c161 upstream.
+
+The refcounts of the OF nodes obtained by of_get_child_by_name() calls
+in anx7411_typec_switch_probe() are not decremented. Replace them with
+device_get_named_child_node() calls and store the return values to the
+newly created fwnode_handle fields in anx7411_data, and call
+fwnode_handle_put() on them in the error path and in the unregister
+functions.
+
+Fixes: e45d7337dc0e ("usb: typec: anx7411: Use of_get_child_by_name() instead of of_find_node_by_name()")
+Cc: stable@vger.kernel.org
+Signed-off-by: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://lore.kernel.org/r/20241126014909.3687917-1-joe@pf.is.s.u-tokyo.ac.jp
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/anx7411.c |   19 ++++++++++++-------
+ 1 file changed, 12 insertions(+), 7 deletions(-)
+
+--- a/drivers/usb/typec/anx7411.c
++++ b/drivers/usb/typec/anx7411.c
+@@ -290,6 +290,8 @@ struct anx7411_data {
+       struct power_supply *psy;
+       struct power_supply_desc psy_desc;
+       struct device *dev;
++      struct fwnode_handle *switch_node;
++      struct fwnode_handle *mux_node;
+ };
+ static u8 snk_identity[] = {
+@@ -1099,6 +1101,7 @@ static void anx7411_unregister_mux(struc
+       if (ctx->typec.typec_mux) {
+               typec_mux_unregister(ctx->typec.typec_mux);
+               ctx->typec.typec_mux = NULL;
++              fwnode_handle_put(ctx->mux_node);
+       }
+ }
+@@ -1107,6 +1110,7 @@ static void anx7411_unregister_switch(st
+       if (ctx->typec.typec_switch) {
+               typec_switch_unregister(ctx->typec.typec_switch);
+               ctx->typec.typec_switch = NULL;
++              fwnode_handle_put(ctx->switch_node);
+       }
+ }
+@@ -1114,28 +1118,29 @@ static int anx7411_typec_switch_probe(st
+                                     struct device *dev)
+ {
+       int ret;
+-      struct device_node *node;
+-      node = of_get_child_by_name(dev->of_node, "orientation_switch");
+-      if (!node)
++      ctx->switch_node = device_get_named_child_node(dev, "orientation_switch");
++      if (!ctx->switch_node)
+               return 0;
+-      ret = anx7411_register_switch(ctx, dev, &node->fwnode);
++      ret = anx7411_register_switch(ctx, dev, ctx->switch_node);
+       if (ret) {
+               dev_err(dev, "failed register switch");
++              fwnode_handle_put(ctx->switch_node);
+               return ret;
+       }
+-      node = of_get_child_by_name(dev->of_node, "mode_switch");
+-      if (!node) {
++      ctx->mux_node = device_get_named_child_node(dev, "mode_switch");
++      if (!ctx->mux_node) {
+               dev_err(dev, "no typec mux exist");
+               ret = -ENODEV;
+               goto unregister_switch;
+       }
+-      ret = anx7411_register_mux(ctx, dev, &node->fwnode);
++      ret = anx7411_register_mux(ctx, dev, ctx->mux_node);
+       if (ret) {
+               dev_err(dev, "failed register mode switch");
++              fwnode_handle_put(ctx->mux_node);
+               ret = -ENODEV;
+               goto unregister_switch;
+       }
diff --git a/queue-6.12/usb-typec-ucsi-fix-completion-notifications.patch b/queue-6.12/usb-typec-ucsi-fix-completion-notifications.patch
new file mode 100644 (file)
index 0000000..358f24f
--- /dev/null
@@ -0,0 +1,97 @@
+From e37b383df91ba9bde9c6a31bf3ea9072561c5126 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=C5=81ukasz=20Bartosik?= <ukaszb@chromium.org>
+Date: Tue, 3 Dec 2024 10:23:18 +0000
+Subject: usb: typec: ucsi: Fix completion notifications
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Łukasz Bartosik <ukaszb@chromium.org>
+
+commit e37b383df91ba9bde9c6a31bf3ea9072561c5126 upstream.
+
+OPM                         PPM                         LPM
+ |        1.send cmd         |                           |
+ |-------------------------->|                           |
+ |                           |--                         |
+ |                           |  | 2.set busy bit in CCI  |
+ |                           |<-                         |
+ |      3.notify the OPM     |                           |
+ |<--------------------------|                           |
+ |                           | 4.send cmd to be executed |
+ |                           |-------------------------->|
+ |                           |                           |
+ |                           |      5.cmd completed      |
+ |                           |<--------------------------|
+ |                           |                           |
+ |                           |--                         |
+ |                           |  | 6.set cmd completed    |
+ |                           |<-       bit in CCI        |
+ |                           |                           |
+ |     7.notify the OPM      |                           |
+ |<--------------------------|                           |
+ |                           |                           |
+ |   8.handle notification   |                           |
+ |   from point 3, read CCI  |                           |
+ |<--------------------------|                           |
+ |                           |                           |
+
+When the PPM receives command from the OPM (p.1) it sets the busy bit
+in the CCI (p.2), sends notification to the OPM (p.3) and forwards the
+command to be executed by the LPM (p.4). When the PPM receives command
+completion from the LPM (p.5) it sets command completion bit in the CCI
+(p.6) and sends notification to the OPM (p.7). If command execution by
+the LPM is fast enough then when the OPM starts handling the notification
+from p.3 in p.8 and reads the CCI value it will see command completion bit
+set and will call complete(). Then complete() might be called again when
+the OPM handles notification from p.7.
+
+This fix replaces test_bit() with test_and_clear_bit()
+in ucsi_notify_common() in order to call complete() only
+once per request.
+
+This fix also reinitializes completion variable in
+ucsi_sync_control_common() before a command is sent.
+
+Fixes: 584e8df58942 ("usb: typec: ucsi: extract common code for command handling")
+Cc: stable@vger.kernel.org
+Signed-off-by: Łukasz Bartosik <ukaszb@chromium.org>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Reviewed-by: Benson Leung <bleung@chromium.org>
+Link: https://lore.kernel.org/r/20241203102318.3386345-1-ukaszb@chromium.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/ucsi/ucsi.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
+index c435c0835744..7a65a7672e18 100644
+--- a/drivers/usb/typec/ucsi/ucsi.c
++++ b/drivers/usb/typec/ucsi/ucsi.c
+@@ -46,11 +46,11 @@ void ucsi_notify_common(struct ucsi *ucsi, u32 cci)
+               ucsi_connector_change(ucsi, UCSI_CCI_CONNECTOR(cci));
+       if (cci & UCSI_CCI_ACK_COMPLETE &&
+-          test_bit(ACK_PENDING, &ucsi->flags))
++          test_and_clear_bit(ACK_PENDING, &ucsi->flags))
+               complete(&ucsi->complete);
+       if (cci & UCSI_CCI_COMMAND_COMPLETE &&
+-          test_bit(COMMAND_PENDING, &ucsi->flags))
++          test_and_clear_bit(COMMAND_PENDING, &ucsi->flags))
+               complete(&ucsi->complete);
+ }
+ EXPORT_SYMBOL_GPL(ucsi_notify_common);
+@@ -65,6 +65,8 @@ int ucsi_sync_control_common(struct ucsi *ucsi, u64 command)
+       else
+               set_bit(COMMAND_PENDING, &ucsi->flags);
++      reinit_completion(&ucsi->complete);
++
+       ret = ucsi->ops->async_control(ucsi, command);
+       if (ret)
+               goto out_clear_bit;
+-- 
+2.47.1
+
diff --git a/queue-6.12/xfs-don-t-drop-errno-values-when-we-fail-to-ficlone-the-entire-range.patch b/queue-6.12/xfs-don-t-drop-errno-values-when-we-fail-to-ficlone-the-entire-range.patch
new file mode 100644 (file)
index 0000000..155b4f4
--- /dev/null
@@ -0,0 +1,61 @@
+From 7ce31f20a0771d71779c3b0ec9cdf474cc3c8e9a Mon Sep 17 00:00:00 2001
+From: "Darrick J. Wong" <djwong@kernel.org>
+Date: Mon, 2 Dec 2024 10:57:27 -0800
+Subject: xfs: don't drop errno values when we fail to ficlone the entire range
+
+From: Darrick J. Wong <djwong@kernel.org>
+
+commit 7ce31f20a0771d71779c3b0ec9cdf474cc3c8e9a upstream.
+
+Way back when we first implemented FICLONE for XFS, life was simple --
+either the the entire remapping completed, or something happened and we
+had to return an errno explaining what happened.  Neither of those
+ioctls support returning partial results, so it's all or nothing.
+
+Then things got complicated when copy_file_range came along, because it
+actually can return the number of bytes copied, so commit 3f68c1f562f1e4
+tried to make it so that we could return a partial result if the
+REMAP_FILE_CAN_SHORTEN flag is set.  This is also how FIDEDUPERANGE can
+indicate that the kernel performed a partial deduplication.
+
+Unfortunately, the logic is wrong if an error stops the remapping and
+CAN_SHORTEN is not set.  Because those callers cannot return partial
+results, it is an error for ->remap_file_range to return a positive
+quantity that is less than the @len passed in.  Implementations really
+should be returning a negative errno in this case, because that's what
+btrfs (which introduced FICLONE{,RANGE}) did.
+
+Therefore, ->remap_range implementations cannot silently drop an errno
+that they might have when the number of bytes remapped is less than the
+number of bytes requested and CAN_SHORTEN is not set.
+
+Found by running generic/562 on a 64k fsblock filesystem and wondering
+why it reported corrupt files.
+
+Cc: <stable@vger.kernel.org> # v4.20
+Fixes: 3fc9f5e409319e ("xfs: remove xfs_reflink_remap_range")
+Really-Fixes: 3f68c1f562f1e4 ("xfs: support returning partial reflink results")
+Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_file.c |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/fs/xfs/xfs_file.c
++++ b/fs/xfs/xfs_file.c
+@@ -1228,6 +1228,14 @@ out_unlock:
+       xfs_iunlock2_remapping(src, dest);
+       if (ret)
+               trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_);
++      /*
++       * If the caller did not set CAN_SHORTEN, then it is not prepared to
++       * handle partial results -- either the whole remap succeeds, or we
++       * must say why it did not.  In this case, any error should be returned
++       * to the caller.
++       */
++      if (ret && remapped < len && !(remap_flags & REMAP_FILE_CAN_SHORTEN))
++              return ret;
+       return remapped > 0 ? remapped : ret;
+ }
diff --git a/queue-6.12/xfs-fix-null-bno_hint-handling-in-xfs_rtallocate_rtg.patch b/queue-6.12/xfs-fix-null-bno_hint-handling-in-xfs_rtallocate_rtg.patch
new file mode 100644 (file)
index 0000000..fc4652f
--- /dev/null
@@ -0,0 +1,45 @@
+From af9f02457f461b23307fe826a37be61ba6e32c92 Mon Sep 17 00:00:00 2001
+From: "Darrick J. Wong" <djwong@kernel.org>
+Date: Mon, 2 Dec 2024 10:57:30 -0800
+Subject: xfs: fix null bno_hint handling in xfs_rtallocate_rtg
+
+From: Darrick J. Wong <djwong@kernel.org>
+
+commit af9f02457f461b23307fe826a37be61ba6e32c92 upstream.
+
+xfs_bmap_rtalloc initializes the bno_hint variable to NULLRTBLOCK (aka
+NULLFSBLOCK).  If the allocation request is for a file range that's
+adjacent to an existing mapping, it will then change bno_hint to the
+blkno hint in the bmalloca structure.
+
+In other words, bno_hint is either a rt block number, or it's all 1s.
+Unfortunately, commit ec12f97f1b8a8f didn't take the NULLRTBLOCK state
+into account, which means that it tries to translate that into a
+realtime extent number.  We then end up with an obnoxiously high rtx
+number and pointlessly feed that to the near allocator.  This often
+fails and falls back to the by-size allocator.  Seeing as we had no
+locality hint anyway, this is a waste of time.
+
+Fix the code to detect a lack of bno_hint correctly.  This was detected
+by running xfs/009 with metadir enabled and a 28k rt extent size.
+
+Cc: <stable@vger.kernel.org> # v6.12
+Fixes: ec12f97f1b8a8f ("xfs: make the rtalloc start hint a xfs_rtblock_t")
+Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_rtalloc.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/xfs/xfs_rtalloc.c
++++ b/fs/xfs/xfs_rtalloc.c
+@@ -1295,7 +1295,7 @@ xfs_rtallocate(
+        * For an allocation to an empty file at offset 0, pick an extent that
+        * will space things out in the rt area.
+        */
+-      if (bno_hint)
++      if (bno_hint != NULLFSBLOCK)
+               start = xfs_rtb_to_rtx(args.mp, bno_hint);
+       else if (initial_user_data)
+               start = xfs_rtpick_extent(args.mp, tp, maxlen);
diff --git a/queue-6.12/xfs-return-a-64-bit-block-count-from-xfs_btree_count_blocks.patch b/queue-6.12/xfs-return-a-64-bit-block-count-from-xfs_btree_count_blocks.patch
new file mode 100644 (file)
index 0000000..a60a24f
--- /dev/null
@@ -0,0 +1,194 @@
+From bd27c7bcdca25ce8067ebb94ded6ac1bd7b47317 Mon Sep 17 00:00:00 2001
+From: "Darrick J. Wong" <djwong@kernel.org>
+Date: Mon, 2 Dec 2024 10:57:26 -0800
+Subject: xfs: return a 64-bit block count from xfs_btree_count_blocks
+
+From: Darrick J. Wong <djwong@kernel.org>
+
+commit bd27c7bcdca25ce8067ebb94ded6ac1bd7b47317 upstream.
+
+With the nrext64 feature enabled, it's possible for a data fork to have
+2^48 extent mappings.  Even with a 64k fsblock size, that maps out to
+a bmbt containing more than 2^32 blocks.  Therefore, this predicate must
+return a u64 count to avoid an integer wraparound that will cause scrub
+to do the wrong thing.
+
+It's unlikely that any such filesystem currently exists, because the
+incore bmbt would consume more than 64GB of kernel memory on its own,
+and so far nobody except me has driven a filesystem that far, judging
+from the lack of complaints.
+
+Cc: <stable@vger.kernel.org> # v5.19
+Fixes: df9ad5cc7a5240 ("xfs: Introduce macros to represent new maximum extent counts for data/attr forks")
+Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/libxfs/xfs_btree.c        |    4 ++--
+ fs/xfs/libxfs/xfs_btree.h        |    2 +-
+ fs/xfs/libxfs/xfs_ialloc_btree.c |    4 +++-
+ fs/xfs/scrub/agheader.c          |    6 +++---
+ fs/xfs/scrub/agheader_repair.c   |    6 +++---
+ fs/xfs/scrub/fscounters.c        |    2 +-
+ fs/xfs/scrub/ialloc.c            |    4 ++--
+ fs/xfs/scrub/refcount.c          |    2 +-
+ fs/xfs/xfs_bmap_util.c           |    2 +-
+ 9 files changed, 17 insertions(+), 15 deletions(-)
+
+--- a/fs/xfs/libxfs/xfs_btree.c
++++ b/fs/xfs/libxfs/xfs_btree.c
+@@ -5173,7 +5173,7 @@ xfs_btree_count_blocks_helper(
+       int                     level,
+       void                    *data)
+ {
+-      xfs_extlen_t            *blocks = data;
++      xfs_filblks_t           *blocks = data;
+       (*blocks)++;
+       return 0;
+@@ -5183,7 +5183,7 @@ xfs_btree_count_blocks_helper(
+ int
+ xfs_btree_count_blocks(
+       struct xfs_btree_cur    *cur,
+-      xfs_extlen_t            *blocks)
++      xfs_filblks_t           *blocks)
+ {
+       *blocks = 0;
+       return xfs_btree_visit_blocks(cur, xfs_btree_count_blocks_helper,
+--- a/fs/xfs/libxfs/xfs_btree.h
++++ b/fs/xfs/libxfs/xfs_btree.h
+@@ -485,7 +485,7 @@ typedef int (*xfs_btree_visit_blocks_fn)
+ int xfs_btree_visit_blocks(struct xfs_btree_cur *cur,
+               xfs_btree_visit_blocks_fn fn, unsigned int flags, void *data);
+-int xfs_btree_count_blocks(struct xfs_btree_cur *cur, xfs_extlen_t *blocks);
++int xfs_btree_count_blocks(struct xfs_btree_cur *cur, xfs_filblks_t *blocks);
+ union xfs_btree_rec *xfs_btree_rec_addr(struct xfs_btree_cur *cur, int n,
+               struct xfs_btree_block *block);
+--- a/fs/xfs/libxfs/xfs_ialloc_btree.c
++++ b/fs/xfs/libxfs/xfs_ialloc_btree.c
+@@ -743,6 +743,7 @@ xfs_finobt_count_blocks(
+ {
+       struct xfs_buf          *agbp = NULL;
+       struct xfs_btree_cur    *cur;
++      xfs_filblks_t           blocks;
+       int                     error;
+       error = xfs_ialloc_read_agi(pag, tp, 0, &agbp);
+@@ -750,9 +751,10 @@ xfs_finobt_count_blocks(
+               return error;
+       cur = xfs_finobt_init_cursor(pag, tp, agbp);
+-      error = xfs_btree_count_blocks(cur, tree_blocks);
++      error = xfs_btree_count_blocks(cur, &blocks);
+       xfs_btree_del_cursor(cur, error);
+       xfs_trans_brelse(tp, agbp);
++      *tree_blocks = blocks;
+       return error;
+ }
+--- a/fs/xfs/scrub/agheader.c
++++ b/fs/xfs/scrub/agheader.c
+@@ -434,7 +434,7 @@ xchk_agf_xref_btreeblks(
+ {
+       struct xfs_agf          *agf = sc->sa.agf_bp->b_addr;
+       struct xfs_mount        *mp = sc->mp;
+-      xfs_agblock_t           blocks;
++      xfs_filblks_t           blocks;
+       xfs_agblock_t           btreeblks;
+       int                     error;
+@@ -483,7 +483,7 @@ xchk_agf_xref_refcblks(
+       struct xfs_scrub        *sc)
+ {
+       struct xfs_agf          *agf = sc->sa.agf_bp->b_addr;
+-      xfs_agblock_t           blocks;
++      xfs_filblks_t           blocks;
+       int                     error;
+       if (!sc->sa.refc_cur)
+@@ -816,7 +816,7 @@ xchk_agi_xref_fiblocks(
+       struct xfs_scrub        *sc)
+ {
+       struct xfs_agi          *agi = sc->sa.agi_bp->b_addr;
+-      xfs_agblock_t           blocks;
++      xfs_filblks_t           blocks;
+       int                     error = 0;
+       if (!xfs_has_inobtcounts(sc->mp))
+--- a/fs/xfs/scrub/agheader_repair.c
++++ b/fs/xfs/scrub/agheader_repair.c
+@@ -256,7 +256,7 @@ xrep_agf_calc_from_btrees(
+       struct xfs_agf          *agf = agf_bp->b_addr;
+       struct xfs_mount        *mp = sc->mp;
+       xfs_agblock_t           btreeblks;
+-      xfs_agblock_t           blocks;
++      xfs_filblks_t           blocks;
+       int                     error;
+       /* Update the AGF counters from the bnobt. */
+@@ -946,7 +946,7 @@ xrep_agi_calc_from_btrees(
+       if (error)
+               goto err;
+       if (xfs_has_inobtcounts(mp)) {
+-              xfs_agblock_t   blocks;
++              xfs_filblks_t   blocks;
+               error = xfs_btree_count_blocks(cur, &blocks);
+               if (error)
+@@ -959,7 +959,7 @@ xrep_agi_calc_from_btrees(
+       agi->agi_freecount = cpu_to_be32(freecount);
+       if (xfs_has_finobt(mp) && xfs_has_inobtcounts(mp)) {
+-              xfs_agblock_t   blocks;
++              xfs_filblks_t   blocks;
+               cur = xfs_finobt_init_cursor(sc->sa.pag, sc->tp, agi_bp);
+               error = xfs_btree_count_blocks(cur, &blocks);
+--- a/fs/xfs/scrub/fscounters.c
++++ b/fs/xfs/scrub/fscounters.c
+@@ -261,7 +261,7 @@ xchk_fscount_btreeblks(
+       struct xchk_fscounters  *fsc,
+       xfs_agnumber_t          agno)
+ {
+-      xfs_extlen_t            blocks;
++      xfs_filblks_t           blocks;
+       int                     error;
+       error = xchk_ag_init_existing(sc, agno, &sc->sa);
+--- a/fs/xfs/scrub/ialloc.c
++++ b/fs/xfs/scrub/ialloc.c
+@@ -652,8 +652,8 @@ xchk_iallocbt_xref_rmap_btreeblks(
+       struct xfs_scrub        *sc)
+ {
+       xfs_filblks_t           blocks;
+-      xfs_extlen_t            inobt_blocks = 0;
+-      xfs_extlen_t            finobt_blocks = 0;
++      xfs_filblks_t           inobt_blocks = 0;
++      xfs_filblks_t           finobt_blocks = 0;
+       int                     error;
+       if (!sc->sa.ino_cur || !sc->sa.rmap_cur ||
+--- a/fs/xfs/scrub/refcount.c
++++ b/fs/xfs/scrub/refcount.c
+@@ -490,7 +490,7 @@ xchk_refcount_xref_rmap(
+       struct xfs_scrub        *sc,
+       xfs_filblks_t           cow_blocks)
+ {
+-      xfs_extlen_t            refcbt_blocks = 0;
++      xfs_filblks_t           refcbt_blocks = 0;
+       xfs_filblks_t           blocks;
+       int                     error;
+--- a/fs/xfs/xfs_bmap_util.c
++++ b/fs/xfs/xfs_bmap_util.c
+@@ -111,7 +111,7 @@ xfs_bmap_count_blocks(
+       struct xfs_mount        *mp = ip->i_mount;
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
+       struct xfs_btree_cur    *cur;
+-      xfs_extlen_t            btblocks = 0;
++      xfs_filblks_t           btblocks = 0;
+       int                     error;
+       *nextents = 0;
diff --git a/queue-6.12/xfs-set-xfs_sick_ino_symlink_zapped-explicitly-when-zapping-a-symlink.patch b/queue-6.12/xfs-set-xfs_sick_ino_symlink_zapped-explicitly-when-zapping-a-symlink.patch
new file mode 100644 (file)
index 0000000..9a1dd68
--- /dev/null
@@ -0,0 +1,47 @@
+From 6f4669708a69fd21f0299c2d5c4780a6ce358ab5 Mon Sep 17 00:00:00 2001
+From: "Darrick J. Wong" <djwong@kernel.org>
+Date: Mon, 2 Dec 2024 10:57:28 -0800
+Subject: xfs: set XFS_SICK_INO_SYMLINK_ZAPPED explicitly when zapping a symlink
+
+From: Darrick J. Wong <djwong@kernel.org>
+
+commit 6f4669708a69fd21f0299c2d5c4780a6ce358ab5 upstream.
+
+If we need to reset a symlink target to the "durr it's busted" string,
+then we clear the zapped flag as well.  However, this should be using
+the provided helper so that we don't set the zapped state on an
+otherwise ok symlink.
+
+Cc: <stable@vger.kernel.org> # v6.10
+Fixes: 2651923d8d8db0 ("xfs: online repair of symbolic links")
+Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/scrub/symlink_repair.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/fs/xfs/scrub/symlink_repair.c b/fs/xfs/scrub/symlink_repair.c
+index d015a86ef460..953ce7be78dc 100644
+--- a/fs/xfs/scrub/symlink_repair.c
++++ b/fs/xfs/scrub/symlink_repair.c
+@@ -36,6 +36,7 @@
+ #include "scrub/tempfile.h"
+ #include "scrub/tempexch.h"
+ #include "scrub/reap.h"
++#include "scrub/health.h"
+ /*
+  * Symbolic Link Repair
+@@ -233,7 +234,7 @@ xrep_symlink_salvage(
+        * target zapped flag.
+        */
+       if (buflen == 0) {
+-              sc->sick_mask |= XFS_SICK_INO_SYMLINK_ZAPPED;
++              xchk_mark_healthy_if_clean(sc, XFS_SICK_INO_SYMLINK_ZAPPED);
+               sprintf(target_buf, DUMMY_TARGET);
+       }
+-- 
+2.47.1
+
diff --git a/queue-6.12/xfs-update-btree-keys-correctly-when-_insrec-splits-an-inode-root-block.patch b/queue-6.12/xfs-update-btree-keys-correctly-when-_insrec-splits-an-inode-root-block.patch
new file mode 100644 (file)
index 0000000..805370e
--- /dev/null
@@ -0,0 +1,79 @@
+From 6d7b4bc1c3e00b1a25b7a05141a64337b4629337 Mon Sep 17 00:00:00 2001
+From: "Darrick J. Wong" <djwong@kernel.org>
+Date: Mon, 2 Dec 2024 10:57:31 -0800
+Subject: xfs: update btree keys correctly when _insrec splits an inode root block
+
+From: Darrick J. Wong <djwong@kernel.org>
+
+commit 6d7b4bc1c3e00b1a25b7a05141a64337b4629337 upstream.
+
+In commit 2c813ad66a72, I partially fixed a bug wherein xfs_btree_insrec
+would erroneously try to update the parent's key for a block that had
+been split if we decided to insert the new record into the new block.
+The solution was to detect this situation and update the in-core key
+value that we pass up to the caller so that the caller will (eventually)
+add the new block to the parent level of the tree with the correct key.
+
+However, I missed a subtlety about the way inode-rooted btrees work.  If
+the full block was a maximally sized inode root block, we'll solve that
+fullness by moving the root block's records to a new block, resizing the
+root block, and updating the root to point to the new block.  We don't
+pass a pointer to the new block to the caller because that work has
+already been done.  The new record will /always/ land in the new block,
+so in this case we need to use xfs_btree_update_keys to update the keys.
+
+This bug can theoretically manifest itself in the very rare case that we
+split a bmbt root block and the new record lands in the very first slot
+of the new block, though I've never managed to trigger it in practice.
+However, it is very easy to reproduce by running generic/522 with the
+realtime rmapbt patchset if rtinherit=1.
+
+Cc: <stable@vger.kernel.org> # v4.8
+Fixes: 2c813ad66a7218 ("xfs: support btrees with overlapping intervals for keys")
+Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/libxfs/xfs_btree.c |   29 +++++++++++++++++++++++------
+ 1 file changed, 23 insertions(+), 6 deletions(-)
+
+--- a/fs/xfs/libxfs/xfs_btree.c
++++ b/fs/xfs/libxfs/xfs_btree.c
+@@ -3569,14 +3569,31 @@ xfs_btree_insrec(
+       xfs_btree_log_block(cur, bp, XFS_BB_NUMRECS);
+       /*
+-       * If we just inserted into a new tree block, we have to
+-       * recalculate nkey here because nkey is out of date.
++       * Update btree keys to reflect the newly added record or keyptr.
++       * There are three cases here to be aware of.  Normally, all we have to
++       * do is walk towards the root, updating keys as necessary.
+        *
+-       * Otherwise we're just updating an existing block (having shoved
+-       * some records into the new tree block), so use the regular key
+-       * update mechanism.
++       * If the caller had us target a full block for the insertion, we dealt
++       * with that by calling the _make_block_unfull function.  If the
++       * "make unfull" function splits the block, it'll hand us back the key
++       * and pointer of the new block.  We haven't yet added the new block to
++       * the next level up, so if we decide to add the new record to the new
++       * block (bp->b_bn != old_bn), we have to update the caller's pointer
++       * so that the caller adds the new block with the correct key.
++       *
++       * However, there is a third possibility-- if the selected block is the
++       * root block of an inode-rooted btree and cannot be expanded further,
++       * the "make unfull" function moves the root block contents to a new
++       * block and updates the root block to point to the new block.  In this
++       * case, no block pointer is passed back because the block has already
++       * been added to the btree.  In this case, we need to use the regular
++       * key update function, just like the first case.  This is critical for
++       * overlapping btrees, because the high key must be updated to reflect
++       * the entire tree, not just the subtree accessible through the first
++       * child of the root (which is now two levels down from the root).
+        */
+-      if (bp && xfs_buf_daddr(bp) != old_bn) {
++      if (!xfs_btree_ptr_is_null(cur, &nptr) &&
++          bp && xfs_buf_daddr(bp) != old_bn) {
+               xfs_btree_get_keys(cur, block, lkey);
+       } else if (xfs_btree_needs_key_update(cur, optr)) {
+               error = xfs_btree_update_keys(cur, level);