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

USB: Support for allocating USB 3.0 streams.

Bulk endpoint streams were added in the USB 3.0 specification. Streams
allow a device driver to overload a bulk endpoint so that multiple
transfers can be queued at once.

The device then decides which transfer it wants to work on first, and can
queue part of a transfer before it switches to a new stream. All this
switching is invisible to the device driver, which just gets a completion
for the URB. Drivers that use streams must be able to handle URBs
completing in a different order than they were submitted to the endpoint.

This requires adding new API to set up xHCI data structures to support
multiple queues ("stream rings") per endpoint. Drivers will allocate a
number of stream IDs before enqueueing URBs to the bulk endpoints of the
device, and free the stream IDs in their disconnect function. See
Documentation/usb/bulk-streams.txt for details.

The new mass storage device class, USB Attached SCSI Protocol (UASP), uses
these streams API.

Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Sarah Sharp and committed by
Greg Kroah-Hartman
eab1cafc e9df17eb

+169
+78
Documentation/usb/bulk-streams.txt
··· 1 + Background 2 + ========== 3 + 4 + Bulk endpoint streams were added in the USB 3.0 specification. Streams allow a 5 + device driver to overload a bulk endpoint so that multiple transfers can be 6 + queued at once. 7 + 8 + Streams are defined in sections 4.4.6.4 and 8.12.1.4 of the Universal Serial Bus 9 + 3.0 specification at http://www.usb.org/developers/docs/ The USB Attached SCSI 10 + Protocol, which uses streams to queue multiple SCSI commands, can be found on 11 + the T10 website (http://t10.org/). 12 + 13 + 14 + Device-side implications 15 + ======================== 16 + 17 + Once a buffer has been queued to a stream ring, the device is notified (through 18 + an out-of-band mechanism on another endpoint) that data is ready for that stream 19 + ID. The device then tells the host which "stream" it wants to start. The host 20 + can also initiate a transfer on a stream without the device asking, but the 21 + device can refuse that transfer. Devices can switch between streams at any 22 + time. 23 + 24 + 25 + Driver implications 26 + =================== 27 + 28 + int usb_alloc_streams(struct usb_interface *interface, 29 + struct usb_host_endpoint **eps, unsigned int num_eps, 30 + unsigned int num_streams, gfp_t mem_flags); 31 + 32 + Device drivers will call this API to request that the host controller driver 33 + allocate memory so the driver can use up to num_streams stream IDs. They must 34 + pass an array of usb_host_endpoints that need to be setup with similar stream 35 + IDs. This is to ensure that a UASP driver will be able to use the same stream 36 + ID for the bulk IN and OUT endpoints used in a Bi-directional command sequence. 37 + 38 + The return value is an error condition (if one of the endpoints doesn't support 39 + streams, or the xHCI driver ran out of memory), or the number of streams the 40 + host controller allocated for this endpoint. The xHCI host controller hardware 41 + declares how many stream IDs it can support, and each bulk endpoint on a 42 + SuperSpeed device will say how many stream IDs it can handle. Therefore, 43 + drivers should be able to deal with being allocated less stream IDs than they 44 + requested. 45 + 46 + Do NOT call this function if you have URBs enqueued for any of the endpoints 47 + passed in as arguments. Do not call this function to request less than two 48 + streams. 49 + 50 + Drivers will only be allowed to call this API once for the same endpoint 51 + without calling usb_free_streams(). This is a simplification for the xHCI host 52 + controller driver, and may change in the future. 53 + 54 + 55 + Picking new Stream IDs to use 56 + ============================ 57 + 58 + Stream ID 0 is reserved, and should not be used to communicate with devices. If 59 + usb_alloc_streams() returns with a value of N, you may use streams 1 though N. 60 + To queue an URB for a specific stream, set the urb->stream_id value. If the 61 + endpoint does not support streams, an error will be returned. 62 + 63 + Note that new API to choose the next stream ID will have to be added if the xHCI 64 + driver supports secondary stream IDs. 65 + 66 + 67 + Clean up 68 + ======== 69 + 70 + If a driver wishes to stop using streams to communicate with the device, it 71 + should call 72 + 73 + void usb_free_streams(struct usb_interface *interface, 74 + struct usb_host_endpoint **eps, unsigned int num_eps, 75 + gfp_t mem_flags); 76 + 77 + All stream IDs will be deallocated when the driver releases the interface, to 78 + ensure that drivers that don't support streams will be able to use the endpoint.
+69
drivers/usb/core/hcd.c
··· 1814 1814 } 1815 1815 } 1816 1816 1817 + /** 1818 + * usb_alloc_streams - allocate bulk endpoint stream IDs. 1819 + * @interface: alternate setting that includes all endpoints. 1820 + * @eps: array of endpoints that need streams. 1821 + * @num_eps: number of endpoints in the array. 1822 + * @num_streams: number of streams to allocate. 1823 + * @mem_flags: flags hcd should use to allocate memory. 1824 + * 1825 + * Sets up a group of bulk endpoints to have num_streams stream IDs available. 1826 + * Drivers may queue multiple transfers to different stream IDs, which may 1827 + * complete in a different order than they were queued. 1828 + */ 1829 + int usb_alloc_streams(struct usb_interface *interface, 1830 + struct usb_host_endpoint **eps, unsigned int num_eps, 1831 + unsigned int num_streams, gfp_t mem_flags) 1832 + { 1833 + struct usb_hcd *hcd; 1834 + struct usb_device *dev; 1835 + int i; 1836 + 1837 + dev = interface_to_usbdev(interface); 1838 + hcd = bus_to_hcd(dev->bus); 1839 + if (!hcd->driver->alloc_streams || !hcd->driver->free_streams) 1840 + return -EINVAL; 1841 + if (dev->speed != USB_SPEED_SUPER) 1842 + return -EINVAL; 1843 + 1844 + /* Streams only apply to bulk endpoints. */ 1845 + for (i = 0; i < num_eps; i++) 1846 + if (!usb_endpoint_xfer_bulk(&eps[i]->desc)) 1847 + return -EINVAL; 1848 + 1849 + return hcd->driver->alloc_streams(hcd, dev, eps, num_eps, 1850 + num_streams, mem_flags); 1851 + } 1852 + EXPORT_SYMBOL_GPL(usb_alloc_streams); 1853 + 1854 + /** 1855 + * usb_free_streams - free bulk endpoint stream IDs. 1856 + * @interface: alternate setting that includes all endpoints. 1857 + * @eps: array of endpoints to remove streams from. 1858 + * @num_eps: number of endpoints in the array. 1859 + * @mem_flags: flags hcd should use to allocate memory. 1860 + * 1861 + * Reverts a group of bulk endpoints back to not using stream IDs. 1862 + * Can fail if we are given bad arguments, or HCD is broken. 1863 + */ 1864 + void usb_free_streams(struct usb_interface *interface, 1865 + struct usb_host_endpoint **eps, unsigned int num_eps, 1866 + gfp_t mem_flags) 1867 + { 1868 + struct usb_hcd *hcd; 1869 + struct usb_device *dev; 1870 + int i; 1871 + 1872 + dev = interface_to_usbdev(interface); 1873 + hcd = bus_to_hcd(dev->bus); 1874 + if (dev->speed != USB_SPEED_SUPER) 1875 + return; 1876 + 1877 + /* Streams only apply to bulk endpoints. */ 1878 + for (i = 0; i < num_eps; i++) 1879 + if (!usb_endpoint_xfer_bulk(&eps[i]->desc)) 1880 + return; 1881 + 1882 + hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags); 1883 + } 1884 + EXPORT_SYMBOL_GPL(usb_free_streams); 1885 + 1817 1886 /* Protect against drivers that try to unlink URBs after the device 1818 1887 * is gone, by waiting until all unlinks for @udev are finished. 1819 1888 * Since we don't currently track URBs by device, simply wait until
+2
drivers/usb/host/xhci-pci.c
··· 132 132 .urb_dequeue = xhci_urb_dequeue, 133 133 .alloc_dev = xhci_alloc_dev, 134 134 .free_dev = xhci_free_dev, 135 + .alloc_streams = xhci_alloc_streams, 136 + .free_streams = xhci_free_streams, 135 137 .add_endpoint = xhci_add_endpoint, 136 138 .drop_endpoint = xhci_drop_endpoint, 137 139 .endpoint_reset = xhci_endpoint_reset,
+10
include/linux/usb.h
··· 570 570 /* for drivers using iso endpoints */ 571 571 extern int usb_get_current_frame_number(struct usb_device *usb_dev); 572 572 573 + /* Sets up a group of bulk endpoints to support multiple stream IDs. */ 574 + extern int usb_alloc_streams(struct usb_interface *interface, 575 + struct usb_host_endpoint **eps, unsigned int num_eps, 576 + unsigned int num_streams, gfp_t mem_flags); 577 + 578 + /* Reverts a group of bulk endpoints back to not using stream IDs. */ 579 + extern void usb_free_streams(struct usb_interface *interface, 580 + struct usb_host_endpoint **eps, unsigned int num_eps, 581 + gfp_t mem_flags); 582 + 573 583 /* used these for multi-interface device registration */ 574 584 extern int usb_driver_claim_interface(struct usb_driver *driver, 575 585 struct usb_interface *iface, void *priv);
+10
include/linux/usb/hcd.h
··· 250 250 int (*alloc_dev)(struct usb_hcd *, struct usb_device *); 251 251 /* Called by usb_disconnect to free HC device structures */ 252 252 void (*free_dev)(struct usb_hcd *, struct usb_device *); 253 + /* Change a group of bulk endpoints to support multiple stream IDs */ 254 + int (*alloc_streams)(struct usb_hcd *hcd, struct usb_device *udev, 255 + struct usb_host_endpoint **eps, unsigned int num_eps, 256 + unsigned int num_streams, gfp_t mem_flags); 257 + /* Reverts a group of bulk endpoints back to not using stream IDs. 258 + * Can fail if we run out of memory. 259 + */ 260 + int (*free_streams)(struct usb_hcd *hcd, struct usb_device *udev, 261 + struct usb_host_endpoint **eps, unsigned int num_eps, 262 + gfp_t mem_flags); 253 263 254 264 /* Bandwidth computation functions */ 255 265 /* Note that add_endpoint() can only be called once per endpoint before