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 <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
14360ab76a
commit
97b9eb91dc
@ -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++) {
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user