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 <[email protected]>
---

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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to