From 1ac3662ec43cca43c83d50cbcc200355202df7e4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 12 May 2025 12:34:42 +0200 Subject: [PATCH] 6.6-stable patches added patches: clocksource-i8253-use-raw_spinlock_irqsave-in-clockevent_i8253_disable.patch memblock-accept-allocated-memory-before-use-in-memblock_double_array.patch module-ensure-that-kobject_put-is-safe-for-module-type-kobjects.patch ocfs2-implement-handshaking-with-ocfs2-recovery-thread.patch ocfs2-stop-quota-recovery-before-disabling-quotas.patch ocfs2-switch-osb-disable_recovery-to-enum.patch smb-client-avoid-race-in-open_cached_dir-with-lease-breaks.patch usb-cdnsp-fix-issue-with-resuming-from-l1.patch usb-cdnsp-fix-l1-resume-issue-for-rtl_revision_new_lpm-version.patch usb-gadget-f_ecm-add-get_status-callback.patch usb-gadget-tegra-xudc-ack-st_rc-after-clearing-ctrl_run.patch usb-gadget-use-get_status-callback-to-set-remote-wakeup-capability.patch usb-host-tegra-prevent-host-controller-crash-when-otg-port-is-used.patch x86-microcode-consolidate-the-loader-enablement-checking.patch xen-swiotlb-use-swiotlb-bouncing-if-kmalloc-allocation-demands-it.patch xenbus-use-kref-to-track-req-lifetime.patch --- ..._irqsave-in-clockevent_i8253_disable.patch | 53 ++++ ...-before-use-in-memblock_double_array.patch | 72 ++++++ ...put-is-safe-for-module-type-kobjects.patch | 43 ++++ ...ndshaking-with-ocfs2-recovery-thread.patch | 139 +++++++++++ ...ota-recovery-before-disabling-quotas.patch | 171 +++++++++++++ ...-switch-osb-disable_recovery-to-enum.patch | 107 ++++++++ queue-6.6/series | 16 ++ ...in-open_cached_dir-with-lease-breaks.patch | 89 +++++++ ...dnsp-fix-issue-with-resuming-from-l1.patch | 149 ++++++++++++ ...sue-for-rtl_revision_new_lpm-version.patch | 76 ++++++ ...gadget-f_ecm-add-get_status-callback.patch | 47 ++++ ...dc-ack-st_rc-after-clearing-ctrl_run.patch | 40 +++ ...back-to-set-remote-wakeup-capability.patch | 63 +++++ ...ntroller-crash-when-otg-port-is-used.patch | 66 +++++ ...idate-the-loader-enablement-checking.patch | 228 ++++++++++++++++++ ...ing-if-kmalloc-allocation-demands-it.patch | 42 ++++ ...enbus-use-kref-to-track-req-lifetime.patch | 172 +++++++++++++ 17 files changed, 1573 insertions(+) create mode 100644 queue-6.6/clocksource-i8253-use-raw_spinlock_irqsave-in-clockevent_i8253_disable.patch create mode 100644 queue-6.6/memblock-accept-allocated-memory-before-use-in-memblock_double_array.patch create mode 100644 queue-6.6/module-ensure-that-kobject_put-is-safe-for-module-type-kobjects.patch create mode 100644 queue-6.6/ocfs2-implement-handshaking-with-ocfs2-recovery-thread.patch create mode 100644 queue-6.6/ocfs2-stop-quota-recovery-before-disabling-quotas.patch create mode 100644 queue-6.6/ocfs2-switch-osb-disable_recovery-to-enum.patch create mode 100644 queue-6.6/smb-client-avoid-race-in-open_cached_dir-with-lease-breaks.patch create mode 100644 queue-6.6/usb-cdnsp-fix-issue-with-resuming-from-l1.patch create mode 100644 queue-6.6/usb-cdnsp-fix-l1-resume-issue-for-rtl_revision_new_lpm-version.patch create mode 100644 queue-6.6/usb-gadget-f_ecm-add-get_status-callback.patch create mode 100644 queue-6.6/usb-gadget-tegra-xudc-ack-st_rc-after-clearing-ctrl_run.patch create mode 100644 queue-6.6/usb-gadget-use-get_status-callback-to-set-remote-wakeup-capability.patch create mode 100644 queue-6.6/usb-host-tegra-prevent-host-controller-crash-when-otg-port-is-used.patch create mode 100644 queue-6.6/x86-microcode-consolidate-the-loader-enablement-checking.patch create mode 100644 queue-6.6/xen-swiotlb-use-swiotlb-bouncing-if-kmalloc-allocation-demands-it.patch create mode 100644 queue-6.6/xenbus-use-kref-to-track-req-lifetime.patch diff --git a/queue-6.6/clocksource-i8253-use-raw_spinlock_irqsave-in-clockevent_i8253_disable.patch b/queue-6.6/clocksource-i8253-use-raw_spinlock_irqsave-in-clockevent_i8253_disable.patch new file mode 100644 index 0000000000..11b6094150 --- /dev/null +++ b/queue-6.6/clocksource-i8253-use-raw_spinlock_irqsave-in-clockevent_i8253_disable.patch @@ -0,0 +1,53 @@ +From 94cff94634e506a4a44684bee1875d2dbf782722 Mon Sep 17 00:00:00 2001 +From: Sebastian Andrzej Siewior +Date: Fri, 4 Apr 2025 15:31:16 +0200 +Subject: clocksource/i8253: Use raw_spinlock_irqsave() in clockevent_i8253_disable() + +From: Sebastian Andrzej Siewior + +commit 94cff94634e506a4a44684bee1875d2dbf782722 upstream. + +On x86 during boot, clockevent_i8253_disable() can be invoked via +x86_late_time_init -> hpet_time_init() -> pit_timer_init() which happens +with enabled interrupts. + +If some of the old i8253 hardware is actually used then lockdep will notice +that i8253_lock is used in hard interrupt context. This causes lockdep to +complain because it observed the lock being acquired with interrupts +enabled and in hard interrupt context. + +Make clockevent_i8253_disable() acquire the lock with +raw_spinlock_irqsave() to cure this. + +[ tglx: Massage change log and use guard() ] + +Fixes: c8c4076723dac ("x86/timer: Skip PIT initialization on modern chipsets") +Signed-off-by: Sebastian Andrzej Siewior +Signed-off-by: Thomas Gleixner +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/all/20250404133116.p-XRWJXf@linutronix.de +Signed-off-by: Greg Kroah-Hartman +--- + drivers/clocksource/i8253.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/clocksource/i8253.c ++++ b/drivers/clocksource/i8253.c +@@ -103,7 +103,7 @@ int __init clocksource_i8253_init(void) + #ifdef CONFIG_CLKEVT_I8253 + void clockevent_i8253_disable(void) + { +- raw_spin_lock(&i8253_lock); ++ guard(raw_spinlock_irqsave)(&i8253_lock); + + /* + * Writing the MODE register should stop the counter, according to +@@ -132,8 +132,6 @@ void clockevent_i8253_disable(void) + outb_p(0, PIT_CH0); + + outb_p(0x30, PIT_MODE); +- +- raw_spin_unlock(&i8253_lock); + } + + static int pit_shutdown(struct clock_event_device *evt) diff --git a/queue-6.6/memblock-accept-allocated-memory-before-use-in-memblock_double_array.patch b/queue-6.6/memblock-accept-allocated-memory-before-use-in-memblock_double_array.patch new file mode 100644 index 0000000000..a4e58b707b --- /dev/null +++ b/queue-6.6/memblock-accept-allocated-memory-before-use-in-memblock_double_array.patch @@ -0,0 +1,72 @@ +From da8bf5daa5e55a6af2b285ecda460d6454712ff4 Mon Sep 17 00:00:00 2001 +From: Tom Lendacky +Date: Thu, 8 May 2025 12:24:10 -0500 +Subject: memblock: Accept allocated memory before use in memblock_double_array() + +From: Tom Lendacky + +commit da8bf5daa5e55a6af2b285ecda460d6454712ff4 upstream. + +When increasing the array size in memblock_double_array() and the slab +is not yet available, a call to memblock_find_in_range() is used to +reserve/allocate memory. However, the range returned may not have been +accepted, which can result in a crash when booting an SNP guest: + + RIP: 0010:memcpy_orig+0x68/0x130 + Code: ... + RSP: 0000:ffffffff9cc03ce8 EFLAGS: 00010006 + RAX: ff11001ff83e5000 RBX: 0000000000000000 RCX: fffffffffffff000 + RDX: 0000000000000bc0 RSI: ffffffff9dba8860 RDI: ff11001ff83e5c00 + RBP: 0000000000002000 R08: 0000000000000000 R09: 0000000000002000 + R10: 000000207fffe000 R11: 0000040000000000 R12: ffffffff9d06ef78 + R13: ff11001ff83e5000 R14: ffffffff9dba7c60 R15: 0000000000000c00 + memblock_double_array+0xff/0x310 + memblock_add_range+0x1fb/0x2f0 + memblock_reserve+0x4f/0xa0 + memblock_alloc_range_nid+0xac/0x130 + memblock_alloc_internal+0x53/0xc0 + memblock_alloc_try_nid+0x3d/0xa0 + swiotlb_init_remap+0x149/0x2f0 + mem_init+0xb/0xb0 + mm_core_init+0x8f/0x350 + start_kernel+0x17e/0x5d0 + x86_64_start_reservations+0x14/0x30 + x86_64_start_kernel+0x92/0xa0 + secondary_startup_64_no_verify+0x194/0x19b + +Mitigate this by calling accept_memory() on the memory range returned +before the slab is available. + +Prior to v6.12, the accept_memory() interface used a 'start' and 'end' +parameter instead of 'start' and 'size', therefore the accept_memory() +call must be adjusted to specify 'start + size' for 'end' when applying +to kernels prior to v6.12. + +Cc: stable@vger.kernel.org # see patch description, needs adjustments for <= 6.11 +Fixes: dcdfdd40fa82 ("mm: Add support for unaccepted memory") +Signed-off-by: Tom Lendacky +Link: https://lore.kernel.org/r/da1ac73bf4ded761e21b4e4bb5178382a580cd73.1746725050.git.thomas.lendacky@amd.com +Signed-off-by: Mike Rapoport (Microsoft) +Signed-off-by: Greg Kroah-Hartman +--- + mm/memblock.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/mm/memblock.c ++++ b/mm/memblock.c +@@ -460,7 +460,14 @@ static int __init_memblock memblock_doub + min(new_area_start, memblock.current_limit), + new_alloc_size, PAGE_SIZE); + +- new_array = addr ? __va(addr) : NULL; ++ if (addr) { ++ /* The memory may not have been accepted, yet. */ ++ accept_memory(addr, new_alloc_size); ++ ++ new_array = __va(addr); ++ } else { ++ new_array = NULL; ++ } + } + if (!addr) { + pr_err("memblock: Failed to double %s array from %ld to %ld entries !\n", diff --git a/queue-6.6/module-ensure-that-kobject_put-is-safe-for-module-type-kobjects.patch b/queue-6.6/module-ensure-that-kobject_put-is-safe-for-module-type-kobjects.patch new file mode 100644 index 0000000000..c648f116bf --- /dev/null +++ b/queue-6.6/module-ensure-that-kobject_put-is-safe-for-module-type-kobjects.patch @@ -0,0 +1,43 @@ +From a6aeb739974ec73e5217c75a7c008a688d3d5cf1 Mon Sep 17 00:00:00 2001 +From: Dmitry Antipov +Date: Wed, 7 May 2025 09:50:44 +0300 +Subject: module: ensure that kobject_put() is safe for module type kobjects + +From: Dmitry Antipov + +commit a6aeb739974ec73e5217c75a7c008a688d3d5cf1 upstream. + +In 'lookup_or_create_module_kobject()', an internal kobject is created +using 'module_ktype'. So call to 'kobject_put()' on error handling +path causes an attempt to use an uninitialized completion pointer in +'module_kobject_release()'. In this scenario, we just want to release +kobject without an extra synchronization required for a regular module +unloading process, so adding an extra check whether 'complete()' is +actually required makes 'kobject_put()' safe. + +Reported-by: syzbot+7fb8a372e1f6add936dd@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=7fb8a372e1f6add936dd +Fixes: 942e443127e9 ("module: Fix mod->mkobj.kobj potentially freed too early") +Cc: stable@vger.kernel.org +Suggested-by: Petr Pavlu +Signed-off-by: Dmitry Antipov +Link: https://lore.kernel.org/r/20250507065044.86529-1-dmantipov@yandex.ru +Signed-off-by: Petr Pavlu +Signed-off-by: Greg Kroah-Hartman +--- + kernel/params.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/kernel/params.c ++++ b/kernel/params.c +@@ -945,7 +945,9 @@ struct kset *module_kset; + static void module_kobj_release(struct kobject *kobj) + { + struct module_kobject *mk = to_module_kobject(kobj); +- complete(mk->kobj_completion); ++ ++ if (mk->kobj_completion) ++ complete(mk->kobj_completion); + } + + const struct kobj_type module_ktype = { diff --git a/queue-6.6/ocfs2-implement-handshaking-with-ocfs2-recovery-thread.patch b/queue-6.6/ocfs2-implement-handshaking-with-ocfs2-recovery-thread.patch new file mode 100644 index 0000000000..68b0f718c3 --- /dev/null +++ b/queue-6.6/ocfs2-implement-handshaking-with-ocfs2-recovery-thread.patch @@ -0,0 +1,139 @@ +From 8f947e0fd595951460f5a6e1ac29baa82fa02eab Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Thu, 24 Apr 2025 15:45:12 +0200 +Subject: ocfs2: implement handshaking with ocfs2 recovery thread + +From: Jan Kara + +commit 8f947e0fd595951460f5a6e1ac29baa82fa02eab upstream. + +We will need ocfs2 recovery thread to acknowledge transitions of +recovery_state when disabling particular types of recovery. This is +similar to what currently happens when disabling recovery completely, just +more general. Implement the handshake and use it for exit from recovery. + +Link: https://lkml.kernel.org/r/20250424134515.18933-5-jack@suse.cz +Fixes: 5f530de63cfc ("ocfs2: Use s_umount for quota recovery protection") +Signed-off-by: Jan Kara +Reviewed-by: Heming Zhao +Tested-by: Heming Zhao +Acked-by: Joseph Qi +Cc: Changwei Ge +Cc: Joel Becker +Cc: Jun Piao +Cc: Junxiao Bi +Cc: Mark Fasheh +Cc: Murad Masimov +Cc: Shichangkuo +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/ocfs2/journal.c | 52 +++++++++++++++++++++++++++++++++++----------------- + fs/ocfs2/ocfs2.h | 4 ++++ + 2 files changed, 39 insertions(+), 17 deletions(-) + +--- a/fs/ocfs2/journal.c ++++ b/fs/ocfs2/journal.c +@@ -190,31 +190,48 @@ int ocfs2_recovery_init(struct ocfs2_sup + return 0; + } + +-/* we can't grab the goofy sem lock from inside wait_event, so we use +- * memory barriers to make sure that we'll see the null task before +- * being woken up */ + static int ocfs2_recovery_thread_running(struct ocfs2_super *osb) + { +- mb(); + return osb->recovery_thread_task != NULL; + } + +-void ocfs2_recovery_exit(struct ocfs2_super *osb) ++static void ocfs2_recovery_disable(struct ocfs2_super *osb, ++ enum ocfs2_recovery_state state) + { +- struct ocfs2_recovery_map *rm; +- +- /* disable any new recovery threads and wait for any currently +- * running ones to exit. Do this before setting the vol_state. */ + mutex_lock(&osb->recovery_lock); +- osb->recovery_state = OCFS2_REC_DISABLED; ++ /* ++ * If recovery thread is not running, we can directly transition to ++ * final state. ++ */ ++ if (!ocfs2_recovery_thread_running(osb)) { ++ osb->recovery_state = state + 1; ++ goto out_lock; ++ } ++ osb->recovery_state = state; ++ /* Wait for recovery thread to acknowledge state transition */ ++ wait_event_cmd(osb->recovery_event, ++ !ocfs2_recovery_thread_running(osb) || ++ osb->recovery_state >= state + 1, ++ mutex_unlock(&osb->recovery_lock), ++ mutex_lock(&osb->recovery_lock)); ++out_lock: + mutex_unlock(&osb->recovery_lock); +- wait_event(osb->recovery_event, !ocfs2_recovery_thread_running(osb)); + +- /* At this point, we know that no more recovery threads can be +- * launched, so wait for any recovery completion work to +- * complete. */ ++ /* ++ * At this point we know that no more recovery work can be queued so ++ * wait for any recovery completion work to complete. ++ */ + if (osb->ocfs2_wq) + flush_workqueue(osb->ocfs2_wq); ++} ++ ++void ocfs2_recovery_exit(struct ocfs2_super *osb) ++{ ++ struct ocfs2_recovery_map *rm; ++ ++ /* disable any new recovery threads and wait for any currently ++ * running ones to exit. Do this before setting the vol_state. */ ++ ocfs2_recovery_disable(osb, OCFS2_REC_WANT_DISABLE); + + /* + * Now that recovery is shut down, and the osb is about to be +@@ -1569,7 +1586,8 @@ bail: + + ocfs2_free_replay_slots(osb); + osb->recovery_thread_task = NULL; +- mb(); /* sync with ocfs2_recovery_thread_running */ ++ if (osb->recovery_state == OCFS2_REC_WANT_DISABLE) ++ osb->recovery_state = OCFS2_REC_DISABLED; + wake_up(&osb->recovery_event); + + mutex_unlock(&osb->recovery_lock); +@@ -1585,13 +1603,13 @@ void ocfs2_recovery_thread(struct ocfs2_ + int was_set = -1; + + mutex_lock(&osb->recovery_lock); +- if (osb->recovery_state < OCFS2_REC_DISABLED) ++ if (osb->recovery_state < OCFS2_REC_WANT_DISABLE) + was_set = ocfs2_recovery_map_set(osb, node_num); + + trace_ocfs2_recovery_thread(node_num, osb->node_num, + osb->recovery_state, osb->recovery_thread_task, was_set); + +- if (osb->recovery_state == OCFS2_REC_DISABLED) ++ if (osb->recovery_state >= OCFS2_REC_WANT_DISABLE) + goto out; + + if (osb->recovery_thread_task) +--- a/fs/ocfs2/ocfs2.h ++++ b/fs/ocfs2/ocfs2.h +@@ -310,6 +310,10 @@ void ocfs2_initialize_journal_triggers(s + + enum ocfs2_recovery_state { + OCFS2_REC_ENABLED = 0, ++ OCFS2_REC_WANT_DISABLE, ++ /* ++ * Must be OCFS2_REC_WANT_DISABLE + 1 for ocfs2_recovery_exit() to work ++ */ + OCFS2_REC_DISABLED, + }; + diff --git a/queue-6.6/ocfs2-stop-quota-recovery-before-disabling-quotas.patch b/queue-6.6/ocfs2-stop-quota-recovery-before-disabling-quotas.patch new file mode 100644 index 0000000000..521965c43a --- /dev/null +++ b/queue-6.6/ocfs2-stop-quota-recovery-before-disabling-quotas.patch @@ -0,0 +1,171 @@ +From fcaf3b2683b05a9684acdebda706a12025a6927a Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Thu, 24 Apr 2025 15:45:13 +0200 +Subject: ocfs2: stop quota recovery before disabling quotas + +From: Jan Kara + +commit fcaf3b2683b05a9684acdebda706a12025a6927a upstream. + +Currently quota recovery is synchronized with unmount using sb->s_umount +semaphore. That is however prone to deadlocks because +flush_workqueue(osb->ocfs2_wq) called from umount code can wait for quota +recovery to complete while ocfs2_finish_quota_recovery() waits for +sb->s_umount semaphore. + +Grabbing of sb->s_umount semaphore in ocfs2_finish_quota_recovery() is +only needed to protect that function from disabling of quotas from +ocfs2_dismount_volume(). Handle this problem by disabling quota recovery +early during unmount in ocfs2_dismount_volume() instead so that we can +drop acquisition of sb->s_umount from ocfs2_finish_quota_recovery(). + +Link: https://lkml.kernel.org/r/20250424134515.18933-6-jack@suse.cz +Fixes: 5f530de63cfc ("ocfs2: Use s_umount for quota recovery protection") +Signed-off-by: Jan Kara +Reported-by: Shichangkuo +Reported-by: Murad Masimov +Reviewed-by: Heming Zhao +Tested-by: Heming Zhao +Acked-by: Joseph Qi +Cc: Changwei Ge +Cc: Joel Becker +Cc: Jun Piao +Cc: Junxiao Bi +Cc: Mark Fasheh +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/ocfs2/journal.c | 20 ++++++++++++++++++-- + fs/ocfs2/journal.h | 1 + + fs/ocfs2/ocfs2.h | 6 ++++++ + fs/ocfs2/quota_local.c | 9 ++------- + fs/ocfs2/super.c | 3 +++ + 5 files changed, 30 insertions(+), 9 deletions(-) + +--- a/fs/ocfs2/journal.c ++++ b/fs/ocfs2/journal.c +@@ -225,6 +225,11 @@ out_lock: + flush_workqueue(osb->ocfs2_wq); + } + ++void ocfs2_recovery_disable_quota(struct ocfs2_super *osb) ++{ ++ ocfs2_recovery_disable(osb, OCFS2_REC_QUOTA_WANT_DISABLE); ++} ++ + void ocfs2_recovery_exit(struct ocfs2_super *osb) + { + struct ocfs2_recovery_map *rm; +@@ -1489,6 +1494,18 @@ static int __ocfs2_recovery_thread(void + } + } + restart: ++ if (quota_enabled) { ++ mutex_lock(&osb->recovery_lock); ++ /* Confirm that recovery thread will no longer recover quotas */ ++ if (osb->recovery_state == OCFS2_REC_QUOTA_WANT_DISABLE) { ++ osb->recovery_state = OCFS2_REC_QUOTA_DISABLED; ++ wake_up(&osb->recovery_event); ++ } ++ if (osb->recovery_state >= OCFS2_REC_QUOTA_DISABLED) ++ quota_enabled = 0; ++ mutex_unlock(&osb->recovery_lock); ++ } ++ + status = ocfs2_super_lock(osb, 1); + if (status < 0) { + mlog_errno(status); +@@ -1592,8 +1609,7 @@ bail: + + mutex_unlock(&osb->recovery_lock); + +- if (quota_enabled) +- kfree(rm_quota); ++ kfree(rm_quota); + + return status; + } +--- a/fs/ocfs2/journal.h ++++ b/fs/ocfs2/journal.h +@@ -148,6 +148,7 @@ void ocfs2_wait_for_recovery(struct ocfs + + int ocfs2_recovery_init(struct ocfs2_super *osb); + void ocfs2_recovery_exit(struct ocfs2_super *osb); ++void ocfs2_recovery_disable_quota(struct ocfs2_super *osb); + + int ocfs2_compute_replay_slots(struct ocfs2_super *osb); + void ocfs2_free_replay_slots(struct ocfs2_super *osb); +--- a/fs/ocfs2/ocfs2.h ++++ b/fs/ocfs2/ocfs2.h +@@ -310,6 +310,12 @@ void ocfs2_initialize_journal_triggers(s + + enum ocfs2_recovery_state { + OCFS2_REC_ENABLED = 0, ++ OCFS2_REC_QUOTA_WANT_DISABLE, ++ /* ++ * Must be OCFS2_REC_QUOTA_WANT_DISABLE + 1 for ++ * ocfs2_recovery_disable_quota() to work. ++ */ ++ OCFS2_REC_QUOTA_DISABLED, + OCFS2_REC_WANT_DISABLE, + /* + * Must be OCFS2_REC_WANT_DISABLE + 1 for ocfs2_recovery_exit() to work +--- a/fs/ocfs2/quota_local.c ++++ b/fs/ocfs2/quota_local.c +@@ -453,8 +453,7 @@ out: + + /* Sync changes in local quota file into global quota file and + * reinitialize local quota file. +- * The function expects local quota file to be already locked and +- * s_umount locked in shared mode. */ ++ * The function expects local quota file to be already locked. */ + static int ocfs2_recover_local_quota_file(struct inode *lqinode, + int type, + struct ocfs2_quota_recovery *rec) +@@ -585,7 +584,6 @@ int ocfs2_finish_quota_recovery(struct o + { + unsigned int ino[OCFS2_MAXQUOTAS] = { LOCAL_USER_QUOTA_SYSTEM_INODE, + LOCAL_GROUP_QUOTA_SYSTEM_INODE }; +- struct super_block *sb = osb->sb; + struct ocfs2_local_disk_dqinfo *ldinfo; + struct buffer_head *bh; + handle_t *handle; +@@ -597,7 +595,6 @@ int ocfs2_finish_quota_recovery(struct o + printk(KERN_NOTICE "ocfs2: Finishing quota recovery on device (%s) for " + "slot %u\n", osb->dev_str, slot_num); + +- down_read(&sb->s_umount); + for (type = 0; type < OCFS2_MAXQUOTAS; type++) { + if (list_empty(&(rec->r_list[type]))) + continue; +@@ -674,7 +671,6 @@ out_put: + break; + } + out: +- up_read(&sb->s_umount); + kfree(rec); + return status; + } +@@ -840,8 +836,7 @@ static int ocfs2_local_free_info(struct + ocfs2_release_local_quota_bitmaps(&oinfo->dqi_chunk); + + /* +- * s_umount held in exclusive mode protects us against racing with +- * recovery thread... ++ * ocfs2_dismount_volume() has already aborted quota recovery... + */ + if (oinfo->dqi_rec) { + ocfs2_free_quota_recovery(oinfo->dqi_rec); +--- a/fs/ocfs2/super.c ++++ b/fs/ocfs2/super.c +@@ -1870,6 +1870,9 @@ static void ocfs2_dismount_volume(struct + /* Orphan scan should be stopped as early as possible */ + ocfs2_orphan_scan_stop(osb); + ++ /* Stop quota recovery so that we can disable quotas */ ++ ocfs2_recovery_disable_quota(osb); ++ + ocfs2_disable_quotas(osb); + + /* All dquots should be freed by now */ diff --git a/queue-6.6/ocfs2-switch-osb-disable_recovery-to-enum.patch b/queue-6.6/ocfs2-switch-osb-disable_recovery-to-enum.patch new file mode 100644 index 0000000000..af2cf292af --- /dev/null +++ b/queue-6.6/ocfs2-switch-osb-disable_recovery-to-enum.patch @@ -0,0 +1,107 @@ +From c0fb83088f0cc4ee4706e0495ee8b06f49daa716 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Thu, 24 Apr 2025 15:45:11 +0200 +Subject: ocfs2: switch osb->disable_recovery to enum + +From: Jan Kara + +commit c0fb83088f0cc4ee4706e0495ee8b06f49daa716 upstream. + +Patch series "ocfs2: Fix deadlocks in quota recovery", v3. + +This implements another approach to fixing quota recovery deadlocks. We +avoid grabbing sb->s_umount semaphore from ocfs2_finish_quota_recovery() +and instead stop quota recovery early in ocfs2_dismount_volume(). + + +This patch (of 3): + +We will need more recovery states than just pure enable / disable to fix +deadlocks with quota recovery. Switch osb->disable_recovery to enum. + +Link: https://lkml.kernel.org/r/20250424134301.1392-1-jack@suse.cz +Link: https://lkml.kernel.org/r/20250424134515.18933-4-jack@suse.cz +Fixes: 5f530de63cfc ("ocfs2: Use s_umount for quota recovery protection") +Signed-off-by: Jan Kara +Reviewed-by: Heming Zhao +Tested-by: Heming Zhao +Acked-by: Joseph Qi +Cc: Mark Fasheh +Cc: Joel Becker +Cc: Junxiao Bi +Cc: Changwei Ge +Cc: Jun Piao +Cc: Murad Masimov +Cc: Shichangkuo +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/ocfs2/journal.c | 14 ++++++++------ + fs/ocfs2/ocfs2.h | 7 ++++++- + 2 files changed, 14 insertions(+), 7 deletions(-) + +--- a/fs/ocfs2/journal.c ++++ b/fs/ocfs2/journal.c +@@ -174,7 +174,7 @@ int ocfs2_recovery_init(struct ocfs2_sup + struct ocfs2_recovery_map *rm; + + mutex_init(&osb->recovery_lock); +- osb->disable_recovery = 0; ++ osb->recovery_state = OCFS2_REC_ENABLED; + osb->recovery_thread_task = NULL; + init_waitqueue_head(&osb->recovery_event); + +@@ -206,7 +206,7 @@ void ocfs2_recovery_exit(struct ocfs2_su + /* disable any new recovery threads and wait for any currently + * running ones to exit. Do this before setting the vol_state. */ + mutex_lock(&osb->recovery_lock); +- osb->disable_recovery = 1; ++ osb->recovery_state = OCFS2_REC_DISABLED; + mutex_unlock(&osb->recovery_lock); + wait_event(osb->recovery_event, !ocfs2_recovery_thread_running(osb)); + +@@ -1582,14 +1582,16 @@ bail: + + void ocfs2_recovery_thread(struct ocfs2_super *osb, int node_num) + { ++ int was_set = -1; ++ + mutex_lock(&osb->recovery_lock); ++ if (osb->recovery_state < OCFS2_REC_DISABLED) ++ was_set = ocfs2_recovery_map_set(osb, node_num); + + trace_ocfs2_recovery_thread(node_num, osb->node_num, +- osb->disable_recovery, osb->recovery_thread_task, +- osb->disable_recovery ? +- -1 : ocfs2_recovery_map_set(osb, node_num)); ++ osb->recovery_state, osb->recovery_thread_task, was_set); + +- if (osb->disable_recovery) ++ if (osb->recovery_state == OCFS2_REC_DISABLED) + goto out; + + if (osb->recovery_thread_task) +--- a/fs/ocfs2/ocfs2.h ++++ b/fs/ocfs2/ocfs2.h +@@ -308,6 +308,11 @@ enum ocfs2_journal_trigger_type { + void ocfs2_initialize_journal_triggers(struct super_block *sb, + struct ocfs2_triggers triggers[]); + ++enum ocfs2_recovery_state { ++ OCFS2_REC_ENABLED = 0, ++ OCFS2_REC_DISABLED, ++}; ++ + struct ocfs2_journal; + struct ocfs2_slot_info; + struct ocfs2_recovery_map; +@@ -370,7 +375,7 @@ struct ocfs2_super + struct ocfs2_recovery_map *recovery_map; + struct ocfs2_replay_map *replay_map; + struct task_struct *recovery_thread_task; +- int disable_recovery; ++ enum ocfs2_recovery_state recovery_state; + wait_queue_head_t checkpoint_event; + struct ocfs2_journal *journal; + unsigned long osb_commit_interval; diff --git a/queue-6.6/series b/queue-6.6/series index dec339c55f..2b6116fab1 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -55,3 +55,19 @@ drm-amdgpu-hdp5.2-use-memcfg-register-to-post-the-write-for-hdp-flush.patch drm-amdgpu-hdp5-use-memcfg-register-to-post-the-write-for-hdp-flush.patch drm-amdgpu-hdp6-use-memcfg-register-to-post-the-write-for-hdp-flush.patch usb-uhci-platform-make-the-clock-really-optional.patch +smb-client-avoid-race-in-open_cached_dir-with-lease-breaks.patch +xen-swiotlb-use-swiotlb-bouncing-if-kmalloc-allocation-demands-it.patch +xenbus-use-kref-to-track-req-lifetime.patch +clocksource-i8253-use-raw_spinlock_irqsave-in-clockevent_i8253_disable.patch +memblock-accept-allocated-memory-before-use-in-memblock_double_array.patch +module-ensure-that-kobject_put-is-safe-for-module-type-kobjects.patch +x86-microcode-consolidate-the-loader-enablement-checking.patch +ocfs2-switch-osb-disable_recovery-to-enum.patch +ocfs2-implement-handshaking-with-ocfs2-recovery-thread.patch +ocfs2-stop-quota-recovery-before-disabling-quotas.patch +usb-cdnsp-fix-issue-with-resuming-from-l1.patch +usb-cdnsp-fix-l1-resume-issue-for-rtl_revision_new_lpm-version.patch +usb-gadget-f_ecm-add-get_status-callback.patch +usb-gadget-tegra-xudc-ack-st_rc-after-clearing-ctrl_run.patch +usb-gadget-use-get_status-callback-to-set-remote-wakeup-capability.patch +usb-host-tegra-prevent-host-controller-crash-when-otg-port-is-used.patch diff --git a/queue-6.6/smb-client-avoid-race-in-open_cached_dir-with-lease-breaks.patch b/queue-6.6/smb-client-avoid-race-in-open_cached_dir-with-lease-breaks.patch new file mode 100644 index 0000000000..1c823c3aa5 --- /dev/null +++ b/queue-6.6/smb-client-avoid-race-in-open_cached_dir-with-lease-breaks.patch @@ -0,0 +1,89 @@ +From 3ca02e63edccb78ef3659bebc68579c7224a6ca2 Mon Sep 17 00:00:00 2001 +From: Paul Aurich +Date: Tue, 6 May 2025 22:28:09 -0700 +Subject: smb: client: Avoid race in open_cached_dir with lease breaks + +From: Paul Aurich + +commit 3ca02e63edccb78ef3659bebc68579c7224a6ca2 upstream. + +A pre-existing valid cfid returned from find_or_create_cached_dir might +race with a lease break, meaning open_cached_dir doesn't consider it +valid, and thinks it's newly-constructed. This leaks a dentry reference +if the allocation occurs before the queued lease break work runs. + +Avoid the race by extending holding the cfid_list_lock across +find_or_create_cached_dir and when the result is checked. + +Cc: stable@vger.kernel.org +Reviewed-by: Henrique Carvalho +Signed-off-by: Paul Aurich +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/smb/client/cached_dir.c | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +--- a/fs/smb/client/cached_dir.c ++++ b/fs/smb/client/cached_dir.c +@@ -29,7 +29,6 @@ static struct cached_fid *find_or_create + { + struct cached_fid *cfid; + +- spin_lock(&cfids->cfid_list_lock); + list_for_each_entry(cfid, &cfids->entries, entry) { + if (!strcmp(cfid->path, path)) { + /* +@@ -38,25 +37,20 @@ static struct cached_fid *find_or_create + * being deleted due to a lease break. + */ + if (!cfid->time || !cfid->has_lease) { +- spin_unlock(&cfids->cfid_list_lock); + return NULL; + } + kref_get(&cfid->refcount); +- spin_unlock(&cfids->cfid_list_lock); + return cfid; + } + } + if (lookup_only) { +- spin_unlock(&cfids->cfid_list_lock); + return NULL; + } + if (cfids->num_entries >= max_cached_dirs) { +- spin_unlock(&cfids->cfid_list_lock); + return NULL; + } + cfid = init_cached_dir(path); + if (cfid == NULL) { +- spin_unlock(&cfids->cfid_list_lock); + return NULL; + } + cfid->cfids = cfids; +@@ -74,7 +68,6 @@ static struct cached_fid *find_or_create + */ + cfid->has_lease = true; + +- spin_unlock(&cfids->cfid_list_lock); + return cfid; + } + +@@ -185,8 +178,10 @@ replay_again: + if (!utf16_path) + return -ENOMEM; + ++ spin_lock(&cfids->cfid_list_lock); + cfid = find_or_create_cached_dir(cfids, path, lookup_only, tcon->max_cached_dirs); + if (cfid == NULL) { ++ spin_unlock(&cfids->cfid_list_lock); + kfree(utf16_path); + return -ENOENT; + } +@@ -195,7 +190,6 @@ replay_again: + * Otherwise, it is either a new entry or laundromat worker removed it + * from @cfids->entries. Caller will put last reference if the latter. + */ +- spin_lock(&cfids->cfid_list_lock); + if (cfid->has_lease && cfid->time) { + spin_unlock(&cfids->cfid_list_lock); + *ret_cfid = cfid; diff --git a/queue-6.6/usb-cdnsp-fix-issue-with-resuming-from-l1.patch b/queue-6.6/usb-cdnsp-fix-issue-with-resuming-from-l1.patch new file mode 100644 index 0000000000..29541d4494 --- /dev/null +++ b/queue-6.6/usb-cdnsp-fix-issue-with-resuming-from-l1.patch @@ -0,0 +1,149 @@ +From 241e2ce88e5a494be7a5d44c0697592f1632fbee Mon Sep 17 00:00:00 2001 +From: Pawel Laszczak +Date: Fri, 18 Apr 2025 04:55:16 +0000 +Subject: usb: cdnsp: Fix issue with resuming from L1 + +From: Pawel Laszczak + +commit 241e2ce88e5a494be7a5d44c0697592f1632fbee upstream. + +In very rare cases after resuming controller from L1 to L0 it reads +registers before the clock UTMI have been enabled and as the result +driver reads incorrect value. +Most of registers are in APB domain clock but some of them (e.g. PORTSC) +are in UTMI domain clock. +After entering to L1 state the UTMI clock can be disabled. +When controller transition from L1 to L0 the port status change event is +reported and in interrupt runtime function driver reads PORTSC. +During this read operation controller synchronize UTMI and APB domain +but UTMI clock is still disabled and in result it reads 0xFFFFFFFF value. +To fix this issue driver increases APB timeout value. + +The issue is platform specific and if the default value of APB timeout +is not sufficient then this time should be set Individually for each +platform. + +Fixes: 3d82904559f4 ("usb: cdnsp: cdns3 Add main part of Cadence USBSSP DRD Driver") +Cc: stable +Signed-off-by: Pawel Laszczak +Acked-by: Peter Chen +Link: https://lore.kernel.org/r/PH7PR07MB953846C57973E4DB134CAA71DDBF2@PH7PR07MB9538.namprd07.prod.outlook.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/cdns3/cdnsp-gadget.c | 29 +++++++++++++++++++++++++++++ + drivers/usb/cdns3/cdnsp-gadget.h | 3 +++ + drivers/usb/cdns3/cdnsp-pci.c | 12 ++++++++++-- + drivers/usb/cdns3/core.h | 3 +++ + 4 files changed, 45 insertions(+), 2 deletions(-) + +--- a/drivers/usb/cdns3/cdnsp-gadget.c ++++ b/drivers/usb/cdns3/cdnsp-gadget.c +@@ -138,6 +138,26 @@ static void cdnsp_clear_port_change_bit( + (portsc & PORT_CHANGE_BITS), port_regs); + } + ++static void cdnsp_set_apb_timeout_value(struct cdnsp_device *pdev) ++{ ++ struct cdns *cdns = dev_get_drvdata(pdev->dev); ++ __le32 __iomem *reg; ++ void __iomem *base; ++ u32 offset = 0; ++ u32 val; ++ ++ if (!cdns->override_apb_timeout) ++ return; ++ ++ base = &pdev->cap_regs->hc_capbase; ++ offset = cdnsp_find_next_ext_cap(base, offset, D_XEC_PRE_REGS_CAP); ++ reg = base + offset + REG_CHICKEN_BITS_3_OFFSET; ++ ++ val = le32_to_cpu(readl(reg)); ++ val = CHICKEN_APB_TIMEOUT_SET(val, cdns->override_apb_timeout); ++ writel(cpu_to_le32(val), reg); ++} ++ + static void cdnsp_set_chicken_bits_2(struct cdnsp_device *pdev, u32 bit) + { + __le32 __iomem *reg; +@@ -1801,6 +1821,15 @@ static int cdnsp_gen_setup(struct cdnsp_ + pdev->hci_version = HC_VERSION(pdev->hcc_params); + pdev->hcc_params = readl(&pdev->cap_regs->hcc_params); + ++ /* ++ * Override the APB timeout value to give the controller more time for ++ * enabling UTMI clock and synchronizing APB and UTMI clock domains. ++ * This fix is platform specific and is required to fixes issue with ++ * reading incorrect value from PORTSC register after resuming ++ * from L1 state. ++ */ ++ cdnsp_set_apb_timeout_value(pdev); ++ + cdnsp_get_rev_cap(pdev); + + /* Make sure the Device Controller is halted. */ +--- a/drivers/usb/cdns3/cdnsp-gadget.h ++++ b/drivers/usb/cdns3/cdnsp-gadget.h +@@ -520,6 +520,9 @@ struct cdnsp_rev_cap { + #define REG_CHICKEN_BITS_2_OFFSET 0x48 + #define CHICKEN_XDMA_2_TP_CACHE_DIS BIT(28) + ++#define REG_CHICKEN_BITS_3_OFFSET 0x4C ++#define CHICKEN_APB_TIMEOUT_SET(p, val) (((p) & ~GENMASK(21, 0)) | (val)) ++ + /* XBUF Extended Capability ID. */ + #define XBUF_CAP_ID 0xCB + #define XBUF_RX_TAG_MASK_0_OFFSET 0x1C +--- a/drivers/usb/cdns3/cdnsp-pci.c ++++ b/drivers/usb/cdns3/cdnsp-pci.c +@@ -33,6 +33,8 @@ + #define CDNS_DRD_ID 0x0100 + #define CDNS_DRD_IF (PCI_CLASS_SERIAL_USB << 8 | 0x80) + ++#define CHICKEN_APB_TIMEOUT_VALUE 0x1C20 ++ + static struct pci_dev *cdnsp_get_second_fun(struct pci_dev *pdev) + { + /* +@@ -144,6 +146,14 @@ static int cdnsp_pci_probe(struct pci_de + cdnsp->otg_irq = pdev->irq; + } + ++ /* ++ * Cadence PCI based platform require some longer timeout for APB ++ * to fixes domain clock synchronization issue after resuming ++ * controller from L1 state. ++ */ ++ cdnsp->override_apb_timeout = CHICKEN_APB_TIMEOUT_VALUE; ++ pci_set_drvdata(pdev, cdnsp); ++ + if (pci_is_enabled(func)) { + cdnsp->dev = dev; + cdnsp->gadget_init = cdnsp_gadget_init; +@@ -153,8 +163,6 @@ static int cdnsp_pci_probe(struct pci_de + goto free_cdnsp; + } + +- pci_set_drvdata(pdev, cdnsp); +- + device_wakeup_enable(&pdev->dev); + if (pci_dev_run_wake(pdev)) + pm_runtime_put_noidle(&pdev->dev); +--- a/drivers/usb/cdns3/core.h ++++ b/drivers/usb/cdns3/core.h +@@ -79,6 +79,8 @@ struct cdns3_platform_data { + * @pdata: platform data from glue layer + * @lock: spinlock structure + * @xhci_plat_data: xhci private data structure pointer ++ * @override_apb_timeout: hold value of APB timeout. For value 0 the default ++ * value in CHICKEN_BITS_3 will be preserved. + * @gadget_init: pointer to gadget initialization function + */ + struct cdns { +@@ -117,6 +119,7 @@ struct cdns { + struct cdns3_platform_data *pdata; + spinlock_t lock; + struct xhci_plat_priv *xhci_plat_data; ++ u32 override_apb_timeout; + + int (*gadget_init)(struct cdns *cdns); + }; diff --git a/queue-6.6/usb-cdnsp-fix-l1-resume-issue-for-rtl_revision_new_lpm-version.patch b/queue-6.6/usb-cdnsp-fix-l1-resume-issue-for-rtl_revision_new_lpm-version.patch new file mode 100644 index 0000000000..a1533c20c5 --- /dev/null +++ b/queue-6.6/usb-cdnsp-fix-l1-resume-issue-for-rtl_revision_new_lpm-version.patch @@ -0,0 +1,76 @@ +From 8614ecdb1570e4fffe87ebdc62b613ed66f1f6a6 Mon Sep 17 00:00:00 2001 +From: Pawel Laszczak +Date: Fri, 25 Apr 2025 05:55:40 +0000 +Subject: usb: cdnsp: fix L1 resume issue for RTL_REVISION_NEW_LPM version + +From: Pawel Laszczak + +commit 8614ecdb1570e4fffe87ebdc62b613ed66f1f6a6 upstream. + +The controllers with rtl version larger than +RTL_REVISION_NEW_LPM (0x00002700) has bug which causes that controller +doesn't resume from L1 state. It happens if after receiving LPM packet +controller starts transitioning to L1 and in this moment the driver force +resuming by write operation to PORTSC.PLS. +It's corner case and happens when write operation to PORTSC occurs during +device delay before transitioning to L1 after transmitting ACK +time (TL1TokenRetry). + +Forcing transition from L1->L0 by driver for revision larger than +RTL_REVISION_NEW_LPM is not needed, so driver can simply fix this issue +through block call of cdnsp_force_l0_go function. + +Fixes: 3d82904559f4 ("usb: cdnsp: cdns3 Add main part of Cadence USBSSP DRD Driver") +Cc: stable +Signed-off-by: Pawel Laszczak +Acked-by: Peter Chen +Link: https://lore.kernel.org/r/PH7PR07MB9538B55C3A6E71F9ED29E980DD842@PH7PR07MB9538.namprd07.prod.outlook.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/cdns3/cdnsp-gadget.c | 2 ++ + drivers/usb/cdns3/cdnsp-gadget.h | 3 +++ + drivers/usb/cdns3/cdnsp-ring.c | 3 ++- + 3 files changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/usb/cdns3/cdnsp-gadget.c ++++ b/drivers/usb/cdns3/cdnsp-gadget.c +@@ -1796,6 +1796,8 @@ static void cdnsp_get_rev_cap(struct cdn + reg += cdnsp_find_next_ext_cap(reg, 0, RTL_REV_CAP); + pdev->rev_cap = reg; + ++ pdev->rtl_revision = readl(&pdev->rev_cap->rtl_revision); ++ + dev_info(pdev->dev, "Rev: %08x/%08x, eps: %08x, buff: %08x/%08x\n", + readl(&pdev->rev_cap->ctrl_revision), + readl(&pdev->rev_cap->rtl_revision), +--- a/drivers/usb/cdns3/cdnsp-gadget.h ++++ b/drivers/usb/cdns3/cdnsp-gadget.h +@@ -1362,6 +1362,7 @@ struct cdnsp_port { + * @rev_cap: Controller Capabilities Registers. + * @hcs_params1: Cached register copies of read-only HCSPARAMS1 + * @hcc_params: Cached register copies of read-only HCCPARAMS1 ++ * @rtl_revision: Cached controller rtl revision. + * @setup: Temporary buffer for setup packet. + * @ep0_preq: Internal allocated request used during enumeration. + * @ep0_stage: ep0 stage during enumeration process. +@@ -1416,6 +1417,8 @@ struct cdnsp_device { + __u32 hcs_params1; + __u32 hcs_params3; + __u32 hcc_params; ++ #define RTL_REVISION_NEW_LPM 0x2700 ++ __u32 rtl_revision; + /* Lock used in interrupt thread context. */ + spinlock_t lock; + struct usb_ctrlrequest setup; +--- a/drivers/usb/cdns3/cdnsp-ring.c ++++ b/drivers/usb/cdns3/cdnsp-ring.c +@@ -308,7 +308,8 @@ static bool cdnsp_ring_ep_doorbell(struc + + writel(db_value, reg_addr); + +- cdnsp_force_l0_go(pdev); ++ if (pdev->rtl_revision < RTL_REVISION_NEW_LPM) ++ cdnsp_force_l0_go(pdev); + + /* Doorbell was set. */ + return true; diff --git a/queue-6.6/usb-gadget-f_ecm-add-get_status-callback.patch b/queue-6.6/usb-gadget-f_ecm-add-get_status-callback.patch new file mode 100644 index 0000000000..3547a20c53 --- /dev/null +++ b/queue-6.6/usb-gadget-f_ecm-add-get_status-callback.patch @@ -0,0 +1,47 @@ +From 8e3820271c517ceb89ab7442656ba49fa23ee1d0 Mon Sep 17 00:00:00 2001 +From: Prashanth K +Date: Tue, 22 Apr 2025 16:02:29 +0530 +Subject: usb: gadget: f_ecm: Add get_status callback + +From: Prashanth K + +commit 8e3820271c517ceb89ab7442656ba49fa23ee1d0 upstream. + +When host sends GET_STATUS to ECM interface, handle the request +from the function driver. Since the interface is wakeup capable, +set the corresponding bit, and set RW bit if the function is +already armed for wakeup by the host. + +Cc: stable +Fixes: 481c225c4802 ("usb: gadget: Handle function suspend feature selector") +Signed-off-by: Prashanth K +Reviewed-by: Thinh Nguyen +Link: https://lore.kernel.org/r/20250422103231.1954387-2-prashanth.k@oss.qualcomm.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/function/f_ecm.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/usb/gadget/function/f_ecm.c ++++ b/drivers/usb/gadget/function/f_ecm.c +@@ -892,6 +892,12 @@ static void ecm_resume(struct usb_functi + gether_resume(&ecm->port); + } + ++static int ecm_get_status(struct usb_function *f) ++{ ++ return (f->func_wakeup_armed ? USB_INTRF_STAT_FUNC_RW : 0) | ++ USB_INTRF_STAT_FUNC_RW_CAP; ++} ++ + static void ecm_free(struct usb_function *f) + { + struct f_ecm *ecm; +@@ -960,6 +966,7 @@ static struct usb_function *ecm_alloc(st + ecm->port.func.disable = ecm_disable; + ecm->port.func.free_func = ecm_free; + ecm->port.func.suspend = ecm_suspend; ++ ecm->port.func.get_status = ecm_get_status; + ecm->port.func.resume = ecm_resume; + + return &ecm->port.func; diff --git a/queue-6.6/usb-gadget-tegra-xudc-ack-st_rc-after-clearing-ctrl_run.patch b/queue-6.6/usb-gadget-tegra-xudc-ack-st_rc-after-clearing-ctrl_run.patch new file mode 100644 index 0000000000..22fed06e1b --- /dev/null +++ b/queue-6.6/usb-gadget-tegra-xudc-ack-st_rc-after-clearing-ctrl_run.patch @@ -0,0 +1,40 @@ +From 59820fde001500c167342257650541280c622b73 Mon Sep 17 00:00:00 2001 +From: Wayne Chang +Date: Fri, 18 Apr 2025 16:12:28 +0800 +Subject: usb: gadget: tegra-xudc: ACK ST_RC after clearing CTRL_RUN + +From: Wayne Chang + +commit 59820fde001500c167342257650541280c622b73 upstream. + +We identified a bug where the ST_RC bit in the status register was not +being acknowledged after clearing the CTRL_RUN bit in the control +register. This could lead to unexpected behavior in the USB gadget +drivers. + +This patch resolves the issue by adding the necessary code to explicitly +acknowledge ST_RC after clearing CTRL_RUN based on the programming +sequence, ensuring proper state transition. + +Fixes: 49db427232fe ("usb: gadget: Add UDC driver for tegra XUSB device mode controller") +Cc: stable +Signed-off-by: Wayne Chang +Link: https://lore.kernel.org/r/20250418081228.1194779-1-waynec@nvidia.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/udc/tegra-xudc.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/usb/gadget/udc/tegra-xudc.c ++++ b/drivers/usb/gadget/udc/tegra-xudc.c +@@ -1749,6 +1749,10 @@ static int __tegra_xudc_ep_disable(struc + val = xudc_readl(xudc, CTRL); + val &= ~CTRL_RUN; + xudc_writel(xudc, val, CTRL); ++ ++ val = xudc_readl(xudc, ST); ++ if (val & ST_RC) ++ xudc_writel(xudc, ST_RC, ST); + } + + dev_info(xudc->dev, "ep %u disabled\n", ep->index); diff --git a/queue-6.6/usb-gadget-use-get_status-callback-to-set-remote-wakeup-capability.patch b/queue-6.6/usb-gadget-use-get_status-callback-to-set-remote-wakeup-capability.patch new file mode 100644 index 0000000000..a2b3065944 --- /dev/null +++ b/queue-6.6/usb-gadget-use-get_status-callback-to-set-remote-wakeup-capability.patch @@ -0,0 +1,63 @@ +From 5977a58dd5a4865198b0204b998adb0f634abe19 Mon Sep 17 00:00:00 2001 +From: Prashanth K +Date: Tue, 22 Apr 2025 16:02:30 +0530 +Subject: usb: gadget: Use get_status callback to set remote wakeup capability + +From: Prashanth K + +commit 5977a58dd5a4865198b0204b998adb0f634abe19 upstream. + +Currently when the host sends GET_STATUS request for an interface, +we use get_status callbacks to set/clear remote wakeup capability +of that interface. And if get_status callback isn't present for +that interface, then we assume its remote wakeup capability based +on bmAttributes. + +Now consider a scenario, where we have a USB configuration with +multiple interfaces (say ECM + ADB), here ECM is remote wakeup +capable and as of now ADB isn't. And bmAttributes will indicate +the device as wakeup capable. With the current implementation, +when host sends GET_STATUS request for both interfaces, we will +set FUNC_RW_CAP for both. This results in USB3 CV Chapter 9.15 +(Function Remote Wakeup Test) failures as host expects remote +wakeup from both interfaces. + +The above scenario is just an example, and the failure can be +observed if we use configuration with any interface except ECM. +Hence avoid configuring remote wakeup capability from composite +driver based on bmAttributes, instead use get_status callbacks +and let the function drivers decide this. + +Cc: stable +Fixes: 481c225c4802 ("usb: gadget: Handle function suspend feature selector") +Signed-off-by: Prashanth K +Reviewed-by: Thinh Nguyen +Link: https://lore.kernel.org/r/20250422103231.1954387-3-prashanth.k@oss.qualcomm.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/composite.c | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +--- a/drivers/usb/gadget/composite.c ++++ b/drivers/usb/gadget/composite.c +@@ -2011,15 +2011,13 @@ composite_setup(struct usb_gadget *gadge + + if (f->get_status) { + status = f->get_status(f); ++ + if (status < 0) + break; +- } else { +- /* Set D0 and D1 bits based on func wakeup capability */ +- if (f->config->bmAttributes & USB_CONFIG_ATT_WAKEUP) { +- status |= USB_INTRF_STAT_FUNC_RW_CAP; +- if (f->func_wakeup_armed) +- status |= USB_INTRF_STAT_FUNC_RW; +- } ++ ++ /* if D5 is not set, then device is not wakeup capable */ ++ if (!(f->config->bmAttributes & USB_CONFIG_ATT_WAKEUP)) ++ status &= ~(USB_INTRF_STAT_FUNC_RW_CAP | USB_INTRF_STAT_FUNC_RW); + } + + put_unaligned_le16(status & 0x0000ffff, req->buf); diff --git a/queue-6.6/usb-host-tegra-prevent-host-controller-crash-when-otg-port-is-used.patch b/queue-6.6/usb-host-tegra-prevent-host-controller-crash-when-otg-port-is-used.patch new file mode 100644 index 0000000000..fb601a490f --- /dev/null +++ b/queue-6.6/usb-host-tegra-prevent-host-controller-crash-when-otg-port-is-used.patch @@ -0,0 +1,66 @@ +From 732f35cf8bdfece582f6e4a9c659119036577308 Mon Sep 17 00:00:00 2001 +From: Jim Lin +Date: Tue, 22 Apr 2025 19:40:01 +0800 +Subject: usb: host: tegra: Prevent host controller crash when OTG port is used + +From: Jim Lin + +commit 732f35cf8bdfece582f6e4a9c659119036577308 upstream. + +When a USB device is connected to the OTG port, the tegra_xhci_id_work() +routine transitions the PHY to host mode and calls xhci_hub_control() +with the SetPortFeature command to enable port power. + +In certain cases, the XHCI controller may be in a low-power state +when this operation occurs. If xhci_hub_control() is invoked while +the controller is suspended, the PORTSC register may return 0xFFFFFFFF, +indicating a read failure. This causes xhci_hc_died() to be triggered, +leading to host controller shutdown. + +Example backtrace: +[ 105.445736] Workqueue: events tegra_xhci_id_work +[ 105.445747] dump_backtrace+0x0/0x1e8 +[ 105.445759] xhci_hc_died.part.48+0x40/0x270 +[ 105.445769] tegra_xhci_set_port_power+0xc0/0x240 +[ 105.445774] tegra_xhci_id_work+0x130/0x240 + +To prevent this, ensure the controller is fully resumed before +interacting with hardware registers by calling pm_runtime_get_sync() +prior to the host mode transition and xhci_hub_control(). + +Fixes: f836e7843036 ("usb: xhci-tegra: Add OTG support") +Cc: stable +Signed-off-by: Jim Lin +Signed-off-by: Wayne Chang +Link: https://lore.kernel.org/r/20250422114001.126367-1-waynec@nvidia.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/host/xhci-tegra.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/host/xhci-tegra.c ++++ b/drivers/usb/host/xhci-tegra.c +@@ -1363,6 +1363,7 @@ static void tegra_xhci_id_work(struct wo + tegra->otg_usb3_port = tegra_xusb_padctl_get_usb3_companion(tegra->padctl, + tegra->otg_usb2_port); + ++ pm_runtime_get_sync(tegra->dev); + if (tegra->host_mode) { + /* switch to host mode */ + if (tegra->otg_usb3_port >= 0) { +@@ -1392,6 +1393,7 @@ static void tegra_xhci_id_work(struct wo + } + + tegra_xhci_set_port_power(tegra, true, true); ++ pm_runtime_mark_last_busy(tegra->dev); + + } else { + if (tegra->otg_usb3_port >= 0) +@@ -1399,6 +1401,7 @@ static void tegra_xhci_id_work(struct wo + + tegra_xhci_set_port_power(tegra, true, false); + } ++ pm_runtime_put_autosuspend(tegra->dev); + } + + #if IS_ENABLED(CONFIG_PM) || IS_ENABLED(CONFIG_PM_SLEEP) diff --git a/queue-6.6/x86-microcode-consolidate-the-loader-enablement-checking.patch b/queue-6.6/x86-microcode-consolidate-the-loader-enablement-checking.patch new file mode 100644 index 0000000000..0e5cd09dce --- /dev/null +++ b/queue-6.6/x86-microcode-consolidate-the-loader-enablement-checking.patch @@ -0,0 +1,228 @@ +From 5214a9f6c0f56644acb9d2cbb58facf1856d322b Mon Sep 17 00:00:00 2001 +From: "Borislav Petkov (AMD)" +Date: Mon, 14 Apr 2025 11:59:33 +0200 +Subject: x86/microcode: Consolidate the loader enablement checking +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Borislav Petkov (AMD) + +commit 5214a9f6c0f56644acb9d2cbb58facf1856d322b upstream. + +Consolidate the whole logic which determines whether the microcode loader +should be enabled or not into a single function and call it everywhere. + +Well, almost everywhere - not in mk_early_pgtbl_32() because there the kernel +is running without paging enabled and checking dis_ucode_ldr et al would +require physical addresses and uglification of the code. + +But since this is 32-bit, the easier thing to do is to simply map the initrd +unconditionally especially since that mapping is getting removed later anyway +by zap_early_initrd_mapping() and avoid the uglification. + +In doing so, address the issue of old 486er machines without CPUID +support, not booting current kernels. + + [ mingo: Fix no previous prototype for ‘microcode_loader_disabled’ [-Wmissing-prototypes] ] + +Fixes: 4c585af7180c1 ("x86/boot/32: Temporarily map initrd for microcode loading") +Signed-off-by: Borislav Petkov (AMD) +Signed-off-by: Ingo Molnar +Signed-off-by: Borislav Petkov (AMD) +Cc: +Link: https://lore.kernel.org/r/CANpbe9Wm3z8fy9HbgS8cuhoj0TREYEEkBipDuhgkWFvqX0UoVQ@mail.gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/include/asm/microcode.h | 2 + + arch/x86/kernel/cpu/microcode/amd.c | 6 ++- + arch/x86/kernel/cpu/microcode/core.c | 58 ++++++++++++++++++------------- + arch/x86/kernel/cpu/microcode/intel.c | 2 - + arch/x86/kernel/cpu/microcode/internal.h | 1 + arch/x86/kernel/head32.c | 4 -- + 6 files changed, 41 insertions(+), 32 deletions(-) + +--- a/arch/x86/include/asm/microcode.h ++++ b/arch/x86/include/asm/microcode.h +@@ -17,10 +17,12 @@ struct ucode_cpu_info { + void load_ucode_bsp(void); + void load_ucode_ap(void); + void microcode_bsp_resume(void); ++bool __init microcode_loader_disabled(void); + #else + static inline void load_ucode_bsp(void) { } + static inline void load_ucode_ap(void) { } + static inline void microcode_bsp_resume(void) { } ++static inline bool __init microcode_loader_disabled(void) { return false; } + #endif + + extern unsigned long initrd_start_early; +--- a/arch/x86/kernel/cpu/microcode/amd.c ++++ b/arch/x86/kernel/cpu/microcode/amd.c +@@ -1102,15 +1102,17 @@ static enum ucode_state load_microcode_a + + static int __init save_microcode_in_initrd(void) + { +- unsigned int cpuid_1_eax = native_cpuid_eax(1); + struct cpuinfo_x86 *c = &boot_cpu_data; + struct cont_desc desc = { 0 }; ++ unsigned int cpuid_1_eax; + enum ucode_state ret; + struct cpio_data cp; + +- if (dis_ucode_ldr || c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) ++ if (microcode_loader_disabled() || c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) + return 0; + ++ cpuid_1_eax = native_cpuid_eax(1); ++ + if (!find_blobs_in_containers(&cp)) + return -EINVAL; + +--- a/arch/x86/kernel/cpu/microcode/core.c ++++ b/arch/x86/kernel/cpu/microcode/core.c +@@ -43,8 +43,8 @@ + + #define DRIVER_VERSION "2.2" + +-static struct microcode_ops *microcode_ops; +-bool dis_ucode_ldr = true; ++static struct microcode_ops *microcode_ops; ++static bool dis_ucode_ldr = false; + + bool force_minrev = IS_ENABLED(CONFIG_MICROCODE_LATE_FORCE_MINREV); + module_param(force_minrev, bool, S_IRUSR | S_IWUSR); +@@ -91,6 +91,9 @@ static bool amd_check_current_patch_leve + u32 lvl, dummy, i; + u32 *levels; + ++ if (x86_cpuid_vendor() != X86_VENDOR_AMD) ++ return false; ++ + native_rdmsr(MSR_AMD64_PATCH_LEVEL, lvl, dummy); + + levels = final_levels; +@@ -102,27 +105,29 @@ static bool amd_check_current_patch_leve + return false; + } + +-static bool __init check_loader_disabled_bsp(void) ++bool __init microcode_loader_disabled(void) + { +- static const char *__dis_opt_str = "dis_ucode_ldr"; +- const char *cmdline = boot_command_line; +- const char *option = __dis_opt_str; ++ if (dis_ucode_ldr) ++ return true; + + /* +- * CPUID(1).ECX[31]: reserved for hypervisor use. This is still not +- * completely accurate as xen pv guests don't see that CPUID bit set but +- * that's good enough as they don't land on the BSP path anyway. ++ * Disable when: ++ * ++ * 1) The CPU does not support CPUID. ++ * ++ * 2) Bit 31 in CPUID[1]:ECX is clear ++ * The bit is reserved for hypervisor use. This is still not ++ * completely accurate as XEN PV guests don't see that CPUID bit ++ * set, but that's good enough as they don't land on the BSP ++ * path anyway. ++ * ++ * 3) Certain AMD patch levels are not allowed to be ++ * overwritten. + */ +- if (native_cpuid_ecx(1) & BIT(31)) +- return true; +- +- if (x86_cpuid_vendor() == X86_VENDOR_AMD) { +- if (amd_check_current_patch_level()) +- return true; +- } +- +- if (cmdline_find_option_bool(cmdline, option) <= 0) +- dis_ucode_ldr = false; ++ if (!have_cpuid_p() || ++ native_cpuid_ecx(1) & BIT(31) || ++ amd_check_current_patch_level()) ++ dis_ucode_ldr = true; + + return dis_ucode_ldr; + } +@@ -132,7 +137,10 @@ void __init load_ucode_bsp(void) + unsigned int cpuid_1_eax; + bool intel = true; + +- if (!have_cpuid_p()) ++ if (cmdline_find_option_bool(boot_command_line, "dis_ucode_ldr") > 0) ++ dis_ucode_ldr = true; ++ ++ if (microcode_loader_disabled()) + return; + + cpuid_1_eax = native_cpuid_eax(1); +@@ -153,9 +161,6 @@ void __init load_ucode_bsp(void) + return; + } + +- if (check_loader_disabled_bsp()) +- return; +- + if (intel) + load_ucode_intel_bsp(&early_data); + else +@@ -166,6 +171,11 @@ void load_ucode_ap(void) + { + unsigned int cpuid_1_eax; + ++ /* ++ * Can't use microcode_loader_disabled() here - .init section ++ * hell. It doesn't have to either - the BSP variant must've ++ * parsed cmdline already anyway. ++ */ + if (dis_ucode_ldr) + return; + +@@ -817,7 +827,7 @@ static int __init microcode_init(void) + struct cpuinfo_x86 *c = &boot_cpu_data; + int error; + +- if (dis_ucode_ldr) ++ if (microcode_loader_disabled()) + return -EINVAL; + + if (c->x86_vendor == X86_VENDOR_INTEL) +--- a/arch/x86/kernel/cpu/microcode/intel.c ++++ b/arch/x86/kernel/cpu/microcode/intel.c +@@ -389,7 +389,7 @@ static int __init save_builtin_microcode + if (xchg(&ucode_patch_va, NULL) != UCODE_BSP_LOADED) + return 0; + +- if (dis_ucode_ldr || boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) ++ if (microcode_loader_disabled() || boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) + return 0; + + uci.mc = get_microcode_blob(&uci, true); +--- a/arch/x86/kernel/cpu/microcode/internal.h ++++ b/arch/x86/kernel/cpu/microcode/internal.h +@@ -94,7 +94,6 @@ static inline unsigned int x86_cpuid_fam + return x86_family(eax); + } + +-extern bool dis_ucode_ldr; + extern bool force_minrev; + + #ifdef CONFIG_CPU_SUP_AMD +--- a/arch/x86/kernel/head32.c ++++ b/arch/x86/kernel/head32.c +@@ -145,10 +145,6 @@ void __init __no_stack_protector mk_earl + *ptr = (unsigned long)ptep + PAGE_OFFSET; + + #ifdef CONFIG_MICROCODE_INITRD32 +- /* Running on a hypervisor? */ +- if (native_cpuid_ecx(1) & BIT(31)) +- return; +- + params = (struct boot_params *)__pa_nodebug(&boot_params); + if (!params->hdr.ramdisk_size || !params->hdr.ramdisk_image) + return; diff --git a/queue-6.6/xen-swiotlb-use-swiotlb-bouncing-if-kmalloc-allocation-demands-it.patch b/queue-6.6/xen-swiotlb-use-swiotlb-bouncing-if-kmalloc-allocation-demands-it.patch new file mode 100644 index 0000000000..8e9aae4d41 --- /dev/null +++ b/queue-6.6/xen-swiotlb-use-swiotlb-bouncing-if-kmalloc-allocation-demands-it.patch @@ -0,0 +1,42 @@ +From cd9c058489053e172a6654cad82ee936d1b09fab Mon Sep 17 00:00:00 2001 +From: John Ernberg +Date: Fri, 2 May 2025 11:40:55 +0000 +Subject: xen: swiotlb: Use swiotlb bouncing if kmalloc allocation demands it + +From: John Ernberg + +commit cd9c058489053e172a6654cad82ee936d1b09fab upstream. + +Xen swiotlb support was missed when the patch set starting with +4ab5f8ec7d71 ("mm/slab: decouple ARCH_KMALLOC_MINALIGN from +ARCH_DMA_MINALIGN") was merged. + +When running Xen on iMX8QXP, a SoC without IOMMU, the effect was that USB +transfers ended up corrupted when there was more than one URB inflight at +the same time. + +Add a call to dma_kmalloc_needs_bounce() to make sure that allocations too +small for DMA get bounced via swiotlb. + +Closes: https://lore.kernel.org/linux-usb/ab2776f0-b838-4cf6-a12a-c208eb6aad59@actia.se/ +Fixes: 4ab5f8ec7d71 ("mm/slab: decouple ARCH_KMALLOC_MINALIGN from ARCH_DMA_MINALIGN") +Cc: stable@kernel.org # v6.5+ +Signed-off-by: John Ernberg +Reviewed-by: Stefano Stabellini +Signed-off-by: Juergen Gross +Message-ID: <20250502114043.1968976-2-john.ernberg@actia.se> +Signed-off-by: Greg Kroah-Hartman +--- + drivers/xen/swiotlb-xen.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/xen/swiotlb-xen.c ++++ b/drivers/xen/swiotlb-xen.c +@@ -216,6 +216,7 @@ static dma_addr_t xen_swiotlb_map_page(s + * buffering it. + */ + if (dma_capable(dev, dev_addr, size, true) && ++ !dma_kmalloc_needs_bounce(dev, size, dir) && + !range_straddles_page_boundary(phys, size) && + !xen_arch_need_swiotlb(dev, phys, dev_addr) && + !is_swiotlb_force_bounce(dev)) diff --git a/queue-6.6/xenbus-use-kref-to-track-req-lifetime.patch b/queue-6.6/xenbus-use-kref-to-track-req-lifetime.patch new file mode 100644 index 0000000000..2b5bf13003 --- /dev/null +++ b/queue-6.6/xenbus-use-kref-to-track-req-lifetime.patch @@ -0,0 +1,172 @@ +From 1f0304dfd9d217c2f8b04a9ef4b3258a66eedd27 Mon Sep 17 00:00:00 2001 +From: Jason Andryuk +Date: Tue, 6 May 2025 17:09:33 -0400 +Subject: xenbus: Use kref to track req lifetime +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jason Andryuk + +commit 1f0304dfd9d217c2f8b04a9ef4b3258a66eedd27 upstream. + +Marek reported seeing a NULL pointer fault in the xenbus_thread +callstack: +BUG: kernel NULL pointer dereference, address: 0000000000000000 +RIP: e030:__wake_up_common+0x4c/0x180 +Call Trace: + + __wake_up_common_lock+0x82/0xd0 + process_msg+0x18e/0x2f0 + xenbus_thread+0x165/0x1c0 + +process_msg+0x18e is req->cb(req). req->cb is set to xs_wake_up(), a +thin wrapper around wake_up(), or xenbus_dev_queue_reply(). It seems +like it was xs_wake_up() in this case. + +It seems like req may have woken up the xs_wait_for_reply(), which +kfree()ed the req. When xenbus_thread resumes, it faults on the zero-ed +data. + +Linux Device Drivers 2nd edition states: +"Normally, a wake_up call can cause an immediate reschedule to happen, +meaning that other processes might run before wake_up returns." +... which would match the behaviour observed. + +Change to keeping two krefs on each request. One for the caller, and +one for xenbus_thread. Each will kref_put() when finished, and the last +will free it. + +This use of kref matches the description in +Documentation/core-api/kref.rst + +Link: https://lore.kernel.org/xen-devel/ZO0WrR5J0xuwDIxW@mail-itl/ +Reported-by: Marek Marczykowski-Górecki +Fixes: fd8aa9095a95 ("xen: optimize xenbus driver for multiple concurrent xenstore accesses") +Cc: stable@vger.kernel.org +Signed-off-by: Jason Andryuk +Reviewed-by: Juergen Gross +Signed-off-by: Juergen Gross +Message-ID: <20250506210935.5607-1-jason.andryuk@amd.com> +Signed-off-by: Greg Kroah-Hartman +--- + drivers/xen/xenbus/xenbus.h | 2 ++ + drivers/xen/xenbus/xenbus_comms.c | 9 ++++----- + drivers/xen/xenbus/xenbus_dev_frontend.c | 2 +- + drivers/xen/xenbus/xenbus_xs.c | 18 ++++++++++++++++-- + 4 files changed, 23 insertions(+), 8 deletions(-) + +--- a/drivers/xen/xenbus/xenbus.h ++++ b/drivers/xen/xenbus/xenbus.h +@@ -77,6 +77,7 @@ enum xb_req_state { + struct xb_req_data { + struct list_head list; + wait_queue_head_t wq; ++ struct kref kref; + struct xsd_sockmsg msg; + uint32_t caller_req_id; + enum xsd_sockmsg_type type; +@@ -103,6 +104,7 @@ int xb_init_comms(void); + void xb_deinit_comms(void); + int xs_watch_msg(struct xs_watch_event *event); + void xs_request_exit(struct xb_req_data *req); ++void xs_free_req(struct kref *kref); + + int xenbus_match(struct device *_dev, struct device_driver *_drv); + int xenbus_dev_probe(struct device *_dev); +--- a/drivers/xen/xenbus/xenbus_comms.c ++++ b/drivers/xen/xenbus/xenbus_comms.c +@@ -309,8 +309,8 @@ static int process_msg(void) + virt_wmb(); + req->state = xb_req_state_got_reply; + req->cb(req); +- } else +- kfree(req); ++ } ++ kref_put(&req->kref, xs_free_req); + } + + mutex_unlock(&xs_response_mutex); +@@ -386,14 +386,13 @@ static int process_writes(void) + state.req->msg.type = XS_ERROR; + state.req->err = err; + list_del(&state.req->list); +- if (state.req->state == xb_req_state_aborted) +- kfree(state.req); +- else { ++ if (state.req->state != xb_req_state_aborted) { + /* write err, then update state */ + virt_wmb(); + state.req->state = xb_req_state_got_reply; + wake_up(&state.req->wq); + } ++ kref_put(&state.req->kref, xs_free_req); + + mutex_unlock(&xb_write_mutex); + +--- a/drivers/xen/xenbus/xenbus_dev_frontend.c ++++ b/drivers/xen/xenbus/xenbus_dev_frontend.c +@@ -406,7 +406,7 @@ void xenbus_dev_queue_reply(struct xb_re + mutex_unlock(&u->reply_mutex); + + kfree(req->body); +- kfree(req); ++ kref_put(&req->kref, xs_free_req); + + kref_put(&u->kref, xenbus_file_free); + +--- a/drivers/xen/xenbus/xenbus_xs.c ++++ b/drivers/xen/xenbus/xenbus_xs.c +@@ -112,6 +112,12 @@ static void xs_suspend_exit(void) + wake_up_all(&xs_state_enter_wq); + } + ++void xs_free_req(struct kref *kref) ++{ ++ struct xb_req_data *req = container_of(kref, struct xb_req_data, kref); ++ kfree(req); ++} ++ + static uint32_t xs_request_enter(struct xb_req_data *req) + { + uint32_t rq_id; +@@ -237,6 +243,12 @@ static void xs_send(struct xb_req_data * + req->caller_req_id = req->msg.req_id; + req->msg.req_id = xs_request_enter(req); + ++ /* ++ * Take 2nd ref. One for this thread, and the second for the ++ * xenbus_thread. ++ */ ++ kref_get(&req->kref); ++ + mutex_lock(&xb_write_mutex); + list_add_tail(&req->list, &xb_write_list); + notify = list_is_singular(&xb_write_list); +@@ -261,8 +273,8 @@ static void *xs_wait_for_reply(struct xb + if (req->state == xb_req_state_queued || + req->state == xb_req_state_wait_reply) + req->state = xb_req_state_aborted; +- else +- kfree(req); ++ ++ kref_put(&req->kref, xs_free_req); + mutex_unlock(&xb_write_mutex); + + return ret; +@@ -291,6 +303,7 @@ int xenbus_dev_request_and_reply(struct + req->cb = xenbus_dev_queue_reply; + req->par = par; + req->user_req = true; ++ kref_init(&req->kref); + + xs_send(req, msg); + +@@ -319,6 +332,7 @@ static void *xs_talkv(struct xenbus_tran + req->num_vecs = num_vecs; + req->cb = xs_wake_up; + req->user_req = false; ++ kref_init(&req->kref); + + msg.req_id = 0; + msg.tx_id = t.id; -- 2.47.3