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 | |
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')
-rw-r--r-- | drivers/usb/serial/cyberjack.c | 19 | ||||
-rw-r--r-- | drivers/usb/serial/generic.c | 24 | ||||
-rw-r--r-- | drivers/usb/serial/ipaq.c | 5 | ||||
-rw-r--r-- | drivers/usb/serial/ipw.c | 14 | ||||
-rw-r--r-- | drivers/usb/serial/ir-usb.c | 16 | ||||
-rw-r--r-- | drivers/usb/serial/keyspan_pda.c | 19 | ||||
-rw-r--r-- | drivers/usb/serial/omninet.c | 17 | ||||
-rw-r--r-- | drivers/usb/serial/safe_serial.c | 13 | ||||
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 1 | ||||
-rw-r--r-- | drivers/usb/serial/usb-serial.h | 3 |
10 files changed, 85 insertions, 46 deletions
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 46a204cd40e1..b5b431067b08 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c | |||
@@ -213,10 +213,14 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b | |||
213 | return (0); | 213 | return (0); |
214 | } | 214 | } |
215 | 215 | ||
216 | if (port->write_urb->status == -EINPROGRESS) { | 216 | spin_lock(&port->lock); |
217 | if (port->write_urb_busy) { | ||
218 | spin_unlock(&port->lock); | ||
217 | dbg("%s - already writing", __FUNCTION__); | 219 | dbg("%s - already writing", __FUNCTION__); |
218 | return (0); | 220 | return 0; |
219 | } | 221 | } |
222 | port->write_urb_busy = 1; | ||
223 | spin_unlock(&port->lock); | ||
220 | 224 | ||
221 | spin_lock_irqsave(&priv->lock, flags); | 225 | spin_lock_irqsave(&priv->lock, flags); |
222 | 226 | ||
@@ -224,6 +228,7 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b | |||
224 | /* To much data for buffer. Reset buffer. */ | 228 | /* To much data for buffer. Reset buffer. */ |
225 | priv->wrfilled=0; | 229 | priv->wrfilled=0; |
226 | spin_unlock_irqrestore(&priv->lock, flags); | 230 | spin_unlock_irqrestore(&priv->lock, flags); |
231 | port->write_urb_busy = 0; | ||
227 | return (0); | 232 | return (0); |
228 | } | 233 | } |
229 | 234 | ||
@@ -268,6 +273,7 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b | |||
268 | priv->wrfilled=0; | 273 | priv->wrfilled=0; |
269 | priv->wrsent=0; | 274 | priv->wrsent=0; |
270 | spin_unlock_irqrestore(&priv->lock, flags); | 275 | spin_unlock_irqrestore(&priv->lock, flags); |
276 | port->write_urb_busy = 0; | ||
271 | return 0; | 277 | return 0; |
272 | } | 278 | } |
273 | 279 | ||
@@ -412,7 +418,8 @@ static void cyberjack_write_bulk_callback (struct urb *urb, struct pt_regs *regs | |||
412 | struct cyberjack_private *priv = usb_get_serial_port_data(port); | 418 | struct cyberjack_private *priv = usb_get_serial_port_data(port); |
413 | 419 | ||
414 | dbg("%s - port %d", __FUNCTION__, port->number); | 420 | dbg("%s - port %d", __FUNCTION__, port->number); |
415 | 421 | ||
422 | port->write_urb_busy = 0; | ||
416 | if (urb->status) { | 423 | if (urb->status) { |
417 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 424 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); |
418 | return; | 425 | return; |
@@ -424,12 +431,6 @@ static void cyberjack_write_bulk_callback (struct urb *urb, struct pt_regs *regs | |||
424 | if( priv->wrfilled ) { | 431 | if( priv->wrfilled ) { |
425 | int length, blksize, result; | 432 | int length, blksize, result; |
426 | 433 | ||
427 | if (port->write_urb->status == -EINPROGRESS) { | ||
428 | dbg("%s - already writing", __FUNCTION__); | ||
429 | spin_unlock(&priv->lock); | ||
430 | return; | ||
431 | } | ||
432 | |||
433 | dbg("%s - transmitting data (frame n)", __FUNCTION__); | 434 | dbg("%s - transmitting data (frame n)", __FUNCTION__); |
434 | 435 | ||
435 | length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ? | 436 | length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ? |
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; |
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 3bd69c4ef24b..c05c2a2a0f31 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c | |||
@@ -818,11 +818,6 @@ static void ipaq_write_gather(struct usb_serial_port *port) | |||
818 | struct ipaq_packet *pkt, *tmp; | 818 | struct ipaq_packet *pkt, *tmp; |
819 | struct urb *urb = port->write_urb; | 819 | struct urb *urb = port->write_urb; |
820 | 820 | ||
821 | if (urb->status == -EINPROGRESS) { | ||
822 | /* Should never happen */ | ||
823 | err("%s - flushing while urb is active !", __FUNCTION__); | ||
824 | return; | ||
825 | } | ||
826 | room = URBDATA_SIZE; | 821 | room = URBDATA_SIZE; |
827 | list_for_each_entry_safe(pkt, tmp, &priv->queue, list) { | 822 | list_for_each_entry_safe(pkt, tmp, &priv->queue, list) { |
828 | count = min(room, (int)(pkt->len - pkt->written)); | 823 | count = min(room, (int)(pkt->len - pkt->written)); |
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 11105d74f461..85e242459c27 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c | |||
@@ -399,16 +399,21 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int | |||
399 | dbg("%s - write request of 0 bytes", __FUNCTION__); | 399 | dbg("%s - write request of 0 bytes", __FUNCTION__); |
400 | return 0; | 400 | return 0; |
401 | } | 401 | } |
402 | 402 | ||
403 | /* Racy and broken, FIXME properly! */ | 403 | spin_lock(&port->lock); |
404 | if (port->write_urb->status == -EINPROGRESS) | 404 | if (port->write_urb_busy) { |
405 | spin_unlock(&port->lock); | ||
406 | dbg("%s - already writing", __FUNCTION__); | ||
405 | return 0; | 407 | return 0; |
408 | } | ||
409 | port->write_urb_busy = 1; | ||
410 | spin_unlock(&port->lock); | ||
406 | 411 | ||
407 | count = min(count, port->bulk_out_size); | 412 | count = min(count, port->bulk_out_size); |
408 | memcpy(port->bulk_out_buffer, buf, count); | 413 | memcpy(port->bulk_out_buffer, buf, count); |
409 | 414 | ||
410 | dbg("%s count now:%d", __FUNCTION__, count); | 415 | dbg("%s count now:%d", __FUNCTION__, count); |
411 | 416 | ||
412 | usb_fill_bulk_urb(port->write_urb, dev, | 417 | usb_fill_bulk_urb(port->write_urb, dev, |
413 | usb_sndbulkpipe(dev, port->bulk_out_endpointAddress), | 418 | usb_sndbulkpipe(dev, port->bulk_out_endpointAddress), |
414 | port->write_urb->transfer_buffer, | 419 | port->write_urb->transfer_buffer, |
@@ -418,6 +423,7 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int | |||
418 | 423 | ||
419 | ret = usb_submit_urb(port->write_urb, GFP_ATOMIC); | 424 | ret = usb_submit_urb(port->write_urb, GFP_ATOMIC); |
420 | if (ret != 0) { | 425 | if (ret != 0) { |
426 | port->write_urb_busy = 0; | ||
421 | dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __FUNCTION__, ret); | 427 | dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __FUNCTION__, ret); |
422 | return ret; | 428 | return ret; |
423 | } | 429 | } |
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 59f234df5f89..937b2fdd7171 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c | |||
@@ -341,10 +341,14 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int | |||
341 | if (count == 0) | 341 | if (count == 0) |
342 | return 0; | 342 | return 0; |
343 | 343 | ||
344 | if (port->write_urb->status == -EINPROGRESS) { | 344 | spin_lock(&port->lock); |
345 | dbg ("%s - already writing", __FUNCTION__); | 345 | if (port->write_urb_busy) { |
346 | spin_unlock(&port->lock); | ||
347 | dbg("%s - already writing", __FUNCTION__); | ||
346 | return 0; | 348 | return 0; |
347 | } | 349 | } |
350 | port->write_urb_busy = 1; | ||
351 | spin_unlock(&port->lock); | ||
348 | 352 | ||
349 | transfer_buffer = port->write_urb->transfer_buffer; | 353 | transfer_buffer = port->write_urb->transfer_buffer; |
350 | transfer_size = min(count, port->bulk_out_size - 1); | 354 | transfer_size = min(count, port->bulk_out_size - 1); |
@@ -374,9 +378,10 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int | |||
374 | port->write_urb->transfer_flags = URB_ZERO_PACKET; | 378 | port->write_urb->transfer_flags = URB_ZERO_PACKET; |
375 | 379 | ||
376 | result = usb_submit_urb (port->write_urb, GFP_ATOMIC); | 380 | result = usb_submit_urb (port->write_urb, GFP_ATOMIC); |
377 | if (result) | 381 | if (result) { |
382 | port->write_urb_busy = 0; | ||
378 | dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); | 383 | dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); |
379 | else | 384 | } else |
380 | result = transfer_size; | 385 | result = transfer_size; |
381 | 386 | ||
382 | return result; | 387 | return result; |
@@ -387,7 +392,8 @@ static void ir_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
387 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 392 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
388 | 393 | ||
389 | dbg("%s - port %d", __FUNCTION__, port->number); | 394 | dbg("%s - port %d", __FUNCTION__, port->number); |
390 | 395 | ||
396 | port->write_urb_busy = 0; | ||
391 | if (urb->status) { | 397 | if (urb->status) { |
392 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 398 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); |
393 | return; | 399 | return; |
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, | |||
520 | the TX urb is in-flight (wait until it completes) | 520 | the TX urb is in-flight (wait until it completes) |
521 | the device is full (wait until it says there is room) | 521 | the device is full (wait until it says there is room) |
522 | */ | 522 | */ |
523 | if (port->write_urb->status == -EINPROGRESS || priv->tx_throttled ) { | 523 | spin_lock(&port->lock); |
524 | return( 0 ); | 524 | if (port->write_urb_busy || priv->tx_throttled) { |
525 | spin_unlock(&port->lock); | ||
526 | return 0; | ||
525 | } | 527 | } |
528 | port->write_urb_busy = 1; | ||
529 | spin_unlock(&port->lock); | ||
526 | 530 | ||
527 | /* At this point the URB is in our control, nobody else can submit it | 531 | /* At this point the URB is in our control, nobody else can submit it |
528 | again (the only sudden transition was the one from EINPROGRESS to | 532 | 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, | |||
570 | memcpy (port->write_urb->transfer_buffer, buf, count); | 574 | memcpy (port->write_urb->transfer_buffer, buf, count); |
571 | /* send the data out the bulk port */ | 575 | /* send the data out the bulk port */ |
572 | port->write_urb->transfer_buffer_length = count; | 576 | port->write_urb->transfer_buffer_length = count; |
573 | 577 | ||
574 | priv->tx_room -= count; | 578 | priv->tx_room -= count; |
575 | 579 | ||
576 | port->write_urb->dev = port->serial->dev; | 580 | port->write_urb->dev = port->serial->dev; |
@@ -593,6 +597,8 @@ static int keyspan_pda_write(struct usb_serial_port *port, | |||
593 | 597 | ||
594 | rc = count; | 598 | rc = count; |
595 | exit: | 599 | exit: |
600 | if (rc < 0) | ||
601 | port->write_urb_busy = 0; | ||
596 | return rc; | 602 | return rc; |
597 | } | 603 | } |
598 | 604 | ||
@@ -602,6 +608,7 @@ static void keyspan_pda_write_bulk_callback (struct urb *urb, struct pt_regs *re | |||
602 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 608 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
603 | struct keyspan_pda_private *priv; | 609 | struct keyspan_pda_private *priv; |
604 | 610 | ||
611 | port->write_urb_busy = 0; | ||
605 | priv = usb_get_serial_port_data(port); | 612 | priv = usb_get_serial_port_data(port); |
606 | 613 | ||
607 | /* queue up a wakeup at scheduler time */ | 614 | /* queue up a wakeup at scheduler time */ |
@@ -626,12 +633,12 @@ static int keyspan_pda_write_room (struct usb_serial_port *port) | |||
626 | static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port) | 633 | static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port) |
627 | { | 634 | { |
628 | struct keyspan_pda_private *priv; | 635 | struct keyspan_pda_private *priv; |
629 | 636 | ||
630 | priv = usb_get_serial_port_data(port); | 637 | priv = usb_get_serial_port_data(port); |
631 | 638 | ||
632 | /* when throttled, return at least WAKEUP_CHARS to tell select() (via | 639 | /* when throttled, return at least WAKEUP_CHARS to tell select() (via |
633 | n_tty.c:normal_poll() ) that we're not writeable. */ | 640 | n_tty.c:normal_poll() ) that we're not writeable. */ |
634 | if( port->write_urb->status == -EINPROGRESS || priv->tx_throttled ) | 641 | if (port->write_urb_busy || priv->tx_throttled) |
635 | return 256; | 642 | return 256; |
636 | return 0; | 643 | return 0; |
637 | } | 644 | } |
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index b5f2c06d4f3e..6a99ae192df1 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c | |||
@@ -254,10 +254,15 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf | |||
254 | dbg("%s - write request of 0 bytes", __FUNCTION__); | 254 | dbg("%s - write request of 0 bytes", __FUNCTION__); |
255 | return (0); | 255 | return (0); |
256 | } | 256 | } |
257 | if (wport->write_urb->status == -EINPROGRESS) { | 257 | |
258 | spin_lock(&port->lock); | ||
259 | if (port->write_urb_busy) { | ||
260 | spin_unlock(&port->lock); | ||
258 | dbg("%s - already writing", __FUNCTION__); | 261 | dbg("%s - already writing", __FUNCTION__); |
259 | return (0); | 262 | return 0; |
260 | } | 263 | } |
264 | port->write_urb_busy = 1; | ||
265 | spin_unlock(&port->lock); | ||
261 | 266 | ||
262 | count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count; | 267 | count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count; |
263 | 268 | ||
@@ -275,9 +280,10 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf | |||
275 | 280 | ||
276 | wport->write_urb->dev = serial->dev; | 281 | wport->write_urb->dev = serial->dev; |
277 | result = usb_submit_urb(wport->write_urb, GFP_ATOMIC); | 282 | result = usb_submit_urb(wport->write_urb, GFP_ATOMIC); |
278 | if (result) | 283 | if (result) { |
284 | port->write_urb_busy = 0; | ||
279 | err("%s - failed submitting write urb, error %d", __FUNCTION__, result); | 285 | err("%s - failed submitting write urb, error %d", __FUNCTION__, result); |
280 | else | 286 | } else |
281 | result = count; | 287 | result = count; |
282 | 288 | ||
283 | return result; | 289 | return result; |
@@ -291,7 +297,7 @@ static int omninet_write_room (struct usb_serial_port *port) | |||
291 | 297 | ||
292 | int room = 0; // Default: no room | 298 | int room = 0; // Default: no room |
293 | 299 | ||
294 | if (wport->write_urb->status != -EINPROGRESS) | 300 | if (wport->write_urb_busy) |
295 | room = wport->bulk_out_size - OMNINET_HEADERLEN; | 301 | room = wport->bulk_out_size - OMNINET_HEADERLEN; |
296 | 302 | ||
297 | // dbg("omninet_write_room returns %d", room); | 303 | // dbg("omninet_write_room returns %d", room); |
@@ -306,6 +312,7 @@ static void omninet_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
306 | 312 | ||
307 | // dbg("omninet_write_bulk_callback, port %0x\n", port); | 313 | // dbg("omninet_write_bulk_callback, port %0x\n", port); |
308 | 314 | ||
315 | port->write_urb_busy = 0; | ||
309 | if (urb->status) { | 316 | if (urb->status) { |
310 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 317 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); |
311 | return; | 318 | return; |
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c index 0e85ed6c6c19..96a17568cbf1 100644 --- a/drivers/usb/serial/safe_serial.c +++ b/drivers/usb/serial/safe_serial.c | |||
@@ -299,10 +299,14 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i | |||
299 | dbg ("%s - write request of 0 bytes", __FUNCTION__); | 299 | dbg ("%s - write request of 0 bytes", __FUNCTION__); |
300 | return (0); | 300 | return (0); |
301 | } | 301 | } |
302 | if (port->write_urb->status == -EINPROGRESS) { | 302 | spin_lock(&port->lock); |
303 | dbg ("%s - already writing", __FUNCTION__); | 303 | if (port->write_urb_busy) { |
304 | return (0); | 304 | spin_unlock(&port->lock); |
305 | dbg("%s - already writing", __FUNCTION__); | ||
306 | return 0; | ||
305 | } | 307 | } |
308 | port->write_urb_busy = 1; | ||
309 | spin_unlock(&port->lock); | ||
306 | 310 | ||
307 | packet_length = port->bulk_out_size; // get max packetsize | 311 | packet_length = port->bulk_out_size; // get max packetsize |
308 | 312 | ||
@@ -354,6 +358,7 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i | |||
354 | #endif | 358 | #endif |
355 | port->write_urb->dev = port->serial->dev; | 359 | port->write_urb->dev = port->serial->dev; |
356 | if ((result = usb_submit_urb (port->write_urb, GFP_KERNEL))) { | 360 | if ((result = usb_submit_urb (port->write_urb, GFP_KERNEL))) { |
361 | port->write_urb_busy = 0; | ||
357 | err ("%s - failed submitting write urb, error %d", __FUNCTION__, result); | 362 | err ("%s - failed submitting write urb, error %d", __FUNCTION__, result); |
358 | return 0; | 363 | return 0; |
359 | } | 364 | } |
@@ -368,7 +373,7 @@ static int safe_write_room (struct usb_serial_port *port) | |||
368 | 373 | ||
369 | dbg ("%s", __FUNCTION__); | 374 | dbg ("%s", __FUNCTION__); |
370 | 375 | ||
371 | if (port->write_urb->status != -EINPROGRESS) | 376 | if (port->write_urb_busy) |
372 | room = port->bulk_out_size - (safe ? 2 : 0); | 377 | room = port->bulk_out_size - (safe ? 2 : 0); |
373 | 378 | ||
374 | if (room) { | 379 | if (room) { |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 5da76dd8fb28..0267b26dde18 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -1047,6 +1047,7 @@ int usb_serial_probe(struct usb_interface *interface, | |||
1047 | memset(port, 0x00, sizeof(struct usb_serial_port)); | 1047 | memset(port, 0x00, sizeof(struct usb_serial_port)); |
1048 | port->number = i + serial->minor; | 1048 | port->number = i + serial->minor; |
1049 | port->serial = serial; | 1049 | port->serial = serial; |
1050 | spin_lock_init(&port->lock); | ||
1050 | INIT_WORK(&port->work, usb_serial_port_softint, port); | 1051 | INIT_WORK(&port->work, usb_serial_port_softint, port); |
1051 | serial->port[i] = port; | 1052 | serial->port[i] = port; |
1052 | } | 1053 | } |
diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h index d1f0c4057fa6..57f92f054c75 100644 --- a/drivers/usb/serial/usb-serial.h +++ b/drivers/usb/serial/usb-serial.h | |||
@@ -69,6 +69,7 @@ | |||
69 | * usb_serial_port: structure for the specific ports of a device. | 69 | * usb_serial_port: structure for the specific ports of a device. |
70 | * @serial: pointer back to the struct usb_serial owner of this port. | 70 | * @serial: pointer back to the struct usb_serial owner of this port. |
71 | * @tty: pointer to the corresponding tty for this port. | 71 | * @tty: pointer to the corresponding tty for this port. |
72 | * @lock: spinlock to grab when updating portions of this structure. | ||
72 | * @number: the number of the port (the minor number). | 73 | * @number: the number of the port (the minor number). |
73 | * @interrupt_in_buffer: pointer to the interrupt in buffer for this port. | 74 | * @interrupt_in_buffer: pointer to the interrupt in buffer for this port. |
74 | * @interrupt_in_urb: pointer to the interrupt in struct urb for this port. | 75 | * @interrupt_in_urb: pointer to the interrupt in struct urb for this port. |
@@ -98,6 +99,7 @@ | |||
98 | struct usb_serial_port { | 99 | struct usb_serial_port { |
99 | struct usb_serial * serial; | 100 | struct usb_serial * serial; |
100 | struct tty_struct * tty; | 101 | struct tty_struct * tty; |
102 | spinlock_t lock; | ||
101 | unsigned char number; | 103 | unsigned char number; |
102 | 104 | ||
103 | unsigned char * interrupt_in_buffer; | 105 | unsigned char * interrupt_in_buffer; |
@@ -117,6 +119,7 @@ struct usb_serial_port { | |||
117 | unsigned char * bulk_out_buffer; | 119 | unsigned char * bulk_out_buffer; |
118 | int bulk_out_size; | 120 | int bulk_out_size; |
119 | struct urb * write_urb; | 121 | struct urb * write_urb; |
122 | int write_urb_busy; | ||
120 | __u8 bulk_out_endpointAddress; | 123 | __u8 bulk_out_endpointAddress; |
121 | 124 | ||
122 | wait_queue_head_t write_wait; | 125 | wait_queue_head_t write_wait; |