diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2005-04-23 23:49:16 +0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-06-28 01:43:47 +0400 |
commit | 507ca9bc0476662f3463888d583864834eab1e11 (patch) | |
tree | 421a373de235fcb4cb46a4723a1e9f00a71f709a /drivers/usb/serial/generic.c | |
parent | f4df0e334a9fc731689e8ba4f42a0d72a7491348 (diff) | |
download | linux-507ca9bc0476662f3463888d583864834eab1e11.tar.xz |
[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/generic.c')
-rw-r--r-- | drivers/usb/serial/generic.c | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 99214aa3cd19..ddde5fb13f6b 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -174,10 +174,14 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char * /* only do something if we have a bulk out endpoint */ if (serial->num_bulk_out) { - if (port->write_urb->status == -EINPROGRESS) { + spin_lock(&port->lock); + if (port->write_urb_busy) { + spin_unlock(&port->lock); dbg("%s - already writing", __FUNCTION__); - return (0); + return 0; } + port->write_urb_busy = 1; + spin_unlock(&port->lock); count = (count > port->bulk_out_size) ? port->bulk_out_size : count; @@ -195,17 +199,20 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char * usb_serial_generic_write_bulk_callback), port); /* send the data out the bulk port */ + port->write_urb_busy = 1; result = usb_submit_urb(port->write_urb, GFP_ATOMIC); - if (result) + if (result) { dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); - else + /* don't have to grab the lock here, as we will retry if != 0 */ + port->write_urb_busy = 0; + } else result = count; return result; } /* no bulk out, so return 0 bytes written */ - return (0); + return 0; } int usb_serial_generic_write_room (struct usb_serial_port *port) @@ -214,9 +221,9 @@ int usb_serial_generic_write_room (struct usb_serial_port *port) int room = 0; dbg("%s - port %d", __FUNCTION__, port->number); - + if (serial->num_bulk_out) { - if (port->write_urb->status != -EINPROGRESS) + if (port->write_urb_busy) room = port->bulk_out_size; } @@ -232,7 +239,7 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port) dbg("%s - port %d", __FUNCTION__, port->number); if (serial->num_bulk_out) { - if (port->write_urb->status == -EINPROGRESS) + if (port->write_urb_busy) chars = port->write_urb->transfer_buffer_length; } @@ -291,6 +298,7 @@ void usb_serial_generic_write_bulk_callback (struct urb *urb, struct pt_regs *re dbg("%s - port %d", __FUNCTION__, port->number); + port->write_urb_busy = 0; if (urb->status) { dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); return; |