aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2010-04-05 13:55:58 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-20 16:21:38 -0400
commiteab1cafc3b524b714b0567ab98fc75ace09db98c (patch)
tree854ed5c4cba741efabec933714dac5c68bcbb452
parente9df17eb1408cfafa3d1844bfc7f22c7237b31b8 (diff)
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>
-rw-r--r--Documentation/usb/bulk-streams.txt78
-rw-r--r--drivers/usb/core/hcd.c69
-rw-r--r--drivers/usb/host/xhci-pci.c2
-rw-r--r--include/linux/usb.h10
-rw-r--r--include/linux/usb/hcd.h10
5 files changed, 169 insertions, 0 deletions
diff --git a/Documentation/usb/bulk-streams.txt b/Documentation/usb/bulk-streams.txt
new file mode 100644
index 000000000000..ffc02021863e
--- /dev/null
+++ b/Documentation/usb/bulk-streams.txt
@@ -0,0 +1,78 @@
1Background
2==========
3
4Bulk endpoint streams were added in the USB 3.0 specification. Streams allow a
5device driver to overload a bulk endpoint so that multiple transfers can be
6queued at once.
7
8Streams are defined in sections 4.4.6.4 and 8.12.1.4 of the Universal Serial Bus
93.0 specification at http://www.usb.org/developers/docs/ The USB Attached SCSI
10Protocol, which uses streams to queue multiple SCSI commands, can be found on
11the T10 website (http://t10.org/).
12
13
14Device-side implications
15========================
16
17Once a buffer has been queued to a stream ring, the device is notified (through
18an out-of-band mechanism on another endpoint) that data is ready for that stream
19ID. The device then tells the host which "stream" it wants to start. The host
20can also initiate a transfer on a stream without the device asking, but the
21device can refuse that transfer. Devices can switch between streams at any
22time.
23
24
25Driver implications
26===================
27
28int 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
32Device drivers will call this API to request that the host controller driver
33allocate memory so the driver can use up to num_streams stream IDs. They must
34pass an array of usb_host_endpoints that need to be setup with similar stream
35IDs. This is to ensure that a UASP driver will be able to use the same stream
36ID for the bulk IN and OUT endpoints used in a Bi-directional command sequence.
37
38The return value is an error condition (if one of the endpoints doesn't support
39streams, or the xHCI driver ran out of memory), or the number of streams the
40host controller allocated for this endpoint. The xHCI host controller hardware
41declares how many stream IDs it can support, and each bulk endpoint on a
42SuperSpeed device will say how many stream IDs it can handle. Therefore,
43drivers should be able to deal with being allocated less stream IDs than they
44requested.
45
46Do NOT call this function if you have URBs enqueued for any of the endpoints
47passed in as arguments. Do not call this function to request less than two
48streams.
49
50Drivers will only be allowed to call this API once for the same endpoint
51without calling usb_free_streams(). This is a simplification for the xHCI host
52controller driver, and may change in the future.
53
54
55Picking new Stream IDs to use
56============================
57
58Stream ID 0 is reserved, and should not be used to communicate with devices. If
59usb_alloc_streams() returns with a value of N, you may use streams 1 though N.
60To queue an URB for a specific stream, set the urb->stream_id value. If the
61endpoint does not support streams, an error will be returned.
62
63Note that new API to choose the next stream ID will have to be added if the xHCI
64driver supports secondary stream IDs.
65
66
67Clean up
68========
69
70If a driver wishes to stop using streams to communicate with the device, it
71should call
72
73void usb_free_streams(struct usb_interface *interface,
74 struct usb_host_endpoint **eps, unsigned int num_eps,
75 gfp_t mem_flags);
76
77All stream IDs will be deallocated when the driver releases the interface, to
78ensure that drivers that don't support streams will be able to use the endpoint.
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 6a05e6934455..3aaee2811f01 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1814,6 +1814,75 @@ void usb_hcd_reset_endpoint(struct usb_device *udev,
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 */
1829int 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}
1852EXPORT_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 */
1864void 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}
1884EXPORT_SYMBOL_GPL(usb_free_streams);
1885
1817/* Protect against drivers that try to unlink URBs after the device 1886/* Protect against drivers that try to unlink URBs after the device
1818 * is gone, by waiting until all unlinks for @udev are finished. 1887 * is gone, by waiting until all unlinks for @udev are finished.
1819 * Since we don't currently track URBs by device, simply wait until 1888 * Since we don't currently track URBs by device, simply wait until
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 98a73cd20cc6..d295bbc15eb7 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -132,6 +132,8 @@ static const struct hc_driver xhci_pci_hc_driver = {
132 .urb_dequeue = xhci_urb_dequeue, 132 .urb_dequeue = xhci_urb_dequeue,
133 .alloc_dev = xhci_alloc_dev, 133 .alloc_dev = xhci_alloc_dev,
134 .free_dev = xhci_free_dev, 134 .free_dev = xhci_free_dev,
135 .alloc_streams = xhci_alloc_streams,
136 .free_streams = xhci_free_streams,
135 .add_endpoint = xhci_add_endpoint, 137 .add_endpoint = xhci_add_endpoint,
136 .drop_endpoint = xhci_drop_endpoint, 138 .drop_endpoint = xhci_drop_endpoint,
137 .endpoint_reset = xhci_endpoint_reset, 139 .endpoint_reset = xhci_endpoint_reset,
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 191af498c4f5..1ea25377ca0d 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -570,6 +570,16 @@ static inline void usb_mark_last_busy(struct usb_device *udev)
570/* for drivers using iso endpoints */ 570/* for drivers using iso endpoints */
571extern int usb_get_current_frame_number(struct usb_device *usb_dev); 571extern 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. */
574extern 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. */
579extern 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/* used these for multi-interface device registration */ 583/* used these for multi-interface device registration */
574extern int usb_driver_claim_interface(struct usb_driver *driver, 584extern int usb_driver_claim_interface(struct usb_driver *driver,
575 struct usb_interface *iface, void *priv); 585 struct usb_interface *iface, void *priv);
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index d268415b7a40..aca73a5c3af7 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -250,6 +250,16 @@ struct hc_driver {
250 int (*alloc_dev)(struct usb_hcd *, struct usb_device *); 250 int (*alloc_dev)(struct usb_hcd *, struct usb_device *);
251 /* Called by usb_disconnect to free HC device structures */ 251 /* Called by usb_disconnect to free HC device structures */
252 void (*free_dev)(struct usb_hcd *, struct usb_device *); 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 /* Bandwidth computation functions */ 264 /* Bandwidth computation functions */
255 /* Note that add_endpoint() can only be called once per endpoint before 265 /* Note that add_endpoint() can only be called once per endpoint before