|
@@ -758,73 +758,59 @@ static ssize_t ffs_epfile_io(struct file *file,
|
|
|
ssize_t ret;
|
|
|
int halt;
|
|
|
|
|
|
- goto first_try;
|
|
|
- do {
|
|
|
- spin_unlock_irq(&epfile->ffs->eps_lock);
|
|
|
- mutex_unlock(&epfile->mutex);
|
|
|
+ /* Are we still active? */
|
|
|
+ if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) {
|
|
|
+ ret = -ENODEV;
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
|
|
|
-first_try:
|
|
|
- /* Are we still active? */
|
|
|
- if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) {
|
|
|
- ret = -ENODEV;
|
|
|
+ /* Wait for endpoint to be enabled */
|
|
|
+ ep = epfile->ep;
|
|
|
+ if (!ep) {
|
|
|
+ if (file->f_flags & O_NONBLOCK) {
|
|
|
+ ret = -EAGAIN;
|
|
|
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;
|
|
|
+ ret = wait_event_interruptible(epfile->wait, (ep = epfile->ep));
|
|
|
+ if (ret) {
|
|
|
+ ret = -EINTR;
|
|
|
goto error;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- /* Allocate & copy */
|
|
|
- if (!halt && !data) {
|
|
|
- data = kzalloc(len, GFP_KERNEL);
|
|
|
- if (unlikely(!data))
|
|
|
- return -ENOMEM;
|
|
|
+ /* Do we halt? */
|
|
|
+ halt = !read == !epfile->in;
|
|
|
+ if (halt && epfile->isoc) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
|
|
|
- if (!read &&
|
|
|
- unlikely(__copy_from_user(data, buf, len))) {
|
|
|
- ret = -EFAULT;
|
|
|
- goto error;
|
|
|
- }
|
|
|
- }
|
|
|
+ /* Allocate & copy */
|
|
|
+ if (!halt) {
|
|
|
+ data = kmalloc(len, GFP_KERNEL);
|
|
|
+ if (unlikely(!data))
|
|
|
+ return -ENOMEM;
|
|
|
|
|
|
- /* We will be using request */
|
|
|
- ret = ffs_mutex_lock(&epfile->mutex,
|
|
|
- file->f_flags & O_NONBLOCK);
|
|
|
- if (unlikely(ret))
|
|
|
+ if (!read && unlikely(copy_from_user(data, buf, len))) {
|
|
|
+ ret = -EFAULT;
|
|
|
goto error;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- /*
|
|
|
- * We're called from user space, we can use _irq rather then
|
|
|
- * _irqsave
|
|
|
- */
|
|
|
- spin_lock_irq(&epfile->ffs->eps_lock);
|
|
|
+ /* We will be using request */
|
|
|
+ ret = ffs_mutex_lock(&epfile->mutex, file->f_flags & O_NONBLOCK);
|
|
|
+ if (unlikely(ret))
|
|
|
+ goto error;
|
|
|
|
|
|
- /*
|
|
|
- * While we were acquiring mutex endpoint got disabled
|
|
|
- * or changed?
|
|
|
- */
|
|
|
- } while (unlikely(epfile->ep != ep));
|
|
|
+ spin_lock_irq(&epfile->ffs->eps_lock);
|
|
|
|
|
|
- /* Halt */
|
|
|
- if (unlikely(halt)) {
|
|
|
+ if (epfile->ep != ep) {
|
|
|
+ /* In the meantime, endpoint got disabled or changed. */
|
|
|
+ ret = -ESHUTDOWN;
|
|
|
+ spin_unlock_irq(&epfile->ffs->eps_lock);
|
|
|
+ } 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);
|