[RFC PATCH 1/1] usb: misc: usbtest: add bulk queue test

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

 



The bulk queue tests are used to show 'best performance' for bulk
transfer, we are often asked this question by users.

It's result should be very close to IC simulation, in order
to get that, the device side should also need to prepare enough
queue.

We have got the 'best performance' (IN: ~41MB, OUT: ~39MB) at i.mx platform
(USB2, ARM Cortex A9) with below command:

Host side:
modprobe usbtest
./testusb -a -t 27 -g 64 -s 16384
./testusb -a -t 28 -g 64 -s 16384
Gadget side:
modprobe g_zero loopdefault=1 qlen=64 buflen=16384

Signed-off-by: Peter Chen <peter.chen@xxxxxxxxxxxxx>
---

I am not sure if it is good to reuse iso structure, so I take
it as RFC. If reuse is accepted, I will rename the iso
structures to common one.

 drivers/usb/misc/usbtest.c | 88 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 69 insertions(+), 19 deletions(-)

diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index ad6dd4a..f1faeb9 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -17,6 +17,7 @@
 static int override_alt = -1;
 module_param_named(alt, override_alt, int, 0644);
 MODULE_PARM_DESC(alt, ">= 0 to override altsetting selection");
+static void iso_callback(struct urb *urb);
 
 /*-------------------------------------------------------------------------*/
 
@@ -239,7 +240,8 @@ static struct urb *usbtest_alloc_urb(
 	unsigned long		bytes,
 	unsigned		transfer_flags,
 	unsigned		offset,
-	u8			bInterval)
+	u8			bInterval,
+	bool			queue_callback)
 {
 	struct urb		*urb;
 
@@ -250,9 +252,14 @@ static struct urb *usbtest_alloc_urb(
 	if (bInterval)
 		usb_fill_int_urb(urb, udev, pipe, NULL, bytes, simple_callback,
 				NULL, bInterval);
-	else
-		usb_fill_bulk_urb(urb, udev, pipe, NULL, bytes, simple_callback,
+	else {
+		if (queue_callback)
+			usb_fill_bulk_urb(urb, udev, pipe, NULL, bytes, iso_callback,
 				NULL);
+		else
+			usb_fill_bulk_urb(urb, udev, pipe, NULL, bytes, simple_callback,
+				NULL);
+	}
 
 	urb->interval = (udev->speed == USB_SPEED_HIGH)
 			? (INTERRUPT_RATE << 3)
@@ -296,7 +303,17 @@ static struct urb *simple_alloc_urb(
 	u8			bInterval)
 {
 	return usbtest_alloc_urb(udev, pipe, bytes, URB_NO_TRANSFER_DMA_MAP, 0,
-			bInterval);
+			bInterval, false);
+}
+
+static struct urb *test_queue_alloc_urb(
+	struct usb_device	*udev,
+	int			pipe,
+	unsigned long		bytes,
+	u8			bInterval)
+{
+	return usbtest_alloc_urb(udev, pipe, bytes, URB_NO_TRANSFER_DMA_MAP, 0,
+			bInterval, true);
 }
 
 static unsigned pattern;
@@ -1809,6 +1826,7 @@ struct iso_context {
 	unsigned long		errors;
 	unsigned long		packet_count;
 	struct usbtest_dev	*dev;
+	bool			is_iso;
 };
 
 static void iso_callback(struct urb *urb)
@@ -1822,7 +1840,7 @@ static void iso_callback(struct urb *urb)
 	if (urb->error_count > 0)
 		ctx->errors += urb->error_count;
 	else if (urb->status != 0)
-		ctx->errors += urb->number_of_packets;
+		ctx->errors += (ctx->is_iso ? urb->number_of_packets : 1);
 	else if (urb->actual_length != urb->transfer_buffer_length)
 		ctx->errors++;
 	else if (check_guard_bytes(ctx->dev, urb) != 0)
@@ -1930,20 +1948,20 @@ test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param,
 	memset(&context, 0, sizeof(context));
 	context.count = param->iterations * param->sglen;
 	context.dev = dev;
+	context.is_iso = !!desc;
 	init_completion(&context.done);
 	spin_lock_init(&context.lock);
 
 	udev = testdev_to_usbdev(dev);
-	dev_info(&dev->intf->dev,
-		"iso period %d %sframes, wMaxPacket %d, transactions: %d\n",
-		1 << (desc->bInterval - 1),
-		(udev->speed == USB_SPEED_HIGH) ? "micro" : "",
-		usb_endpoint_maxp(desc) & 0x7ff,
-		1 + (0x3 & (usb_endpoint_maxp(desc) >> 11)));
 
 	for (i = 0; i < param->sglen; i++) {
-		urbs[i] = iso_alloc_urb(udev, pipe, desc,
+		if (context.is_iso)
+			urbs[i] = iso_alloc_urb(udev, pipe, desc,
 					param->length, offset);
+		else
+			urbs[i] = test_queue_alloc_urb(udev, pipe,
+					param->length, 0);
+
 		if (!urbs[i]) {
 			status = -ENOMEM;
 			goto fail;
@@ -1952,11 +1970,21 @@ test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param,
 		urbs[i]->context = &context;
 	}
 	packets *= param->iterations;
-	dev_info(&dev->intf->dev,
-		"total %lu msec (%lu packets)\n",
-		(packets * (1 << (desc->bInterval - 1)))
-			/ ((udev->speed == USB_SPEED_HIGH) ? 8 : 1),
-		packets);
+
+	if (context.is_iso) {
+		dev_info(&dev->intf->dev,
+			"iso period %d %sframes, wMaxPacket %d, transactions: %d\n",
+			1 << (desc->bInterval - 1),
+			(udev->speed == USB_SPEED_HIGH) ? "micro" : "",
+			usb_endpoint_maxp(desc) & 0x7ff,
+			1 + (0x3 & (usb_endpoint_maxp(desc) >> 11)));
+
+		dev_info(&dev->intf->dev,
+			"total %lu msec (%lu packets)\n",
+			(packets * (1 << (desc->bInterval - 1)))
+				/ ((udev->speed == USB_SPEED_HIGH) ? 8 : 1),
+			packets);
+	}
 
 	spin_lock_irq(&context.lock);
 	for (i = 0; i < param->sglen; i++) {
@@ -1993,7 +2021,7 @@ test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param,
 		;
 	else if (context.submit_error)
 		status = -EACCES;
-	else if (context.errors > context.packet_count / 10)
+	else if (context.errors > (context.is_iso ? context.packet_count / 10 : 0))
 		status = -EIO;
 	return status;
 
@@ -2015,7 +2043,7 @@ static int test_unaligned_bulk(
 {
 	int retval;
 	struct urb *urb = usbtest_alloc_urb(
-		testdev_to_usbdev(tdev), pipe, length, transfer_flags, 1, 0);
+		testdev_to_usbdev(tdev), pipe, length, transfer_flags, 1, 0, false);
 
 	if (!urb)
 		return -ENOMEM;
@@ -2504,6 +2532,28 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
 		retval = simple_io(dev, urb, param->iterations, 0, 0, "test26");
 		simple_free_urb(urb);
 		break;
+	case 27:
+		if (dev->out_pipe == 0 || param->sglen == 0)
+			break;
+		dev_info(&intf->dev,
+			"TEST 27:  write %d bulk, %d entries of %d bytes\n",
+				param->iterations,
+				param->sglen, param->length);
+		retval = test_iso_queue(dev, param,
+				dev->out_pipe, NULL, 0);
+		break;
+
+	/* iso read tests */
+	case 28:
+		if (dev->in_pipe == 0 || param->sglen == 0)
+			break;
+		dev_info(&intf->dev,
+			"TEST 28:  read %d bulk, %d entries of %d bytes\n",
+				param->iterations,
+				param->sglen, param->length);
+		retval = test_iso_queue(dev, param,
+				dev->in_pipe, NULL, 0);
+		break;
 	}
 	do_gettimeofday(&param->duration);
 	param->duration.tv_sec -= start.tv_sec;
-- 
1.9.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