aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChunfeng Yun <chunfeng.yun@mediatek.com>2018-09-20 12:13:33 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-09-28 09:04:45 -0400
commit95b516c18621d1626662bc161cbbf6281fd8d767 (patch)
treef4dcb5dc918ede4aefb481a1fd192ce5ec58da9e
parent87173acc0d8f0987bda8827da35fff67f52ad15d (diff)
usb: xhci-mtk: improve bandwidth scheduling
Mainly improve SuperSpeed ISOC bandwidth in last microframe, and LowSpeed/FullSpeed IN INT/ISOC bandwidth in split and idle microframes by introduing a bandwidth budget table; Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/host/xhci-mtk-sch.c162
-rw-r--r--drivers/usb/host/xhci-mtk.h2
2 files changed, 104 insertions, 60 deletions
diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c
index 057f453e06c5..7efd8901b2db 100644
--- a/drivers/usb/host/xhci-mtk-sch.c
+++ b/drivers/usb/host/xhci-mtk-sch.c
@@ -18,6 +18,11 @@
18#define HS_BW_BOUNDARY 6144 18#define HS_BW_BOUNDARY 6144
19/* usb2 spec section11.18.1: at most 188 FS bytes per microframe */ 19/* usb2 spec section11.18.1: at most 188 FS bytes per microframe */
20#define FS_PAYLOAD_MAX 188 20#define FS_PAYLOAD_MAX 188
21/*
22 * max number of microframes for split transfer,
23 * for fs isoc in : 1 ss + 1 idle + 7 cs
24 */
25#define TT_MICROFRAMES_MAX 9
21 26
22/* mtk scheduler bitmasks */ 27/* mtk scheduler bitmasks */
23#define EP_BPKTS(p) ((p) & 0x3f) 28#define EP_BPKTS(p) ((p) & 0x3f)
@@ -64,20 +69,57 @@ static int get_bw_index(struct xhci_hcd *xhci, struct usb_device *udev,
64 return bw_index; 69 return bw_index;
65} 70}
66 71
72static u32 get_esit(struct xhci_ep_ctx *ep_ctx)
73{
74 u32 esit;
75
76 esit = 1 << CTX_TO_EP_INTERVAL(le32_to_cpu(ep_ctx->ep_info));
77 if (esit > XHCI_MTK_MAX_ESIT)
78 esit = XHCI_MTK_MAX_ESIT;
79
80 return esit;
81}
82
83static struct mu3h_sch_ep_info *create_sch_ep(struct usb_device *udev,
84 struct usb_host_endpoint *ep, struct xhci_ep_ctx *ep_ctx)
85{
86 struct mu3h_sch_ep_info *sch_ep;
87 u32 len_bw_budget_table;
88 size_t mem_size;
89
90 if (is_fs_or_ls(udev->speed))
91 len_bw_budget_table = TT_MICROFRAMES_MAX;
92 else if ((udev->speed == USB_SPEED_SUPER)
93 && usb_endpoint_xfer_isoc(&ep->desc))
94 len_bw_budget_table = get_esit(ep_ctx);
95 else
96 len_bw_budget_table = 1;
97
98 mem_size = sizeof(struct mu3h_sch_ep_info) +
99 len_bw_budget_table * sizeof(u32);
100 sch_ep = kzalloc(mem_size, GFP_KERNEL);
101 if (!sch_ep)
102 return ERR_PTR(-ENOMEM);
103
104 sch_ep->ep = ep;
105
106 return sch_ep;
107}
108
67static void setup_sch_info(struct usb_device *udev, 109static void setup_sch_info(struct usb_device *udev,
68 struct xhci_ep_ctx *ep_ctx, struct mu3h_sch_ep_info *sch_ep) 110 struct xhci_ep_ctx *ep_ctx, struct mu3h_sch_ep_info *sch_ep)
69{ 111{
70 u32 ep_type; 112 u32 ep_type;
71 u32 ep_interval; 113 u32 maxpkt;
72 u32 max_packet_size;
73 u32 max_burst; 114 u32 max_burst;
74 u32 mult; 115 u32 mult;
75 u32 esit_pkts; 116 u32 esit_pkts;
76 u32 max_esit_payload; 117 u32 max_esit_payload;
118 u32 *bwb_table = sch_ep->bw_budget_table;
119 int i;
77 120
78 ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2)); 121 ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2));
79 ep_interval = CTX_TO_EP_INTERVAL(le32_to_cpu(ep_ctx->ep_info)); 122 maxpkt = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
80 max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
81 max_burst = CTX_TO_MAX_BURST(le32_to_cpu(ep_ctx->ep_info2)); 123 max_burst = CTX_TO_MAX_BURST(le32_to_cpu(ep_ctx->ep_info2));
82 mult = CTX_TO_EP_MULT(le32_to_cpu(ep_ctx->ep_info)); 124 mult = CTX_TO_EP_MULT(le32_to_cpu(ep_ctx->ep_info));
83 max_esit_payload = 125 max_esit_payload =
@@ -85,9 +127,10 @@ static void setup_sch_info(struct usb_device *udev,
85 le32_to_cpu(ep_ctx->ep_info)) << 16) | 127 le32_to_cpu(ep_ctx->ep_info)) << 16) |
86 CTX_TO_MAX_ESIT_PAYLOAD(le32_to_cpu(ep_ctx->tx_info)); 128 CTX_TO_MAX_ESIT_PAYLOAD(le32_to_cpu(ep_ctx->tx_info));
87 129
88 sch_ep->esit = 1 << ep_interval; 130 sch_ep->esit = get_esit(ep_ctx);
89 sch_ep->offset = 0; 131 sch_ep->offset = 0;
90 sch_ep->burst_mode = 0; 132 sch_ep->burst_mode = 0;
133 sch_ep->repeat = 0;
91 134
92 if (udev->speed == USB_SPEED_HIGH) { 135 if (udev->speed == USB_SPEED_HIGH) {
93 sch_ep->cs_count = 0; 136 sch_ep->cs_count = 0;
@@ -98,7 +141,6 @@ static void setup_sch_info(struct usb_device *udev,
98 * in a interval 141 * in a interval
99 */ 142 */
100 sch_ep->num_budget_microframes = 1; 143 sch_ep->num_budget_microframes = 1;
101 sch_ep->repeat = 0;
102 144
103 /* 145 /*
104 * xHCI spec section6.2.3.4 146 * xHCI spec section6.2.3.4
@@ -106,26 +148,30 @@ static void setup_sch_info(struct usb_device *udev,
106 * opportunities per microframe 148 * opportunities per microframe
107 */ 149 */
108 sch_ep->pkts = max_burst + 1; 150 sch_ep->pkts = max_burst + 1;
109 sch_ep->bw_cost_per_microframe = max_packet_size * sch_ep->pkts; 151 sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts;
152 bwb_table[0] = sch_ep->bw_cost_per_microframe;
110 } else if (udev->speed == USB_SPEED_SUPER) { 153 } else if (udev->speed == USB_SPEED_SUPER) {
111 /* usb3_r1 spec section4.4.7 & 4.4.8 */ 154 /* usb3_r1 spec section4.4.7 & 4.4.8 */
112 sch_ep->cs_count = 0; 155 sch_ep->cs_count = 0;
156 sch_ep->burst_mode = 1;
113 /* 157 /*
114 * some device's (d)wBytesPerInterval is set as 0, 158 * some device's (d)wBytesPerInterval is set as 0,
115 * then max_esit_payload is 0, so evaluate esit_pkts from 159 * then max_esit_payload is 0, so evaluate esit_pkts from
116 * mult and burst 160 * mult and burst
117 */ 161 */
118 esit_pkts = DIV_ROUND_UP(max_esit_payload, max_packet_size); 162 esit_pkts = DIV_ROUND_UP(max_esit_payload, maxpkt);
119 if (esit_pkts == 0) 163 if (esit_pkts == 0)
120 esit_pkts = (mult + 1) * (max_burst + 1); 164 esit_pkts = (mult + 1) * (max_burst + 1);
121 165
122 if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) { 166 if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) {
123 sch_ep->pkts = esit_pkts; 167 sch_ep->pkts = esit_pkts;
124 sch_ep->num_budget_microframes = 1; 168 sch_ep->num_budget_microframes = 1;
125 sch_ep->repeat = 0; 169 bwb_table[0] = maxpkt * sch_ep->pkts;
126 } 170 }
127 171
128 if (ep_type == ISOC_IN_EP || ep_type == ISOC_OUT_EP) { 172 if (ep_type == ISOC_IN_EP || ep_type == ISOC_OUT_EP) {
173 u32 remainder;
174
129 if (sch_ep->esit == 1) 175 if (sch_ep->esit == 1)
130 sch_ep->pkts = esit_pkts; 176 sch_ep->pkts = esit_pkts;
131 else if (esit_pkts <= sch_ep->esit) 177 else if (esit_pkts <= sch_ep->esit)
@@ -137,43 +183,37 @@ static void setup_sch_info(struct usb_device *udev,
137 sch_ep->num_budget_microframes = 183 sch_ep->num_budget_microframes =
138 DIV_ROUND_UP(esit_pkts, sch_ep->pkts); 184 DIV_ROUND_UP(esit_pkts, sch_ep->pkts);
139 185
140 if (sch_ep->num_budget_microframes > 1) 186 sch_ep->repeat = !!(sch_ep->num_budget_microframes > 1);
141 sch_ep->repeat = 1; 187 sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts;
142 else 188
143 sch_ep->repeat = 0; 189 remainder = sch_ep->bw_cost_per_microframe;
190 remainder *= sch_ep->num_budget_microframes;
191 remainder -= (maxpkt * esit_pkts);
192 for (i = 0; i < sch_ep->num_budget_microframes - 1; i++)
193 bwb_table[i] = sch_ep->bw_cost_per_microframe;
194
195 /* last one <= bw_cost_per_microframe */
196 bwb_table[i] = remainder;
144 } 197 }
145 sch_ep->bw_cost_per_microframe = max_packet_size * sch_ep->pkts;
146 } else if (is_fs_or_ls(udev->speed)) { 198 } else if (is_fs_or_ls(udev->speed)) {
147
148 /*
149 * usb_20 spec section11.18.4
150 * assume worst cases
151 */
152 sch_ep->repeat = 0;
153 sch_ep->pkts = 1; /* at most one packet for each microframe */ 199 sch_ep->pkts = 1; /* at most one packet for each microframe */
154 if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) { 200 sch_ep->cs_count = DIV_ROUND_UP(maxpkt, FS_PAYLOAD_MAX);
155 sch_ep->cs_count = 3; /* at most need 3 CS*/ 201 sch_ep->num_budget_microframes = sch_ep->cs_count + 2;
156 /* one for SS and one for budgeted transaction */ 202 sch_ep->bw_cost_per_microframe =
157 sch_ep->num_budget_microframes = sch_ep->cs_count + 2; 203 (maxpkt < FS_PAYLOAD_MAX) ? maxpkt : FS_PAYLOAD_MAX;
158 sch_ep->bw_cost_per_microframe = max_packet_size;
159 }
160 if (ep_type == ISOC_OUT_EP) {
161 204
162 /* 205 /* init budget table */
163 * the best case FS budget assumes that 188 FS bytes 206 if (ep_type == ISOC_OUT_EP) {
164 * occur in each microframe 207 for (i = 0; i < sch_ep->num_budget_microframes; i++)
165 */ 208 bwb_table[i] = sch_ep->bw_cost_per_microframe;
166 sch_ep->num_budget_microframes = DIV_ROUND_UP( 209 } else if (ep_type == INT_OUT_EP) {
167 max_packet_size, FS_PAYLOAD_MAX); 210 /* only first one consumes bandwidth, others as zero */
168 sch_ep->bw_cost_per_microframe = FS_PAYLOAD_MAX; 211 bwb_table[0] = sch_ep->bw_cost_per_microframe;
169 sch_ep->cs_count = sch_ep->num_budget_microframes; 212 } else { /* INT_IN_EP or ISOC_IN_EP */
170 } 213 bwb_table[0] = 0; /* start split */
171 if (ep_type == ISOC_IN_EP) { 214 bwb_table[1] = 0; /* idle */
172 /* at most need additional two CS. */ 215 for (i = 2; i < sch_ep->num_budget_microframes; i++)
173 sch_ep->cs_count = DIV_ROUND_UP( 216 bwb_table[i] = sch_ep->bw_cost_per_microframe;
174 max_packet_size, FS_PAYLOAD_MAX) + 2;
175 sch_ep->num_budget_microframes = sch_ep->cs_count + 2;
176 sch_ep->bw_cost_per_microframe = FS_PAYLOAD_MAX;
177 } 217 }
178 } 218 }
179} 219}
@@ -184,6 +224,7 @@ static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw,
184{ 224{
185 u32 num_esit; 225 u32 num_esit;
186 u32 max_bw = 0; 226 u32 max_bw = 0;
227 u32 bw;
187 int i; 228 int i;
188 int j; 229 int j;
189 230
@@ -192,15 +233,17 @@ static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw,
192 u32 base = offset + i * sch_ep->esit; 233 u32 base = offset + i * sch_ep->esit;
193 234
194 for (j = 0; j < sch_ep->num_budget_microframes; j++) { 235 for (j = 0; j < sch_ep->num_budget_microframes; j++) {
195 if (sch_bw->bus_bw[base + j] > max_bw) 236 bw = sch_bw->bus_bw[base + j] +
196 max_bw = sch_bw->bus_bw[base + j]; 237 sch_ep->bw_budget_table[j];
238 if (bw > max_bw)
239 max_bw = bw;
197 } 240 }
198 } 241 }
199 return max_bw; 242 return max_bw;
200} 243}
201 244
202static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw, 245static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw,
203 struct mu3h_sch_ep_info *sch_ep, int bw_cost) 246 struct mu3h_sch_ep_info *sch_ep, bool used)
204{ 247{
205 u32 num_esit; 248 u32 num_esit;
206 u32 base; 249 u32 base;
@@ -210,8 +253,14 @@ static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw,
210 num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit; 253 num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
211 for (i = 0; i < num_esit; i++) { 254 for (i = 0; i < num_esit; i++) {
212 base = sch_ep->offset + i * sch_ep->esit; 255 base = sch_ep->offset + i * sch_ep->esit;
213 for (j = 0; j < sch_ep->num_budget_microframes; j++) 256 for (j = 0; j < sch_ep->num_budget_microframes; j++) {
214 sch_bw->bus_bw[base + j] += bw_cost; 257 if (used)
258 sch_bw->bus_bw[base + j] +=
259 sch_ep->bw_budget_table[j];
260 else
261 sch_bw->bus_bw[base + j] -=
262 sch_ep->bw_budget_table[j];
263 }
215 } 264 }
216} 265}
217 266
@@ -220,17 +269,12 @@ static int check_sch_bw(struct usb_device *udev,
220{ 269{
221 u32 offset; 270 u32 offset;
222 u32 esit; 271 u32 esit;
223 u32 num_budget_microframes;
224 u32 min_bw; 272 u32 min_bw;
225 u32 min_index; 273 u32 min_index;
226 u32 worst_bw; 274 u32 worst_bw;
227 u32 bw_boundary; 275 u32 bw_boundary;
228 276
229 if (sch_ep->esit > XHCI_MTK_MAX_ESIT)
230 sch_ep->esit = XHCI_MTK_MAX_ESIT;
231
232 esit = sch_ep->esit; 277 esit = sch_ep->esit;
233 num_budget_microframes = sch_ep->num_budget_microframes;
234 278
235 /* 279 /*
236 * Search through all possible schedule microframes. 280 * Search through all possible schedule microframes.
@@ -239,7 +283,7 @@ static int check_sch_bw(struct usb_device *udev,
239 min_bw = ~0; 283 min_bw = ~0;
240 min_index = 0; 284 min_index = 0;
241 for (offset = 0; offset < esit; offset++) { 285 for (offset = 0; offset < esit; offset++) {
242 if ((offset + num_budget_microframes) > sch_ep->esit) 286 if ((offset + sch_ep->num_budget_microframes) > sch_ep->esit)
243 break; 287 break;
244 288
245 /* 289 /*
@@ -263,11 +307,11 @@ static int check_sch_bw(struct usb_device *udev,
263 ? SS_BW_BOUNDARY : HS_BW_BOUNDARY; 307 ? SS_BW_BOUNDARY : HS_BW_BOUNDARY;
264 308
265 /* check bandwidth */ 309 /* check bandwidth */
266 if (min_bw + sch_ep->bw_cost_per_microframe > bw_boundary) 310 if (min_bw > bw_boundary)
267 return -ERANGE; 311 return -ERANGE;
268 312
269 /* update bus bandwidth info */ 313 /* update bus bandwidth info */
270 update_bus_bw(sch_bw, sch_ep, sch_ep->bw_cost_per_microframe); 314 update_bus_bw(sch_bw, sch_ep, 1);
271 315
272 return 0; 316 return 0;
273} 317}
@@ -362,8 +406,8 @@ int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
362 bw_index = get_bw_index(xhci, udev, ep); 406 bw_index = get_bw_index(xhci, udev, ep);
363 sch_bw = &sch_array[bw_index]; 407 sch_bw = &sch_array[bw_index];
364 408
365 sch_ep = kzalloc(sizeof(struct mu3h_sch_ep_info), GFP_NOIO); 409 sch_ep = create_sch_ep(udev, ep, ep_ctx);
366 if (!sch_ep) 410 if (IS_ERR_OR_NULL(sch_ep))
367 return -ENOMEM; 411 return -ENOMEM;
368 412
369 setup_sch_info(udev, ep_ctx, sch_ep); 413 setup_sch_info(udev, ep_ctx, sch_ep);
@@ -376,7 +420,6 @@ int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
376 } 420 }
377 421
378 list_add_tail(&sch_ep->endpoint, &sch_bw->bw_ep_list); 422 list_add_tail(&sch_ep->endpoint, &sch_bw->bw_ep_list);
379 sch_ep->ep = ep;
380 423
381 ep_ctx->reserved[0] |= cpu_to_le32(EP_BPKTS(sch_ep->pkts) 424 ep_ctx->reserved[0] |= cpu_to_le32(EP_BPKTS(sch_ep->pkts)
382 | EP_BCSCOUNT(sch_ep->cs_count) | EP_BBM(sch_ep->burst_mode)); 425 | EP_BCSCOUNT(sch_ep->cs_count) | EP_BBM(sch_ep->burst_mode));
@@ -421,8 +464,7 @@ void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
421 464
422 list_for_each_entry(sch_ep, &sch_bw->bw_ep_list, endpoint) { 465 list_for_each_entry(sch_ep, &sch_bw->bw_ep_list, endpoint) {
423 if (sch_ep->ep == ep) { 466 if (sch_ep->ep == ep) {
424 update_bus_bw(sch_bw, sch_ep, 467 update_bus_bw(sch_bw, sch_ep, 0);
425 -sch_ep->bw_cost_per_microframe);
426 list_del(&sch_ep->endpoint); 468 list_del(&sch_ep->endpoint);
427 kfree(sch_ep); 469 kfree(sch_ep);
428 break; 470 break;
diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h
index cc59d80b663b..f8864fcbd461 100644
--- a/drivers/usb/host/xhci-mtk.h
+++ b/drivers/usb/host/xhci-mtk.h
@@ -57,6 +57,7 @@ struct mu3h_sch_bw_info {
57 * times; 1: distribute the (bMaxBurst+1)*(Mult+1) packets 57 * times; 1: distribute the (bMaxBurst+1)*(Mult+1) packets
58 * according to @pkts and @repeat. normal mode is used by 58 * according to @pkts and @repeat. normal mode is used by
59 * default 59 * default
60 * @bw_budget_table: table to record bandwidth budget per microframe
60 */ 61 */
61struct mu3h_sch_ep_info { 62struct mu3h_sch_ep_info {
62 u32 esit; 63 u32 esit;
@@ -73,6 +74,7 @@ struct mu3h_sch_ep_info {
73 u32 pkts; 74 u32 pkts;
74 u32 cs_count; 75 u32 cs_count;
75 u32 burst_mode; 76 u32 burst_mode;
77 u32 bw_budget_table[0];
76}; 78};
77 79
78#define MU3C_U3_PORT_MAX 4 80#define MU3C_U3_PORT_MAX 4