diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2005-04-23 21:49:16 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-06-27 23:43:47 +0200 |
commit | 507ca9bc0476662f3463888d583864834eab1e11 (patch) | |
tree | 421a373de235fcb4cb46a4723a1e9f00a71f709a /drivers/usb/serial/keyspan_pda.c | |
parent | [PATCH] USB: add reboot notifier to ohci (diff) | |
download | linux-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.c | 19 |
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; } |