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

Commit ea6ae44c authored by Mayank Rana's avatar Mayank Rana
Browse files

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.

CRs-Fixed: 881892
Change-Id: I26b9ec1b6218d00cc0965ce3e71fcea49f9bf567
Signed-off-by: default avatarMayank Rana <mrana@codeaurora.org>
parent bccaa565
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -209,6 +209,7 @@ struct ffs_epfile {
	unsigned char			isoc;	/* P: ffs->eps_lock */

	unsigned char			_pad;
	atomic_t			opened;
};

struct ffs_buffer {
@@ -1206,6 +1207,15 @@ ffs_epfile_open(struct inode *inode, struct file *file)
	if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
		return -ENODEV;

	/* to get updated opened atomic variable value */
	smp_mb__before_atomic();
	if (atomic_read(&epfile->opened)) {
		pr_err("%s(): ep(%s) is already opened.\n",
					__func__, epfile->name);
		return -EBUSY;
	}

	atomic_set(&epfile->opened, 1);
	file->private_data = epfile;
	ffs_data_opened(epfile->ffs);
	atomic_set(&epfile->error, 0);
@@ -1342,6 +1352,7 @@ ffs_epfile_release(struct inode *inode, struct file *file)

	ENTER();

	atomic_set(&epfile->opened, 0);
	__ffs_epfile_read_buffer_free(epfile);
	ffs_log("enter:state %d setup_state %d flag %lu", epfile->ffs->state,
		epfile->ffs->setup_state, epfile->ffs->flags);
@@ -2027,6 +2038,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