From 3f0f67e02866b1dda6f7a69446490af149ecb60c Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Sun, 1 May 2016 22:15:04 -0700 Subject: [PATCH] USB: f_mtp: Fix corner cases in MTP driver while syncing Currently if USB composition switch happens while file transfer is happening either from/to device, ep_queue fails and sets device state to ERROR even if device state is already set to OFFLINE in function disable call. As part of ioctl call, if the state is not offline, moving the device state to READY and returning the error. Since the device state is marked as READY, the next write call tries to queue the request to hardware and is blocked and due to this, userspace is not calling the release function. Hence next mtp open fails even after cable reconnection. Signed-off-by: Vijayavardhan Vennapusa Change-Id: Ia8cbd1cd8c81b90389900b83744b2bed89068db5 Signed-off-by: Hemant Kumar --- drivers/usb/gadget/function/f_mtp.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/function/f_mtp.c b/drivers/usb/gadget/function/f_mtp.c index 9305e96f804c..38583b220dd1 100644 --- a/drivers/usb/gadget/function/f_mtp.c +++ b/drivers/usb/gadget/function/f_mtp.c @@ -780,7 +780,8 @@ static void send_file_work(struct work_struct *data) ret = usb_ep_queue(dev->ep_in, req, GFP_KERNEL); if (ret < 0) { DBG(cdev, "send_file_work: xfer error %d\n", ret); - dev->state = STATE_ERROR; + if (dev->state != STATE_OFFLINE) + dev->state = STATE_ERROR; r = -EIO; break; } @@ -837,7 +838,8 @@ static void receive_file_work(struct work_struct *data) ret = usb_ep_queue(dev->ep_out, read_req, GFP_KERNEL); if (ret < 0) { r = -EIO; - dev->state = STATE_ERROR; + if (dev->state != STATE_OFFLINE) + dev->state = STATE_ERROR; break; } } @@ -849,7 +851,8 @@ static void receive_file_work(struct work_struct *data) DBG(cdev, "vfs_write %d\n", ret); if (ret != write_req->actual) { r = -EIO; - dev->state = STATE_ERROR; + if (dev->state != STATE_OFFLINE) + dev->state = STATE_ERROR; break; } write_req = NULL;