From 97b9eb91dc131a10342da1f604e5bd8b1316abdb Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 26 Feb 2007 14:56:14 -0500 Subject: [PATCH] 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: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 13 ++++++------- drivers/usb/core/message.c | 9 +++++++-- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 274f14f163..36e7a843bf 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -912,7 +912,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, struct async *as; struct usb_ctrlrequest *dr = NULL; 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| 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) != USB_ENDPOINT_XFER_ISOC) return -EINVAL; - interval = 1 << min (15, ep->desc.bInterval - 1); isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets; if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL))) 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) != USB_ENDPOINT_XFER_INT) 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) return -EINVAL; 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->start_frame = uurb->start_frame; 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->complete = async_completed; for (totlen = u = 0; u < uurb->number_of_packets; u++) { diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 2f17468b5c..217a3d6d0a 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -221,10 +221,15 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == 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); usb_fill_int_urb(urb, usb_dev, pipe, data, len, - usb_api_blocking_completion, NULL, - ep->desc.bInterval); + usb_api_blocking_completion, NULL, interval); } else usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, usb_api_blocking_completion, NULL); -- 2.20.1