# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.548   -> 1.549  
#	drivers/usb/serial/ipaq.c	1.5     -> 1.6    
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/03/19	ganesh@tuxtop.vxindia.veritas.com	1.549
# USB ipaq driver
# 
# Don't submit urbs while holding spinlocks. Not strictly required in
# 2.5.x, but it's always better to do less while holding a spinlock.
# Also a good idea to keep 2.{4,5}.x drivers in sync.
# --------------------------------------------
#
diff -Nru a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
--- a/drivers/usb/serial/ipaq.c	Wed Apr  3 16:40:02 2002
+++ b/drivers/usb/serial/ipaq.c	Wed Apr  3 16:40:02 2002
@@ -9,6 +9,10 @@
  *	the Free Software Foundation; either version 2 of the License, or
  *	(at your option) any later version.
  *
+ * (19/3/2002) ganesh
+ *	Don't submit urbs while holding spinlocks. Not strictly necessary
+ *	in 2.5.x.
+ *
  * (8/3/2002) ganesh
  * 	The ipaq sometimes emits a '\0' before the CLIENT string. At this
  * 	point of time, the ppp ldisc is not yet attached to the tty, so
@@ -65,7 +69,7 @@
 		       int count);
 static int ipaq_write_bulk(struct usb_serial_port *port, int from_user, const unsigned char *buf,
 			   int count);
-static int ipaq_write_flush(struct usb_serial_port *port);
+static void ipaq_write_gather(struct usb_serial_port *port);
 static void ipaq_read_bulk_callback (struct urb *urb);
 static void ipaq_write_bulk_callback(struct urb *urb);
 static int ipaq_write_room(struct usb_serial_port *port);
@@ -367,17 +371,23 @@
 	priv->queue_len += count;
 	if (priv->active == 0) {
 		priv->active = 1;
-		result = ipaq_write_flush(port);
+		ipaq_write_gather(port);
+		spin_unlock_irqrestore(&write_list_lock, flags);
+		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+		if (result) {
+			err(__FUNCTION__ " - failed submitting write urb, error %d", result);
+		}
+	} else {
+		spin_unlock_irqrestore(&write_list_lock, flags);
 	}
-	spin_unlock_irqrestore(&write_list_lock, flags);
 	return result;
 }
 
-static int ipaq_write_flush(struct usb_serial_port *port)
+static void ipaq_write_gather(struct usb_serial_port *port)
 {
 	struct ipaq_private	*priv = (struct ipaq_private *)port->private;
 	struct usb_serial	*serial = port->serial;
-	int			count, room, result;
+	int			count, room;
 	struct ipaq_packet	*pkt;
 	struct urb		*urb = port->write_urb;
 	struct list_head	*tmp;
@@ -385,7 +395,7 @@
 	if (urb->status == -EINPROGRESS) {
 		/* Should never happen */
 		err(__FUNCTION__ " - flushing while urb is active !");
-		return -EAGAIN;
+		return;
 	}
 	room = URBDATA_SIZE;
 	for (tmp = priv->queue.next; tmp != &priv->queue;) {
@@ -412,11 +422,7 @@
 		      usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
 		      port->write_urb->transfer_buffer, count, ipaq_write_bulk_callback,
 		      port);
-	result = usb_submit_urb(urb, GFP_ATOMIC);
-	if (result) {
-		err(__FUNCTION__ " - failed submitting write urb, error %d", result);
-	}
-	return result;
+	return;
 }
 
 static void ipaq_write_bulk_callback(struct urb *urb)
@@ -424,6 +430,7 @@
 	struct usb_serial_port	*port = (struct usb_serial_port *)urb->context;
 	struct ipaq_private	*priv = (struct ipaq_private *)port->private;
 	unsigned long		flags;
+	int			result;
 
 	if (port_paranoia_check (port, __FUNCTION__)) {
 		return;
@@ -437,11 +444,16 @@
 
 	spin_lock_irqsave(&write_list_lock, flags);
 	if (!list_empty(&priv->queue)) {
-		ipaq_write_flush(port);
+		ipaq_write_gather(port);
+		spin_unlock_irqrestore(&write_list_lock, flags);
+		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+		if (result) {
+			err(__FUNCTION__ " - failed submitting write urb, error %d", result);
+		}
 	} else {
 		priv->active = 0;
+		spin_unlock_irqrestore(&write_list_lock, flags);
 	}
-	spin_unlock_irqrestore(&write_list_lock, flags);
 	queue_task(&port->tqueue, &tq_immediate);
 	mark_bh(IMMEDIATE_BH);
 	
