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

Commit fa6fed84 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: gadget: Add snapshot of f_fs changes from msm-3.10"

parents d95c521e 1021c15e
Loading
Loading
Loading
Loading
+99 −18
Original line number Diff line number Diff line
@@ -123,6 +123,7 @@ struct ffs_epfile {
	/* Protects ep->ep and ep->req. */
	struct mutex			mutex;
	wait_queue_head_t		wait;
	atomic_t                        error;

	struct ffs_data			*ffs;
	struct ffs_ep			*ep;	/* P: ffs->eps_lock */
@@ -538,6 +539,10 @@ static int ffs_ep0_open(struct inode *inode, struct file *file)
	if (unlikely(ffs->state == FFS_CLOSING))
		return -EBUSY;

	smp_mb__before_atomic();
	if (atomic_read(&ffs->opened))
		return -EBUSY;

	file->private_data = ffs;
	ffs_data_opened(ffs);

@@ -630,8 +635,12 @@ static const struct file_operations ffs_ep0_operations = {

static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req)
{
	struct ffs_ep *ep = _ep->driver_data;

	ENTER();
	if (likely(req->context)) {

	/* req may be freed during unbind */
	if (ep && ep->req && likely(req->context)) {
		struct ffs_ep *ep = _ep->driver_data;
		ep->status = req->status ? req->status : req->actual;
		/* Set is_busy false to indicate completion of last request */
@@ -705,6 +714,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
	ssize_t ret, data_len = -EINVAL;
	int halt;

	pr_debug("%s: len %zu, read %d\n", __func__, io_data->len,
			io_data->read);

	if (atomic_read(&epfile->error))
		return -ENODEV;

	/* Are we still active? */
	if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) {
		ret = -ENODEV;
@@ -719,9 +734,24 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
			goto error;
		}

		ret = wait_event_interruptible(epfile->wait, (ep = epfile->ep));
		if (ret) {
			ret = -EINTR;
		/* Don't wait on write if device is offline */
		if (!io_data->read) {
			ret = -ENODEV;
			goto error;
		}

		/*
		 * 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->wait,
					(ep = epfile->ep));
			if (ret < 0)
				goto error;
		}
		if (!ep) {
			ret = -ENODEV;
			goto error;
		}
	}
@@ -843,16 +873,26 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)

			spin_unlock_irq(&epfile->ffs->eps_lock);
		} else {
			DECLARE_COMPLETION_ONSTACK(done);
			struct completion *done;

			req = ep->req;
			req->buf      = data;
			req->length   = data_len;

			req->context  = &done;
			req->complete = ffs_epfile_io_complete;
			ret	      = 0;

			if (io_data->read) {
				reinit_completion(
						&epfile->ffs->epout_completion);
				done = &epfile->ffs->epout_completion;
				req->context  = done;
			} else {
				reinit_completion(
						&epfile->ffs->epin_completion);
				done = &epfile->ffs->epin_completion;
				req->context  = done;
			}

			/* Don't queue another read if previous is still busy */
			if (!(io_data->read && ep->is_busy)) {
				ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC);
@@ -862,11 +902,19 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
			spin_unlock_irq(&epfile->ffs->eps_lock);

			if (unlikely(ret < 0)) {
				/* nop */
				ret = -EIO;
			} else if (unlikely(
				   wait_for_completion_interruptible(&done))) {
				ret = -EINTR;
				   wait_for_completion_interruptible(done))) {
				spin_lock_irq(&epfile->ffs->eps_lock);
				/*
				 * While we were acquiring lock endpoint got
				 * disabled (disconnect) or changed
				 * (composition switch)
				 */
				if (epfile->ep == ep)
					usb_ep_dequeue(ep->ep, req);
				spin_unlock_irq(&epfile->ffs->eps_lock);
				ret = -EINTR;
			} else {
				/*
				 * XXX We may end up silently droping data
@@ -875,7 +923,18 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
				 * to maxpacketsize), we may end up with more
				 * data then user space has space for.
				 */
				spin_lock_irq(&epfile->ffs->eps_lock);
				/*
				 * While we were acquiring lock endpoint got
				 * disabled (disconnect) or changed
				 * (composition switch)
				 */
				if (epfile->ep == ep)
					ret = ep->status;
				else
					ret = -ENODEV;
				spin_unlock_irq(&epfile->ffs->eps_lock);

				if (io_data->read && ret > 0) {
					if (io_data->len != MAX_BUF_LEN &&
							ret < io_data->len)
@@ -955,6 +1014,7 @@ ffs_epfile_open(struct inode *inode, struct file *file)

	file->private_data = epfile;
	ffs_data_opened(epfile->ffs);
	atomic_set(&epfile->error, 0);

	return 0;
}
@@ -1049,7 +1109,9 @@ ffs_epfile_release(struct inode *inode, struct file *file)

	ENTER();

	atomic_set(&epfile->error, 1);
	ffs_data_closed(epfile->ffs);
	file->private_data = NULL;

	return 0;
}
@@ -1487,6 +1549,8 @@ static struct ffs_data *ffs_data_new(void)
	spin_lock_init(&ffs->eps_lock);
	init_waitqueue_head(&ffs->ev.waitq);
	init_completion(&ffs->ep0req_completion);
	init_completion(&ffs->epout_completion);
	init_completion(&ffs->epin_completion);

	/* XXX REVISIT need to update it in some places, or do we? */
	ffs->ev.can_stall = 1;
@@ -1498,9 +1562,16 @@ static void ffs_data_clear(struct ffs_data *ffs)
{
	ENTER();

	pr_debug("%s: ffs->gadget= %p, ffs->flags= %lu\n", __func__,
			ffs->gadget, ffs->flags);

	if (test_and_clear_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags))
		ffs_closed(ffs);

	/* Dump ffs->gadget and ffs->flags */
	if (ffs->gadget)
		pr_err("%s: ffs:%p ffs->gadget= %p, ffs->flags= %lu\n",
				__func__, ffs, ffs->gadget, ffs->flags);
	BUG_ON(ffs->gadget);

	if (ffs->epfiles)
@@ -1543,7 +1614,6 @@ static void ffs_data_reset(struct ffs_data *ffs)
static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev)
{
	struct usb_gadget_strings **lang;
	int first_id;

	ENTER();

@@ -1551,9 +1621,14 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev)
		 || test_and_set_bit(FFS_FL_BOUND, &ffs->flags)))
		return -EBADFD;

	first_id = usb_string_ids_n(cdev, ffs->strings_count);
	if (!ffs->first_id || ffs->old_strings_count < ffs->strings_count) {
		int first_id = usb_string_ids_n(cdev, ffs->strings_count);

		if (unlikely(first_id < 0))
			return first_id;
		ffs->first_id = first_id;
		ffs->old_strings_count = ffs->strings_count;
	}

	ffs->ep0req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
	if (unlikely(!ffs->ep0req))
@@ -1565,7 +1640,7 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev)
	if (lang) {
		for (; *lang; ++lang) {
			struct usb_string *str = (*lang)->strings;
			int id = first_id;
			int id = ffs->first_id;
			for (; str->s; ++id, ++str)
				str->id = id;
		}
@@ -1652,9 +1727,12 @@ static void ffs_func_eps_disable(struct ffs_function *func)

	spin_lock_irqsave(&func->ffs->eps_lock, flags);
	do {
		atomic_set(&epfile->error, 1);
		/* pending requests get nuked */
		if (likely(ep->ep))
		if (likely(ep->ep)) {
			usb_ep_disable(ep->ep);
			ep->ep->driver_data = NULL;
		}
		epfile->ep = NULL;

		++ep;
@@ -2935,8 +3013,10 @@ static int ffs_func_set_alt(struct usb_function *f,
			return intf;
	}

	if (ffs->func)
	if (ffs->func) {
		ffs_func_eps_disable(ffs->func);
		ffs->func = NULL;
	}

	if (ffs->state != FFS_ACTIVE)
		return -ENODEV;
@@ -3231,6 +3311,7 @@ static void ffs_func_unbind(struct usb_configuration *c,
		if (ep->ep && ep->req)
			usb_ep_free_request(ep->ep, ep->req);
		ep->req = NULL;
		ep->ep = NULL;
		++ep;
	} while (--count);
	spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
+5 −0
Original line number Diff line number Diff line
@@ -154,6 +154,8 @@ struct ffs_data {
	 */
	struct usb_request		*ep0req;		/* P: mutex */
	struct completion		ep0req_completion;	/* P: mutex */
	struct completion               epin_completion;
	struct completion               epout_completion;

	/* reference counter */
	atomic_t			ref;
@@ -233,6 +235,9 @@ struct ffs_data {
	unsigned short			eps_count;
	unsigned short			_pad1;

	int                             first_id;
	int                             old_strings_count;

	/* filled by __ffs_data_got_strings() */
	/* ids in stringtabs are set in functionfs_bind() */
	const void			*raw_strings;