]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/usb/serial/generic.c
Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block
[linux-2.6-omap-h63xx.git] / drivers / usb / serial / generic.c
index 53baeec8f265a041bc45ae3a3010cd6c30d71c7d..537f12a027c224e2a2253224ae020e515714416d 100644 (file)
 #include <linux/usb/serial.h>
 #include <asm/uaccess.h>
 
-static int generic_probe(struct usb_interface *interface,
-                        const struct usb_device_id *id);
-
 
 static int debug;
 
 #ifdef CONFIG_USB_SERIAL_GENERIC
+
+static int generic_probe(struct usb_interface *interface,
+                        const struct usb_device_id *id);
+
 static __u16 vendor  = 0x05f9;
 static __u16 product = 0xffff;
 
@@ -61,13 +62,11 @@ struct usb_serial_driver usb_serial_generic_device = {
        },
        .id_table =             generic_device_ids,
        .usb_driver =           &generic_driver,
-       .num_interrupt_in =     NUM_DONT_CARE,
-       .num_bulk_in =          NUM_DONT_CARE,
-       .num_bulk_out =         NUM_DONT_CARE,
        .num_ports =            1,
        .shutdown =             usb_serial_generic_shutdown,
        .throttle =             usb_serial_generic_throttle,
        .unthrottle =           usb_serial_generic_unthrottle,
+       .resume =               usb_serial_generic_resume,
 };
 
 static int generic_probe(struct usb_interface *interface,
@@ -119,7 +118,7 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
        int result = 0;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        /* force low_latency on so that our tty_push actually forces the data through, 
           otherwise it is scheduled, and with high data rates (like with OHCI) data
@@ -146,7 +145,7 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
                                   port);
                result = usb_submit_urb(port->read_urb, GFP_KERNEL);
                if (result)
-                       dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+                       dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
        }
 
        return result;
@@ -157,7 +156,7 @@ static void generic_cleanup (struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (serial->dev) {
                /* shutdown any bulk reads that might be going on */
@@ -168,9 +167,34 @@ static void generic_cleanup (struct usb_serial_port *port)
        }
 }
 
+int usb_serial_generic_resume(struct usb_serial *serial)
+{
+       struct usb_serial_port *port;
+       int i, c = 0, r;
+
+#ifdef CONFIG_PM
+       /*
+        * If this is an autoresume, don't submit URBs.
+        * They will be submitted in the open function instead.
+        */
+       if (serial->dev->auto_pm)
+               return 0;
+#endif
+       for (i = 0; i < serial->num_ports; i++) {
+               port = serial->port[i];
+               if (port->open_count && port->read_urb) {
+                       r = usb_submit_urb(port->read_urb, GFP_NOIO);
+                       if (r < 0)
+                               c++;
+               }
+       }
+
+       return c ? -EIO : 0;
+}
+
 void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp)
 {
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
        generic_cleanup (port);
 }
 
@@ -180,29 +204,30 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
        int result;
        unsigned char *data;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (count == 0) {
-               dbg("%s - write request of 0 bytes", __FUNCTION__);
+               dbg("%s - write request of 0 bytes", __func__);
                return (0);
        }
 
        /* only do something if we have a bulk out endpoint */
        if (serial->num_bulk_out) {
-               spin_lock_bh(&port->lock);
+               unsigned long flags;
+               spin_lock_irqsave(&port->lock, flags);
                if (port->write_urb_busy) {
-                       spin_unlock_bh(&port->lock);
-                       dbg("%s - already writing", __FUNCTION__);
+                       spin_unlock_irqrestore(&port->lock, flags);
+                       dbg("%s - already writing", __func__);
                        return 0;
                }
                port->write_urb_busy = 1;
-               spin_unlock_bh(&port->lock);
+               spin_unlock_irqrestore(&port->lock, flags);
 
                count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
 
                memcpy (port->write_urb->transfer_buffer, buf, count);
                data = port->write_urb->transfer_buffer;
-               usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, data);
+               usb_serial_debug_data(debug, &port->dev, __func__, count, data);
 
                /* set up our urb */
                usb_fill_bulk_urb (port->write_urb, serial->dev,
@@ -217,7 +242,7 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
                port->write_urb_busy = 1;
                result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
                if (result) {
-                       dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
+                       dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
                        /* don't have to grab the lock here, as we will retry if != 0 */
                        port->write_urb_busy = 0;
                } else
@@ -235,15 +260,16 @@ int usb_serial_generic_write_room (struct usb_serial_port *port)
        struct usb_serial *serial = port->serial;
        int room = 0;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
+       /* FIXME: Locking */
        if (serial->num_bulk_out) {
                if (!(port->write_urb_busy))
                        room = port->bulk_out_size;
        }
 
-       dbg("%s - returns %d", __FUNCTION__, room);
-       return (room);
+       dbg("%s - returns %d", __func__, room);
+       return room;
 }
 
 int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
@@ -251,93 +277,99 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
        struct usb_serial *serial = port->serial;
        int chars = 0;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
+       /* FIXME: Locking */
        if (serial->num_bulk_out) {
                if (port->write_urb_busy)
                        chars = port->write_urb->transfer_buffer_length;
        }
 
-       dbg("%s - returns %d", __FUNCTION__, chars);
+       dbg("%s - returns %d", __func__, chars);
        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);
+               dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, 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);
+               }
+       }
+
+       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;
+       struct usb_serial_port *port = urb->context;
        unsigned char *data = urb->transfer_buffer;
-       int is_throttled;
+       int status = urb->status;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
-       if (urb->status) {
-               dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+       if (unlikely(status != 0)) {
+               dbg("%s - nonzero read bulk status received: %d",
+                   __func__, status);
                return;
        }
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+       usb_serial_debug_data(debug, &port->dev, __func__, 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_lock_irqsave(&port->lock, flags);
+       if (!(port->throttled = port->throttle_req)) {
+               spin_unlock_irqrestore(&port->lock, flags);
+               flush_and_resubmit_read_urb(port);
+       } else {
                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);
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
 
 void usb_serial_generic_write_bulk_callback (struct urb *urb)
 {
-       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial_port *port = urb->context;
+       int status = urb->status;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        port->write_urb_busy = 0;
-       if (urb->status) {
-               dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+       if (status) {
+               dbg("%s - nonzero write bulk status received: %d",
+                   __func__, status);
                return;
        }
-
        usb_serial_port_softint(port);
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
@@ -346,7 +378,7 @@ void usb_serial_generic_throttle (struct usb_serial_port *port)
 {
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        /* Set the throttle request flag. It will be picked up
         * by usb_serial_generic_read_bulk_callback(). */
@@ -360,7 +392,7 @@ void usb_serial_generic_unthrottle (struct usb_serial_port *port)
        int was_throttled;
        unsigned long flags;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        /* Clear the throttle flags */
        spin_lock_irqsave(&port->lock, flags);
@@ -369,8 +401,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);
        }
 }
 
@@ -378,7 +410,7 @@ void usb_serial_generic_shutdown (struct usb_serial *serial)
 {
        int i;
 
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __func__);
 
        /* stop reads and writes on all ports */
        for (i=0; i < serial->num_ports; ++i) {