FAILED: patch "[PATCH] Input: iforce - wake up after clearing IFORCE_XMIT_RUNNING" failed to apply to 4.14-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 4.14-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]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 98e01215708b6d416345465c09dce2bd4868c67a Mon Sep 17 00:00:00 2001
From: Tetsuo Handa <[email protected]>
Date: Sat, 27 Aug 2022 20:36:27 -0700
Subject: [PATCH] Input: iforce - wake up after clearing IFORCE_XMIT_RUNNING
flag
syzbot is reporting hung task at __input_unregister_device() [1], for iforce_close() waiting at wait_event_interruptible() with dev->mutex held is blocking input_disconnect_device() from __input_unregister_device().
It seems that the cause is simply that commit c2b27ef672992a20 ("Input:
iforce - wait for command completion when closing the device") forgot to call wake_up() after clear_bit().
Fix this problem by introducing a helper that calls clear_bit() followed by wake_up_all().
drivers/input/joystick/iforce/iforce-serio.c +3 -3
@@ -39,7 +39,7 @@ static void iforce_serio_xmit(struct iforce *iforce) again:if (iforce->xmit.head == iforce->xmit.tail) { -clear_bit (IFORCE_XMIT_RUNNING , iforce->xmit_flags); +iforce_clear_xmit_and_wake (iforce);spin_unlock_irqrestore (&iforce->xmit_lock, flags);return ; }
@@ -64,7 +64,7 @@ static void iforce_serio_xmit(struct iforce *iforce)if (test_and_clear_bit (IFORCE_XMIT_AGAIN , iforce->xmit_flags)) goto again; -clear_bit (IFORCE_XMIT_RUNNING , iforce->xmit_flags); +iforce_clear_xmit_and_wake (iforce);spin_unlock_irqrestore (&iforce->xmit_lock, flags); }
@@ -169,7 +169,7 @@ static irqreturn_t iforce_serio_irq(struct serio *serio, iforce_serio->cmd_response_len = iforce_serio->len;/* Signal that command is done */ -wake_up (&iforce->wait); +wake_up_all (&iforce->wait); }else if (likely (iforce->type)) { iforce_process_packet(iforce, iforce_serio->id, iforce_serio->data_in,
drivers/input/joystick/iforce/iforce-usb.c +4 -4
@@ -30,7 +30,7 @@ static void __iforce_usb_xmit(struct iforce *iforce)spin_lock_irqsave (&iforce->xmit_lock, flags);if (iforce->xmit.head == iforce->xmit.tail) { -clear_bit (IFORCE_XMIT_RUNNING , iforce->xmit_flags); +iforce_clear_xmit_and_wake (iforce);spin_unlock_irqrestore (&iforce->xmit_lock, flags);return ; }
@@ -58,9 +58,9 @@ static void __iforce_usb_xmit(struct iforce *iforce)XMIT_INC (iforce->xmit.tail, n);if ( (n=usb_submit_urb (iforce_usb->out,GFP_ATOMIC )) ) { -clear_bit (IFORCE_XMIT_RUNNING , iforce->xmit_flags);dev_warn (&iforce_usb->intf->dev,"usb_submit_urb failed %d\n" , n); +iforce_clear_xmit_and_wake (iforce); }/* The IFORCE_XMIT_RUNNING bit is not cleared here. That's intended.
@@ -175,15 +175,15 @@ static void iforce_usb_out(struct urb *urb)struct iforce *iforce = &iforce_usb->iforce;if (urb->status) { -clear_bit (IFORCE_XMIT_RUNNING , iforce->xmit_flags);dev_dbg (&iforce_usb->intf->dev,"urb->status %d, exiting\n" , urb->status); +iforce_clear_xmit_and_wake (iforce);return ; }__iforce_usb_xmit (iforce); -wake_up (&iforce->wait); +wake_up_all (&iforce->wait); } static int iforce_usb_probe(struct usb_interface *intf,
drivers/input/joystick/iforce/iforce.h +6 -0
@@ -119,6 +119,12 @@ static inline int iforce_get_id_packet(struct iforce *iforce, u8 id, response_data, response_len); } +static inline void iforce_clear_xmit_and_wake (struct iforce *iforce) +{ +clear_bit (IFORCE_XMIT_RUNNING , iforce->xmit_flags); +wake_up_all (&iforce->wait); +} +/* Public functions */ /* iforce-main.c */ int iforce_init_device(struct device *parent, u16 bustype,