FAILED: patch "[PATCH] usb: gadget: f_fs: initialize reset_work at allocation time" failed to apply to 6.12-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x 3137b243c93982fe3460335e12f9247739766e10
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026071455-slacker-valium-0309@gregkh' --subject-prefix 'PATCH 6.12.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 3137b243c93982fe3460335e12f9247739766e10 Mon Sep 17 00:00:00 2001
From: Tyler Baker <[email protected]>
Date: Tue, 9 Jun 2026 15:36:34 -0400
Subject: [PATCH] usb: gadget: f_fs: initialize reset_work at allocation time
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
ffs_fs_kill_sb() unconditionally calls cancel_work_sync() on ffs->reset_work when a functionfs instance is unmounted:
ffs_data_reset(ffs); cancel_work_sync(&ffs->reset_work);
However ffs->reset_work is only ever initialized via INIT_WORK() in ffs_func_set_alt() and ffs_func_disable(), and only on the FFS_DEACTIVATED path. That state is reached solely by ffs_data_closed() when the instance is mounted with the "no_disconnect" option, so for the common case (no "no_disconnect", or mounted and unmounted without ever being deactivated) reset_work is never initialized.
ffs_data_new() allocates the ffs_data with kzalloc_obj() and does not initialize reset_work, and ffs_data_reset()/ffs_data_clear() do not touch it either, so reset_work.func is left NULL. cancel_work_sync() on such a work then trips the WARN_ON(!work->func) guard in __flush_work():
WARNING: kernel/workqueue.c:4301 at __flush_work+0x330/0x360, CPU#3: umount Call trace: __flush_work cancel_work_sync ffs_fs_kill_sb [usb_f_fs] deactivate_locked_super deactivate_super cleanup_mnt __cleanup_mnt task_work_run exit_to_user_mode_loop el0_svc
On older kernels cancel_work_sync() on a zero-initialized work struct was a silent no-op, which hid the missing initialization.
Initialize reset_work once in ffs_data_new() so it is always valid for the lifetime of the ffs_data, and drop the now-redundant INIT_WORK() calls from the two deactivation paths.
drivers/usb/gadget/function/f_fs.c +2 -2
@@ -288,6 +288,7 @@ static int ffs_acquire_dev(const char *dev_name, struct ffs_data *ffs_data);static void ffs_release_dev (struct ffs_dev *ffs_dev);static int ffs_ready (struct ffs_data *ffs);static void ffs_closed (struct ffs_data *ffs); +static void ffs_reset_work (struct work_struct *work);/* Misc helper functions ****************************************************/
@@ -2222,6 +2223,7 @@ static struct ffs_data *ffs_data_new(const char *dev_name)init_waitqueue_head (&ffs->ev.waitq);init_waitqueue_head (&ffs->wait);init_completion (&ffs->ep0req_completion); +INIT_WORK (&ffs->reset_work, ffs_reset_work);/* XXX REVISIT need to update it in some places, or do we? */ ffs->ev.can_stall =1 ;
@@ -3776,7 +3778,6 @@ static int ffs_func_set_alt(struct usb_function *f,if (ffs->state ==FFS_DEACTIVATED ) { ffs->state =FFS_CLOSING ;spin_unlock_irqrestore (&ffs->eps_lock, flags); -INIT_WORK (&ffs->reset_work, ffs_reset_work);schedule_work (&ffs->reset_work);return -ENODEV ; }
@@ -3807,7 +3808,6 @@ static void ffs_func_disable(struct usb_function *f)if (ffs->state ==FFS_DEACTIVATED ) { ffs->state =FFS_CLOSING ;spin_unlock_irqrestore (&ffs->eps_lock, flags); -INIT_WORK (&ffs->reset_work, ffs_reset_work);schedule_work (&ffs->reset_work);return ; }
Sasha Levin
maintainerPATCH 1/1 usb: gadget: f_fs: initialize reset_work at allocation time
From: Tyler Baker <[email protected]>
[ Upstream commit 3137b243c93982fe3460335e12f9247739766e10 ]
ffs_fs_kill_sb() unconditionally calls cancel_work_sync() on ffs->reset_work when a functionfs instance is unmounted:
ffs_data_reset(ffs); cancel_work_sync(&ffs->reset_work);
However ffs->reset_work is only ever initialized via INIT_WORK() in ffs_func_set_alt() and ffs_func_disable(), and only on the FFS_DEACTIVATED path. That state is reached solely by ffs_data_closed() when the instance is mounted with the "no_disconnect" option, so for the common case (no "no_disconnect", or mounted and unmounted without ever being deactivated) reset_work is never initialized.
ffs_data_new() allocates the ffs_data with kzalloc_obj() and does not initialize reset_work, and ffs_data_reset()/ffs_data_clear() do not touch it either, so reset_work.func is left NULL. cancel_work_sync() on such a work then trips the WARN_ON(!work->func) guard in __flush_work():
WARNING: kernel/workqueue.c:4301 at __flush_work+0x330/0x360, CPU#3: umount Call trace: __flush_work cancel_work_sync ffs_fs_kill_sb [usb_f_fs] deactivate_locked_super deactivate_super cleanup_mnt __cleanup_mnt task_work_run exit_to_user_mode_loop el0_svc
On older kernels cancel_work_sync() on a zero-initialized work struct was a silent no-op, which hid the missing initialization.
Initialize reset_work once in ffs_data_new() so it is always valid for the lifetime of the ffs_data, and drop the now-redundant INIT_WORK() calls from the two deactivation paths.
--- drivers/usb/gadget/function/f_fs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/usb/gadget/function/f_fs.c +2 -2
@@ -291,6 +291,7 @@ static int ffs_acquire_dev(const char *dev_name, struct ffs_data *ffs_data);static void ffs_release_dev (struct ffs_dev *ffs_dev);static int ffs_ready (struct ffs_data *ffs);static void ffs_closed (struct ffs_data *ffs); +static void ffs_reset_work (struct work_struct *work);/* Misc helper functions ****************************************************/
@@ -2224,6 +2225,7 @@ static struct ffs_data *ffs_data_new(const char *dev_name)init_waitqueue_head (&ffs->ev.waitq);init_waitqueue_head (&ffs->wait);init_completion (&ffs->ep0req_completion); +INIT_WORK (&ffs->reset_work, ffs_reset_work);/* XXX REVISIT need to update it in some places, or do we? */ ffs->ev.can_stall =1 ;
@@ -3770,7 +3772,6 @@ static int ffs_func_set_alt(struct usb_function *f,if (ffs->state ==FFS_DEACTIVATED ) { ffs->state =FFS_CLOSING ; -INIT_WORK (&ffs->reset_work, ffs_reset_work);schedule_work (&ffs->reset_work);return -ENODEV ; }
@@ -3797,7 +3798,6 @@ static void ffs_func_disable(struct usb_function *f)if (ffs->state ==FFS_DEACTIVATED ) { ffs->state =FFS_CLOSING ; -INIT_WORK (&ffs->reset_work, ffs_reset_work);schedule_work (&ffs->reset_work);return ; }
Signature · 1 line
2.53.0