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>
This commit is contained in:
Oliver Neukum 2007-03-23 11:58:03 +01:00 committed by Greg Kroah-Hartman
parent b19d402a34
commit b80349b17c

View File

@ -384,19 +384,21 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf,
dbg("%s - write limit hit\n", __FUNCTION__); dbg("%s - write limit hit\n", __FUNCTION__);
return 0; return 0;
} }
priv->outstanding_urbs++;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
buffer = kmalloc (count, GFP_ATOMIC); buffer = kmalloc (count, GFP_ATOMIC);
if (!buffer) { if (!buffer) {
dev_err(&port->dev, "out of memory\n"); dev_err(&port->dev, "out of memory\n");
return -ENOMEM; count = -ENOMEM;
goto error_no_buffer;
} }
urb = usb_alloc_urb(0, GFP_ATOMIC); urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) { if (!urb) {
dev_err(&port->dev, "no more free urbs\n"); dev_err(&port->dev, "no more free urbs\n");
kfree (buffer); count = -ENOMEM;
return -ENOMEM; goto error_no_urb;
} }
memcpy (buffer, buf, count); memcpy (buffer, buf, count);
@ -415,18 +417,26 @@ static int visor_write (struct usb_serial_port *port, const unsigned char *buf,
dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n", dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n",
__FUNCTION__, status); __FUNCTION__, status);
count = status; count = status;
kfree (buffer); goto error;
} else { } else {
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
++priv->outstanding_urbs;
priv->bytes_out += count; priv->bytes_out += count;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
} }
/* we are done with this urb, so let the host driver /* we are done with this urb, so let the host driver
* really free it when it is finished with it */ * really free it when it is finished with it */
usb_free_urb (urb); usb_free_urb(urb);
return count;
error:
usb_free_urb(urb);
error_no_urb:
kfree(buffer);
error_no_buffer:
spin_lock_irqsave(&priv->lock, flags);
--priv->outstanding_urbs;
spin_unlock_irqrestore(&priv->lock, flags);
return count; return count;
} }