1
2
3
4
5
6
7
8
9#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/slab.h>
12
13#include "xhci.h"
14#include "xhci-mtk.h"
15
16#define SSP_BW_BOUNDARY 130000
17#define SS_BW_BOUNDARY 51000
18
19#define HS_BW_BOUNDARY 6144
20
21#define FS_PAYLOAD_MAX 188
22
23
24
25
26#define TT_MICROFRAMES_MAX 9
27
28#define DBG_BUF_EN 64
29
30
31#define ESCH_SS_Y6 1001
32#define ESCH_SS_OVERLAP 1002
33#define ESCH_CS_OVERFLOW 1003
34#define ESCH_BW_OVERFLOW 1004
35#define ESCH_FIXME 1005
36
37
38#define EP_BPKTS(p) ((p) & 0x7f)
39#define EP_BCSCOUNT(p) (((p) & 0x7) << 8)
40#define EP_BBM(p) ((p) << 11)
41#define EP_BOFFSET(p) ((p) & 0x3fff)
42#define EP_BREPEAT(p) (((p) & 0x7fff) << 16)
43
44static char *sch_error_string(int err_num)
45{
46 switch (err_num) {
47 case ESCH_SS_Y6:
48 return "Can't schedule Start-Split in Y6";
49 case ESCH_SS_OVERLAP:
50 return "Can't find a suitable Start-Split location";
51 case ESCH_CS_OVERFLOW:
52 return "The last Complete-Split is greater than 7";
53 case ESCH_BW_OVERFLOW:
54 return "Bandwidth exceeds the maximum limit";
55 case ESCH_FIXME:
56 return "FIXME, to be resolved";
57 default:
58 return "Unknown";
59 }
60}
61
62static int is_fs_or_ls(enum usb_device_speed speed)
63{
64 return speed == USB_SPEED_FULL || speed == USB_SPEED_LOW;
65}
66
67static const char *
68decode_ep(struct usb_host_endpoint *ep, enum usb_device_speed speed)
69{
70 static char buf[DBG_BUF_EN];
71 struct usb_endpoint_descriptor *epd = &ep->desc;
72 unsigned int interval;
73 const char *unit;
74
75 interval = usb_decode_interval(epd, speed);
76 if (interval % 1000) {
77 unit = "us";
78 } else {
79 unit = "ms";
80 interval /= 1000;
81 }
82
83 snprintf(buf, DBG_BUF_EN, "%s ep%d%s %s, mpkt:%d, interval:%d/%d%s",
84 usb_speed_string(speed), usb_endpoint_num(epd),
85 usb_endpoint_dir_in(epd) ? "in" : "out",
86 usb_ep_type_string(usb_endpoint_type(epd)),
87 usb_endpoint_maxp(epd), epd->bInterval, interval, unit);
88
89 return buf;
90}
91
92static u32 get_bw_boundary(enum usb_device_speed speed)
93{
94 u32 boundary;
95
96 switch (speed) {
97 case USB_SPEED_SUPER_PLUS:
98 boundary = SSP_BW_BOUNDARY;
99 break;
100 case USB_SPEED_SUPER:
101 boundary = SS_BW_BOUNDARY;
102 break;
103 default:
104 boundary = HS_BW_BOUNDARY;
105 break;
106 }
107
108 return boundary;
109}
110
111
112
113
114
115
116
117
118
119
120
121
122
123static struct mu3h_sch_bw_info *
124get_bw_info(struct xhci_hcd_mtk *mtk, struct usb_device *udev,
125 struct usb_host_endpoint *ep)
126{
127 struct xhci_hcd *xhci = hcd_to_xhci(mtk->hcd);
128 struct xhci_virt_device *virt_dev;
129 int bw_index;
130
131 virt_dev = xhci->devs[udev->slot_id];
132 if (!virt_dev->real_port) {
133 WARN_ONCE(1, "%s invalid real_port\n", dev_name(&udev->dev));
134 return NULL;
135 }
136
137 if (udev->speed >= USB_SPEED_SUPER) {
138 if (usb_endpoint_dir_out(&ep->desc))
139 bw_index = (virt_dev->real_port - 1) * 2;
140 else
141 bw_index = (virt_dev->real_port - 1) * 2 + 1;
142 } else {
143
144 bw_index = virt_dev->real_port + xhci->usb3_rhub.num_ports - 1;
145 }
146
147 return &mtk->sch_array[bw_index];
148}
149
150static u32 get_esit(struct xhci_ep_ctx *ep_ctx)
151{
152 u32 esit;
153
154 esit = 1 << CTX_TO_EP_INTERVAL(le32_to_cpu(ep_ctx->ep_info));
155 if (esit > XHCI_MTK_MAX_ESIT)
156 esit = XHCI_MTK_MAX_ESIT;
157
158 return esit;
159}
160
161static struct mu3h_sch_tt *find_tt(struct usb_device *udev)
162{
163 struct usb_tt *utt = udev->tt;
164 struct mu3h_sch_tt *tt, **tt_index, **ptt;
165 bool allocated_index = false;
166
167 if (!utt)
168 return NULL;
169
170
171
172
173
174
175 tt_index = NULL;
176 if (utt->multi) {
177 tt_index = utt->hcpriv;
178 if (!tt_index) {
179 tt_index = kcalloc(utt->hub->maxchild,
180 sizeof(*tt_index), GFP_KERNEL);
181 if (!tt_index)
182 return ERR_PTR(-ENOMEM);
183 utt->hcpriv = tt_index;
184 allocated_index = true;
185 }
186 ptt = &tt_index[udev->ttport - 1];
187 } else {
188 ptt = (struct mu3h_sch_tt **) &utt->hcpriv;
189 }
190
191 tt = *ptt;
192 if (!tt) {
193 tt = kzalloc(sizeof(*tt), GFP_KERNEL);
194 if (!tt) {
195 if (allocated_index) {
196 utt->hcpriv = NULL;
197 kfree(tt_index);
198 }
199 return ERR_PTR(-ENOMEM);
200 }
201 INIT_LIST_HEAD(&tt->ep_list);
202 *ptt = tt;
203 }
204
205 return tt;
206}
207
208
209static void drop_tt(struct usb_device *udev)
210{
211 struct usb_tt *utt = udev->tt;
212 struct mu3h_sch_tt *tt, **tt_index, **ptt;
213 int i, cnt;
214
215 if (!utt || !utt->hcpriv)
216 return;
217
218 cnt = 0;
219 if (utt->multi) {
220 tt_index = utt->hcpriv;
221 ptt = &tt_index[udev->ttport - 1];
222
223 for (i = 0; i < utt->hub->maxchild; ++i)
224 cnt += !!tt_index[i];
225 } else {
226 tt_index = NULL;
227 ptt = (struct mu3h_sch_tt **)&utt->hcpriv;
228 }
229
230 tt = *ptt;
231 if (!tt || !list_empty(&tt->ep_list))
232 return;
233
234 *ptt = NULL;
235 kfree(tt);
236
237 if (cnt == 1) {
238 utt->hcpriv = NULL;
239 kfree(tt_index);
240 }
241}
242
243static struct mu3h_sch_ep_info *
244create_sch_ep(struct xhci_hcd_mtk *mtk, struct usb_device *udev,
245 struct usb_host_endpoint *ep, struct xhci_ep_ctx *ep_ctx)
246{
247 struct mu3h_sch_ep_info *sch_ep;
248 struct mu3h_sch_bw_info *bw_info;
249 struct mu3h_sch_tt *tt = NULL;
250 u32 len_bw_budget_table;
251 size_t mem_size;
252
253 bw_info = get_bw_info(mtk, udev, ep);
254 if (!bw_info)
255 return ERR_PTR(-ENODEV);
256
257 if (is_fs_or_ls(udev->speed))
258 len_bw_budget_table = TT_MICROFRAMES_MAX;
259 else if ((udev->speed >= USB_SPEED_SUPER)
260 && usb_endpoint_xfer_isoc(&ep->desc))
261 len_bw_budget_table = get_esit(ep_ctx);
262 else
263 len_bw_budget_table = 1;
264
265 mem_size = sizeof(struct mu3h_sch_ep_info) +
266 len_bw_budget_table * sizeof(u32);
267 sch_ep = kzalloc(mem_size, GFP_KERNEL);
268 if (!sch_ep)
269 return ERR_PTR(-ENOMEM);
270
271 if (is_fs_or_ls(udev->speed)) {
272 tt = find_tt(udev);
273 if (IS_ERR(tt)) {
274 kfree(sch_ep);
275 return ERR_PTR(-ENOMEM);
276 }
277 }
278
279 sch_ep->bw_info = bw_info;
280 sch_ep->sch_tt = tt;
281 sch_ep->ep = ep;
282 sch_ep->speed = udev->speed;
283 INIT_LIST_HEAD(&sch_ep->endpoint);
284 INIT_LIST_HEAD(&sch_ep->tt_endpoint);
285 INIT_HLIST_NODE(&sch_ep->hentry);
286
287 return sch_ep;
288}
289
290static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
291 struct mu3h_sch_ep_info *sch_ep)
292{
293 u32 ep_type;
294 u32 maxpkt;
295 u32 max_burst;
296 u32 mult;
297 u32 esit_pkts;
298 u32 max_esit_payload;
299 u32 *bwb_table = sch_ep->bw_budget_table;
300 int i;
301
302 ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2));
303 maxpkt = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
304 max_burst = CTX_TO_MAX_BURST(le32_to_cpu(ep_ctx->ep_info2));
305 mult = CTX_TO_EP_MULT(le32_to_cpu(ep_ctx->ep_info));
306 max_esit_payload =
307 (CTX_TO_MAX_ESIT_PAYLOAD_HI(
308 le32_to_cpu(ep_ctx->ep_info)) << 16) |
309 CTX_TO_MAX_ESIT_PAYLOAD(le32_to_cpu(ep_ctx->tx_info));
310
311 sch_ep->esit = get_esit(ep_ctx);
312 sch_ep->num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
313 sch_ep->ep_type = ep_type;
314 sch_ep->maxpkt = maxpkt;
315 sch_ep->offset = 0;
316 sch_ep->burst_mode = 0;
317 sch_ep->repeat = 0;
318
319 if (sch_ep->speed == USB_SPEED_HIGH) {
320 sch_ep->cs_count = 0;
321
322
323
324
325
326
327 sch_ep->num_budget_microframes = 1;
328
329
330
331
332
333
334 sch_ep->pkts = max_burst + 1;
335 sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts;
336 bwb_table[0] = sch_ep->bw_cost_per_microframe;
337 } else if (sch_ep->speed >= USB_SPEED_SUPER) {
338
339 sch_ep->cs_count = 0;
340 sch_ep->burst_mode = 1;
341
342
343
344
345
346 esit_pkts = DIV_ROUND_UP(max_esit_payload, maxpkt);
347 if (esit_pkts == 0)
348 esit_pkts = (mult + 1) * (max_burst + 1);
349
350 if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) {
351 sch_ep->pkts = esit_pkts;
352 sch_ep->num_budget_microframes = 1;
353 bwb_table[0] = maxpkt * sch_ep->pkts;
354 }
355
356 if (ep_type == ISOC_IN_EP || ep_type == ISOC_OUT_EP) {
357
358 if (sch_ep->esit == 1)
359 sch_ep->pkts = esit_pkts;
360 else if (esit_pkts <= sch_ep->esit)
361 sch_ep->pkts = 1;
362 else
363 sch_ep->pkts = roundup_pow_of_two(esit_pkts)
364 / sch_ep->esit;
365
366 sch_ep->num_budget_microframes =
367 DIV_ROUND_UP(esit_pkts, sch_ep->pkts);
368
369 sch_ep->repeat = !!(sch_ep->num_budget_microframes > 1);
370 sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts;
371
372 for (i = 0; i < sch_ep->num_budget_microframes - 1; i++)
373 bwb_table[i] = sch_ep->bw_cost_per_microframe;
374
375
376 bwb_table[i] = maxpkt * esit_pkts
377 - i * sch_ep->bw_cost_per_microframe;
378 }
379 } else if (is_fs_or_ls(sch_ep->speed)) {
380 sch_ep->pkts = 1;
381
382
383
384
385
386 sch_ep->cs_count = DIV_ROUND_UP(maxpkt, FS_PAYLOAD_MAX);
387 sch_ep->num_budget_microframes = sch_ep->cs_count;
388 sch_ep->bw_cost_per_microframe =
389 (maxpkt < FS_PAYLOAD_MAX) ? maxpkt : FS_PAYLOAD_MAX;
390
391
392 if (ep_type == ISOC_OUT_EP) {
393 for (i = 0; i < sch_ep->num_budget_microframes; i++)
394 bwb_table[i] = sch_ep->bw_cost_per_microframe;
395 } else if (ep_type == INT_OUT_EP) {
396
397 bwb_table[0] = sch_ep->bw_cost_per_microframe;
398 } else {
399 bwb_table[0] = 0;
400 bwb_table[1] = 0;
401
402
403
404
405
406
407 for (i = 2; i < TT_MICROFRAMES_MAX; i++)
408 bwb_table[i] = sch_ep->bw_cost_per_microframe;
409 }
410 }
411}
412
413
414static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw,
415 struct mu3h_sch_ep_info *sch_ep, u32 offset)
416{
417 u32 max_bw = 0;
418 u32 bw;
419 int i, j, k;
420
421 for (i = 0; i < sch_ep->num_esit; i++) {
422 u32 base = offset + i * sch_ep->esit;
423
424 for (j = 0; j < sch_ep->num_budget_microframes; j++) {
425 k = XHCI_MTK_BW_INDEX(base + j);
426 bw = sch_bw->bus_bw[k] + sch_ep->bw_budget_table[j];
427 if (bw > max_bw)
428 max_bw = bw;
429 }
430 }
431 return max_bw;
432}
433
434static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw,
435 struct mu3h_sch_ep_info *sch_ep, bool used)
436{
437 u32 base;
438 int i, j, k;
439
440 for (i = 0; i < sch_ep->num_esit; i++) {
441 base = sch_ep->offset + i * sch_ep->esit;
442 for (j = 0; j < sch_ep->num_budget_microframes; j++) {
443 k = XHCI_MTK_BW_INDEX(base + j);
444 if (used)
445 sch_bw->bus_bw[k] += sch_ep->bw_budget_table[j];
446 else
447 sch_bw->bus_bw[k] -= sch_ep->bw_budget_table[j];
448 }
449 }
450}
451
452static int check_fs_bus_bw(struct mu3h_sch_ep_info *sch_ep, int offset)
453{
454 struct mu3h_sch_tt *tt = sch_ep->sch_tt;
455 u32 tmp;
456 int base;
457 int i, j, k;
458
459 for (i = 0; i < sch_ep->num_esit; i++) {
460 base = offset + i * sch_ep->esit;
461
462
463
464
465
466 for (j = 0; j < sch_ep->num_budget_microframes; j++) {
467 k = XHCI_MTK_BW_INDEX(base + j);
468 tmp = tt->fs_bus_bw[k] + sch_ep->bw_budget_table[j];
469 if (tmp > FS_PAYLOAD_MAX)
470 return -ESCH_BW_OVERFLOW;
471 }
472 }
473
474 return 0;
475}
476
477static int check_sch_tt(struct mu3h_sch_ep_info *sch_ep, u32 offset)
478{
479 u32 extra_cs_count;
480 u32 start_ss, last_ss;
481 u32 start_cs, last_cs;
482
483 if (!sch_ep->sch_tt)
484 return 0;
485
486 start_ss = offset % 8;
487
488 if (sch_ep->ep_type == ISOC_OUT_EP) {
489 last_ss = start_ss + sch_ep->cs_count - 1;
490
491
492
493
494
495 if (!(start_ss == 7 || last_ss < 6))
496 return -ESCH_SS_Y6;
497
498 } else {
499 u32 cs_count = DIV_ROUND_UP(sch_ep->maxpkt, FS_PAYLOAD_MAX);
500
501
502
503
504
505 if (start_ss == 6)
506 return -ESCH_SS_Y6;
507
508
509 start_cs = (start_ss + 2) % 8;
510 last_cs = start_cs + cs_count - 1;
511
512 if (last_cs > 7)
513 return -ESCH_CS_OVERFLOW;
514
515 if (sch_ep->ep_type == ISOC_IN_EP)
516 extra_cs_count = (last_cs == 7) ? 1 : 2;
517 else
518 extra_cs_count = 1;
519
520 cs_count += extra_cs_count;
521 if (cs_count > 7)
522 cs_count = 7;
523
524 sch_ep->cs_count = cs_count;
525
526 sch_ep->num_budget_microframes = cs_count + 2;
527
528
529
530
531
532 if (sch_ep->num_budget_microframes > sch_ep->esit)
533 sch_ep->num_budget_microframes = sch_ep->esit;
534 }
535
536 return check_fs_bus_bw(sch_ep, offset);
537}
538
539static void update_sch_tt(struct mu3h_sch_ep_info *sch_ep, bool used)
540{
541 struct mu3h_sch_tt *tt = sch_ep->sch_tt;
542 u32 base;
543 int i, j, k;
544
545 for (i = 0; i < sch_ep->num_esit; i++) {
546 base = sch_ep->offset + i * sch_ep->esit;
547
548 for (j = 0; j < sch_ep->num_budget_microframes; j++) {
549 k = XHCI_MTK_BW_INDEX(base + j);
550 if (used)
551 tt->fs_bus_bw[k] += sch_ep->bw_budget_table[j];
552 else
553 tt->fs_bus_bw[k] -= sch_ep->bw_budget_table[j];
554 }
555 }
556
557 if (used)
558 list_add_tail(&sch_ep->tt_endpoint, &tt->ep_list);
559 else
560 list_del(&sch_ep->tt_endpoint);
561}
562
563static int load_ep_bw(struct mu3h_sch_bw_info *sch_bw,
564 struct mu3h_sch_ep_info *sch_ep, bool loaded)
565{
566 if (sch_ep->sch_tt)
567 update_sch_tt(sch_ep, loaded);
568
569
570 update_bus_bw(sch_bw, sch_ep, loaded);
571 sch_ep->allocated = loaded;
572
573 return 0;
574}
575
576static int check_sch_bw(struct mu3h_sch_ep_info *sch_ep)
577{
578 struct mu3h_sch_bw_info *sch_bw = sch_ep->bw_info;
579 const u32 bw_boundary = get_bw_boundary(sch_ep->speed);
580 u32 offset;
581 u32 worst_bw;
582 u32 min_bw = ~0;
583 int min_index = -1;
584 int ret = 0;
585
586
587
588
589
590 for (offset = 0; offset < sch_ep->esit; offset++) {
591 ret = check_sch_tt(sch_ep, offset);
592 if (ret)
593 continue;
594
595 worst_bw = get_max_bw(sch_bw, sch_ep, offset);
596 if (worst_bw > bw_boundary)
597 continue;
598
599 if (min_bw > worst_bw) {
600 min_bw = worst_bw;
601 min_index = offset;
602 }
603
604
605 if (sch_ep->sch_tt && min_index >= 0)
606 break;
607
608 if (min_bw == 0)
609 break;
610 }
611
612 if (min_index < 0)
613 return ret ? ret : -ESCH_BW_OVERFLOW;
614
615 sch_ep->offset = min_index;
616
617 return load_ep_bw(sch_bw, sch_ep, true);
618}
619
620static void destroy_sch_ep(struct xhci_hcd_mtk *mtk, struct usb_device *udev,
621 struct mu3h_sch_ep_info *sch_ep)
622{
623
624 if (sch_ep->allocated)
625 load_ep_bw(sch_ep->bw_info, sch_ep, false);
626
627 if (sch_ep->sch_tt)
628 drop_tt(udev);
629
630 list_del(&sch_ep->endpoint);
631 hlist_del(&sch_ep->hentry);
632 kfree(sch_ep);
633}
634
635static bool need_bw_sch(struct usb_device *udev,
636 struct usb_host_endpoint *ep)
637{
638 bool has_tt = udev->tt && udev->tt->hub->parent;
639
640
641 if (usb_endpoint_xfer_control(&ep->desc)
642 || usb_endpoint_xfer_bulk(&ep->desc))
643 return false;
644
645
646
647
648
649
650 if (is_fs_or_ls(udev->speed) && !has_tt)
651 return false;
652
653
654 if (usb_endpoint_maxp(&ep->desc) == 0)
655 return false;
656
657 return true;
658}
659
660int xhci_mtk_sch_init(struct xhci_hcd_mtk *mtk)
661{
662 struct xhci_hcd *xhci = hcd_to_xhci(mtk->hcd);
663 struct mu3h_sch_bw_info *sch_array;
664 int num_usb_bus;
665
666
667 num_usb_bus = xhci->usb3_rhub.num_ports * 2 + xhci->usb2_rhub.num_ports;
668
669 sch_array = kcalloc(num_usb_bus, sizeof(*sch_array), GFP_KERNEL);
670 if (sch_array == NULL)
671 return -ENOMEM;
672
673 mtk->sch_array = sch_array;
674
675 INIT_LIST_HEAD(&mtk->bw_ep_chk_list);
676 hash_init(mtk->sch_ep_hash);
677
678 return 0;
679}
680
681void xhci_mtk_sch_exit(struct xhci_hcd_mtk *mtk)
682{
683 kfree(mtk->sch_array);
684}
685
686static int add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
687 struct usb_host_endpoint *ep)
688{
689 struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
690 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
691 struct xhci_ep_ctx *ep_ctx;
692 struct xhci_virt_device *virt_dev;
693 struct mu3h_sch_ep_info *sch_ep;
694 unsigned int ep_index;
695
696 virt_dev = xhci->devs[udev->slot_id];
697 ep_index = xhci_get_endpoint_index(&ep->desc);
698 ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
699
700 if (!need_bw_sch(udev, ep)) {
701
702
703
704
705 if (usb_endpoint_xfer_int(&ep->desc)
706 || usb_endpoint_xfer_isoc(&ep->desc))
707 ep_ctx->reserved[0] = cpu_to_le32(EP_BPKTS(1));
708
709 return 0;
710 }
711
712 xhci_dbg(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed));
713
714 sch_ep = create_sch_ep(mtk, udev, ep, ep_ctx);
715 if (IS_ERR_OR_NULL(sch_ep))
716 return -ENOMEM;
717
718 setup_sch_info(ep_ctx, sch_ep);
719
720 list_add_tail(&sch_ep->endpoint, &mtk->bw_ep_chk_list);
721 hash_add(mtk->sch_ep_hash, &sch_ep->hentry, (unsigned long)ep);
722
723 return 0;
724}
725
726static void drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
727 struct usb_host_endpoint *ep)
728{
729 struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
730 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
731 struct mu3h_sch_ep_info *sch_ep;
732 struct hlist_node *hn;
733
734 if (!need_bw_sch(udev, ep))
735 return;
736
737 xhci_err(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed));
738
739 hash_for_each_possible_safe(mtk->sch_ep_hash, sch_ep,
740 hn, hentry, (unsigned long)ep) {
741 if (sch_ep->ep == ep) {
742 destroy_sch_ep(mtk, udev, sch_ep);
743 break;
744 }
745 }
746}
747
748int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
749{
750 struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
751 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
752 struct xhci_virt_device *virt_dev = xhci->devs[udev->slot_id];
753 struct mu3h_sch_ep_info *sch_ep;
754 int ret;
755
756 xhci_dbg(xhci, "%s() udev %s\n", __func__, dev_name(&udev->dev));
757
758 list_for_each_entry(sch_ep, &mtk->bw_ep_chk_list, endpoint) {
759 struct xhci_ep_ctx *ep_ctx;
760 struct usb_host_endpoint *ep = sch_ep->ep;
761 unsigned int ep_index = xhci_get_endpoint_index(&ep->desc);
762
763 ret = check_sch_bw(sch_ep);
764 if (ret) {
765 xhci_err(xhci, "Not enough bandwidth! (%s)\n",
766 sch_error_string(-ret));
767 return -ENOSPC;
768 }
769
770 ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
771 ep_ctx->reserved[0] = cpu_to_le32(EP_BPKTS(sch_ep->pkts)
772 | EP_BCSCOUNT(sch_ep->cs_count)
773 | EP_BBM(sch_ep->burst_mode));
774 ep_ctx->reserved[1] = cpu_to_le32(EP_BOFFSET(sch_ep->offset)
775 | EP_BREPEAT(sch_ep->repeat));
776
777 xhci_dbg(xhci, " PKTS:%x, CSCOUNT:%x, BM:%x, OFFSET:%x, REPEAT:%x\n",
778 sch_ep->pkts, sch_ep->cs_count, sch_ep->burst_mode,
779 sch_ep->offset, sch_ep->repeat);
780 }
781
782 ret = xhci_check_bandwidth(hcd, udev);
783 if (!ret)
784 INIT_LIST_HEAD(&mtk->bw_ep_chk_list);
785
786 return ret;
787}
788
789void xhci_mtk_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
790{
791 struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
792 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
793 struct mu3h_sch_ep_info *sch_ep, *tmp;
794
795 xhci_dbg(xhci, "%s() udev %s\n", __func__, dev_name(&udev->dev));
796
797 list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_chk_list, endpoint)
798 destroy_sch_ep(mtk, udev, sch_ep);
799
800 xhci_reset_bandwidth(hcd, udev);
801}
802
803int xhci_mtk_add_ep(struct usb_hcd *hcd, struct usb_device *udev,
804 struct usb_host_endpoint *ep)
805{
806 int ret;
807
808 ret = xhci_add_endpoint(hcd, udev, ep);
809 if (ret)
810 return ret;
811
812 if (ep->hcpriv)
813 ret = add_ep_quirk(hcd, udev, ep);
814
815 return ret;
816}
817
818int xhci_mtk_drop_ep(struct usb_hcd *hcd, struct usb_device *udev,
819 struct usb_host_endpoint *ep)
820{
821 int ret;
822
823 ret = xhci_drop_endpoint(hcd, udev, ep);
824 if (ret)
825 return ret;
826
827 if (ep->hcpriv)
828 drop_ep_quirk(hcd, udev, ep);
829
830 return 0;
831}
832