aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/hcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core/hcd.c')
-rw-r--r--drivers/usb/core/hcd.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 6a05e693445..3aaee2811f0 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