diff options
| -rw-r--r-- | drivers/usb/core/hcd.c | 34 | ||||
| -rw-r--r-- | include/linux/usb.h | 2 |
2 files changed, 28 insertions, 8 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 9b445f43f825..9c4e2922b04d 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
| @@ -2049,7 +2049,7 @@ int usb_alloc_streams(struct usb_interface *interface, | |||
| 2049 | { | 2049 | { |
| 2050 | struct usb_hcd *hcd; | 2050 | struct usb_hcd *hcd; |
| 2051 | struct usb_device *dev; | 2051 | struct usb_device *dev; |
| 2052 | int i; | 2052 | int i, ret; |
| 2053 | 2053 | ||
| 2054 | dev = interface_to_usbdev(interface); | 2054 | dev = interface_to_usbdev(interface); |
| 2055 | hcd = bus_to_hcd(dev->bus); | 2055 | hcd = bus_to_hcd(dev->bus); |
| @@ -2058,13 +2058,24 @@ int usb_alloc_streams(struct usb_interface *interface, | |||
| 2058 | if (dev->speed != USB_SPEED_SUPER) | 2058 | if (dev->speed != USB_SPEED_SUPER) |
| 2059 | return -EINVAL; | 2059 | return -EINVAL; |
| 2060 | 2060 | ||
| 2061 | /* Streams only apply to bulk endpoints. */ | 2061 | for (i = 0; i < num_eps; i++) { |
| 2062 | for (i = 0; i < num_eps; i++) | 2062 | /* Streams only apply to bulk endpoints. */ |
| 2063 | if (!usb_endpoint_xfer_bulk(&eps[i]->desc)) | 2063 | if (!usb_endpoint_xfer_bulk(&eps[i]->desc)) |
| 2064 | return -EINVAL; | 2064 | return -EINVAL; |
| 2065 | /* Re-alloc is not allowed */ | ||
| 2066 | if (eps[i]->streams) | ||
| 2067 | return -EINVAL; | ||
| 2068 | } | ||
| 2065 | 2069 | ||
| 2066 | return hcd->driver->alloc_streams(hcd, dev, eps, num_eps, | 2070 | ret = hcd->driver->alloc_streams(hcd, dev, eps, num_eps, |
| 2067 | num_streams, mem_flags); | 2071 | num_streams, mem_flags); |
| 2072 | if (ret < 0) | ||
| 2073 | return ret; | ||
| 2074 | |||
| 2075 | for (i = 0; i < num_eps; i++) | ||
| 2076 | eps[i]->streams = ret; | ||
| 2077 | |||
| 2078 | return ret; | ||
| 2068 | } | 2079 | } |
| 2069 | EXPORT_SYMBOL_GPL(usb_alloc_streams); | 2080 | EXPORT_SYMBOL_GPL(usb_alloc_streams); |
| 2070 | 2081 | ||
| @@ -2086,19 +2097,26 @@ int usb_free_streams(struct usb_interface *interface, | |||
| 2086 | { | 2097 | { |
| 2087 | struct usb_hcd *hcd; | 2098 | struct usb_hcd *hcd; |
| 2088 | struct usb_device *dev; | 2099 | struct usb_device *dev; |
| 2089 | int i; | 2100 | int i, ret; |
| 2090 | 2101 | ||
| 2091 | dev = interface_to_usbdev(interface); | 2102 | dev = interface_to_usbdev(interface); |
| 2092 | hcd = bus_to_hcd(dev->bus); | 2103 | hcd = bus_to_hcd(dev->bus); |
| 2093 | if (dev->speed != USB_SPEED_SUPER) | 2104 | if (dev->speed != USB_SPEED_SUPER) |
| 2094 | return -EINVAL; | 2105 | return -EINVAL; |
| 2095 | 2106 | ||
| 2096 | /* Streams only apply to bulk endpoints. */ | 2107 | /* Double-free is not allowed */ |
| 2097 | for (i = 0; i < num_eps; i++) | 2108 | for (i = 0; i < num_eps; i++) |
| 2098 | if (!eps[i] || !usb_endpoint_xfer_bulk(&eps[i]->desc)) | 2109 | if (!eps[i] || !eps[i]->streams) |
| 2099 | return -EINVAL; | 2110 | return -EINVAL; |
| 2100 | 2111 | ||
| 2101 | return hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags); | 2112 | ret = hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags); |
| 2113 | if (ret < 0) | ||
| 2114 | return ret; | ||
| 2115 | |||
| 2116 | for (i = 0; i < num_eps; i++) | ||
| 2117 | eps[i]->streams = 0; | ||
| 2118 | |||
| 2119 | return ret; | ||
| 2102 | } | 2120 | } |
| 2103 | EXPORT_SYMBOL_GPL(usb_free_streams); | 2121 | EXPORT_SYMBOL_GPL(usb_free_streams); |
| 2104 | 2122 | ||
diff --git a/include/linux/usb.h b/include/linux/usb.h index 9b73dd782c09..f1015cee5944 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
| @@ -57,6 +57,7 @@ struct ep_device; | |||
| 57 | * @extra: descriptors following this endpoint in the configuration | 57 | * @extra: descriptors following this endpoint in the configuration |
| 58 | * @extralen: how many bytes of "extra" are valid | 58 | * @extralen: how many bytes of "extra" are valid |
| 59 | * @enabled: URBs may be submitted to this endpoint | 59 | * @enabled: URBs may be submitted to this endpoint |
| 60 | * @streams: number of USB-3 streams allocated on the endpoint | ||
| 60 | * | 61 | * |
| 61 | * USB requests are always queued to a given endpoint, identified by a | 62 | * USB requests are always queued to a given endpoint, identified by a |
| 62 | * descriptor within an active interface in a given USB configuration. | 63 | * descriptor within an active interface in a given USB configuration. |
| @@ -71,6 +72,7 @@ struct usb_host_endpoint { | |||
| 71 | unsigned char *extra; /* Extra descriptors */ | 72 | unsigned char *extra; /* Extra descriptors */ |
| 72 | int extralen; | 73 | int extralen; |
| 73 | int enabled; | 74 | int enabled; |
| 75 | int streams; | ||
| 74 | }; | 76 | }; |
| 75 | 77 | ||
| 76 | /* host-side wrapper for one interface setting's parsed descriptors */ | 78 | /* host-side wrapper for one interface setting's parsed descriptors */ |
