wait_queue_head_t intr_wq;
struct usb_request *rx_req[RX_REQ_MAX];
int rx_done;
+ int tx_done;
/* for processing MTP_SEND_FILE, MTP_RECEIVE_FILE and
* MTP_SEND_FILE_WITH_HEADER ioctls on a work queue
static void mtp_complete_in(struct usb_ep *ep, struct usb_request *req)
{
struct mtp_dev *dev = _mtp_dev;
-
- if (req->status != 0)
+ dev->tx_done = 1;
+ if ((req->status != 0) && (dev->state != STATE_CANCELED))
dev->state = STATE_ERROR;
mtp_req_put(dev, &dev->tx_idle, req);
struct mtp_dev *dev = _mtp_dev;
dev->rx_done = 1;
- if (req->status != 0 && dev->state != STATE_CANCELED)
+ if ((req->status != 0) && (dev->state != STATE_CANCELED))
dev->state = STATE_ERROR;
wake_up(&dev->read_wq);
}
/* wait for a request to complete */
- ret = wait_event_interruptible(dev->read_wq, dev->rx_done);
+ ret = wait_event_interruptible(dev->read_wq,
+ dev->rx_done|| (dev->state != STATE_BUSY));
+ if (dev->state == STATE_CANCELED) {
+ r = -ECANCELED;
+ if (!dev->rx_done)
+ usb_ep_dequeue(dev->ep_out, req);
+ goto done;
+ }
if (ret < 0) {
r = ret;
usb_ep_dequeue(dev->ep_out, req);
r = -EFAULT;
break;
}
+ dev->tx_done = 0;
req->length = xfer;
ret = usb_ep_queue(dev->ep_in, req, GFP_KERNEL);
r = -EIO;
break;
}
+ ret = wait_event_interruptible(dev->write_wq,
+ dev->tx_done|| (dev->state != STATE_BUSY));
+ if (dev->state == STATE_CANCELED) {
+ r = -ECANCELED;
+ if (!dev->rx_done)
+ usb_ep_dequeue(dev->ep_out, req);
+ goto done;
+ }
buf += xfer;
count -= xfer;
else if (dev->state != STATE_OFFLINE)
dev->state = STATE_READY;
spin_unlock_irq(&dev->lock);
-
+done:
DBG(cdev, "mtp_write returning %d\n", r);
return r;
}
req = 0;
ret = wait_event_interruptible(dev->write_wq,
(req = mtp_req_get(dev, &dev->tx_idle))
- || dev->state != STATE_BUSY);
+ || (dev->state != STATE_BUSY));
if (dev->state == STATE_CANCELED) {
r = -ECANCELED;
break;
if (read_req) {
/* wait for our last read to complete */
ret = wait_event_interruptible(dev->read_wq,
- dev->rx_done || dev->state != STATE_BUSY);
+ dev->rx_done || (dev->state != STATE_BUSY));
if (dev->state == STATE_CANCELED) {
r = -ECANCELED;
if (!dev->rx_done)
if (ctrl->bRequest == MTP_REQ_CANCEL && w_index == 0
&& w_value == 0) {
- DBG(cdev, "MTP_REQ_CANCEL\n");
+ DBG(cdev, "MTP_REQ_CANCEL %d\n", dev->state);
spin_lock_irqsave(&dev->lock, flags);
if (dev->state == STATE_BUSY) {
status->wLength =
__constant_cpu_to_le16(sizeof(*status));
- DBG(cdev, "MTP_REQ_GET_DEVICE_STATUS\n");
+ DBG(cdev, "MTP_REQ_GET_DEVICE_STATUS %d\n", dev->state);
spin_lock_irqsave(&dev->lock, flags);
/* device status is "busy" until we report
* the cancelation to userspace