diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2005-04-23 15:49:16 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-06-27 17:43:47 -0400 |
commit | 507ca9bc0476662f3463888d583864834eab1e11 (patch) | |
tree | 421a373de235fcb4cb46a4723a1e9f00a71f709a /drivers/usb/serial/generic.c | |
parent | f4df0e334a9fc731689e8ba4f42a0d72a7491348 (diff) |
[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 * | |||
174 | 174 | ||
175 | /* only do something if we have a bulk out endpoint */ | 175 | /* only do something if we have a bulk out endpoint */ |
176 | if (serial->num_bulk_out) { | 176 | if (serial->num_bulk_out) { |
177 | if (port->write_urb->status == -EINPROGRESS) { | 177 | spin_lock(&port->lock); |
178 | if (port->write_urb_busy) { | ||
179 | spin_unlock(&port->lock); | ||
178 | dbg("%s - already writing", __FUNCTION__); | 180 | dbg("%s - already writing", __FUNCTION__); |
179 | return (0); | 181 | return 0; |
180 | } | 182 | } |
183 | port->write_urb_busy = 1; | ||
184 | spin_unlock(&port->lock); | ||
181 | 185 | ||
182 | count = (count > port->bulk_out_size) ? port->bulk_out_size : count; | 186 | count = (count > port->bulk_out_size) ? port->bulk_out_size : count; |
183 | 187 | ||
@@ -195,17 +199,20 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char * | |||
195 | usb_serial_generic_write_bulk_callback), port); | 199 | usb_serial_generic_write_bulk_callback), port); |
196 | 200 | ||
197 | /* send the data out the bulk port */ | 201 | /* send the data out the bulk port */ |
202 | port->write_urb_busy = 1; | ||
198 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | 203 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); |
199 | if (result) | 204 | if (result) { |
200 | dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); | 205 | dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); |
201 | else | 206 | /* don't have to grab the lock here, as we will retry if != 0 */ |
207 | port->write_urb_busy = 0; | ||
208 | } else | ||
202 | result = count; | 209 | result = count; |
203 | 210 | ||
204 | return result; | 211 | return result; |
205 | } | 212 | } |
206 | 213 | ||
207 | /* no bulk out, so return 0 bytes written */ | 214 | /* no bulk out, so return 0 bytes written */ |
208 | return (0); | 215 | return 0; |
209 | } | 216 | } |
210 | 217 | ||
211 | int usb_serial_generic_write_room (struct usb_serial_port *port) | 218 | 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) | |||
214 | int room = 0; | 221 | int room = 0; |
215 | 222 | ||
216 | dbg("%s - port %d", __FUNCTION__, port->number); | 223 | dbg("%s - port %d", __FUNCTION__, port->number); |
217 | 224 | ||
218 | if (serial->num_bulk_out) { | 225 | if (serial->num_bulk_out) { |
219 | if (port->write_urb->status != -EINPROGRESS) | 226 | if (port->write_urb_busy) |
220 | room = port->bulk_out_size; | 227 | room = port->bulk_out_size; |
221 | } | 228 | } |
222 | 229 | ||
@@ -232,7 +239,7 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port) | |||
232 | dbg("%s - port %d", __FUNCTION__, port->number); | 239 | dbg("%s - port %d", __FUNCTION__, port->number); |
233 | 240 | ||
234 | if (serial->num_bulk_out) { | 241 | if (serial->num_bulk_out) { |
235 | if (port->write_urb->status == -EINPROGRESS) | 242 | if (port->write_urb_busy) |
236 | chars = port->write_urb->transfer_buffer_length; | 243 | chars = port->write_urb->transfer_buffer_length; |
237 | } | 244 | } |
238 | 245 | ||
@@ -291,6 +298,7 @@ void usb_serial_generic_write_bulk_callback (struct urb *urb, struct pt_regs *re | |||
291 | 298 | ||
292 | dbg("%s - port %d", __FUNCTION__, port->number); | 299 | dbg("%s - port %d", __FUNCTION__, port->number); |
293 | 300 | ||
301 | port->write_urb_busy = 0; | ||
294 | if (urb->status) { | 302 | if (urb->status) { |
295 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 303 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); |
296 | return; | 304 | return; |