diff options
author | Oliver Neukum <oneukum@suse.de> | 2007-03-23 06:58:03 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-04-27 16:28:38 -0400 |
commit | b80349b17c6e1236a24616f71e59ed31279de25a (patch) | |
tree | 185e0cf25beaf31c9a3787b3a8f552f81d0e423d /drivers/usb/serial/visor.c | |
parent | b19d402a3450bb2597d0c1b54f6139462a5f35ae (diff) |
USB: fix race in visor_write
this fixes a small race in visor_write.
Signed-off-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/visor.c')
-rw-r--r-- | drivers/usb/serial/visor.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 2f59ff226e2c..ffbe601cde2a 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c | |||
@@ -384,19 +384,21 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf, | |||
384 | dbg("%s - write limit hit\n", __FUNCTION__); | 384 | dbg("%s - write limit hit\n", __FUNCTION__); |
385 | return 0; | 385 | return 0; |
386 | } | 386 | } |
387 | priv->outstanding_urbs++; | ||
387 | spin_unlock_irqrestore(&priv->lock, flags); | 388 | spin_unlock_irqrestore(&priv->lock, flags); |
388 | 389 | ||
389 | buffer = kmalloc (count, GFP_ATOMIC); | 390 | buffer = kmalloc (count, GFP_ATOMIC); |
390 | if (!buffer) { | 391 | if (!buffer) { |
391 | dev_err(&port->dev, "out of memory\n"); | 392 | dev_err(&port->dev, "out of memory\n"); |
392 | return -ENOMEM; | 393 | count = -ENOMEM; |
394 | goto error_no_buffer; | ||
393 | } | 395 | } |
394 | 396 | ||
395 | urb = usb_alloc_urb(0, GFP_ATOMIC); | 397 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
396 | if (!urb) { | 398 | if (!urb) { |
397 | dev_err(&port->dev, "no more free urbs\n"); | 399 | dev_err(&port->dev, "no more free urbs\n"); |
398 | kfree (buffer); | 400 | count = -ENOMEM; |
399 | return -ENOMEM; | 401 | goto error_no_urb; |
400 | } | 402 | } |
401 | 403 | ||
402 | memcpy (buffer, buf, count); | 404 | memcpy (buffer, buf, count); |
@@ -415,19 +417,27 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf, | |||
415 | dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n", | 417 | dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n", |
416 | __FUNCTION__, status); | 418 | __FUNCTION__, status); |
417 | count = status; | 419 | count = status; |
418 | kfree (buffer); | 420 | goto error; |
419 | } else { | 421 | } else { |
420 | spin_lock_irqsave(&priv->lock, flags); | 422 | spin_lock_irqsave(&priv->lock, flags); |
421 | ++priv->outstanding_urbs; | ||
422 | priv->bytes_out += count; | 423 | priv->bytes_out += count; |
423 | spin_unlock_irqrestore(&priv->lock, flags); | 424 | spin_unlock_irqrestore(&priv->lock, flags); |
424 | } | 425 | } |
425 | 426 | ||
426 | /* we are done with this urb, so let the host driver | 427 | /* we are done with this urb, so let the host driver |
427 | * really free it when it is finished with it */ | 428 | * really free it when it is finished with it */ |
428 | usb_free_urb (urb); | 429 | usb_free_urb(urb); |
429 | 430 | ||
430 | return count; | 431 | return count; |
432 | error: | ||
433 | usb_free_urb(urb); | ||
434 | error_no_urb: | ||
435 | kfree(buffer); | ||
436 | error_no_buffer: | ||
437 | spin_lock_irqsave(&priv->lock, flags); | ||
438 | --priv->outstanding_urbs; | ||
439 | spin_unlock_irqrestore(&priv->lock, flags); | ||
440 | return count; | ||
431 | } | 441 | } |
432 | 442 | ||
433 | 443 | ||