diff options
-rw-r--r-- | drivers/usb/host/xhci.c | 69 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 3 |
2 files changed, 67 insertions, 5 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 7583b24c3387..54cb762d15c8 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c | |||
@@ -1810,6 +1810,22 @@ static int xhci_check_tt_bw_table(struct xhci_hcd *xhci, | |||
1810 | return 0; | 1810 | return 0; |
1811 | } | 1811 | } |
1812 | 1812 | ||
1813 | static int xhci_check_ss_bw(struct xhci_hcd *xhci, | ||
1814 | struct xhci_virt_device *virt_dev) | ||
1815 | { | ||
1816 | unsigned int bw_reserved; | ||
1817 | |||
1818 | bw_reserved = DIV_ROUND_UP(SS_BW_RESERVED*SS_BW_LIMIT_IN, 100); | ||
1819 | if (virt_dev->bw_table->ss_bw_in > (SS_BW_LIMIT_IN - bw_reserved)) | ||
1820 | return -ENOMEM; | ||
1821 | |||
1822 | bw_reserved = DIV_ROUND_UP(SS_BW_RESERVED*SS_BW_LIMIT_OUT, 100); | ||
1823 | if (virt_dev->bw_table->ss_bw_out > (SS_BW_LIMIT_OUT - bw_reserved)) | ||
1824 | return -ENOMEM; | ||
1825 | |||
1826 | return 0; | ||
1827 | } | ||
1828 | |||
1813 | /* | 1829 | /* |
1814 | * This algorithm is a very conservative estimate of the worst-case scheduling | 1830 | * This algorithm is a very conservative estimate of the worst-case scheduling |
1815 | * scenario for any one interval. The hardware dynamically schedules the | 1831 | * scenario for any one interval. The hardware dynamically schedules the |
@@ -1866,6 +1882,9 @@ static int xhci_check_bw_table(struct xhci_hcd *xhci, | |||
1866 | unsigned int packets_remaining = 0; | 1882 | unsigned int packets_remaining = 0; |
1867 | unsigned int i; | 1883 | unsigned int i; |
1868 | 1884 | ||
1885 | if (virt_dev->udev->speed == USB_SPEED_SUPER) | ||
1886 | return xhci_check_ss_bw(xhci, virt_dev); | ||
1887 | |||
1869 | if (virt_dev->udev->speed == USB_SPEED_HIGH) { | 1888 | if (virt_dev->udev->speed == USB_SPEED_HIGH) { |
1870 | max_bandwidth = HS_BW_LIMIT; | 1889 | max_bandwidth = HS_BW_LIMIT; |
1871 | /* Convert percent of bus BW reserved to blocks reserved */ | 1890 | /* Convert percent of bus BW reserved to blocks reserved */ |
@@ -2028,6 +2047,25 @@ static bool xhci_is_async_ep(unsigned int ep_type) | |||
2028 | ep_type != INT_IN_EP); | 2047 | ep_type != INT_IN_EP); |
2029 | } | 2048 | } |
2030 | 2049 | ||
2050 | static bool xhci_is_sync_in_ep(unsigned int ep_type) | ||
2051 | { | ||
2052 | return (ep_type == ISOC_IN_EP || ep_type != INT_IN_EP); | ||
2053 | } | ||
2054 | |||
2055 | static unsigned int xhci_get_ss_bw_consumed(struct xhci_bw_info *ep_bw) | ||
2056 | { | ||
2057 | unsigned int mps = DIV_ROUND_UP(ep_bw->max_packet_size, SS_BLOCK); | ||
2058 | |||
2059 | if (ep_bw->ep_interval == 0) | ||
2060 | return SS_OVERHEAD_BURST + | ||
2061 | (ep_bw->mult * ep_bw->num_packets * | ||
2062 | (SS_OVERHEAD + mps)); | ||
2063 | return DIV_ROUND_UP(ep_bw->mult * ep_bw->num_packets * | ||
2064 | (SS_OVERHEAD + mps + SS_OVERHEAD_BURST), | ||
2065 | 1 << ep_bw->ep_interval); | ||
2066 | |||
2067 | } | ||
2068 | |||
2031 | void xhci_drop_ep_from_interval_table(struct xhci_hcd *xhci, | 2069 | void xhci_drop_ep_from_interval_table(struct xhci_hcd *xhci, |
2032 | struct xhci_bw_info *ep_bw, | 2070 | struct xhci_bw_info *ep_bw, |
2033 | struct xhci_interval_bw_table *bw_table, | 2071 | struct xhci_interval_bw_table *bw_table, |
@@ -2038,10 +2076,24 @@ void xhci_drop_ep_from_interval_table(struct xhci_hcd *xhci, | |||
2038 | struct xhci_interval_bw *interval_bw; | 2076 | struct xhci_interval_bw *interval_bw; |
2039 | int normalized_interval; | 2077 | int normalized_interval; |
2040 | 2078 | ||
2041 | if (xhci_is_async_ep(ep_bw->type) || | 2079 | if (xhci_is_async_ep(ep_bw->type)) |
2042 | list_empty(&virt_ep->bw_endpoint_list)) | ||
2043 | return; | 2080 | return; |
2044 | 2081 | ||
2082 | if (udev->speed == USB_SPEED_SUPER) { | ||
2083 | if (xhci_is_sync_in_ep(ep_bw->type)) | ||
2084 | xhci->devs[udev->slot_id]->bw_table->ss_bw_in -= | ||
2085 | xhci_get_ss_bw_consumed(ep_bw); | ||
2086 | else | ||
2087 | xhci->devs[udev->slot_id]->bw_table->ss_bw_out -= | ||
2088 | xhci_get_ss_bw_consumed(ep_bw); | ||
2089 | return; | ||
2090 | } | ||
2091 | |||
2092 | /* SuperSpeed endpoints never get added to intervals in the table, so | ||
2093 | * this check is only valid for HS/FS/LS devices. | ||
2094 | */ | ||
2095 | if (list_empty(&virt_ep->bw_endpoint_list)) | ||
2096 | return; | ||
2045 | /* For LS/FS devices, we need to translate the interval expressed in | 2097 | /* For LS/FS devices, we need to translate the interval expressed in |
2046 | * microframes to frames. | 2098 | * microframes to frames. |
2047 | */ | 2099 | */ |
@@ -2091,6 +2143,16 @@ static void xhci_add_ep_to_interval_table(struct xhci_hcd *xhci, | |||
2091 | if (xhci_is_async_ep(ep_bw->type)) | 2143 | if (xhci_is_async_ep(ep_bw->type)) |
2092 | return; | 2144 | return; |
2093 | 2145 | ||
2146 | if (udev->speed == USB_SPEED_SUPER) { | ||
2147 | if (xhci_is_sync_in_ep(ep_bw->type)) | ||
2148 | xhci->devs[udev->slot_id]->bw_table->ss_bw_in += | ||
2149 | xhci_get_ss_bw_consumed(ep_bw); | ||
2150 | else | ||
2151 | xhci->devs[udev->slot_id]->bw_table->ss_bw_out += | ||
2152 | xhci_get_ss_bw_consumed(ep_bw); | ||
2153 | return; | ||
2154 | } | ||
2155 | |||
2094 | /* For LS/FS devices, we need to translate the interval expressed in | 2156 | /* For LS/FS devices, we need to translate the interval expressed in |
2095 | * microframes to frames. | 2157 | * microframes to frames. |
2096 | */ | 2158 | */ |
@@ -2169,9 +2231,6 @@ static int xhci_reserve_bandwidth(struct xhci_hcd *xhci, | |||
2169 | struct xhci_input_control_ctx *ctrl_ctx; | 2231 | struct xhci_input_control_ctx *ctrl_ctx; |
2170 | int old_active_eps = 0; | 2232 | int old_active_eps = 0; |
2171 | 2233 | ||
2172 | if (virt_dev->udev->speed == USB_SPEED_SUPER) | ||
2173 | return 0; | ||
2174 | |||
2175 | if (virt_dev->tt_info) | 2234 | if (virt_dev->tt_info) |
2176 | old_active_eps = virt_dev->tt_info->active_eps; | 2235 | old_active_eps = virt_dev->tt_info->active_eps; |
2177 | 2236 | ||
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 752a500f8695..2882074eb2c8 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h | |||
@@ -799,6 +799,7 @@ struct xhci_bw_info { | |||
799 | /* Percentage of bus bandwidth reserved for non-periodic transfers */ | 799 | /* Percentage of bus bandwidth reserved for non-periodic transfers */ |
800 | #define FS_BW_RESERVED 10 | 800 | #define FS_BW_RESERVED 10 |
801 | #define HS_BW_RESERVED 20 | 801 | #define HS_BW_RESERVED 20 |
802 | #define SS_BW_RESERVED 10 | ||
802 | 803 | ||
803 | struct xhci_virt_ep { | 804 | struct xhci_virt_ep { |
804 | struct xhci_ring *ring; | 805 | struct xhci_ring *ring; |
@@ -869,6 +870,8 @@ struct xhci_interval_bw_table { | |||
869 | struct xhci_interval_bw interval_bw[XHCI_MAX_INTERVAL]; | 870 | struct xhci_interval_bw interval_bw[XHCI_MAX_INTERVAL]; |
870 | /* Includes reserved bandwidth for async endpoints */ | 871 | /* Includes reserved bandwidth for async endpoints */ |
871 | unsigned int bw_used; | 872 | unsigned int bw_used; |
873 | unsigned int ss_bw_in; | ||
874 | unsigned int ss_bw_out; | ||
872 | }; | 875 | }; |
873 | 876 | ||
874 | 877 | ||