On Wed, Aug 04, 2010 at 03:45:57PM +0200, Johan Hovold wrote: > As David VomLehn points out, it was possible to receive an interrupt > before clearing the free-urb flag which could lead to the urb being > incorrectly marked as busy. > > For the same reason, move tx_bytes accounting so that it will never be > negative. > > Note that the free-flags set and clear operations do not need any > additional locking as they are manipulated while USB_SERIAL_WRITE_BUSY > is set. > > Reported-by: David VomLehn <dvomlehn@xxxxxxxxx> > Signed-off-by: Johan Hovold <jhovold@xxxxxxxxx> > --- > > Hi, > > I was able to trigger the bug David identified by simply inserting a delay > after submit_urb, and I have also verified that the patch below solves the > problem. > > Note that the set/clear bit operations below do not need any additional > locking as the write-busy flag is set. > > Thanks, > Johan > > drivers/usb/serial/generic.c | 15 ++++++++++----- > 1 files changed, 10 insertions(+), 5 deletions(-) > > diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c > index a817ced..ca92f67 100644 > --- a/drivers/usb/serial/generic.c > +++ b/drivers/usb/serial/generic.c > @@ -208,18 +208,23 @@ retry: > urb->transfer_buffer_length = count; > usb_serial_debug_data(debug, &port->dev, __func__, count, > urb->transfer_buffer); > + spin_lock_irqsave(&port->lock, flags); > + port->tx_bytes += count; > + spin_unlock_irqrestore(&port->lock, flags); > + > + clear_bit(i, &port->write_urbs_free); > result = usb_submit_urb(urb, GFP_ATOMIC); > if (result) { > dev_err(&port->dev, "%s - error submitting urb: %d\n", > __func__, result); > + set_bit(i, &port->write_urbs_free); > + spin_lock_irqsave(&port->lock, flags); > + port->tx_bytes -= count; > + spin_unlock_irqrestore(&port->lock, flags); > + > clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags); > return result; > } > - clear_bit(i, &port->write_urbs_free); > - > - spin_lock_irqsave(&port->lock, flags); > - port->tx_bytes += count; > - spin_unlock_irqrestore(&port->lock, flags); > > /* Try sending off another urb, unless in irq context (in which case > * there will be no free urb). */ > -- > 1.7.1.1 > This works great for me. Feel free to add: Tested-by: David VomLehn <dvomlehn@xxxxxxxxx> -- David VL -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html