# 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.233 -> 1.234 # drivers/usb/serial/ipaq.c 1.3 -> 1.4 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/03/22 ganesh@tuxtop.vxindia.veritas.com 1.234 # USB ipaq driver # # Don't submit urbs while holding spinlocks # -------------------------------------------- # diff -Nru a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c --- a/drivers/usb/serial/ipaq.c Fri Mar 22 15:48:16 2002 +++ b/drivers/usb/serial/ipaq.c Fri Mar 22 15:48:16 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. Thanks to Greg for pointing + * this out. + * * (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); @@ -382,17 +386,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); + 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; @@ -400,7 +410,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;) { @@ -427,11 +437,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); - if (result) { - err(__FUNCTION__ " - failed submitting write urb, error %d", result); - } - return result; + return; } static void ipaq_write_bulk_callback(struct urb *urb) @@ -439,6 +445,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; @@ -452,11 +459,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); + 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);