Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3a88d4ba authored by ChandanaKishori Chiluveru's avatar ChandanaKishori Chiluveru Committed by Hemant Kumar
Browse files

usb: gadget: f_mtp: Fix mtp enumeration failure issue



If cable is disconnected while send_file work is in progress,
Endpoints will be disabled and state will be marked as OFFLINE.
As a part of endpoint disable pending requests will be retire out
with -ECONNRESET error. Due to this we will modify the device state
as ERROR in completion callback. If the state is not offline then
we will mark the device state to ready in send_file_work. This results
in mtp driver to not returning any error for next mtp_write operation
and mtp release will not be called.

Hence fix this issue by adding a proper check in completions to not
moving device state to ERROR in case of disconnect.

Change-Id: Idb4e075c89bdf94790a321bc464d30eba546eeaa
Signed-off-by: default avatarChandanaKishori Chiluveru <cchilu@codeaurora.org>
parent 6872338a
Loading
Loading
Loading
Loading
+19 −10
Original line number Diff line number Diff line
@@ -455,7 +455,7 @@ static void mtp_complete_in(struct usb_ep *ep, struct usb_request *req)
{
	struct mtp_dev *dev = _mtp_dev;

	if (req->status != 0)
	if (req->status != 0 && dev->state != STATE_OFFLINE)
		dev->state = STATE_ERROR;

	mtp_req_put(dev, &dev->tx_idle, req);
@@ -468,7 +468,7 @@ static void mtp_complete_out(struct usb_ep *ep, struct usb_request *req)
	struct mtp_dev *dev = _mtp_dev;

	dev->rx_done = 1;
	if (req->status != 0)
	if (req->status != 0 && dev->state != STATE_OFFLINE)
		dev->state = STATE_ERROR;

	wake_up(&dev->read_wq);
@@ -478,7 +478,7 @@ static void mtp_complete_intr(struct usb_ep *ep, struct usb_request *req)
{
	struct mtp_dev *dev = _mtp_dev;

	if (req->status != 0)
	if (req->status != 0 && dev->state != STATE_OFFLINE)
		dev->state = STATE_ERROR;

	mtp_req_put(dev, &dev->intr_idle, req);
@@ -592,7 +592,7 @@ static ssize_t mtp_read(struct file *fp, char __user *buf,
	ssize_t r = count, xfer, len;
	int ret = 0;

	DBG(cdev, "mtp_read(%zu)\n", count);
	DBG(cdev, "%s(%zu) state:%d\n", __func__, count, dev->state);

	/* we will block until we're online */
	DBG(cdev, "mtp_read: waiting for online state\n");
@@ -686,7 +686,7 @@ static ssize_t mtp_read(struct file *fp, char __user *buf,
		dev->state = STATE_READY;
	spin_unlock_irq(&dev->lock);

	DBG(cdev, "mtp_read returning %zd\n", r);
	DBG(cdev, "%s returning %zd state:%d\n", __func__, r, dev->state);
	return r;
}

@@ -701,7 +701,7 @@ static ssize_t mtp_write(struct file *fp, const char __user *buf,
	int sendZLP = 0;
	int ret;

	DBG(cdev, "mtp_write(%zu)\n", count);
	DBG(cdev, "%s(%zu) state:%d\n", __func__, count, dev->state);

	spin_lock_irq(&dev->lock);
	if (dev->state == STATE_CANCELED) {
@@ -740,6 +740,8 @@ static ssize_t mtp_write(struct file *fp, const char __user *buf,
			((req = mtp_req_get(dev, &dev->tx_idle))
				|| dev->state != STATE_BUSY));
		if (!req) {
			DBG(cdev, "%s request NULL ret:%d state:%d\n",
				__func__, ret, dev->state);
			r = ret;
			break;
		}
@@ -778,7 +780,7 @@ static ssize_t mtp_write(struct file *fp, const char __user *buf,
		dev->state = STATE_READY;
	spin_unlock_irq(&dev->lock);

	DBG(cdev, "mtp_write returning %zd\n", r);
	DBG(cdev, "%s returning %zd state:%d\n", __func__, r, dev->state);
	return r;
}

@@ -834,6 +836,9 @@ static void send_file_work(struct work_struct *data)
			break;
		}
		if (!req) {
			DBG(cdev,
				"%s request NULL ret:%d state:%d\n", __func__,
				ret, dev->state);
			r = ret;
			break;
		}
@@ -891,7 +896,7 @@ static void send_file_work(struct work_struct *data)
	if (req)
		mtp_req_put(dev, &dev->tx_idle, req);

	DBG(cdev, "send_file_work returning %d\n", r);
	DBG(cdev, "%s returning %d state:%d\n", __func__, r, dev->state);
	/* write the result */
	dev->xfer_result = r;
	smp_wmb();
@@ -1048,8 +1053,10 @@ static long mtp_send_receive_ioctl(struct file *fp, unsigned int code,
	struct work_struct *work;
	int ret = -EINVAL;

	if (mtp_lock(&dev->ioctl_excl))
	if (mtp_lock(&dev->ioctl_excl)) {
		DBG(dev->cdev, "ioctl returning EBUSY state:%d\n", dev->state);
		return -EBUSY;
	}

	spin_lock_irq(&dev->lock);
	if (dev->state == STATE_CANCELED) {
@@ -1229,8 +1236,10 @@ static long compat_mtp_ioctl(struct file *fp, unsigned int code,
static int mtp_open(struct inode *ip, struct file *fp)
{
	printk(KERN_INFO "mtp_open\n");
	if (mtp_lock(&_mtp_dev->open_excl))
	if (mtp_lock(&_mtp_dev->open_excl)) {
		pr_err("%s mtp_release not called returning EBUSY\n", __func__);
		return -EBUSY;
	}

	/* clear any error condition */
	if (_mtp_dev->state != STATE_OFFLINE)