summaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/keyspan_pda.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2005-04-23 21:49:16 +0200
committerGreg Kroah-Hartman <gregkh@suse.de>2005-06-27 23:43:47 +0200
commit507ca9bc0476662f3463888d583864834eab1e11 (patch)
tree421a373de235fcb4cb46a4723a1e9f00a71f709a /drivers/usb/serial/keyspan_pda.c
parent[PATCH] USB: add reboot notifier to ohci (diff)
downloadlinux-507ca9bc0476662f3463888d583864834eab1e11.tar.xz
linux-507ca9bc0476662f3463888d583864834eab1e11.zip
[PATCH] USB: add ability for usb-serial drivers to determine if their write urb is currently being used.
This removes a lot of racy and buggy code by trying to check the status of the urb. Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/keyspan_pda.c')
-rw-r--r--drivers/usb/serial/keyspan_pda.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 7fd0aa9eccf6..635c384cb15a 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -520,9 +520,13 @@ static int keyspan_pda_write(struct usb_serial_port *port,
the TX urb is in-flight (wait until it completes)
the device is full (wait until it says there is room)
*/
- if (port->write_urb->status == -EINPROGRESS || priv->tx_throttled ) {
- return( 0 );
+ spin_lock(&port->lock);
+ if (port->write_urb_busy || priv->tx_throttled) {
+ spin_unlock(&port->lock);
+ return 0;
}
+ port->write_urb_busy = 1;
+ spin_unlock(&port->lock);
/* At this point the URB is in our control, nobody else can submit it
again (the only sudden transition was the one from EINPROGRESS to
@@ -570,7 +574,7 @@ static int keyspan_pda_write(struct usb_serial_port *port,
memcpy (port->write_urb->transfer_buffer, buf, count);
/* send the data out the bulk port */
port->write_urb->transfer_buffer_length = count;
-
+
priv->tx_room -= count;
port->write_urb->dev = port->serial->dev;
@@ -593,6 +597,8 @@ static int keyspan_pda_write(struct usb_serial_port *port,
rc = count;
exit:
+ if (rc < 0)
+ port->write_urb_busy = 0;
return rc;
}
@@ -602,6 +608,7 @@ static void keyspan_pda_write_bulk_callback (struct urb *urb, struct pt_regs *re
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct keyspan_pda_private *priv;
+ port->write_urb_busy = 0;
priv = usb_get_serial_port_data(port);
/* queue up a wakeup at scheduler time */
@@ -626,12 +633,12 @@ static int keyspan_pda_write_room (struct usb_serial_port *port)
static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port)
{
struct keyspan_pda_private *priv;
-
+
priv = usb_get_serial_port_data(port);
-
+
/* when throttled, return at least WAKEUP_CHARS to tell select() (via
n_tty.c:normal_poll() ) that we're not writeable. */
- if( port->write_urb->status == -EINPROGRESS || priv->tx_throttled )
+ if (port->write_urb_busy || priv->tx_throttled)
return 256;
return 0;
}