USB: f_fs: Allow epfile to be opened only once
Due to USB cable disconnect, ADBD closes its epfiles and re-opens the same. In normal operation the sequence is: ffs_func_eps_disable() setting epfile->error to 1 ffs_epfile_release() setting epfile->error to 1 ffs_epfile_open() setting epfile->error to 0 In some cases when above sequeunce gets changed, epfile->error is set to 1. Hence there is no data transfer happening on ep-IN endpoint. Fix this by not allowing opening of epfiles until it has being successfully released. Change-Id: I26b9ec1b6218d00cc0965ce3e71fcea49f9bf567 Signed-off-by: Mayank Rana <mrana@codeaurora.org>
This commit is contained in:
parent
86751cfb33
commit
dbe778eee0
1 changed files with 16 additions and 0 deletions
|
@ -138,6 +138,7 @@ struct ffs_epfile {
|
|||
unsigned char isoc; /* P: ffs->eps_lock */
|
||||
|
||||
unsigned char _pad;
|
||||
atomic_t opened;
|
||||
};
|
||||
|
||||
/* ffs_io_data structure ***************************************************/
|
||||
|
@ -947,8 +948,19 @@ ffs_epfile_open(struct inode *inode, struct file *file)
|
|||
if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
|
||||
return -ENODEV;
|
||||
|
||||
smp_mb__before_atomic();
|
||||
if (atomic_read(&epfile->opened)) {
|
||||
pr_err("%s(): ep(%s) is already opened.\n",
|
||||
__func__, epfile->name);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
smp_mb__before_atomic();
|
||||
atomic_set(&epfile->opened, 1);
|
||||
file->private_data = epfile;
|
||||
ffs_data_opened(epfile->ffs);
|
||||
|
||||
smp_mb__before_atomic();
|
||||
atomic_set(&epfile->error, 0);
|
||||
|
||||
return 0;
|
||||
|
@ -1065,6 +1077,8 @@ ffs_epfile_release(struct inode *inode, struct file *file)
|
|||
|
||||
ENTER();
|
||||
|
||||
smp_mb__before_atomic();
|
||||
atomic_set(&epfile->opened, 0);
|
||||
atomic_set(&epfile->error, 1);
|
||||
ffs_data_closed(epfile->ffs);
|
||||
file->private_data = NULL;
|
||||
|
@ -1662,6 +1676,7 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
|
|||
epfile->ffs = ffs;
|
||||
mutex_init(&epfile->mutex);
|
||||
init_waitqueue_head(&epfile->wait);
|
||||
atomic_set(&epfile->opened, 0);
|
||||
if (ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
|
||||
sprintf(epfile->name, "ep%02x", ffs->eps_addrmap[i]);
|
||||
else
|
||||
|
@ -1708,6 +1723,7 @@ static void ffs_func_eps_disable(struct ffs_function *func)
|
|||
spin_lock_irqsave(&func->ffs->eps_lock, flags);
|
||||
do {
|
||||
|
||||
smp_mb__before_atomic();
|
||||
if (epfile)
|
||||
atomic_set(&epfile->error, 1);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue