struct ffs_epfile {
/* Protects ep->ep and ep->req. */
struct mutex mutex;
-
+ atomic_t error;
struct ffs_data *ffs;
struct ffs_ep *ep; /* P: ffs->eps_lock */
char *data = NULL;
ssize_t ret, data_len = -EINVAL;
int halt;
+ /* to get updated error atomic variable value */
+ smp_mb__before_atomic();
+ if (atomic_read(&epfile->error))
+ return -ENODEV;
/* Are we still active? */
if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
if (!ep) {
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
+ /* Don't wait on write if device is offline */
+ if (!io_data->read)
+ return -ENODEV;
+ /* to get updated error atomic variable value */
+ smp_mb__before_atomic();
- ret = wait_event_interruptible(
+ /*
+ * if ep is disabled, this fails all current IOs
+ * and wait for next epfile open to happen
+ */
+ if (!atomic_read(&epfile->error)) {
+ ret = wait_event_interruptible(
epfile->ffs->wait, (ep = epfile->ep));
- if (ret)
- return -EINTR;
+ if (ret)
+ return -EINTR;
+ }
+ if (!ep)
+ return -ENODEV;
}
/* Do we halt? */
file->private_data = epfile;
ffs_data_opened(epfile->ffs);
-
+ /* to get updated opened atomic variable value */
+ smp_mb__before_atomic();
+ atomic_set(&epfile->error, 0);
return 0;
}
ENTER();
__ffs_epfile_read_buffer_free(epfile);
+ atomic_set(&epfile->error, 1);
ffs_data_closed(epfile->ffs);
return 0;
unsigned long flags;
spin_lock_irqsave(&func->ffs->eps_lock, flags);
- while (count--) {
+ do {
+
+ if (epfile)
+ atomic_set(&epfile->error, 1);
+
/* pending requests get nuked */
if (likely(ep->ep))
usb_ep_disable(ep->ep);
__ffs_epfile_read_buffer_free(epfile);
++epfile;
}
- }
+ } while (--count);
spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
}
int ret = 0;
spin_lock_irqsave(&func->ffs->eps_lock, flags);
- while(count--) {
+ do {
ep->ep->driver_data = ep;
ret = config_ep_by_speed(func->gadget, &func->function, ep->ep);
++ep;
++epfile;
- }
+ } while (--count);
wake_up_interruptible(&ffs->wait);
spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
/* cleanup after autoconfig */
spin_lock_irqsave(&func->ffs->eps_lock, flags);
- while (count--) {
+ do {
if (ep->ep && ep->req)
usb_ep_free_request(ep->ep, ep->req);
ep->req = NULL;
++ep;
- }
+ } while (--count);
spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
kfree(func->eps);
func->eps = NULL;