--- /dev/null
+From foo@baz Tue Apr 9 12:12:43 2002
+To: Greg KH <greg@kroah.com>
+Date: 23 Mar 2005 15:26:40 -08:00
+From: gregkh@suse.de
+Subject: USB: fix bug in visor driver with throttle/unthrottle causing oopses.
+
+Thanks to Mark Lord <mlord@pobox.com> for reporting this and helping with testing.
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
+--- a/drivers/usb/serial/visor.c 2005-05-11 00:52:29 -07:00
++++ b/drivers/usb/serial/visor.c 2005-05-11 00:52:29 -07:00
+@@ -386,6 +386,7 @@
+ 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 @@
+ 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 @@
+ struct tty_struct *tty;
+ unsigned long flags;
+ int i;
++ int throttled;
+ int result;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+@@ -627,18 +630,21 @@
+ }
+ 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 @@
+
+ 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);