diff options
| author | Duncan Sands <baldrick@free.fr> | 2004-08-05 23:55:57 -0700 |
|---|---|---|
| committer | Greg Kroah-Hartman <greg@kroah.com> | 2004-08-05 23:55:57 -0700 |
| commit | 0760ab15b0ff83933eb9338422e3740f9221d75a (patch) | |
| tree | d5f9decb57f043a90ae411da0c53fd1fb516e189 | |
| parent | 1fa89efc144321c7ece5e04e417a534ca5eafd10 (diff) | |
[PATCH] USB: usbfs: drop the device semaphore in proc_bulk and proc_control
usb_control_msg and usb_bulk_msg may sleep for a long time, so drop the per device
semaphore before calling them. This fixes OSDL bug 3108. Dropping the semaphore
is racy, but (1) the race is fairly harmless, (2) it can be occur elsewhere as an inevitable
consequence of the current usbfs api, this just makes it fractionally more likely.
Signed-off-by: Duncan Sands <baldrick@free.fr>
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
| -rw-r--r-- | drivers/usb/core/devio.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 6f969a4da8e9..125544010416 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -555,8 +555,10 @@ static int proc_control(struct dev_state *ps, void __user *arg) snoop(&dev->dev, "control read: bRequest=%02x bRrequestType=%02x wValue=%04x wIndex=%04x\n", ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex); + up(&dev->serialize); i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo); + down(&dev->serialize); if ((i > 0) && ctrl.wLength) { if (usbfs_snoop) { dev_info(&dev->dev, "control read: data "); @@ -584,8 +586,10 @@ static int proc_control(struct dev_state *ps, void __user *arg) printk ("%02x ", (unsigned char)(tbuf)[j]); printk("\n"); } + up(&dev->serialize); i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo); + down(&dev->serialize); } free_page((unsigned long)tbuf); if (i<0) { @@ -627,7 +631,9 @@ static int proc_bulk(struct dev_state *ps, void __user *arg) kfree(tbuf); return -EINVAL; } + up(&dev->serialize); i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); + down(&dev->serialize); if (!i && len2) { if (copy_to_user(bulk.data, tbuf, len2)) { kfree(tbuf); @@ -641,7 +647,9 @@ static int proc_bulk(struct dev_state *ps, void __user *arg) return -EFAULT; } } + up(&dev->serialize); i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); + down(&dev->serialize); } kfree(tbuf); if (i < 0) { |
