[PATCH v4 3/4] usb: usbtest: add super speed isoc support to usbtest

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.

Signed-off-by: Paul Zimmerman <paulz@xxxxxxxxxxxx>
---
 drivers/usb/misc/usbtest.c |   52 ++++++++++++++++++++++++++++++++-----------
 1 files changed, 38 insertions(+), 14 deletions(-)

diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 8fe901d..e96d9f4 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -64,6 +64,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
@@ -87,6 +88,10 @@ static struct usb_device *testdev_to_usbdev(struct usbtest_dev *test)
 
 /*-------------------------------------------------------------------------*/
 
+static unsigned need_iso;
+module_param(need_iso, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(need_iso, "require ISO endpoints");
+
 static int
 get_endpoints(struct usbtest_dev *dev, struct usb_interface *intf)
 {
@@ -137,12 +142,17 @@ 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:
+	if (need_iso)
+		dev->info->alt = tmp;
 	udev = testdev_to_usbdev(dev);
 	if (alt->desc.bAlternateSetting != 0) {
 		tmp = usb_set_interface(udev,
@@ -160,6 +170,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 +178,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 +213,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 +489,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)
@@ -1583,6 +1596,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
 )
@@ -1594,6 +1608,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);
@@ -1639,7 +1655,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;
@@ -1662,11 +1679,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;
@@ -1679,7 +1697,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);
@@ -2062,7 +2081,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 */
@@ -2075,7 +2095,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) */
@@ -2156,7 +2177,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:
@@ -2167,7 +2189,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 */
@@ -2248,6 +2271,8 @@ usbtest_probe(struct usb_interface *intf, const struct usb_device_id *id)
 	if (!dev)
 		return -ENOMEM;
 	info = (struct usbtest_info *) id->driver_info;
+	if (need_iso)
+		info->iso = 1;
 	dev->info = info;
 	mutex_init(&dev->lock);
 
@@ -2523,4 +2548,3 @@ module_exit(usbtest_exit);
 
 MODULE_DESCRIPTION("USB Core/HCD Testing Driver");
 MODULE_LICENSE("GPL");
-
-- 
1.7.1

--
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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux