Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / usb / serial / option.c
index b722175..5cf2b80 100644 (file)
   History:
 
   2005-05-19  v0.1   Initial version, based on incomplete docs
-                     and analysis of misbehavior of the standard driver
+                     and analysis of misbehavior with the standard driver
   2005-05-20  v0.2   Extended the input buffer to avoid losing
                      random 64-byte chunks of data
   2005-05-21  v0.3   implemented chars_in_buffer()
                      turned on low_latency
                      simplified the code somewhat
+  2005-05-24  v0.4   option_write() sometimes deadlocked under heavy load
+                     removed some dead code
+                     added sponsor notice
+                     coding style clean-up
+  2005-06-20  v0.4.1 add missing braces :-/
+                     killed end-of-line whitespace
+  2005-07-15  v0.4.2 rename WLAN product to FUSION, add FUSION2
+  2005-09-10  v0.4.3 added HUAWEI E600 card and Audiovox AirCard
+  2005-09-20  v0.4.4 increased recv buffer size: the card sometimes
+                     wants to send >2000 bytes.
+  2006-04-10  v0.4.2 fixed two array overrun errors :-/
+
+  Work sponsored by: Sigos GmbH, Germany <info@sigos.de>
+
 */
-#define DRIVER_VERSION "v0.3"
+
+#define DRIVER_VERSION "v0.4"
 #define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
 #define DRIVER_DESC "Option Card (PC-Card to) USB to Serial Driver"
 
 #include "usb-serial.h"
 
 /* Function prototypes */
-static int  option_open (struct usb_serial_port *port, struct file *filp);
-static void option_close (struct usb_serial_port *port, struct file *filp);
-static int  option_startup (struct usb_serial *serial);
-static void option_shutdown (struct usb_serial *serial);
-static void option_rx_throttle (struct usb_serial_port *port);
-static void option_rx_unthrottle (struct usb_serial_port *port);
-static int  option_write_room (struct usb_serial_port *port);
+static int  option_open(struct usb_serial_port *port, struct file *filp);
+static void option_close(struct usb_serial_port *port, struct file *filp);
+static int  option_startup(struct usb_serial *serial);
+static void option_shutdown(struct usb_serial *serial);
+static void option_rx_throttle(struct usb_serial_port *port);
+static void option_rx_unthrottle(struct usb_serial_port *port);
+static int  option_write_room(struct usb_serial_port *port);
 
 static void option_instat_callback(struct urb *urb, struct pt_regs *regs);
 
+static int option_write(struct usb_serial_port *port,
+                       const unsigned char *buf, int count);
 
-static int  option_write (struct usb_serial_port *port,
-                          const unsigned char *buf, int count);
-
-static int  option_chars_in_buffer (struct usb_serial_port *port);
-static int  option_ioctl (struct usb_serial_port *port, struct file *file,
-                          unsigned int cmd, unsigned long arg);
-static void option_set_termios (struct usb_serial_port *port,
-                                struct termios *old);
-static void option_break_ctl (struct usb_serial_port *port, int break_state);
-static int  option_tiocmget (struct usb_serial_port *port, struct file *file);
-static int  option_tiocmset (struct usb_serial_port *port, struct file *file,
-                             unsigned int set, unsigned int clear);
-static int  option_send_setup (struct usb_serial_port *port);
+static int  option_chars_in_buffer(struct usb_serial_port *port);
+static int  option_ioctl(struct usb_serial_port *port, struct file *file,
+                       unsigned int cmd, unsigned long arg);
+static void option_set_termios(struct usb_serial_port *port,
+                               struct termios *old);
+static void option_break_ctl(struct usb_serial_port *port, int break_state);
+static int  option_tiocmget(struct usb_serial_port *port, struct file *file);
+static int  option_tiocmset(struct usb_serial_port *port, struct file *file,
+                               unsigned int set, unsigned int clear);
+static int  option_send_setup(struct usb_serial_port *port);
 
 /* Vendor and product IDs */
-#define OPTION_VENDOR_ID               0x0AF0
+#define OPTION_VENDOR_ID                       0x0AF0
+#define HUAWEI_VENDOR_ID                       0x12D1
+#define AUDIOVOX_VENDOR_ID                     0x0F3D
 
-#define        OPTION_PRODUCT_OLD              0x5000
-#define        OPTION_PRODUCT_WLAN             0x6000
+#define OPTION_PRODUCT_OLD             0x5000
+#define OPTION_PRODUCT_FUSION  0x6000
+#define OPTION_PRODUCT_FUSION2 0x6300
+#define HUAWEI_PRODUCT_E600     0x1001
+#define AUDIOVOX_PRODUCT_AIRCARD 0x0112
 
 static struct usb_device_id option_ids[] = {
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
-       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_WLAN) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
+       { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
+       { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
+       { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
        { } /* Terminating entry */
 };
 
 MODULE_DEVICE_TABLE(usb, option_ids);
 
 static struct usb_driver option_driver = {
-       .owner      = THIS_MODULE,
        .name       = "option",
        .probe      = usb_serial_probe,
        .disconnect = usb_serial_disconnect,
        .id_table   = option_ids,
+       .no_dynamic_id =        1,
 };
 
-/* The card has three separate interfaces, wich the serial driver
+/* The card has three separate interfaces, which the serial driver
  * recognizes separately, thus num_port=1.
  */
-static struct usb_serial_device_type option_3port_device = {
-       .owner                  = THIS_MODULE,
-       .name                   = "Option 3-port card",
-       .short_name             = "option",
-       .id_table               = option_ids,
-       .num_interrupt_in       = NUM_DONT_CARE,
-       .num_bulk_in            = NUM_DONT_CARE,
-       .num_bulk_out           = NUM_DONT_CARE,
-       .num_ports              = 1, /* 3 */
-       .open                   = option_open,
-       .close                  = option_close,
-       .write                  = option_write,
-       .write_room             = option_write_room,
-       .chars_in_buffer        = option_chars_in_buffer,
-       .throttle               = option_rx_throttle,
-       .unthrottle             = option_rx_unthrottle,
-       .ioctl                  = option_ioctl,
-       .set_termios            = option_set_termios,
-       .break_ctl              = option_break_ctl,
-       .tiocmget               = option_tiocmget,
-       .tiocmset               = option_tiocmset,
-       .attach                 = option_startup,
-       .shutdown               = option_shutdown,
-       .read_int_callback      = option_instat_callback,
+static struct usb_serial_driver option_3port_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "option",
+       },
+       .description       = "Option 3G data card",
+       .id_table          = option_ids,
+       .num_interrupt_in  = NUM_DONT_CARE,
+       .num_bulk_in       = NUM_DONT_CARE,
+       .num_bulk_out      = NUM_DONT_CARE,
+       .num_ports         = 1, /* 3, but the card reports its ports separately */
+       .open              = option_open,
+       .close             = option_close,
+       .write             = option_write,
+       .write_room        = option_write_room,
+       .chars_in_buffer   = option_chars_in_buffer,
+       .throttle          = option_rx_throttle,
+       .unthrottle        = option_rx_unthrottle,
+       .ioctl             = option_ioctl,
+       .set_termios       = option_set_termios,
+       .break_ctl         = option_break_ctl,
+       .tiocmget          = option_tiocmget,
+       .tiocmset          = option_tiocmset,
+       .attach            = option_startup,
+       .shutdown          = option_shutdown,
+       .read_int_callback = option_instat_callback,
 };
 
+#ifdef CONFIG_USB_DEBUG
 static int debug;
+#else
+#define debug 0
+#endif
 
 /* per port private data */
 
-#define N_IN_URB       4
-#define N_OUT_URB      1
-#define IN_BUFLEN      1024
-#define OUT_BUFLEN     1024
+#define N_IN_URB 4
+#define N_OUT_URB 1
+#define IN_BUFLEN 4096
+#define OUT_BUFLEN 128
 
 struct option_port_private {
        /* Input endpoints and buffer for this port */
-       struct urb      *in_urbs[N_IN_URB];
-       char            in_buffer[N_IN_URB][IN_BUFLEN];
+       struct urb *in_urbs[N_IN_URB];
+       char in_buffer[N_IN_URB][IN_BUFLEN];
        /* Output endpoints and buffer for this port */
-       struct urb      *out_urbs[N_OUT_URB];
-       char            out_buffer[N_OUT_URB][OUT_BUFLEN];
+       struct urb *out_urbs[N_OUT_URB];
+       char out_buffer[N_OUT_URB][OUT_BUFLEN];
 
        /* Settings for the port */
-       int             rts_state;      /* Handshaking pins (outputs) */
-       int             dtr_state;
-       int             cts_state;      /* Handshaking pins (inputs) */
-       int             dsr_state;
-       int             dcd_state;
-       int             ri_state;
-       // int          break_on;
-
-       unsigned long   tx_start_time[N_OUT_URB];
+       int rts_state;  /* Handshaking pins (outputs) */
+       int dtr_state;
+       int cts_state;  /* Handshaking pins (inputs) */
+       int dsr_state;
+       int dcd_state;
+       int ri_state;
+
+       unsigned long tx_start_time[N_OUT_URB];
 };
 
-
 /* Functions used by new usb-serial code. */
-static int __init
-option_init (void)
+static int __init option_init(void)
 {
        int retval;
        retval = usb_serial_register(&option_3port_device);
@@ -162,8 +187,7 @@ failed_3port_device_register:
        return retval;
 }
 
-static void __exit
-option_exit (void)
+static void __exit option_exit(void)
 {
        usb_deregister (&option_driver);
        usb_serial_deregister (&option_3port_device);
@@ -172,42 +196,34 @@ option_exit (void)
 module_init(option_init);
 module_exit(option_exit);
 
-static void
-option_rx_throttle (struct usb_serial_port *port)
+static void option_rx_throttle(struct usb_serial_port *port)
 {
        dbg("%s", __FUNCTION__);
 }
 
-
-static void
-option_rx_unthrottle (struct usb_serial_port *port)
+static void option_rx_unthrottle(struct usb_serial_port *port)
 {
        dbg("%s", __FUNCTION__);
 }
 
-
-static void
-option_break_ctl (struct usb_serial_port *port, int break_state)
+static void option_break_ctl(struct usb_serial_port *port, int break_state)
 {
        /* Unfortunately, I don't know how to send a break */
-       dbg("%s", __FUNCTION__);
+       dbg("%s", __FUNCTION__);
 }
 
-
-static void
-option_set_termios (struct usb_serial_port *port,
-                                    struct termios *old_termios)
+static void option_set_termios(struct usb_serial_port *port,
+                       struct termios *old_termios)
 {
        dbg("%s", __FUNCTION__);
 
        option_send_setup(port);
 }
 
-static int
-option_tiocmget(struct usb_serial_port *port, struct file *file)
+static int option_tiocmget(struct usb_serial_port *port, struct file *file)
 {
-       unsigned int                    value;
-       struct option_port_private      *portdata;
+       unsigned int value;
+       struct option_port_private *portdata;
 
        portdata = usb_get_serial_port_data(port);
 
@@ -221,11 +237,10 @@ option_tiocmget(struct usb_serial_port *port, struct file *file)
        return value;
 }
 
-static int
-option_tiocmset (struct usb_serial_port *port, struct file *file,
-                 unsigned int set, unsigned int clear)
+static int option_tiocmset(struct usb_serial_port *port, struct file *file,
+                       unsigned int set, unsigned int clear)
 {
-       struct option_port_private      *portdata;
+       struct option_port_private *portdata;
 
        portdata = usb_get_serial_port_data(port);
 
@@ -241,80 +256,58 @@ option_tiocmset (struct usb_serial_port *port, struct file *file,
        return option_send_setup(port);
 }
 
-static int
-option_ioctl (struct usb_serial_port *port, struct file *file,
-              unsigned int cmd, unsigned long arg)
+static int option_ioctl(struct usb_serial_port *port, struct file *file,
+                       unsigned int cmd, unsigned long arg)
 {
        return -ENOIOCTLCMD;
 }
 
 /* Write */
-static int
-option_write(struct usb_serial_port *port,
-                        const unsigned char *buf, int count)
+static int option_write(struct usb_serial_port *port,
+                       const unsigned char *buf, int count)
 {
-       struct option_port_private      *portdata;
-       int                             i;
-       int                             left, todo;
-       struct urb                      *this_urb = NULL; /* spurious */
-       int                             err;
+       struct option_port_private *portdata;
+       int i;
+       int left, todo;
+       struct urb *this_urb = NULL; /* spurious */
+       int err;
 
        portdata = usb_get_serial_port_data(port);
 
        dbg("%s: write (%d chars)", __FUNCTION__, count);
 
-#if 0
-       spin_lock(&port->lock);
-       if (port->write_urb_busy) {
-               spin_unlock(&port->lock);
-               dbg("%s: already writing", __FUNCTION__);
-               return 0;
-       }
-       port->write_urb_busy = 1;
-       spin_unlock(&port->lock);
-#endif
-
        i = 0;
        left = count;
-       while (left>0) {
+       for (i=0; left > 0 && i < N_OUT_URB; i++) {
                todo = left;
                if (todo > OUT_BUFLEN)
                        todo = OUT_BUFLEN;
 
-               for (;i < N_OUT_URB; i++) {
-                       /* Check we have a valid urb/endpoint before we use it... */
-                       this_urb = portdata->out_urbs[i];
-                       if (this_urb->status != -EINPROGRESS)
-                               break;
-                       if (this_urb->transfer_flags & URB_ASYNC_UNLINK)
-                               continue;
-                       if (time_before(jiffies, portdata->tx_start_time[i] + 10 * HZ))
+               this_urb = portdata->out_urbs[i];
+               if (this_urb->status == -EINPROGRESS) {
+                       if (time_before(jiffies,
+                                       portdata->tx_start_time[i] + 10 * HZ))
                                continue;
-                       this_urb->transfer_flags |= URB_ASYNC_UNLINK;
                        usb_unlink_urb(this_urb);
+                       continue;
                }
+               if (this_urb->status != 0)
+                       dbg("usb_write %p failed (err=%d)",
+                               this_urb, this_urb->status);
 
-               if (i == N_OUT_URB) {
-                       /* no bulk out free! */
-                       dbg("%s: no output urb -- left %d", __FUNCTION__,count-left);
-#if 0
-                       port->write_urb_busy = 0;
-#endif
-                       return count-left;
-               }
-
-               dbg("%s: endpoint %d buf %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe), i);
+               dbg("%s: endpoint %d buf %d", __FUNCTION__,
+                       usb_pipeendpoint(this_urb->pipe), i);
 
+               /* send the data */
                memcpy (this_urb->transfer_buffer, buf, todo);
-
-               /* send the data out the bulk port */
                this_urb->transfer_buffer_length = todo;
 
-               this_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
                this_urb->dev = port->serial->dev;
                err = usb_submit_urb(this_urb, GFP_ATOMIC);
                if (err) {
-                       dbg("usb_submit_urb %p (write bulk) failed (%d,, has %d)", this_urb, err, this_urb->status);
+                       dbg("usb_submit_urb %p (write bulk) failed "
+                               "(%d, has %d)", this_urb,
+                               err, this_urb->status);
                        continue;
                }
                portdata->tx_start_time[i] = jiffies;
@@ -323,17 +316,13 @@ option_write(struct usb_serial_port *port,
        }
 
        count -= left;
-#if 0
-       port->write_urb_busy = 0;
-#endif
        dbg("%s: wrote (did %d)", __FUNCTION__, count);
        return count;
 }
 
-static void
-option_indat_callback (struct urb *urb, struct pt_regs *regs)
+static void option_indat_callback(struct urb *urb, struct pt_regs *regs)
 {
-       int     i, err;
+       int err;
        int endpoint;
        struct usb_serial_port *port;
        struct tty_struct *tty;
@@ -350,11 +339,8 @@ option_indat_callback (struct urb *urb, struct pt_regs *regs)
        } else {
                tty = port->tty;
                if (urb->actual_length) {
-                       for (i = 0; i < urb->actual_length ; ++i) {
-                               if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-                                       tty_flip_buffer_push(tty);
-                               tty_insert_flip_char(tty, data[i], 0);
-                       }
+                       tty_buffer_request_room(tty, urb->actual_length);
+                       tty_insert_flip_string(tty, data, urb->actual_length);
                        tty_flip_buffer_push(tty);
                } else {
                        dbg("%s: empty read urb received", __FUNCTION__);
@@ -364,14 +350,14 @@ option_indat_callback (struct urb *urb, struct pt_regs *regs)
                if (port->open_count && urb->status != -ESHUTDOWN) {
                        err = usb_submit_urb(urb, GFP_ATOMIC);
                        if (err)
-                               printk(KERN_ERR "%s: resubmit read urb failed. (%d)", __FUNCTION__, err);
+                               printk(KERN_ERR "%s: resubmit read urb failed. "
+                                       "(%d)", __FUNCTION__, err);
                }
        }
        return;
 }
 
-static void
-option_outdat_callback (struct urb *urb, struct pt_regs *regs)
+static void option_outdat_callback(struct urb *urb, struct pt_regs *regs)
 {
        struct usb_serial_port *port;
 
@@ -383,8 +369,7 @@ option_outdat_callback (struct urb *urb, struct pt_regs *regs)
                schedule_work(&port->work);
 }
 
-static void
-option_instat_callback (struct urb *urb, struct pt_regs *regs)
+static void option_instat_callback(struct urb *urb, struct pt_regs *regs)
 {
        int err;
        struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
@@ -402,10 +387,12 @@ option_instat_callback (struct urb *urb, struct pt_regs *regs)
                        dbg("%s: NULL req_pkt\n", __FUNCTION__);
                        return;
                }
-               if ((req_pkt->bRequestType == 0xA1) && (req_pkt->bRequest == 0x20)) {
+               if ((req_pkt->bRequestType == 0xA1) &&
+                               (req_pkt->bRequest == 0x20)) {
                        int old_dcd_state;
                        unsigned char signals = *((unsigned char *)
-                                       urb->transfer_buffer + sizeof(struct usb_ctrlrequest));
+                                       urb->transfer_buffer +
+                                       sizeof(struct usb_ctrlrequest));
 
                        dbg("%s: signal x%x", __FUNCTION__, signals);
 
@@ -415,12 +402,13 @@ option_instat_callback (struct urb *urb, struct pt_regs *regs)
                        portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
                        portdata->ri_state = ((signals & 0x08) ? 1 : 0);
 
-                       if (port->tty && !C_CLOCAL(port->tty)
-                                       && old_dcd_state && !portdata->dcd_state) {
+                       if (port->tty && !C_CLOCAL(port->tty) &&
+                                       old_dcd_state && !portdata->dcd_state)
                                tty_hangup(port->tty);
-                       }
-               } else
-                       dbg("%s: type %x req %x", __FUNCTION__, req_pkt->bRequestType,req_pkt->bRequest);
+               } else {
+                       dbg("%s: type %x req %x", __FUNCTION__,
+                               req_pkt->bRequestType,req_pkt->bRequest);
+               }
        } else
                dbg("%s: error %d", __FUNCTION__, urb->status);
 
@@ -429,13 +417,12 @@ option_instat_callback (struct urb *urb, struct pt_regs *regs)
                urb->dev = serial->dev;
                err = usb_submit_urb(urb, GFP_ATOMIC);
                if (err)
-                       dbg("%s: resubmit intr urb failed. (%d)", __FUNCTION__, err);
+                       dbg("%s: resubmit intr urb failed. (%d)",
+                               __FUNCTION__, err);
        }
 }
 
-
-static int
-option_write_room (struct usb_serial_port *port)
+static int option_write_room(struct usb_serial_port *port)
 {
        struct option_port_private *portdata;
        int i;
@@ -444,18 +431,17 @@ option_write_room (struct usb_serial_port *port)
 
        portdata = usb_get_serial_port_data(port);
 
-       for (i=0; i < N_OUT_URB; i++)
+       for (i=0; i < N_OUT_URB; i++) {
                this_urb = portdata->out_urbs[i];
                if (this_urb && this_urb->status != -EINPROGRESS)
                        data_len += OUT_BUFLEN;
+       }
 
        dbg("%s: %d", __FUNCTION__, data_len);
        return data_len;
 }
 
-
-static int
-option_chars_in_buffer (struct usb_serial_port *port)
+static int option_chars_in_buffer(struct usb_serial_port *port)
 {
        struct option_port_private *portdata;
        int i;
@@ -464,23 +450,21 @@ option_chars_in_buffer (struct usb_serial_port *port)
 
        portdata = usb_get_serial_port_data(port);
 
-       for (i=0; i < N_OUT_URB; i++)
+       for (i=0; i < N_OUT_URB; i++) {
                this_urb = portdata->out_urbs[i];
                if (this_urb && this_urb->status == -EINPROGRESS)
                        data_len += this_urb->transfer_buffer_length;
-
+       }
        dbg("%s: %d", __FUNCTION__, data_len);
        return data_len;
 }
 
-
-static int
-option_open (struct usb_serial_port *port, struct file *filp)
+static int option_open(struct usb_serial_port *port, struct file *filp)
 {
-       struct option_port_private      *portdata;
-       struct usb_serial               *serial = port->serial;
-       int                             i, err;
-       struct urb                      *urb;
+       struct option_port_private *portdata;
+       struct usb_serial *serial = port->serial;
+       int i, err;
+       struct urb *urb;
 
        portdata = usb_get_serial_port_data(port);
 
@@ -496,17 +480,21 @@ option_open (struct usb_serial_port *port, struct file *filp)
                if (! urb)
                        continue;
                if (urb->dev != serial->dev) {
-                       dbg("%s: dev %p != %p", __FUNCTION__, urb->dev, serial->dev);
+                       dbg("%s: dev %p != %p", __FUNCTION__,
+                               urb->dev, serial->dev);
                        continue;
                }
 
-               /* make sure endpoint data toggle is synchronized with the device */
-
+               /*
+                * make sure endpoint data toggle is synchronized with the
+                * device
+                */
                usb_clear_halt(urb->dev, urb->pipe);
 
                err = usb_submit_urb(urb, GFP_KERNEL);
                if (err) {
-                       dbg("%s: submit urb %d failed (%d) %d", __FUNCTION__, i, err,
+                       dbg("%s: submit urb %d failed (%d) %d",
+                               __FUNCTION__, i, err,
                                urb->transfer_buffer_length);
                }
        }
@@ -517,7 +505,8 @@ option_open (struct usb_serial_port *port, struct file *filp)
                if (! urb)
                        continue;
                urb->dev = serial->dev;
-               /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */
+               /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+                               usb_pipeout(urb->pipe), 0); */
        }
 
        port->tty->low_latency = 1;
@@ -527,21 +516,17 @@ option_open (struct usb_serial_port *port, struct file *filp)
        return (0);
 }
 
-static inline void
-stop_urb(struct urb *urb)
+static inline void stop_urb(struct urb *urb)
 {
-       if (urb && urb->status == -EINPROGRESS) {
-               urb->transfer_flags &= ~URB_ASYNC_UNLINK;
+       if (urb && urb->status == -EINPROGRESS)
                usb_kill_urb(urb);
-       }
 }
 
-static void
-option_close(struct usb_serial_port *port, struct file *filp)
+static void option_close(struct usb_serial_port *port, struct file *filp)
 {
-       int                     i;
-       struct usb_serial       *serial = port->serial;
-       struct option_port_private      *portdata;
+       int i;
+       struct usb_serial *serial = port->serial;
+       struct option_port_private *portdata;
 
        dbg("%s", __FUNCTION__);
        portdata = usb_get_serial_port_data(port);
@@ -561,12 +546,10 @@ option_close(struct usb_serial_port *port, struct file *filp)
        port->tty = NULL;
 }
 
-
 /* Helper functions used by option_setup_urbs */
-static struct urb *
-option_setup_urb (struct usb_serial *serial, int endpoint,
-                  int dir, void *ctx, char *buf, int len,
-                  void (*callback)(struct urb *, struct pt_regs *regs))
+static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint,
+               int dir, void *ctx, char *buf, int len,
+               void (*callback)(struct urb *, struct pt_regs *regs))
 {
        struct urb *urb;
 
@@ -588,12 +571,11 @@ option_setup_urb (struct usb_serial *serial, int endpoint,
 }
 
 /* Setup urbs */
-static void
-option_setup_urbs(struct usb_serial *serial)
+static void option_setup_urbs(struct usb_serial *serial)
 {
-       int                             j;
-       struct usb_serial_port          *port;
-       struct option_port_private      *portdata;
+       int j;
+       struct usb_serial_port *port;
+       struct option_port_private *portdata;
 
        dbg("%s", __FUNCTION__);
 
@@ -601,23 +583,21 @@ option_setup_urbs(struct usb_serial *serial)
        portdata = usb_get_serial_port_data(port);
 
        /* Do indat endpoints first */
-       for (j = 0; j <= N_IN_URB; ++j) {
+       for (j = 0; j < N_IN_URB; ++j) {
                portdata->in_urbs[j] = option_setup_urb (serial,
                   port->bulk_in_endpointAddress, USB_DIR_IN, port,
                   portdata->in_buffer[j], IN_BUFLEN, option_indat_callback);
        }
 
        /* outdat endpoints */
-       for (j = 0; j <= N_OUT_URB; ++j) {
+       for (j = 0; j < N_OUT_URB; ++j) {
                portdata->out_urbs[j] = option_setup_urb (serial,
                   port->bulk_out_endpointAddress, USB_DIR_OUT, port,
                   portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback);
        }
 }
 
-
-static int
-option_send_setup(struct usb_serial_port *port)
+static int option_send_setup(struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
        struct option_port_private *portdata;
@@ -633,32 +613,31 @@ option_send_setup(struct usb_serial_port *port)
                if (portdata->rts_state)
                        val |= 0x02;
 
-               return usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
-                                       0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
+               return usb_control_msg(serial->dev,
+                               usb_rcvctrlpipe(serial->dev, 0),
+                               0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
        }
 
        return 0;
 }
 
-
-static int
-option_startup (struct usb_serial *serial)
+static int option_startup(struct usb_serial *serial)
 {
-       int                             i, err;
-       struct usb_serial_port          *port;
-       struct option_port_private      *portdata;
+       int i, err;
+       struct usb_serial_port *port;
+       struct option_port_private *portdata;
 
        dbg("%s", __FUNCTION__);
 
        /* Now setup per port private data */
        for (i = 0; i < serial->num_ports; i++) {
                port = serial->port[i];
-               portdata = kmalloc(sizeof(struct option_port_private), GFP_KERNEL);
+               portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
                if (!portdata) {
-                       dbg("%s: kmalloc for option_port_private (%d) failed!.", __FUNCTION__, i);
+                       dbg("%s: kmalloc for option_port_private (%d) failed!.",
+                                       __FUNCTION__, i);
                        return (1);
                }
-               memset(portdata, 0, sizeof(struct option_port_private));
 
                usb_set_serial_port_data(port, portdata);
 
@@ -666,7 +645,8 @@ option_startup (struct usb_serial *serial)
                        continue;
                err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
                if (err)
-                       dbg("%s: submit irq_in urb failed %d", __FUNCTION__, err);
+                       dbg("%s: submit irq_in urb failed %d",
+                               __FUNCTION__, err);
        }
 
        option_setup_urbs(serial);
@@ -674,12 +654,11 @@ option_startup (struct usb_serial *serial)
        return (0);
 }
 
-static void
-option_shutdown (struct usb_serial *serial)
+static void option_shutdown(struct usb_serial *serial)
 {
-       int                             i, j;
-       struct usb_serial_port          *port;
-       struct option_port_private      *portdata;
+       int i, j;
+       struct usb_serial_port *port;
+       struct option_port_private *portdata;
 
        dbg("%s", __FUNCTION__);
 
@@ -724,6 +703,8 @@ MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
+#ifdef CONFIG_USB_DEBUG
 module_param(debug, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug messages");
+#endif