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

Commit 5ee481c8 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: gadget: f_fs: Fail waiting IO after eps disabled"

parents 3c03dde7 d3b60e7b
Loading
Loading
Loading
Loading
+29 −7
Original line number Diff line number Diff line
@@ -139,6 +139,7 @@ struct ffs_epfile {

	struct ffs_data			*ffs;
	struct ffs_ep			*ep;	/* P: ffs->eps_lock */
	atomic_t			opened;

	struct dentry			*dentry;

@@ -205,7 +206,7 @@ struct ffs_epfile {
	unsigned char			in;	/* P: ffs->eps_lock */
	unsigned char			isoc;	/* P: ffs->eps_lock */

	unsigned char			_pad;
	bool				invalid;
};

struct ffs_buffer {
@@ -956,6 +957,16 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
		if (file->f_flags & O_NONBLOCK)
			return -EAGAIN;

		/*
		 * epfile->invalid is set when EPs are disabled. Userspace
		 * might have stale threads continuing to do I/O and may be
		 * unaware of that especially if we block here. Instead return
		 * an error immediately here and don't allow any more I/O
		 * until the epfile is reopened.
		 */
		if (epfile->invalid)
			return -ENODEV;

		ret = wait_event_interruptible(
				epfile->ffs->wait, (ep = epfile->ep));
		if (ret)
@@ -1152,15 +1163,16 @@ ffs_epfile_open(struct inode *inode, struct file *file)

	ENTER();

	ffs_log("%s: state %d setup_state %d flag %lu", epfile->name,
		epfile->ffs->state, epfile->ffs->setup_state,
		epfile->ffs->flags);
	ffs_log("%s: state %d setup_state %d flag %lu opened %u",
		epfile->name, epfile->ffs->state, epfile->ffs->setup_state,
		epfile->ffs->flags, atomic_read(&epfile->opened));

	if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
		return -ENODEV;

	file->private_data = epfile;
	ffs_data_opened(epfile->ffs);
	atomic_inc(&epfile->opened);

	return 0;
}
@@ -1301,9 +1313,12 @@ ffs_epfile_release(struct inode *inode, struct file *file)
	ENTER();

	__ffs_epfile_read_buffer_free(epfile);
	ffs_log("%s: state %d setup_state %d flag %lu", epfile->name,
			epfile->ffs->state, epfile->ffs->setup_state,
			epfile->ffs->flags);
	ffs_log("%s: state %d setup_state %d flag %lu opened %u",
		epfile->name, epfile->ffs->state, epfile->ffs->setup_state,
		epfile->ffs->flags, atomic_read(&epfile->opened));

	if (atomic_dec_and_test(&epfile->opened))
		epfile->invalid = false;

	ffs_data_closed(epfile->ffs);

@@ -1333,6 +1348,10 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
		if (file->f_flags & O_NONBLOCK)
			return -EAGAIN;

		/* don't allow any I/O until file is reopened */
		if (epfile->invalid)
			return -ENODEV;

		ret = wait_event_interruptible(
				epfile->ffs->wait, (ep = epfile->ep));
		if (ret)
@@ -1998,6 +2017,8 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
			ffs_epfiles_destroy(epfiles, i - 1);
			return -ENOMEM;
		}

		atomic_set(&epfile->opened, 0);
	}

	ffs->epfiles = epfiles;
@@ -2045,6 +2066,7 @@ static void ffs_func_eps_disable(struct ffs_function *func)
		++ep;

		if (epfile) {
			epfile->invalid = true; /* until file is reopened */
			epfile->ep = NULL;
			__ffs_epfile_read_buffer_free(epfile);
			++epfile;