Re: [PATCH] USB: serial: fix stalled writes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux