@@ -1810,6 +1810,22 @@ static int xhci_check_tt_bw_table(struct xhci_hcd *xhci,
1810
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
1830
* This algorithm is a very conservative estimate of the worst-case scheduling
1815
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
1882
unsigned int packets_remaining = 0 ;
1867
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
1888
if (virt_dev -> udev -> speed == USB_SPEED_HIGH ) {
1870
1889
max_bandwidth = HS_BW_LIMIT ;
1871
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
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
2069
void xhci_drop_ep_from_interval_table (struct xhci_hcd * xhci ,
2032
2070
struct xhci_bw_info * ep_bw ,
2033
2071
struct xhci_interval_bw_table * bw_table ,
@@ -2038,10 +2076,24 @@ void xhci_drop_ep_from_interval_table(struct xhci_hcd *xhci,
2038
2076
struct xhci_interval_bw * interval_bw ;
2039
2077
int normalized_interval ;
2040
2078
2041
- if (xhci_is_async_ep (ep_bw -> type ) ||
2042
- list_empty (& virt_ep -> bw_endpoint_list ))
2079
+ if (xhci_is_async_ep (ep_bw -> type ))
2043
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
2097
/* For LS/FS devices, we need to translate the interval expressed in
2046
2098
* microframes to frames.
2047
2099
*/
@@ -2091,6 +2143,16 @@ static void xhci_add_ep_to_interval_table(struct xhci_hcd *xhci,
2091
2143
if (xhci_is_async_ep (ep_bw -> type ))
2092
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
2156
/* For LS/FS devices, we need to translate the interval expressed in
2095
2157
* microframes to frames.
2096
2158
*/
@@ -2169,9 +2231,6 @@ static int xhci_reserve_bandwidth(struct xhci_hcd *xhci,
2169
2231
struct xhci_input_control_ctx * ctrl_ctx ;
2170
2232
int old_active_eps = 0 ;
2171
2233
2172
- if (virt_dev -> udev -> speed == USB_SPEED_SUPER )
2173
- return 0 ;
2174
-
2175
2234
if (virt_dev -> tt_info )
2176
2235
old_active_eps = virt_dev -> tt_info -> active_eps ;
2177
2236
0 commit comments