patch-2.4.0-test11 linux/drivers/usb/serial/digi_acceleport.c

Next file: linux/drivers/usb/serial/ftdi_sio.c
Previous file: linux/drivers/usb/serial/belkin_sa.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/serial/digi_acceleport.c linux/drivers/usb/serial/digi_acceleport.c
@@ -1,5 +1,5 @@
 /*
-*  Digi AccelePort USB-4 Serial Converter
+*  Digi AccelePort USB-4 and USB-2 Serial Converters
 *
 *  Copyright 2000 by Digi International
 *
@@ -14,6 +14,16 @@
 *  Peter Berger (pberger@brimson.com)
 *  Al Borchers (borchers@steinerpoint.com)
 *
+* (11/01/2000) Adam J. Richter
+*	usb_device_id table support
+* 
+* (11/01/2000) pberger and borchers
+*    -- Turned off the USB_DISABLE_SPD flag for write bulk urbs--it caused
+*       USB 4 ports to hang on startup.
+*    -- Serialized access to write urbs by adding the dp_write_urb_in_use
+*       flag; otherwise, the driver caused SMP system hangs.  Watching the
+*       urb status is not sufficient.
+*
 * (10/05/2000) gkh
 *    -- Fixed bug with urb->dev not being set properly, now that the usb
 *	core needs it.
@@ -213,7 +223,7 @@
 *  - Following Documentation/DocBook/kernel-locking.pdf no spin locks
 *    are held when calling copy_to/from_user or printk.
 *    
-*  $Id: digi_acceleport.c,v 1.80 2000/08/09 06:36:18 root Exp $
+*  $Id: digi_acceleport.c,v 1.80.1.2 2000/11/02 05:45:08 root Exp $
 */
 
 #include <linux/config.h>
@@ -411,6 +421,7 @@
 	int dp_in_buf_len;
 	unsigned char dp_in_buf[DIGI_IN_BUF_SIZE];
 	unsigned char dp_in_flag_buf[DIGI_IN_BUF_SIZE];
+	int dp_write_urb_in_use;
 	unsigned int dp_modem_signals;
 	wait_queue_head_t dp_modem_change_wait;
 	int dp_open_count;			/* inc on open, dec on close */
@@ -461,15 +472,29 @@
 
 /* Statics */
 
+static __devinitdata struct usb_device_id id_table_combined [] = {
+    { idVendor: DIGI_VENDOR_ID, idProduct: DIGI_2_ID },
+    { idVendor: DIGI_VENDOR_ID, idProduct: DIGI_4_ID },
+    { }						/* Terminating entry */
+};
+
+static __devinitdata struct usb_device_id id_table_2 [] = {
+    { idVendor: DIGI_VENDOR_ID, idProduct: DIGI_2_ID },
+    { }						/* Terminating entry */
+};
+
+static __devinitdata struct usb_device_id id_table_4 [] = {
+    { idVendor: DIGI_VENDOR_ID, idProduct: DIGI_4_ID },
+    { }						/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, id_table_combined);
+
 /* device info needed for the Digi serial converter */
-static u16 digi_vendor_id = DIGI_VENDOR_ID;
-static u16 digi_product_2_id = DIGI_2_ID;	/* USB 2 */
-static u16 digi_product_4_id = DIGI_4_ID;	/* USB 4 */
 
 static struct usb_serial_device_type digi_acceleport_2_device = {
 	name:				"Digi USB",
-	idVendor:			&digi_vendor_id,
-	idProduct:			&digi_product_2_id,
+	id_table:			id_table_2,
 	needs_interrupt_in:		DONT_CARE,
 	needs_bulk_in:			MUST_HAVE,
 	needs_bulk_out:			MUST_HAVE,
@@ -495,8 +520,7 @@
 
 static struct usb_serial_device_type digi_acceleport_4_device = {
 	name:				"Digi USB",
-	idVendor:			&digi_vendor_id,
-	idProduct:			&digi_product_4_id,
+	id_table:			id_table_4,
 	needs_interrupt_in:		DONT_CARE,
 	needs_bulk_in:			MUST_HAVE,
 	needs_bulk_out:			MUST_HAVE,
@@ -629,7 +653,8 @@
 
 	while( count > 0 ) {
 
-		while( oob_port->write_urb->status == -EINPROGRESS ) {
+		while( oob_port->write_urb->status == -EINPROGRESS
+		|| oob_priv->dp_write_urb_in_use ) {
 			cond_wait_interruptible_timeout_irqrestore(
 				&oob_port->write_wait, DIGI_RETRY_TIMEOUT,
 				&oob_priv->dp_port_lock, flags );
@@ -647,8 +672,9 @@
 		memcpy( oob_port->write_urb->transfer_buffer, buf, len );
 		oob_port->write_urb->transfer_buffer_length = len;
 		oob_port->write_urb->dev = port->serial->dev;
-		
+
 		if( (ret=usb_submit_urb(oob_port->write_urb)) == 0 ) {
+			oob_priv->dp_write_urb_in_use = 1;
 			count -= len;
 			buf += len;
 		}
@@ -702,8 +728,8 @@
 
 	while( count > 0 && ret == 0 ) {
 
-		while( port->write_urb->status == -EINPROGRESS
-		&& jiffies < timeout ) {
+		while( (port->write_urb->status == -EINPROGRESS
+		|| priv->dp_write_urb_in_use) && jiffies < timeout ) {
 			cond_wait_interruptible_timeout_irqrestore(
 				&port->write_wait, DIGI_RETRY_TIMEOUT,
 				&priv->dp_port_lock, flags );
@@ -736,6 +762,7 @@
 		port->write_urb->dev = port->serial->dev;
 
 		if( (ret=usb_submit_urb(port->write_urb)) == 0 ) {
+			priv->dp_write_urb_in_use = 1;
 			priv->dp_out_buf_len = 0;
 			count -= len;
 			buf += len;
@@ -783,7 +810,8 @@
 	spin_lock_irqsave( &oob_priv->dp_port_lock, flags );
 	spin_lock( &port_priv->dp_port_lock );
 
-	while( oob_port->write_urb->status == -EINPROGRESS ) {
+	while( oob_port->write_urb->status == -EINPROGRESS
+	|| oob_priv->dp_write_urb_in_use ) {
 		spin_unlock( &port_priv->dp_port_lock );
 		cond_wait_interruptible_timeout_irqrestore(
 			&oob_port->write_wait, DIGI_RETRY_TIMEOUT,
@@ -811,6 +839,7 @@
 	oob_port->write_urb->dev = port->serial->dev;
 
 	if( (ret=usb_submit_urb(oob_port->write_urb)) == 0 ) {
+		oob_priv->dp_write_urb_in_use = 1;
 		port_priv->dp_modem_signals =
 			(port_priv->dp_modem_signals&~(TIOCM_DTR|TIOCM_RTS))
 			| (modem_signals&(TIOCM_DTR|TIOCM_RTS));
@@ -1249,7 +1278,8 @@
 	spin_lock_irqsave( &priv->dp_port_lock, flags );
 
 	/* wait for urb status clear to submit another urb */
-	if( port->write_urb->status == -EINPROGRESS ) {
+	if( port->write_urb->status == -EINPROGRESS
+	|| priv->dp_write_urb_in_use ) {
 
 		/* buffer data if count is 1 (probably put_char) if possible */
 		if( count == 1 ) {
@@ -1292,6 +1322,7 @@
 	memcpy( data, from_user ? user_buf : buf, new_len );
 
 	if( (ret=usb_submit_urb(port->write_urb)) == 0 ) {
+		priv->dp_write_urb_in_use = 1;
 		ret = new_len;
 		priv->dp_out_buf_len = 0;
 	}
@@ -1337,6 +1368,7 @@
 	== ((digi_serial_t *)(serial->private))->ds_oob_port_num ) {
 		dbg( "digi_write_bulk_callback: oob callback" );
 		spin_lock( &priv->dp_port_lock );
+		priv->dp_write_urb_in_use = 0;
 		wake_up_interruptible( &port->write_wait );
 		spin_unlock( &priv->dp_port_lock );
 		return;
@@ -1349,6 +1381,7 @@
 
 	/* try to send any buffered data on this port, if it is open */
 	spin_lock( &priv->dp_port_lock );
+	priv->dp_write_urb_in_use = 0;
 	if( priv->dp_open_count && port->write_urb->status != -EINPROGRESS
 	&& priv->dp_out_buf_len > 0 ) {
 
@@ -1365,6 +1398,7 @@
 			priv->dp_out_buf_len );
 
 		if( (ret=usb_submit_urb(port->write_urb)) == 0 ) {
+			priv->dp_write_urb_in_use = 1;
 			priv->dp_out_buf_len = 0;
 		}
 
@@ -1397,7 +1431,8 @@
 
 	spin_lock_irqsave( &priv->dp_port_lock, flags );
 
-	if( port->write_urb->status == -EINPROGRESS )
+	if( port->write_urb->status == -EINPROGRESS
+	|| priv->dp_write_urb_in_use )
 		room = 0;
 	else
 		room = port->bulk_out_size - 2 - priv->dp_out_buf_len;
@@ -1416,7 +1451,8 @@
 	digi_port_t *priv = (digi_port_t *)(port->private);
 
 
-	if( port->write_urb->status == -EINPROGRESS ) {
+	if( port->write_urb->status == -EINPROGRESS
+	|| priv->dp_write_urb_in_use ) {
 dbg( "digi_chars_in_buffer: port=%d, chars=%d", priv->dp_port_num, port->bulk_out_size - 2 );
 		/* return( port->bulk_out_size - 2 ); */
 		return( 256 );
@@ -1601,6 +1637,7 @@
 
 	spin_lock_irqsave( &priv->dp_port_lock, flags );
 	port->active = 0;
+	priv->dp_write_urb_in_use = 0;
 	priv->dp_in_close = 0;
 	--priv->dp_open_count;
 	MOD_DEC_USE_COUNT;
@@ -1641,7 +1678,6 @@
 
 		port = &serial->port[i];
 
-		port->write_urb->transfer_flags |= USB_DISABLE_SPD;
 		port->write_urb->dev = port->serial->dev;
 
 		if( (ret=usb_submit_urb(port->read_urb)) != 0 ) {
@@ -1689,6 +1725,7 @@
 		priv->dp_port_num = i;
 		priv->dp_out_buf_len = 0;
 		priv->dp_in_buf_len = 0;
+		priv->dp_write_urb_in_use = 0;
 		priv->dp_modem_signals = 0;
 		init_waitqueue_head( &priv->dp_modem_change_wait );
 		priv->dp_open_count = 0;
@@ -2047,5 +2084,5 @@
 
 
 MODULE_AUTHOR("Peter Berger <pberger@brimson.com>, Al Borchers <borchers@steinerpoint.com>");
-MODULE_DESCRIPTION("Digi AccelePort USB-4 Serial Converter driver");
+MODULE_DESCRIPTION("Digi AccelePort USB-2/USB-4 Serial Converter driver");
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)