get rid of temporary iso frame descriptor (isopkt) only set urb fields if applicable for respective urb type Signed-off-by: Stefan Brüns <stefan.bruens@xxxxxxxxxxxxxx> --- drivers/usb/core/devio.c | 64 +++++++++++++++++++++------------------------- 1 files changed, 29 insertions(+), 35 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 6e8bcdf..4a66dcf 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1061,6 +1061,11 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, } if (!ep) return -ENOENT; + if(uurb->type != USBDEVFS_URB_TYPE_ISO) { + as = alloc_async(0); + if (!as) + return -ENOMEM; + } switch(uurb->type) { case USBDEVFS_URB_TYPE_CONTROL: if (!usb_endpoint_xfer_control(&ep->desc)) @@ -1071,20 +1076,23 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, uurb->buffer_length > (8 + MAX_USBFS_BUFFER_SIZE)) return -EINVAL; dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); - if (!dr) + if (!dr) { + free_async(as); return -ENOMEM; + } + as->urb->setup_packet = (unsigned char *)dr; if (copy_from_user(dr, uurb->buffer, 8)) { - kfree(dr); + free_async(as); return -EFAULT; } if (uurb->buffer_length < (le16_to_cpup(&dr->wLength) + 8)) { - kfree(dr); + free_async(as); return -EINVAL; } ret = check_ctrlrecip(ps, dr->bRequestType, le16_to_cpup(&dr->wIndex)); if (ret) { - kfree(dr); + free_async(as); return ret; } uurb->number_of_packets = 0; @@ -1120,27 +1128,31 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, return -EINVAL; isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets; - if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL))) - return -ENOMEM; - if (copy_from_user(isopkt, iso_frame_desc, isofrmlen)) { - kfree(isopkt); + if (!access_ok(VERIFY_READ, iso_frame_desc, isofrmlen)) { return -EFAULT; } + as = alloc_async(uurb->number_of_packets); + if(!as) + return -ENOMEM; for (totlen = u = 0; u < uurb->number_of_packets; u++) { /* arbitrary limit, * sufficient for USB 2.0 high-bandwidth iso */ - if (isopkt[u].length > 8192) { - kfree(isopkt); + if (iso_frame_desc[u].length > 8192) { + free_async(as); return -EINVAL; } - totlen += isopkt[u].length; + as->urb->iso_frame_desc[u].offset = totlen; + as->urb->iso_frame_desc[u].length = iso_frame_desc[u].length; + totlen += iso_frame_desc[u].length; } /* 3072 * 64 microframes */ if (totlen > 196608) { - kfree(isopkt); + free_async(as); return -EINVAL; } uurb->buffer_length = totlen; + as->urb->start_frame = uurb->start_frame; + as->urb->interval = 1 << min(15, ep->desc.bInterval - 1); break; case USBDEVFS_URB_TYPE_INTERRUPT: @@ -1149,6 +1161,10 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, return -EINVAL; if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) return -EINVAL; + if (ps->dev->speed == USB_SPEED_HIGH) + as->urb->interval = 1 << min(15, ep->desc.bInterval - 1); + else + as->urb->interval = ep->desc.bInterval; break; default: @@ -1157,22 +1173,13 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, if (uurb->buffer_length > 0 && !access_ok(is_in ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length)) { - kfree(isopkt); - kfree(dr); + free_async(as); return -EFAULT; } - as = alloc_async(uurb->number_of_packets); - if (!as) { - kfree(isopkt); - kfree(dr); - return -ENOMEM; - } if (uurb->buffer_length > 0) { as->urb->transfer_buffer = kmalloc(uurb->buffer_length, GFP_KERNEL); if (!as->urb->transfer_buffer) { - kfree(isopkt); - kfree(dr); free_async(as); return -ENOMEM; } @@ -1200,22 +1207,9 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, as->urb->transfer_flags = u; as->urb->transfer_buffer_length = uurb->buffer_length; - as->urb->setup_packet = (unsigned char *)dr; - as->urb->start_frame = uurb->start_frame; as->urb->number_of_packets = uurb->number_of_packets; - 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++) { - as->urb->iso_frame_desc[u].offset = totlen; - as->urb->iso_frame_desc[u].length = isopkt[u].length; - totlen += isopkt[u].length; - } - kfree(isopkt); as->ps = ps; as->userurb = arg; if (is_in && uurb->buffer_length > 0) -- 1.5.6 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html