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

Commit 97b9eb91 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman
Browse files

USB: set the correct interval for interrupt URBs



This patch (as862) fixes a couple of bugs in the way usbcore handles
intervals for interrupt URBs.  usb_interrupt_msg (and usb_bulk_msg for
backward compatibility) don't set the interval correctly for
high-speed devices.  proc_do_submiturb() doesn't set it correctly when
a bulk URB is submitted to an interrupt endpoint.

Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 14360ab7
Loading
Loading
Loading
Loading
+6 −7
Original line number Original line Diff line number Diff line
@@ -912,7 +912,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
	struct async *as;
	struct async *as;
	struct usb_ctrlrequest *dr = NULL;
	struct usb_ctrlrequest *dr = NULL;
	unsigned int u, totlen, isofrmlen;
	unsigned int u, totlen, isofrmlen;
	int ret, interval = 0, ifnum = -1;
	int ret, ifnum = -1;


	if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK|
	if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK|
			   URB_NO_FSBR|URB_ZERO_PACKET))
			   URB_NO_FSBR|URB_ZERO_PACKET))
@@ -992,7 +992,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
		if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
		if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
				!= USB_ENDPOINT_XFER_ISOC)
				!= USB_ENDPOINT_XFER_ISOC)
			return -EINVAL;
			return -EINVAL;
		interval = 1 << min (15, ep->desc.bInterval - 1);
		isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets;
		isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets;
		if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
		if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
			return -ENOMEM;
			return -ENOMEM;
@@ -1021,10 +1020,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
		if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
		if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
				!= USB_ENDPOINT_XFER_INT)
				!= USB_ENDPOINT_XFER_INT)
			return -EINVAL;
			return -EINVAL;
		if (ps->dev->speed == USB_SPEED_HIGH)
			interval = 1 << min (15, ep->desc.bInterval - 1);
		else
			interval = ep->desc.bInterval;
		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
			return -EINVAL;
			return -EINVAL;
		if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length))
		if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length))
@@ -1053,7 +1048,11 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
	as->urb->setup_packet = (unsigned char*)dr;
	as->urb->setup_packet = (unsigned char*)dr;
	as->urb->start_frame = uurb->start_frame;
	as->urb->start_frame = uurb->start_frame;
	as->urb->number_of_packets = uurb->number_of_packets;
	as->urb->number_of_packets = uurb->number_of_packets;
	as->urb->interval = interval;
	if (uurb->type == USBDEVFS_URB_TYPE_ISO ||
			ps->dev->speed == USB_SPEED_HIGH)
		as->urb->interval = 1 << min(15, ep->desc.bInterval - 1);
	else
		as->urb->interval = ep->desc.bInterval;
        as->urb->context = as;
        as->urb->context = as;
        as->urb->complete = async_completed;
        as->urb->complete = async_completed;
	for (totlen = u = 0; u < uurb->number_of_packets; u++) {
	for (totlen = u = 0; u < uurb->number_of_packets; u++) {
+7 −2
Original line number Original line Diff line number Diff line
@@ -221,10 +221,15 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,


	if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
	if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
			USB_ENDPOINT_XFER_INT) {
			USB_ENDPOINT_XFER_INT) {
		int interval;

		if (usb_dev->speed == USB_SPEED_HIGH)
			interval = 1 << min(15, ep->desc.bInterval - 1);
		else
			interval = ep->desc.bInterval;
		pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
		pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
		usb_fill_int_urb(urb, usb_dev, pipe, data, len,
		usb_fill_int_urb(urb, usb_dev, pipe, data, len,
				usb_api_blocking_completion, NULL,
				usb_api_blocking_completion, NULL, interval);
				ep->desc.bInterval);
	} else
	} else
		usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
		usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
				usb_api_blocking_completion, NULL);
				usb_api_blocking_completion, NULL);