Linux USB
 help / color / mirror / Atom feed
* [PATCH] USB: serial: garmin_gps: queue the device reset
@ 2026-10-27 14:29 Greg Kroah-Hartman
  2026-10-27 14:38 ` sashiko-bot
  2026-10-29  8:30 ` Johan Hovold
  0 siblings, 2 replies; 5+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-27 14:29 UTC (permalink / raw)
  To: johan; +Cc: linux-usb, Josef Bacik, stable, Greg Kroah-Hartman

From: Josef Bacik <josef@toxicpanda.com>

A private packet with the ID PRIV_PKTID_RESET_REQ that is written to the
port makes garmin_write() call usb_kill_urb() and usb_reset_device().
Both sleep, but the write operation of a tty driver must not: a line
discipline may call it in atomic context, synchronous PPP for one under
a spinlock with bottom halves disabled.  In addition usb_reset_device()
has to be called with the device locked, which it is not here.

The reset also unbinds the driver inside the write: the disconnect hangs
the tty up, ppp_sync_close() calls ppp_unregister_channel(), and that
spins on pch->downl, which the writer holds.  The CPU is lost.

Unlink the URB and use usb_queue_reset_device(), which locks the device
and resets it from a work item.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable <stable@kernel.org>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
Johan, this was sent to me, but I really don't know if PPP is used for
this device to talk to the port or not.  If not, this isn't a real
issue, but if it is, then maybe it is?  I can't tell so I'm tossing it
to you :)

 drivers/usb/serial/garmin_gps.c | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 8020149f5658..c2b29a7a6674 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -818,10 +818,9 @@ static void priv_status_resp(struct usb_serial_port *port)
  * Garmin specific driver functions
  ******************************************************************************/
 
-static int process_resetdev_request(struct usb_serial_port *port)
+static void process_resetdev_request(struct usb_serial_port *port)
 {
 	unsigned long flags;
-	int status;
 	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
 
 	spin_lock_irqsave(&garmin_data_p->lock, flags);
@@ -830,13 +829,10 @@ static int process_resetdev_request(struct usb_serial_port *port)
 	garmin_data_p->serial_num = 0;
 	spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
-	usb_kill_urb(port->interrupt_in_urb);
-	dev_dbg(&port->dev, "%s - usb_reset_device\n", __func__);
-	status = usb_reset_device(port->serial->dev);
-	if (status)
-		dev_dbg(&port->dev, "%s - usb_reset_device failed: %d\n",
-			__func__, status);
-	return status;
+	/* This is called by the write operation, which must not sleep */
+	usb_unlink_urb(port->interrupt_in_urb);
+	dev_dbg(&port->dev, "%s - usb_queue_reset_device\n", __func__);
+	usb_queue_reset_device(port->serial->interface);
 }
 
 
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-10-29  9:40 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-27 14:29 [PATCH] USB: serial: garmin_gps: queue the device reset Greg Kroah-Hartman
2026-10-27 14:38 ` sashiko-bot
2026-10-29  8:30 ` Johan Hovold
2026-10-29  9:38   ` Greg Kroah-Hartman
2026-10-29  9:40     ` Johan Hovold

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox