--- /dev/null
+From cf234231fcbc7d391e2135b9518613218cc5347f Mon Sep 17 00:00:00 2001
+From: Philip Yang <Philip.Yang@amd.com>
+Date: Fri, 20 Jun 2025 18:32:32 -0400
+Subject: drm/amdkfd: Don't call mmput from MMU notifier callback
+
+From: Philip Yang <Philip.Yang@amd.com>
+
+commit cf234231fcbc7d391e2135b9518613218cc5347f upstream.
+
+If the process is exiting, the mmput inside mmu notifier callback from
+compactd or fork or numa balancing could release the last reference
+of mm struct to call exit_mmap and free_pgtable, this triggers deadlock
+with below backtrace.
+
+The deadlock will leak kfd process as mmu notifier release is not called
+and cause VRAM leaking.
+
+The fix is to take mm reference mmget_non_zero when adding prange to the
+deferred list to pair with mmput in deferred list work.
+
+If prange split and add into pchild list, the pchild work_item.mm is not
+used, so remove the mm parameter from svm_range_unmap_split and
+svm_range_add_child.
+
+The backtrace of hung task:
+
+ INFO: task python:348105 blocked for more than 64512 seconds.
+ Call Trace:
+ __schedule+0x1c3/0x550
+ schedule+0x46/0xb0
+ rwsem_down_write_slowpath+0x24b/0x4c0
+ unlink_anon_vmas+0xb1/0x1c0
+ free_pgtables+0xa9/0x130
+ exit_mmap+0xbc/0x1a0
+ mmput+0x5a/0x140
+ svm_range_cpu_invalidate_pagetables+0x2b/0x40 [amdgpu]
+ mn_itree_invalidate+0x72/0xc0
+ __mmu_notifier_invalidate_range_start+0x48/0x60
+ try_to_unmap_one+0x10fa/0x1400
+ rmap_walk_anon+0x196/0x460
+ try_to_unmap+0xbb/0x210
+ migrate_page_unmap+0x54d/0x7e0
+ migrate_pages_batch+0x1c3/0xae0
+ migrate_pages_sync+0x98/0x240
+ migrate_pages+0x25c/0x520
+ compact_zone+0x29d/0x590
+ compact_zone_order+0xb6/0xf0
+ try_to_compact_pages+0xbe/0x220
+ __alloc_pages_direct_compact+0x96/0x1a0
+ __alloc_pages_slowpath+0x410/0x930
+ __alloc_pages_nodemask+0x3a9/0x3e0
+ do_huge_pmd_anonymous_page+0xd7/0x3e0
+ __handle_mm_fault+0x5e3/0x5f0
+ handle_mm_fault+0xf7/0x2e0
+ hmm_vma_fault.isra.0+0x4d/0xa0
+ walk_pmd_range.isra.0+0xa8/0x310
+ walk_pud_range+0x167/0x240
+ walk_pgd_range+0x55/0x100
+ __walk_page_range+0x87/0x90
+ walk_page_range+0xf6/0x160
+ hmm_range_fault+0x4f/0x90
+ amdgpu_hmm_range_get_pages+0x123/0x230 [amdgpu]
+ amdgpu_ttm_tt_get_user_pages+0xb1/0x150 [amdgpu]
+ init_user_pages+0xb1/0x2a0 [amdgpu]
+ amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu+0x543/0x7d0 [amdgpu]
+ kfd_ioctl_alloc_memory_of_gpu+0x24c/0x4e0 [amdgpu]
+ kfd_ioctl+0x29d/0x500 [amdgpu]
+
+Fixes: fa582c6f3684 ("drm/amdkfd: Use mmget_not_zero in MMU notifier")
+Signed-off-by: Philip Yang <Philip.Yang@amd.com>
+Reviewed-by: Felix Kuehling <felix.kuehling@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit a29e067bd38946f752b0ef855f3dfff87e77bec7)
+Cc: stable@vger.kernel.org
+[ updated additional svm_range_add_child calls in svm_range_split_by_granularity to remove mm parameter ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 47 ++++++++++++++++-------------------
+ 1 file changed, 22 insertions(+), 25 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+@@ -1130,13 +1130,12 @@ svm_range_split_head(struct svm_range *p
+ }
+
+ static void
+-svm_range_add_child(struct svm_range *prange, struct mm_struct *mm,
+- struct svm_range *pchild, enum svm_work_list_ops op)
++svm_range_add_child(struct svm_range *prange, struct svm_range *pchild, enum svm_work_list_ops op)
+ {
+ pr_debug("add child 0x%p [0x%lx 0x%lx] to prange 0x%p child list %d\n",
+ pchild, pchild->start, pchild->last, prange, op);
+
+- pchild->work_item.mm = mm;
++ pchild->work_item.mm = NULL;
+ pchild->work_item.op = op;
+ list_add_tail(&pchild->child_list, &prange->child_list);
+ }
+@@ -1182,14 +1181,14 @@ svm_range_split_by_granularity(struct kf
+ r = svm_range_split(prange, start, prange->last, &head);
+ if (r)
+ return r;
+- svm_range_add_child(parent, mm, head, SVM_OP_ADD_RANGE);
++ svm_range_add_child(parent, head, SVM_OP_ADD_RANGE);
+ }
+
+ if (last < prange->last) {
+ r = svm_range_split(prange, prange->start, last, &tail);
+ if (r)
+ return r;
+- svm_range_add_child(parent, mm, tail, SVM_OP_ADD_RANGE);
++ svm_range_add_child(parent, tail, SVM_OP_ADD_RANGE);
+ }
+
+ /* xnack on, update mapping on GPUs with ACCESS_IN_PLACE */
+@@ -2393,15 +2392,17 @@ svm_range_add_list_work(struct svm_range
+ prange->work_item.op != SVM_OP_UNMAP_RANGE)
+ prange->work_item.op = op;
+ } else {
+- prange->work_item.op = op;
+-
+- /* Pairs with mmput in deferred_list_work */
+- mmget(mm);
+- prange->work_item.mm = mm;
+- list_add_tail(&prange->deferred_list,
+- &prange->svms->deferred_range_list);
+- pr_debug("add prange 0x%p [0x%lx 0x%lx] to work list op %d\n",
+- prange, prange->start, prange->last, op);
++ /* Pairs with mmput in deferred_list_work.
++ * If process is exiting and mm is gone, don't update mmu notifier.
++ */
++ if (mmget_not_zero(mm)) {
++ prange->work_item.mm = mm;
++ prange->work_item.op = op;
++ list_add_tail(&prange->deferred_list,
++ &prange->svms->deferred_range_list);
++ pr_debug("add prange 0x%p [0x%lx 0x%lx] to work list op %d\n",
++ prange, prange->start, prange->last, op);
++ }
+ }
+ spin_unlock(&svms->deferred_list_lock);
+ }
+@@ -2415,8 +2416,7 @@ void schedule_deferred_list_work(struct
+ }
+
+ static void
+-svm_range_unmap_split(struct mm_struct *mm, struct svm_range *parent,
+- struct svm_range *prange, unsigned long start,
++svm_range_unmap_split(struct svm_range *parent, struct svm_range *prange, unsigned long start,
+ unsigned long last)
+ {
+ struct svm_range *head;
+@@ -2437,12 +2437,12 @@ svm_range_unmap_split(struct mm_struct *
+ svm_range_split(tail, last + 1, tail->last, &head);
+
+ if (head != prange && tail != prange) {
+- svm_range_add_child(parent, mm, head, SVM_OP_UNMAP_RANGE);
+- svm_range_add_child(parent, mm, tail, SVM_OP_ADD_RANGE);
++ svm_range_add_child(parent, head, SVM_OP_UNMAP_RANGE);
++ svm_range_add_child(parent, tail, SVM_OP_ADD_RANGE);
+ } else if (tail != prange) {
+- svm_range_add_child(parent, mm, tail, SVM_OP_UNMAP_RANGE);
++ svm_range_add_child(parent, tail, SVM_OP_UNMAP_RANGE);
+ } else if (head != prange) {
+- svm_range_add_child(parent, mm, head, SVM_OP_UNMAP_RANGE);
++ svm_range_add_child(parent, head, SVM_OP_UNMAP_RANGE);
+ } else if (parent != prange) {
+ prange->work_item.op = SVM_OP_UNMAP_RANGE;
+ }
+@@ -2481,14 +2481,14 @@ svm_range_unmap_from_cpu(struct mm_struc
+ l = min(last, pchild->last);
+ if (l >= s)
+ svm_range_unmap_from_gpus(pchild, s, l, trigger);
+- svm_range_unmap_split(mm, prange, pchild, start, last);
++ svm_range_unmap_split(prange, pchild, start, last);
+ mutex_unlock(&pchild->lock);
+ }
+ s = max(start, prange->start);
+ l = min(last, prange->last);
+ if (l >= s)
+ svm_range_unmap_from_gpus(prange, s, l, trigger);
+- svm_range_unmap_split(mm, prange, prange, start, last);
++ svm_range_unmap_split(prange, prange, start, last);
+
+ if (unmap_parent)
+ svm_range_add_list_work(svms, prange, mm, SVM_OP_UNMAP_RANGE);
+@@ -2531,8 +2531,6 @@ svm_range_cpu_invalidate_pagetables(stru
+
+ if (range->event == MMU_NOTIFY_RELEASE)
+ return true;
+- if (!mmget_not_zero(mni->mm))
+- return true;
+
+ start = mni->interval_tree.start;
+ last = mni->interval_tree.last;
+@@ -2559,7 +2557,6 @@ svm_range_cpu_invalidate_pagetables(stru
+ }
+
+ svm_range_unlock(prange);
+- mmput(mni->mm);
+
+ return true;
+ }
selftests-mptcp-connect-also-cover-alt-modes.patch
selftests-mptcp-connect-also-cover-checksum.patch
mm-zsmalloc-do-not-pass-__gfp_movable-if-config_compaction-n.patch
+drm-amdkfd-don-t-call-mmput-from-mmu-notifier-callback.patch
+usb-typec-tcpm-allow-to-use-sink-in-accessory-mode.patch
+usb-typec-tcpm-allow-switching-to-mode-accessory-to-mux-properly.patch
+usb-typec-tcpm-apply-vbus-before-data-bringup-in-tcpm_src_attach.patch
--- /dev/null
+From 8a50da849151e7e12b43c1d8fe7ad302223aef6b Mon Sep 17 00:00:00 2001
+From: Michael Grzeschik <m.grzeschik@pengutronix.de>
+Date: Fri, 4 Apr 2025 00:43:06 +0200
+Subject: usb: typec: tcpm: allow switching to mode accessory to mux properly
+
+From: Michael Grzeschik <m.grzeschik@pengutronix.de>
+
+commit 8a50da849151e7e12b43c1d8fe7ad302223aef6b upstream.
+
+The funciton tcpm_acc_attach is not setting the proper state when
+calling tcpm_set_role. The function tcpm_set_role is currently only
+handling TYPEC_STATE_USB. For the tcpm_acc_attach to switch into other
+modal states tcpm_set_role needs to be extended by an extra state
+parameter. This patch is handling the proper state change when calling
+tcpm_acc_attach.
+
+Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://lore.kernel.org/r/20250404-ml-topic-tcpm-v1-3-b99f44badce8@pengutronix.de
+Stable-dep-of: bec15191d523 ("usb: typec: tcpm: apply vbus before data bringup in tcpm_src_attach")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/tcpm/tcpm.c | 27 ++++++++++++++++++---------
+ 1 file changed, 18 insertions(+), 9 deletions(-)
+
+--- a/drivers/usb/typec/tcpm/tcpm.c
++++ b/drivers/usb/typec/tcpm/tcpm.c
+@@ -1041,7 +1041,7 @@ static int tcpm_set_attached_state(struc
+ port->data_role);
+ }
+
+-static int tcpm_set_roles(struct tcpm_port *port, bool attached,
++static int tcpm_set_roles(struct tcpm_port *port, bool attached, int state,
+ enum typec_role role, enum typec_data_role data)
+ {
+ enum typec_orientation orientation;
+@@ -1078,7 +1078,7 @@ static int tcpm_set_roles(struct tcpm_po
+ }
+ }
+
+- ret = tcpm_mux_set(port, TYPEC_STATE_USB, usb_role, orientation);
++ ret = tcpm_mux_set(port, state, usb_role, orientation);
+ if (ret < 0)
+ return ret;
+
+@@ -3622,7 +3622,8 @@ static int tcpm_src_attach(struct tcpm_p
+
+ tcpm_enable_auto_vbus_discharge(port, true);
+
+- ret = tcpm_set_roles(port, true, TYPEC_SOURCE, tcpm_data_role_for_source(port));
++ ret = tcpm_set_roles(port, true, TYPEC_STATE_USB,
++ TYPEC_SOURCE, tcpm_data_role_for_source(port));
+ if (ret < 0)
+ return ret;
+
+@@ -3780,7 +3781,8 @@ static int tcpm_snk_attach(struct tcpm_p
+
+ tcpm_enable_auto_vbus_discharge(port, true);
+
+- ret = tcpm_set_roles(port, true, TYPEC_SINK, tcpm_data_role_for_sink(port));
++ ret = tcpm_set_roles(port, true, TYPEC_STATE_USB,
++ TYPEC_SINK, tcpm_data_role_for_sink(port));
+ if (ret < 0)
+ return ret;
+
+@@ -3804,6 +3806,7 @@ static int tcpm_acc_attach(struct tcpm_p
+ int ret;
+ enum typec_role role;
+ enum typec_data_role data;
++ int state = TYPEC_STATE_USB;
+
+ if (port->attached)
+ return 0;
+@@ -3812,7 +3815,13 @@ static int tcpm_acc_attach(struct tcpm_p
+ data = tcpm_port_is_sink(port) ? tcpm_data_role_for_sink(port)
+ : tcpm_data_role_for_source(port);
+
+- ret = tcpm_set_roles(port, true, role, data);
++ if (tcpm_port_is_audio(port))
++ state = TYPEC_MODE_AUDIO;
++
++ if (tcpm_port_is_debug(port))
++ state = TYPEC_MODE_DEBUG;
++
++ ret = tcpm_set_roles(port, true, state, role, data);
+ if (ret < 0)
+ return ret;
+
+@@ -4514,7 +4523,7 @@ static void run_state_machine(struct tcp
+ */
+ tcpm_set_vconn(port, false);
+ tcpm_set_vbus(port, false);
+- tcpm_set_roles(port, port->self_powered, TYPEC_SOURCE,
++ tcpm_set_roles(port, port->self_powered, TYPEC_STATE_USB, TYPEC_SOURCE,
+ tcpm_data_role_for_source(port));
+ /*
+ * If tcpc fails to notify vbus off, TCPM will wait for PD_T_SAFE_0V +
+@@ -4546,7 +4555,7 @@ static void run_state_machine(struct tcp
+ tcpm_set_vconn(port, false);
+ if (port->pd_capable)
+ tcpm_set_charge(port, false);
+- tcpm_set_roles(port, port->self_powered, TYPEC_SINK,
++ tcpm_set_roles(port, port->self_powered, TYPEC_STATE_USB, TYPEC_SINK,
+ tcpm_data_role_for_sink(port));
+ /*
+ * VBUS may or may not toggle, depending on the adapter.
+@@ -4652,10 +4661,10 @@ static void run_state_machine(struct tcp
+ case DR_SWAP_CHANGE_DR:
+ tcpm_unregister_altmodes(port);
+ if (port->data_role == TYPEC_HOST)
+- tcpm_set_roles(port, true, port->pwr_role,
++ tcpm_set_roles(port, true, TYPEC_STATE_USB, port->pwr_role,
+ TYPEC_DEVICE);
+ else
+- tcpm_set_roles(port, true, port->pwr_role,
++ tcpm_set_roles(port, true, TYPEC_STATE_USB, port->pwr_role,
+ TYPEC_HOST);
+ tcpm_ams_finish(port);
+ tcpm_set_state(port, ready_state(port), 0);
--- /dev/null
+From 64843d0ba96d3eae297025562111d57585273366 Mon Sep 17 00:00:00 2001
+From: Michael Grzeschik <m.grzeschik@pengutronix.de>
+Date: Fri, 4 Apr 2025 00:43:04 +0200
+Subject: usb: typec: tcpm: allow to use sink in accessory mode
+
+From: Michael Grzeschik <m.grzeschik@pengutronix.de>
+
+commit 64843d0ba96d3eae297025562111d57585273366 upstream.
+
+Since the function tcpm_acc_attach is not setting the data and role for
+for the sink case we extend it to check for it first.
+
+Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://lore.kernel.org/r/20250404-ml-topic-tcpm-v1-1-b99f44badce8@pengutronix.de
+Stable-dep-of: bec15191d523 ("usb: typec: tcpm: apply vbus before data bringup in tcpm_src_attach")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/tcpm/tcpm.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/typec/tcpm/tcpm.c
++++ b/drivers/usb/typec/tcpm/tcpm.c
+@@ -3802,12 +3802,17 @@ static void tcpm_snk_detach(struct tcpm_
+ static int tcpm_acc_attach(struct tcpm_port *port)
+ {
+ int ret;
++ enum typec_role role;
++ enum typec_data_role data;
+
+ if (port->attached)
+ return 0;
+
+- ret = tcpm_set_roles(port, true, TYPEC_SOURCE,
+- tcpm_data_role_for_source(port));
++ role = tcpm_port_is_sink(port) ? TYPEC_SINK : TYPEC_SOURCE;
++ data = tcpm_port_is_sink(port) ? tcpm_data_role_for_sink(port)
++ : tcpm_data_role_for_source(port);
++
++ ret = tcpm_set_roles(port, true, role, data);
+ if (ret < 0)
+ return ret;
+
--- /dev/null
+From bec15191d52300defa282e3fd83820f69e447116 Mon Sep 17 00:00:00 2001
+From: RD Babiera <rdbabiera@google.com>
+Date: Wed, 18 Jun 2025 23:06:04 +0000
+Subject: usb: typec: tcpm: apply vbus before data bringup in tcpm_src_attach
+
+From: RD Babiera <rdbabiera@google.com>
+
+commit bec15191d52300defa282e3fd83820f69e447116 upstream.
+
+This patch fixes Type-C compliance test TD 4.7.6 - Try.SNK DRP Connect
+SNKAS.
+
+tVbusON has a limit of 275ms when entering SRC_ATTACHED. Compliance
+testers can interpret the TryWait.Src to Attached.Src transition after
+Try.Snk as being in Attached.Src the entire time, so ~170ms is lost
+to the debounce timer.
+
+Setting the data role can be a costly operation in host mode, and when
+completed after 100ms can cause Type-C compliance test check TD 4.7.5.V.4
+to fail.
+
+Turn VBUS on before tcpm_set_roles to meet timing requirement.
+
+Fixes: f0690a25a140 ("staging: typec: USB Type-C Port Manager (tcpm)")
+Cc: stable <stable@kernel.org>
+Signed-off-by: RD Babiera <rdbabiera@google.com>
+Reviewed-by: Badhri Jagan Sridharan <badhri@google.com>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://lore.kernel.org/r/20250618230606.3272497-2-rdbabiera@google.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/tcpm/tcpm.c | 34 +++++++++++++++++-----------------
+ 1 file changed, 17 insertions(+), 17 deletions(-)
+
+--- a/drivers/usb/typec/tcpm/tcpm.c
++++ b/drivers/usb/typec/tcpm/tcpm.c
+@@ -3622,17 +3622,6 @@ static int tcpm_src_attach(struct tcpm_p
+
+ tcpm_enable_auto_vbus_discharge(port, true);
+
+- ret = tcpm_set_roles(port, true, TYPEC_STATE_USB,
+- TYPEC_SOURCE, tcpm_data_role_for_source(port));
+- if (ret < 0)
+- return ret;
+-
+- if (port->pd_supported) {
+- ret = port->tcpc->set_pd_rx(port->tcpc, true);
+- if (ret < 0)
+- goto out_disable_mux;
+- }
+-
+ /*
+ * USB Type-C specification, version 1.2,
+ * chapter 4.5.2.2.8.1 (Attached.SRC Requirements)
+@@ -3642,13 +3631,24 @@ static int tcpm_src_attach(struct tcpm_p
+ (polarity == TYPEC_POLARITY_CC2 && port->cc1 == TYPEC_CC_RA)) {
+ ret = tcpm_set_vconn(port, true);
+ if (ret < 0)
+- goto out_disable_pd;
++ return ret;
+ }
+
+ ret = tcpm_set_vbus(port, true);
+ if (ret < 0)
+ goto out_disable_vconn;
+
++ ret = tcpm_set_roles(port, true, TYPEC_STATE_USB, TYPEC_SOURCE,
++ tcpm_data_role_for_source(port));
++ if (ret < 0)
++ goto out_disable_vbus;
++
++ if (port->pd_supported) {
++ ret = port->tcpc->set_pd_rx(port->tcpc, true);
++ if (ret < 0)
++ goto out_disable_mux;
++ }
++
+ port->pd_capable = false;
+
+ port->partner = NULL;
+@@ -3658,14 +3658,14 @@ static int tcpm_src_attach(struct tcpm_p
+
+ return 0;
+
+-out_disable_vconn:
+- tcpm_set_vconn(port, false);
+-out_disable_pd:
+- if (port->pd_supported)
+- port->tcpc->set_pd_rx(port->tcpc, false);
+ out_disable_mux:
+ tcpm_mux_set(port, TYPEC_STATE_SAFE, USB_ROLE_NONE,
+ TYPEC_ORIENTATION_NONE);
++out_disable_vbus:
++ tcpm_set_vbus(port, false);
++out_disable_vconn:
++ tcpm_set_vconn(port, false);
++
+ return ret;
+ }
+