From: gregkh@suse.de Date: Wed, 23 Mar 2005 23:26:40 +0000 (-0800) Subject: [PATCH] USB: fix bug in visor driver with throttle/unthrottle causing oopses. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=77068954f8f2354b3dfd65253f2a41e473b58f66;p=thirdparty%2Fkernel%2Fstable.git [PATCH] USB: fix bug in visor driver with throttle/unthrottle causing oopses. Thanks to Mark Lord for reporting this and helping with testing. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Chris Wright --- diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 6c0d51638824b..0bb6262ad89c7 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -386,6 +386,7 @@ struct visor_private { int bytes_in; int bytes_out; int outstanding_urbs; + int throttled; }; /* number of outstanding urbs to prevent userspace DoS from happening */ @@ -415,6 +416,7 @@ static int visor_open (struct usb_serial_port *port, struct file *filp) priv->bytes_in = 0; priv->bytes_out = 0; priv->outstanding_urbs = 0; + priv->throttled = 0; spin_unlock_irqrestore(&priv->lock, flags); /* @@ -602,6 +604,7 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs) struct tty_struct *tty; unsigned long flags; int i; + int throttled; int result; dbg("%s - port %d", __FUNCTION__, port->number); @@ -627,18 +630,21 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs) } spin_lock_irqsave(&priv->lock, flags); priv->bytes_in += urb->actual_length; + throttled = priv->throttled; spin_unlock_irqrestore(&priv->lock, flags); - /* Continue trying to always read */ - usb_fill_bulk_urb (port->read_urb, port->serial->dev, - usb_rcvbulkpipe(port->serial->dev, - port->bulk_in_endpointAddress), - port->read_urb->transfer_buffer, - port->read_urb->transfer_buffer_length, - visor_read_bulk_callback, port); - result = usb_submit_urb(port->read_urb, GFP_ATOMIC); - if (result) - dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); + /* Continue trying to always read if we should */ + if (!throttled) { + usb_fill_bulk_urb (port->read_urb, port->serial->dev, + usb_rcvbulkpipe(port->serial->dev, + port->bulk_in_endpointAddress), + port->read_urb->transfer_buffer, + port->read_urb->transfer_buffer_length, + visor_read_bulk_callback, port); + result = usb_submit_urb(port->read_urb, GFP_ATOMIC); + if (result) + dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); + } return; } @@ -683,16 +689,26 @@ exit: static void visor_throttle (struct usb_serial_port *port) { + struct visor_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + dbg("%s - port %d", __FUNCTION__, port->number); - usb_kill_urb(port->read_urb); + spin_lock_irqsave(&priv->lock, flags); + priv->throttled = 1; + spin_unlock_irqrestore(&priv->lock, flags); } static void visor_unthrottle (struct usb_serial_port *port) { + struct visor_private *priv = usb_get_serial_port_data(port); + unsigned long flags; int result; dbg("%s - port %d", __FUNCTION__, port->number); + spin_lock_irqsave(&priv->lock, flags); + priv->throttled = 0; + spin_unlock_irqrestore(&priv->lock, flags); port->read_urb->dev = port->serial->dev; result = usb_submit_urb(port->read_urb, GFP_ATOMIC);