* [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* Re: [PATCH] USB: serial: garmin_gps: queue the device reset
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
1 sibling, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-10-27 14:38 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: linux-usb
> 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>
Sashiko has reviewed this patch and found no issues.
--
Sashiko AI review · https://sashiko.dev/#/patchset/2026102733-prayer-drainer-56f3@gregkh?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] USB: serial: garmin_gps: queue the device reset
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
1 sibling, 1 reply; 5+ messages in thread
From: Johan Hovold @ 2026-10-29 8:30 UTC (permalink / raw)
To: Greg Kroah-Hartman, Josef Bacik; +Cc: linux-usb, stable
On Tue, Oct 27, 2026 at 03:29:34PM +0100, Greg Kroah-Hartman wrote:
> 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 :)
No, you would not use PPP with this device, but if someone tried to I
don't believe they would be able to trigger the reset due the PPP
packet framing not matching the garmin_gps header format.
So basically the patch is fine but the commit message is misleading.
You will still get a deadlock with the default line discipline however
so that's enough of a motivation to fix this (even if that doesn't wedge
a CPU).
> - 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);
USB core will unlink (and the driver will kill) all three URBs as part
of disconnect so I think we can just drop the interrupt-in unlink here.
> + dev_dbg(&port->dev, "%s - usb_queue_reset_device\n", __func__);
> + usb_queue_reset_device(port->serial->interface);
> }
Josef, do you want a send a v2 of this or shall I treat this patch as a
bug report and fix it up myself?
Johan
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] USB: serial: garmin_gps: queue the device reset
2026-10-29 8:30 ` Johan Hovold
@ 2026-10-29 9:38 ` Greg Kroah-Hartman
2026-10-29 9:40 ` Johan Hovold
0 siblings, 1 reply; 5+ messages in thread
From: Greg Kroah-Hartman @ 2026-10-29 9:38 UTC (permalink / raw)
To: Johan Hovold; +Cc: Josef Bacik, linux-usb, stable
On Thu, Oct 29, 2026 at 09:30:58AM +0100, Johan Hovold wrote:
> On Tue, Oct 27, 2026 at 03:29:34PM +0100, Greg Kroah-Hartman wrote:
> > 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 :)
>
> No, you would not use PPP with this device, but if someone tried to I
> don't believe they would be able to trigger the reset due the PPP
> packet framing not matching the garmin_gps header format.
>
> So basically the patch is fine but the commit message is misleading.
>
> You will still get a deadlock with the default line discipline however
> so that's enough of a motivation to fix this (even if that doesn't wedge
> a CPU).
>
> > - 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);
>
> USB core will unlink (and the driver will kill) all three URBs as part
> of disconnect so I think we can just drop the interrupt-in unlink here.
>
> > + dev_dbg(&port->dev, "%s - usb_queue_reset_device\n", __func__);
> > + usb_queue_reset_device(port->serial->interface);
> > }
>
> Josef, do you want a send a v2 of this or shall I treat this patch as a
> bug report and fix it up myself?
I'm guessing at Josef's current load, so it might just be faster for you
to fix it up yourself :)
thanks,
greg k-h
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] USB: serial: garmin_gps: queue the device reset
2026-10-29 9:38 ` Greg Kroah-Hartman
@ 2026-10-29 9:40 ` Johan Hovold
0 siblings, 0 replies; 5+ messages in thread
From: Johan Hovold @ 2026-10-29 9:40 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Josef Bacik, linux-usb, stable
On Thu, Oct 29, 2026 at 10:38:31AM +0100, Greg Kroah-Hartman wrote:
> On Thu, Oct 29, 2026 at 09:30:58AM +0100, Johan Hovold wrote:
> > Josef, do you want a send a v2 of this or shall I treat this patch as a
> > bug report and fix it up myself?
>
> I'm guessing at Josef's current load, so it might just be faster for you
> to fix it up yourself :)
That was my guess as well. I'll do so.
Johan
^ permalink raw reply [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