]> git.karo-electronics.de Git - linux-beck.git/commitdiff
USB: generic usb serial to new buffering scheme
authorOliver Neukum <oneukum@suse.de>
Mon, 7 May 2007 10:09:33 +0000 (12:09 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 12 Jul 2007 23:29:51 +0000 (16:29 -0700)
the generic driver also had its own buffering.

Signed-off-by: Oliver Neukum <oneukum@suse.de_
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/serial/generic.c

index b90ef3f70f4c1cbd43d034532e5b0ba33f810769..b09bed4b77d323b0ac7a912ad168cc3e29078126 100644 (file)
@@ -281,45 +281,54 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
        return (chars);
 }
 
-/* Push data to tty layer and resubmit the bulk read URB */
-static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
+
+static void resubmit_read_urb(struct usb_serial_port *port, gfp_t mem_flags)
 {
-       struct usb_serial *serial = port->serial;
        struct urb *urb = port->read_urb;
-       struct tty_struct *tty = port->tty;
+       struct usb_serial *serial = port->serial;
        int result;
 
-       /* Push data to tty */
-       if (tty && urb->actual_length) {
-               tty_buffer_request_room(tty, urb->actual_length);
-               tty_insert_flip_string(tty, urb->transfer_buffer, urb->actual_length);
-               tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */
-       }
-
        /* Continue reading from device */
-       usb_fill_bulk_urb (port->read_urb, serial->dev,
+       usb_fill_bulk_urb (urb, serial->dev,
                           usb_rcvbulkpipe (serial->dev,
                                            port->bulk_in_endpointAddress),
-                          port->read_urb->transfer_buffer,
-                          port->read_urb->transfer_buffer_length,
+                          urb->transfer_buffer,
+                          urb->transfer_buffer_length,
                           ((serial->type->read_bulk_callback) ? 
                             serial->type->read_bulk_callback : 
                             usb_serial_generic_read_bulk_callback), port);
-       result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+       result = usb_submit_urb(urb, mem_flags);
        if (result)
                dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
 }
 
+/* Push data to tty layer and resubmit the bulk read URB */
+static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
+{
+       struct urb *urb = port->read_urb;
+       struct tty_struct *tty = port->tty;
+       int room;
+
+       /* Push data to tty */
+       if (tty && urb->actual_length) {
+               room = tty_buffer_request_room(tty, urb->actual_length);
+               if (room) {
+                       tty_insert_flip_string(tty, urb->transfer_buffer, room);
+                       tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */
+               }
+       }
+
+       resubmit_read_urb(port, GFP_ATOMIC);
+}
+
 void usb_serial_generic_read_bulk_callback (struct urb *urb)
 {
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        unsigned char *data = urb->transfer_buffer;
-       int is_throttled;
-       unsigned long flags;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
-       if (urb->status) {
+       if (unlikely(urb->status != 0)) {
                dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
                return;
        }
@@ -327,21 +336,11 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb)
        usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
 
        /* Throttle the device if requested by tty */
-       if (urb->actual_length) {
-               spin_lock_irqsave(&port->lock, flags);
-               is_throttled = port->throttled = port->throttle_req;
-               spin_unlock_irqrestore(&port->lock, flags);
-               if (is_throttled) {
-                       /* Let the received data linger in the read URB;
-                        * usb_serial_generic_unthrottle() will pick it
-                        * up later. */
-                       dbg("%s - throttling device", __FUNCTION__);
-                       return;
-               }
-       }
-
-       /* Handle data and continue reading from device */
-       flush_and_resubmit_read_urb(port);
+       spin_lock(&port->lock);
+       if (!(port->throttled = port->throttle_req))
+               /* Handle data and continue reading from device */
+               flush_and_resubmit_read_urb(port);
+       spin_unlock(&port->lock);
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
 
@@ -388,8 +387,8 @@ void usb_serial_generic_unthrottle (struct usb_serial_port *port)
        spin_unlock_irqrestore(&port->lock, flags);
 
        if (was_throttled) {
-               /* Handle pending data and resume reading from device */
-               flush_and_resubmit_read_urb(port);
+               /* Resume reading from device */
+               resubmit_read_urb(port, GFP_KERNEL);
        }
 }