Enable the usbtest driver to test peripherals with super speed isoc endpoints. So far this has only been tested with the modified gadget zero with isoc endpoint support. A module parameter 'need_iso' is added to force the driver to look for an alternate interface containing isoc endpoints, instead of stopping at the first one with bulk endpoints. --- drivers/usb/misc/usbtest.c | 60 ++++++++++++++++++++++++++++++++----------- 1 files changed, 44 insertions(+), 16 deletions(-) diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 959145b..8ddfb91 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -11,6 +11,10 @@ #include <linux/usb.h> +static unsigned need_iso; +module_param(need_iso, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(need_iso, "require ISO endpoints"); + /*-------------------------------------------------------------------------*/ /* FIXME make these public somewhere; usbdevfs.h? */ @@ -64,6 +68,7 @@ struct usbtest_dev { int in_iso_pipe; int out_iso_pipe; struct usb_endpoint_descriptor *iso_in, *iso_out; + struct usb_ss_ep_comp_descriptor *iso_in_comp, *iso_out_comp; struct mutex lock; #define TBUF_SIZE 256 @@ -137,12 +142,16 @@ try_iso: iso_out = e; } } - if ((in && out) || iso_in || iso_out) + if (need_iso && (!iso_in || !iso_out) && + tmp != intf->num_altsetting - 1) + continue; + if ((in && out) || iso_in || iso_out) goto found; } return -EINVAL; found: + dev->info->alt = tmp; udev = testdev_to_usbdev(dev); if (alt->desc.bAlternateSetting != 0) { tmp = usb_set_interface(udev, @@ -160,6 +169,7 @@ found: } if (iso_in) { dev->iso_in = &iso_in->desc; + dev->iso_in_comp = &iso_in->ss_ep_comp; dev->in_iso_pipe = usb_rcvisocpipe(udev, iso_in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); @@ -167,6 +177,7 @@ found: if (iso_out) { dev->iso_out = &iso_out->desc; + dev->iso_out_comp = &iso_out->ss_ep_comp; dev->out_iso_pipe = usb_sndisocpipe(udev, iso_out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); @@ -201,7 +212,8 @@ static struct urb *usbtest_alloc_urb( if (!urb) return urb; usb_fill_bulk_urb(urb, udev, pipe, NULL, bytes, simple_callback, NULL); - urb->interval = (udev->speed == USB_SPEED_HIGH) + urb->interval = (udev->speed == USB_SPEED_HIGH || + udev->speed == USB_SPEED_SUPER) ? (INTERRUPT_RATE << 3) : INTERRUPT_RATE; urb->transfer_flags = transfer_flags; @@ -476,9 +488,9 @@ static int perform_sglist( while (retval == 0 && iterations-- > 0) { retval = usb_sg_init(req, udev, pipe, - (udev->speed == USB_SPEED_HIGH) - ? (INTERRUPT_RATE << 3) - : INTERRUPT_RATE, + (udev->speed == USB_SPEED_HIGH || + udev->speed == USB_SPEED_SUPER) + ? (INTERRUPT_RATE << 3) : INTERRUPT_RATE, sg, nents, 0, GFP_KERNEL); if (retval) @@ -1025,7 +1037,10 @@ test_ctrl_queue(struct usbtest_dev *dev, struct usbtest_param *param) case 13: /* short read, resembling case 10 */ req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0); /* last data packet "should" be DATA1, not DATA0 */ - len = 1024 - udev->descriptor.bMaxPacketSize0; + if (udev->speed == USB_SPEED_SUPER) + len = 512; + else + len = 1024 - udev->descriptor.bMaxPacketSize0; expected = -EREMOTEIO; break; case 14: /* short read; try to fill the last packet */ @@ -1388,7 +1403,10 @@ static int halt_simple(struct usbtest_dev *dev) int retval = 0; struct urb *urb; - urb = simple_alloc_urb(testdev_to_usbdev(dev), 0, 512); + if (testdev_to_usbdev(dev)->speed == USB_SPEED_SUPER) + urb = simple_alloc_urb(testdev_to_usbdev(dev), 0, 1024); + else + urb = simple_alloc_urb(testdev_to_usbdev(dev), 0, 512); if (urb == NULL) return -ENOMEM; @@ -1576,6 +1594,7 @@ static struct urb *iso_alloc_urb( struct usb_device *udev, int pipe, struct usb_endpoint_descriptor *desc, + struct usb_ss_ep_comp_descriptor *comp, long bytes, unsigned offset ) @@ -1587,6 +1606,8 @@ static struct urb *iso_alloc_urb( return NULL; maxp = 0x7ff & usb_endpoint_maxp(desc); maxp *= 1 + (0x3 & (usb_endpoint_maxp(desc) >> 11)); + maxp *= USB_SS_MULT(comp->bmAttributes); + maxp *= 1 + comp->bMaxBurst; packets = DIV_ROUND_UP(bytes, maxp); urb = usb_alloc_urb(packets, GFP_KERNEL); @@ -1632,7 +1653,8 @@ static struct urb *iso_alloc_urb( static int test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param, - int pipe, struct usb_endpoint_descriptor *desc, unsigned offset) + int pipe, struct usb_endpoint_descriptor *desc, + struct usb_ss_ep_comp_descriptor *comp, unsigned offset) { struct iso_context context; struct usb_device *udev; @@ -1655,11 +1677,12 @@ test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param, dev_info(&dev->intf->dev, "... iso period %d %sframes, wMaxPacket %04x\n", 1 << (desc->bInterval - 1), - (udev->speed == USB_SPEED_HIGH) ? "micro" : "", + (udev->speed == USB_SPEED_HIGH || + udev->speed == USB_SPEED_SUPER) ? "micro" : "", usb_endpoint_maxp(desc)); for (i = 0; i < param->sglen; i++) { - urbs[i] = iso_alloc_urb(udev, pipe, desc, + urbs[i] = iso_alloc_urb(udev, pipe, desc, comp, param->length, offset); if (!urbs[i]) { status = -ENOMEM; @@ -1672,7 +1695,8 @@ test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param, dev_info(&dev->intf->dev, "... total %lu msec (%lu packets)\n", (packets * (1 << (desc->bInterval - 1))) - / ((udev->speed == USB_SPEED_HIGH) ? 8 : 1), + / ((udev->speed == USB_SPEED_HIGH || + udev->speed == USB_SPEED_SUPER) ? 8 : 1), packets); spin_lock_irq(&context.lock); @@ -2055,7 +2079,8 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) param->sglen, param->length); /* FIRMWARE: iso sink */ retval = test_iso_queue(dev, param, - dev->out_iso_pipe, dev->iso_out, 0); + dev->out_iso_pipe, dev->iso_out, + dev->iso_out_comp, 0); break; /* iso read tests */ @@ -2068,7 +2093,8 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) param->sglen, param->length); /* FIRMWARE: iso source */ retval = test_iso_queue(dev, param, - dev->in_iso_pipe, dev->iso_in, 0); + dev->in_iso_pipe, dev->iso_in, + dev->iso_in_comp, 0); break; /* FIXME scatterlist cancel (needs helper thread) */ @@ -2149,7 +2175,8 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) param->iterations, param->sglen, param->length); retval = test_iso_queue(dev, param, - dev->out_iso_pipe, dev->iso_out, 1); + dev->out_iso_pipe, dev->iso_out, + dev->iso_out_comp, 1); break; case 23: @@ -2160,7 +2187,8 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) param->iterations, param->sglen, param->length); retval = test_iso_queue(dev, param, - dev->in_iso_pipe, dev->iso_in, 1); + dev->in_iso_pipe, dev->iso_in, + dev->iso_in_comp, 1); break; /* unlink URBs from a bulk-OUT queue */ @@ -2376,6 +2404,7 @@ static struct usbtest_info gz_info = { .name = "Linux gadget zero", .autoconf = 1, .ctrl_out = 1, + .iso = 1, .alt = 0, }; @@ -2516,4 +2545,3 @@ module_exit(usbtest_exit); MODULE_DESCRIPTION("USB Core/HCD Testing Driver"); MODULE_LICENSE("GPL"); - -- 1.7.4.4 -- 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