forked from Minki/linux
usb: gadget: f_fs: remove loop from I/O function
When endpoint changes (due to it being disabled or alt setting changed), mimic the action as if the change happened after the request has been queued, instead of retrying with the new endpoint. Signed-off-by: Michal Nazarewicz <mina86@mina86.com> Cc: David Cohen <david.a.cohen@linux.intel.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
parent
0b2d2bbade
commit
7fa6803483
@ -758,73 +758,59 @@ static ssize_t ffs_epfile_io(struct file *file,
|
||||
ssize_t ret;
|
||||
int halt;
|
||||
|
||||
goto first_try;
|
||||
do {
|
||||
/* Are we still active? */
|
||||
if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) {
|
||||
ret = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Wait for endpoint to be enabled */
|
||||
ep = epfile->ep;
|
||||
if (!ep) {
|
||||
if (file->f_flags & O_NONBLOCK) {
|
||||
ret = -EAGAIN;
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = wait_event_interruptible(epfile->wait, (ep = epfile->ep));
|
||||
if (ret) {
|
||||
ret = -EINTR;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do we halt? */
|
||||
halt = !read == !epfile->in;
|
||||
if (halt && epfile->isoc) {
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Allocate & copy */
|
||||
if (!halt) {
|
||||
data = kmalloc(len, GFP_KERNEL);
|
||||
if (unlikely(!data))
|
||||
return -ENOMEM;
|
||||
|
||||
if (!read && unlikely(copy_from_user(data, buf, len))) {
|
||||
ret = -EFAULT;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* We will be using request */
|
||||
ret = ffs_mutex_lock(&epfile->mutex, file->f_flags & O_NONBLOCK);
|
||||
if (unlikely(ret))
|
||||
goto error;
|
||||
|
||||
spin_lock_irq(&epfile->ffs->eps_lock);
|
||||
|
||||
if (epfile->ep != ep) {
|
||||
/* In the meantime, endpoint got disabled or changed. */
|
||||
ret = -ESHUTDOWN;
|
||||
spin_unlock_irq(&epfile->ffs->eps_lock);
|
||||
mutex_unlock(&epfile->mutex);
|
||||
|
||||
first_try:
|
||||
/* Are we still active? */
|
||||
if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) {
|
||||
ret = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Wait for endpoint to be enabled */
|
||||
ep = epfile->ep;
|
||||
if (!ep) {
|
||||
if (file->f_flags & O_NONBLOCK) {
|
||||
ret = -EAGAIN;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (wait_event_interruptible(epfile->wait,
|
||||
(ep = epfile->ep))) {
|
||||
ret = -EINTR;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do we halt? */
|
||||
halt = !read == !epfile->in;
|
||||
if (halt && epfile->isoc) {
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Allocate & copy */
|
||||
if (!halt && !data) {
|
||||
data = kzalloc(len, GFP_KERNEL);
|
||||
if (unlikely(!data))
|
||||
return -ENOMEM;
|
||||
|
||||
if (!read &&
|
||||
unlikely(__copy_from_user(data, buf, len))) {
|
||||
ret = -EFAULT;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* We will be using request */
|
||||
ret = ffs_mutex_lock(&epfile->mutex,
|
||||
file->f_flags & O_NONBLOCK);
|
||||
if (unlikely(ret))
|
||||
goto error;
|
||||
|
||||
/*
|
||||
* We're called from user space, we can use _irq rather then
|
||||
* _irqsave
|
||||
*/
|
||||
spin_lock_irq(&epfile->ffs->eps_lock);
|
||||
|
||||
/*
|
||||
* While we were acquiring mutex endpoint got disabled
|
||||
* or changed?
|
||||
*/
|
||||
} while (unlikely(epfile->ep != ep));
|
||||
|
||||
/* Halt */
|
||||
if (unlikely(halt)) {
|
||||
} else if (halt) {
|
||||
/* Halt */
|
||||
if (likely(epfile->ep == ep) && !WARN_ON(!ep->ep))
|
||||
usb_ep_set_halt(ep->ep);
|
||||
spin_unlock_irq(&epfile->ffs->eps_lock);
|
||||
|
Loading…
Reference in New Issue
Block a user