[PATCH] Option Card driver update, Maintainer entry

This patch updates the Option Card driver:
- remove a deadlock
- add sponsor notice
- add new card
- renamed the device to what's usually printed on it
- removed some dead code
- clean up a bunch of irregular whitespace (end-of-line, tabs)

Also add a MAINTAINERS entry for the Option Card driver.

Signed-Off-By: Matthias Urlichs <smurf@smurf.noris.de>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
diff --git a/MAINTAINERS b/MAINTAINERS
index 5d01472..f73381a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2420,6 +2420,12 @@
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Maintained
 
+USB OPTION-CARD DRIVER
+P:	Matthias Urlichs
+M:	smurf@smurf.noris.de
+L:	linux-usb-devel@lists.sourceforge.net
+S:	Maintained
+
 USB OV511 DRIVER
 P:	Mark McClelland
 M:	mmcclell@bigfoot.com
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index b722175..e925640 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -12,14 +12,25 @@
   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
+
+  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"
 
@@ -44,7 +55,6 @@
 
 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);
 
@@ -60,14 +70,17 @@
 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	OPTION_PRODUCT_OLD		0x5000
-#define	OPTION_PRODUCT_WLAN		0x6000
+#define OPTION_PRODUCT_OLD		0x5000
+#define OPTION_PRODUCT_FUSION	0x6000
+#define OPTION_PRODUCT_FUSION2	0x6300
+
 
 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) },
 	{ } /* Terminating entry */
 };
 
@@ -85,58 +98,62 @@
  * 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,
+	.owner             = THIS_MODULE,
+	.name              = "Option 3G data 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, 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 1024
+#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;
+	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];
+	unsigned long tx_start_time[N_OUT_URB];
 };
 
 
@@ -190,13 +207,13 @@
 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)
+                    struct termios *old_termios)
 {
 	dbg("%s", __FUNCTION__);
 
@@ -204,10 +221,10 @@
 }
 
 static int
-option_tiocmget(struct usb_serial_port *port, struct file *file)
+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);
 
@@ -225,7 +242,7 @@
 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);
 
@@ -250,71 +267,50 @@
 
 /* Write */
 static int
-option_write(struct usb_serial_port *port,
-			 const unsigned char *buf, int count)
+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;
+		this_urb = portdata->out_urbs[i];
+		if (this_urb->status == -EINPROGRESS) {
 			if (this_urb->transfer_flags & URB_ASYNC_UNLINK)
 				continue;
 			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 (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;
-		}
+		if (this_urb->status != 0)
+			dbg("usb_write %p failed (err=%d)", this_urb, this_urb->status);
 
 		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,9 +319,6 @@
 	}
 
 	count -= left;
-#if 0
-	port->write_urb_busy = 0;
-#endif
 	dbg("%s: wrote (did %d)", __FUNCTION__, count);
 	return count;
 }
@@ -333,7 +326,7 @@
 static void
 option_indat_callback (struct urb *urb, struct pt_regs *regs)
 {
-	int	i, err;
+	int i, err;
 	int endpoint;
 	struct usb_serial_port *port;
 	struct tty_struct *tty;
@@ -444,10 +437,11 @@
 
 	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;
@@ -464,11 +458,11 @@
 
 	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;
 }
@@ -477,10 +471,10 @@
 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);
 
@@ -528,7 +522,7 @@
 }
 
 static inline void
-stop_urb(struct urb *urb)
+stop_urb (struct urb *urb)
 {
 	if (urb && urb->status == -EINPROGRESS) {
 		urb->transfer_flags &= ~URB_ASYNC_UNLINK;
@@ -537,11 +531,11 @@
 }
 
 static void
-option_close(struct usb_serial_port *port, struct file *filp)
+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);
@@ -589,11 +583,11 @@
 
 /* Setup urbs */
 static void
-option_setup_urbs(struct usb_serial *serial)
+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__);
 
@@ -617,7 +611,7 @@
 
 
 static int
-option_send_setup(struct usb_serial_port *port)
+option_send_setup (struct usb_serial_port *port)
 {
 	struct usb_serial *serial = port->serial;
 	struct option_port_private *portdata;
@@ -644,9 +638,9 @@
 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__);
 
@@ -677,9 +671,9 @@
 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 +718,8 @@
 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