summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/f_mtp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/f_mtp.c')
-rw-r--r--drivers/usb/gadget/f_mtp.c32
1 files changed, 16 insertions, 16 deletions
diff --git a/drivers/usb/gadget/f_mtp.c b/drivers/usb/gadget/f_mtp.c
index e07224fd9f89..8128b203e76f 100644
--- a/drivers/usb/gadget/f_mtp.c
+++ b/drivers/usb/gadget/f_mtp.c
@@ -92,7 +92,6 @@ struct mtp_dev {
wait_queue_head_t read_wq;
wait_queue_head_t write_wq;
- wait_queue_head_t intr_wq;
struct usb_request *rx_req[RX_REQ_MAX];
struct usb_request *intr_req;
int rx_done;
@@ -373,12 +372,11 @@ static void mtp_complete_intr(struct usb_ep *ep, struct usb_request *req)
{
struct mtp_dev *dev = _mtp_dev;
- DBG(dev->cdev, "mtp_complete_intr status: %d actual: %d\n", req->status, req->actual);
+ DBG(dev->cdev, "mtp_complete_intr status: %d actual: %d\n",
+ req->status, req->actual);
dev->intr_busy = 0;
if (req->status != 0)
dev->state = STATE_ERROR;
-
- wake_up(&dev->intr_wq);
}
static int __init create_bulk_endpoints(struct mtp_dev *dev,
@@ -662,6 +660,10 @@ static void send_file_work(struct work_struct *data) {
ret = wait_event_interruptible(dev->write_wq,
(req = req_get(dev, &dev->tx_idle))
|| dev->state != STATE_BUSY);
+ if (dev->state == STATE_CANCELED) {
+ r = -ECANCELED;
+ break;
+ }
if (!req) {
r = ret;
break;
@@ -794,13 +796,15 @@ static int mtp_send_event(struct mtp_dev *dev, struct mtp_event *event)
if (length < 0 || length > INTR_BUFFER_SIZE)
return -EINVAL;
-
- /* wait for a request to complete */
- ret = wait_event_interruptible(dev->intr_wq, !dev->intr_busy || dev->state == STATE_OFFLINE);
- if (ret < 0)
- return ret;
if (dev->state == STATE_OFFLINE)
return -ENODEV;
+ /* unfortunately an interrupt request might hang indefinitely if the host
+ * is not listening on the interrupt endpoint, so instead of waiting,
+ * we just fail if the endpoint is busy.
+ */
+ if (dev->intr_busy)
+ return -EBUSY;
+
req = dev->intr_req;
if (copy_from_user(req->buf, (void __user *)event->data, length))
return -EFAULT;
@@ -1012,7 +1016,6 @@ mtp_function_unbind(struct usb_configuration *c, struct usb_function *f)
mtp_request_free(dev->intr_req, dev->ep_intr);
dev->state = STATE_OFFLINE;
spin_unlock_irq(&dev->lock);
- wake_up(&dev->intr_wq);
misc_deregister(&mtp_device);
kfree(_mtp_dev);
@@ -1098,14 +1101,13 @@ static int mtp_function_setup(struct usb_function *f,
/* device status is "busy" until we report
* the cancelation to userspace
*/
- if (dev->state == STATE_BUSY
- || dev->state == STATE_CANCELED)
+ if (dev->state == STATE_CANCELED)
status->wCode =
__cpu_to_le16(MTP_RESPONSE_DEVICE_BUSY);
else
status->wCode =
__cpu_to_le16(MTP_RESPONSE_OK);
- spin_unlock_irqrestore(&dev->lock, flags);
+ spin_unlock_irqrestore(&dev->lock, flags);
value = sizeof(*status);
}
}
@@ -1177,7 +1179,6 @@ static void mtp_function_disable(struct usb_function *f)
/* readers may be blocked waiting for us to go online */
wake_up(&dev->read_wq);
- wake_up(&dev->intr_wq);
VDBG(cdev, "%s disabled\n", dev->function.name);
}
@@ -1185,7 +1186,7 @@ static void mtp_function_disable(struct usb_function *f)
static int mtp_bind_config(struct usb_configuration *c)
{
struct mtp_dev *dev;
- int ret;
+ int ret = 0;
printk(KERN_INFO "mtp_bind_config\n");
@@ -1205,7 +1206,6 @@ static int mtp_bind_config(struct usb_configuration *c)
spin_lock_init(&dev->lock);
init_waitqueue_head(&dev->read_wq);
init_waitqueue_head(&dev->write_wq);
- init_waitqueue_head(&dev->intr_wq);
atomic_set(&dev->open_excl, 0);
atomic_set(&dev->ioctl_excl, 0);
INIT_LIST_HEAD(&dev->tx_idle);