summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDuncan Sands <baldrick@free.fr>2004-08-05 23:55:57 -0700
committerGreg Kroah-Hartman <greg@kroah.com>2004-08-05 23:55:57 -0700
commit0760ab15b0ff83933eb9338422e3740f9221d75a (patch)
treed5f9decb57f043a90ae411da0c53fd1fb516e189
parent1fa89efc144321c7ece5e04e417a534ca5eafd10 (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.c8
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) {