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

Commit 9f2952db authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (22 commits)
  USB: gadget: f_mass_storage: stale common->fsg value bug fix
  USB: gadget: f_mass_storage: fixed fs descriptors not being updated
  USB: musb: Enable the maximum supported burst mode for DMA
  USB: musb: fix Blackfin ulpi stubs
  USB: MUSB: make non-OMAP platforms build with CONFIG_PM=y
  USB: musb_core: make disconnect and suspend interrupts work again
  USB: obey the sysfs power/wakeup setting
  USB: gadget eth: Fix calculate CRC32 in EEM
  USB: qcserial: fix a memory leak in qcprobe error path
  USB: gadget/printer, fix sleep inside atomic
  USB: isp1362-hcd, fix double lock
  USB: serial: ftdi: correct merge conflict with CONTEC id
  USB: fix oops in usb_sg_init()
  USB: s3c2410: deactivate endpoints before gadget unbinding
  USB: ehci-mxc: bail out on transceiver problems
  USB: otg/ulpi: bail out on read errors
  usb: musb: Fix a bug by making suspend interrupt available in device mode
  USB: r8a66597: Fix failure in change of status
  USB: xHCI: Fix bug in link TRB activation change.
  USB: gadget: g_fs: possible invalid pointer reference bug fixed
  ...
parents 59e76486 b894f60a
Loading
Loading
Loading
Loading
+3 −10
Original line number Diff line number Diff line
@@ -1272,8 +1272,7 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg)

static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
{
	int			w, i;
	struct usb_interface	*intf;
	int	w;

	/* Remote wakeup is needed only when we actually go to sleep.
	 * For things like FREEZE and QUIESCE, if the device is already
@@ -1285,16 +1284,10 @@ static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
		return;
	}

	/* If remote wakeup is permitted, see whether any interface drivers
	/* Enable remote wakeup if it is allowed, even if no interface drivers
	 * actually want it.
	 */
	w = 0;
	if (device_may_wakeup(&udev->dev) && udev->actconfig) {
		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
			intf = udev->actconfig->interface[i];
			w |= intf->needs_remote_wakeup;
		}
	}
	w = device_may_wakeup(&udev->dev);

	/* If the device is autosuspended with the wrong wakeup setting,
	 * autoresume now so the setting can be changed.
+5 −2
Original line number Diff line number Diff line
@@ -416,8 +416,11 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
			/* A length of zero means transfer the whole sg list */
			len = length;
			if (len == 0) {
				for_each_sg(sg, sg, nents, i)
					len += sg->length;
				struct scatterlist	*sg2;
				int			j;

				for_each_sg(sg, sg2, nents, j)
					len += sg2->length;
			}
		} else {
			/*
+1 −2
Original line number Diff line number Diff line
@@ -469,8 +469,7 @@ static int eem_unwrap(struct gether *port,
				crc = get_unaligned_le32(skb->data + len
							- ETH_FCS_LEN);
				crc2 = ~crc32_le(~0,
						skb->data,
						skb->len - ETH_FCS_LEN);
						skb->data, len - ETH_FCS_LEN);
			} else {
				crc = get_unaligned_be32(skb->data + len
							- ETH_FCS_LEN);
+73 −121
Original line number Diff line number Diff line
@@ -321,8 +321,8 @@ struct fsg_dev;
/* Data shared by all the FSG instances. */
struct fsg_common {
	struct usb_gadget	*gadget;
	struct fsg_dev		*fsg;
	struct fsg_dev		*prev_fsg;
	struct fsg_dev		*fsg, *new_fsg;
	wait_queue_head_t	fsg_wait;

	/* filesem protects: backing files in use */
	struct rw_semaphore	filesem;
@@ -351,7 +351,6 @@ struct fsg_common {
	enum fsg_state		state;		/* For exception handling */
	unsigned int		exception_req_tag;

	u8			config, new_config;
	enum data_direction	data_dir;
	u32			data_size;
	u32			data_size_from_cmnd;
@@ -595,7 +594,7 @@ static int fsg_setup(struct usb_function *f,
	u16			w_value = le16_to_cpu(ctrl->wValue);
	u16			w_length = le16_to_cpu(ctrl->wLength);

	if (!fsg->common->config)
	if (!fsg_is_set(fsg->common))
		return -EOPNOTSUPP;

	switch (ctrl->bRequest) {
@@ -2303,24 +2302,20 @@ static int alloc_request(struct fsg_common *common, struct usb_ep *ep,
	return -ENOMEM;
}

/*
 * Reset interface setting and re-init endpoint state (toggle etc).
 * Call with altsetting < 0 to disable the interface.  The only other
 * available altsetting is 0, which enables the interface.
 */
static int do_set_interface(struct fsg_common *common, int altsetting)
/* Reset interface setting and re-init endpoint state (toggle etc). */
static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg)
{
	int	rc = 0;
	int	i;
	const struct usb_endpoint_descriptor *d;
	struct fsg_dev *fsg;
	int i, rc = 0;

	if (common->running)
		DBG(common, "reset interface\n");

reset:
	/* Deallocate the requests */
	if (common->prev_fsg) {
		struct fsg_dev *fsg = common->prev_fsg;
	if (common->fsg) {
		fsg = common->fsg;

		for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
			struct fsg_buffhd *bh = &common->buffhds[i];
@@ -2345,18 +2340,16 @@ static int do_set_interface(struct fsg_common *common, int altsetting)
			fsg->bulk_out_enabled = 0;
		}

		common->prev_fsg = 0;
		common->fsg = NULL;
		wake_up(&common->fsg_wait);
	}

	common->running = 0;
	if (altsetting < 0 || rc != 0)
	if (!new_fsg || rc)
		return rc;

	DBG(common, "set interface %d\n", altsetting);

	if (fsg_is_set(common)) {
		struct fsg_dev *fsg = common->fsg;
		common->prev_fsg = common->fsg;
	common->fsg = new_fsg;
	fsg = common->fsg;

	/* Enable the endpoints */
	d = fsg_ep_desc(common->gadget,
@@ -2395,39 +2388,6 @@ static int do_set_interface(struct fsg_common *common, int altsetting)
	for (i = 0; i < common->nluns; ++i)
		common->luns[i].unit_attention_data = SS_RESET_OCCURRED;
	return rc;
	} else {
		return -EIO;
	}
}


/*
 * Change our operational configuration.  This code must agree with the code
 * that returns config descriptors, and with interface altsetting code.
 *
 * It's also responsible for power management interactions.  Some
 * configurations might not work with our current power sources.
 * For now we just assume the gadget is always self-powered.
 */
static int do_set_config(struct fsg_common *common, u8 new_config)
{
	int	rc = 0;

	/* Disable the single interface */
	if (common->config != 0) {
		DBG(common, "reset config\n");
		common->config = 0;
		rc = do_set_interface(common, -1);
	}

	/* Enable the interface */
	if (new_config != 0) {
		common->config = new_config;
		rc = do_set_interface(common, 0);
		if (rc != 0)
			common->config = 0;	/* Reset on errors */
	}
	return rc;
}


@@ -2437,9 +2397,7 @@ static int do_set_config(struct fsg_common *common, u8 new_config)
static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
{
	struct fsg_dev *fsg = fsg_from_func(f);
	fsg->common->prev_fsg = fsg->common->fsg;
	fsg->common->fsg = fsg;
	fsg->common->new_config = 1;
	fsg->common->new_fsg = fsg;
	raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
	return 0;
}
@@ -2447,9 +2405,7 @@ static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
static void fsg_disable(struct usb_function *f)
{
	struct fsg_dev *fsg = fsg_from_func(f);
	fsg->common->prev_fsg = fsg->common->fsg;
	fsg->common->fsg = fsg;
	fsg->common->new_config = 0;
	fsg->common->new_fsg = NULL;
	raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
}

@@ -2459,19 +2415,17 @@ static void fsg_disable(struct usb_function *f)
static void handle_exception(struct fsg_common *common)
{
	siginfo_t		info;
	int			sig;
	int			i;
	struct fsg_buffhd	*bh;
	enum fsg_state		old_state;
	u8			new_config;
	struct fsg_lun		*curlun;
	unsigned int		exception_req_tag;
	int			rc;

	/* Clear the existing signals.  Anything but SIGUSR1 is converted
	 * into a high-priority EXIT exception. */
	for (;;) {
		sig = dequeue_signal_lock(current, &current->blocked, &info);
		int sig =
			dequeue_signal_lock(current, &current->blocked, &info);
		if (!sig)
			break;
		if (sig != SIGUSR1) {
@@ -2482,7 +2436,7 @@ static void handle_exception(struct fsg_common *common)
	}

	/* Cancel all the pending transfers */
	if (fsg_is_set(common)) {
	if (likely(common->fsg)) {
		for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
			bh = &common->buffhds[i];
			if (bh->inreq_busy)
@@ -2523,7 +2477,6 @@ static void handle_exception(struct fsg_common *common)
	common->next_buffhd_to_fill = &common->buffhds[0];
	common->next_buffhd_to_drain = &common->buffhds[0];
	exception_req_tag = common->exception_req_tag;
	new_config = common->new_config;
	old_state = common->state;

	if (old_state == FSG_STATE_ABORT_BULK_OUT)
@@ -2573,12 +2526,12 @@ static void handle_exception(struct fsg_common *common)
		break;

	case FSG_STATE_CONFIG_CHANGE:
		rc = do_set_config(common, new_config);
		do_set_interface(common, common->new_fsg);
		break;

	case FSG_STATE_EXIT:
	case FSG_STATE_TERMINATED:
		do_set_config(common, 0);		/* Free resources */
		do_set_interface(common, NULL);		/* Free resources */
		spin_lock_irq(&common->lock);
		common->state = FSG_STATE_TERMINATED;	/* Stop the thread */
		spin_unlock_irq(&common->lock);
@@ -2863,6 +2816,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
		goto error_release;
	}
	init_completion(&common->thread_notifier);
	init_waitqueue_head(&common->fsg_wait);
#undef OR


@@ -2957,9 +2911,17 @@ static void fsg_common_release(struct kref *ref)
static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
{
	struct fsg_dev		*fsg = fsg_from_func(f);
	struct fsg_common	*common = fsg->common;

	DBG(fsg, "unbind\n");
	fsg_common_put(fsg->common);
	if (fsg->common->fsg == fsg) {
		fsg->common->new_fsg = NULL;
		raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
		/* FIXME: make interruptible or killable somehow? */
		wait_event(common->fsg_wait, common->fsg != fsg);
	}

	fsg_common_put(common);
	usb_free_descriptors(fsg->function.descriptors);
	usb_free_descriptors(fsg->function.hs_descriptors);
	kfree(fsg);
@@ -2970,7 +2932,6 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
{
	struct fsg_dev		*fsg = fsg_from_func(f);
	struct usb_gadget	*gadget = c->cdev->gadget;
	int			rc;
	int			i;
	struct usb_ep		*ep;

@@ -2996,6 +2957,11 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
	ep->driver_data = fsg->common;	/* claim the endpoint */
	fsg->bulk_out = ep;

	/* Copy descriptors */
	f->descriptors = usb_copy_descriptors(fsg_fs_function);
	if (unlikely(!f->descriptors))
		return -ENOMEM;

	if (gadget_is_dualspeed(gadget)) {
		/* Assume endpoint addresses are the same for both speeds */
		fsg_hs_bulk_in_desc.bEndpointAddress =
@@ -3003,16 +2969,17 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
		fsg_hs_bulk_out_desc.bEndpointAddress =
			fsg_fs_bulk_out_desc.bEndpointAddress;
		f->hs_descriptors = usb_copy_descriptors(fsg_hs_function);
		if (unlikely(!f->hs_descriptors))
		if (unlikely(!f->hs_descriptors)) {
			usb_free_descriptors(f->descriptors);
			return -ENOMEM;
		}
	}

	return 0;

autoconf_fail:
	ERROR(fsg, "unable to autoconfigure all endpoints\n");
	rc = -ENOTSUPP;
	return rc;
	return -ENOTSUPP;
}


@@ -3036,11 +3003,6 @@ static int fsg_add(struct usb_composite_dev *cdev,

	fsg->function.name        = FSG_DRIVER_DESC;
	fsg->function.strings     = fsg_strings_array;
	fsg->function.descriptors = usb_copy_descriptors(fsg_fs_function);
	if (unlikely(!fsg->function.descriptors)) {
		rc = -ENOMEM;
		goto error_free_fsg;
	}
	fsg->function.bind        = fsg_bind;
	fsg->function.unbind      = fsg_unbind;
	fsg->function.setup       = fsg_setup;
@@ -3056,19 +3018,9 @@ static int fsg_add(struct usb_composite_dev *cdev,

	rc = usb_add_function(c, &fsg->function);
	if (unlikely(rc))
		goto error_free_all;

	fsg_common_get(fsg->common);
	return 0;

error_free_all:
	usb_free_descriptors(fsg->function.descriptors);
	/* fsg_bind() might have copied those; or maybe not? who cares
	 * -- free it just in case. */
	usb_free_descriptors(fsg->function.hs_descriptors);
error_free_fsg:
		kfree(fsg);

	else
		fsg_common_get(fsg->common);
	return rc;
}

+11 −0
Original line number Diff line number Diff line
@@ -392,6 +392,17 @@ static int __gfs_do_config(struct usb_configuration *c,
	if (unlikely(ret < 0))
		return ret;

	/* After previous do_configs there may be some invalid
	 * pointers in c->interface array.  This happens every time
	 * a user space function with fewer interfaces than a user
	 * space function that was run before the new one is run.  The
	 * compasit's set_config() assumes that if there is no more
	 * then MAX_CONFIG_INTERFACES interfaces in a configuration
	 * then there is a NULL pointer after the last interface in
	 * c->interface array.  We need to make sure this is true. */
	if (c->next_interface_id < ARRAY_SIZE(c->interface))
		c->interface[c->next_interface_id] = NULL;

	return 0;
}

Loading