Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: usbtest: Add TEST 29, toggle sync, Clear toggle between bulk writes

Clear Feature Endpoint Halt should reset the data toggle even if the
endpoint isn't halted. Host should manage to clear the host side data
toggle to keep in sync with the device.

Test by sending a "3 data packet URB" before and after clearing the halt.
this should create a toggle sequence with two consecutive DATA0 packets.

A successful test sequence looks like this
ClearFeature(ENDPOINT_HALT) - initial toggle clear
DATA0 (max packet sized)
DATA1 (max packet sized)
DATA0 (zero length packet)
ClearFeature(ENDPOINT_HALT) - resets toggle
DATA0 (max packet sized), if clear halt fails then toggle is DATA1
DATA1 (max packet sized)
DATA0 (zero length packet)

Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Mathias Nyman and committed by
Greg Kroah-Hartman
cc2e60df 886ee36e

+70
+70
drivers/usb/misc/usbtest.c
··· 1710 1710 return 0; 1711 1711 } 1712 1712 1713 + static int test_toggle_sync(struct usbtest_dev *tdev, int ep, struct urb *urb) 1714 + { 1715 + int retval; 1716 + 1717 + /* clear initial data toggle to DATA0 */ 1718 + retval = usb_clear_halt(urb->dev, urb->pipe); 1719 + if (retval < 0) { 1720 + ERROR(tdev, "ep %02x couldn't clear halt, %d\n", ep, retval); 1721 + return retval; 1722 + } 1723 + 1724 + /* transfer 3 data packets, should be DATA0, DATA1, DATA0 */ 1725 + retval = simple_io(tdev, urb, 1, 0, 0, __func__); 1726 + if (retval != 0) 1727 + return -EINVAL; 1728 + 1729 + /* clear halt resets device side data toggle, host should react to it */ 1730 + retval = usb_clear_halt(urb->dev, urb->pipe); 1731 + if (retval < 0) { 1732 + ERROR(tdev, "ep %02x couldn't clear halt, %d\n", ep, retval); 1733 + return retval; 1734 + } 1735 + 1736 + /* host should use DATA0 again after clear halt */ 1737 + retval = simple_io(tdev, urb, 1, 0, 0, __func__); 1738 + 1739 + return retval; 1740 + } 1741 + 1713 1742 static int halt_simple(struct usbtest_dev *dev) 1714 1743 { 1715 1744 int ep; ··· 1767 1738 retval = test_halt(dev, ep, urb); 1768 1739 } 1769 1740 done: 1741 + simple_free_urb(urb); 1742 + return retval; 1743 + } 1744 + 1745 + static int toggle_sync_simple(struct usbtest_dev *dev) 1746 + { 1747 + int ep; 1748 + int retval = 0; 1749 + struct urb *urb; 1750 + struct usb_device *udev = testdev_to_usbdev(dev); 1751 + unsigned maxp = get_maxpacket(udev, dev->out_pipe); 1752 + 1753 + /* 1754 + * Create a URB that causes a transfer of uneven amount of data packets 1755 + * This way the clear toggle has an impact on the data toggle sequence. 1756 + * Use 2 maxpacket length packets and one zero packet. 1757 + */ 1758 + urb = simple_alloc_urb(udev, 0, 2 * maxp, 0); 1759 + if (urb == NULL) 1760 + return -ENOMEM; 1761 + 1762 + urb->transfer_flags |= URB_ZERO_PACKET; 1763 + 1764 + ep = usb_pipeendpoint(dev->out_pipe); 1765 + urb->pipe = dev->out_pipe; 1766 + retval = test_toggle_sync(dev, ep, urb); 1767 + 1770 1768 simple_free_urb(urb); 1771 1769 return retval; 1772 1770 } ··· 2579 2523 param->sglen * param->length) / (1024 * 1024)); 2580 2524 retval = test_queue(dev, param, 2581 2525 dev->in_pipe, NULL, 0); 2526 + break; 2527 + /* Test data Toggle/seq_nr clear between bulk out transfers */ 2528 + case 29: 2529 + if (dev->out_pipe == 0) 2530 + break; 2531 + retval = 0; 2532 + dev_info(&intf->dev, "TEST 29: Clear toggle between bulk writes %d times\n", 2533 + param->iterations); 2534 + for (i = param->iterations; retval == 0 && i > 0; --i) 2535 + retval = toggle_sync_simple(dev); 2536 + 2537 + if (retval) 2538 + ERROR(dev, "toggle sync failed, iterations left %d\n", 2539 + i); 2582 2540 break; 2583 2541 } 2584 2542 return retval;