1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2015 MediaTek Inc.
5 * Zhigang.Wei <zhigang.wei@mediatek.com>
6 * Chunfeng.Yun <chunfeng.yun@mediatek.com>
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/slab.h>
16 #define SSP_BW_BOUNDARY 130000
17 #define SS_BW_BOUNDARY 51000
18 /* table 5-5. High-speed Isoc Transaction Limits in usb_20 spec */
19 #define HS_BW_BOUNDARY 6144
20 /* usb2 spec section11.18.1: at most 188 FS bytes per microframe */
21 #define FS_PAYLOAD_MAX 188
23 * max number of microframes for split transfer,
24 * for fs isoc in : 1 ss + 1 idle + 7 cs
26 #define TT_MICROFRAMES_MAX 9
28 /* mtk scheduler bitmasks */
29 #define EP_BPKTS(p) ((p) & 0x7f)
30 #define EP_BCSCOUNT(p) (((p) & 0x7) << 8)
31 #define EP_BBM(p) ((p) << 11)
32 #define EP_BOFFSET(p) ((p) & 0x3fff)
33 #define EP_BREPEAT(p) (((p) & 0x7fff) << 16)
35 static int is_fs_or_ls(enum usb_device_speed speed
)
37 return speed
== USB_SPEED_FULL
|| speed
== USB_SPEED_LOW
;
41 * get the index of bandwidth domains array which @ep belongs to.
43 * the bandwidth domain array is saved to @sch_array of struct xhci_hcd_mtk,
44 * each HS root port is treated as a single bandwidth domain,
45 * but each SS root port is treated as two bandwidth domains, one for IN eps,
47 * @real_port value is defined as follow according to xHCI spec:
48 * 1 for SSport0, ..., N+1 for SSportN, N+2 for HSport0, N+3 for HSport1, etc
49 * so the bandwidth domain array is organized as follow for simplification:
50 * SSport0-OUT, SSport0-IN, ..., SSportX-OUT, SSportX-IN, HSport0, ..., HSportY
52 static int get_bw_index(struct xhci_hcd
*xhci
, struct usb_device
*udev
,
53 struct usb_host_endpoint
*ep
)
55 struct xhci_virt_device
*virt_dev
;
58 virt_dev
= xhci
->devs
[udev
->slot_id
];
60 if (udev
->speed
>= USB_SPEED_SUPER
) {
61 if (usb_endpoint_dir_out(&ep
->desc
))
62 bw_index
= (virt_dev
->real_port
- 1) * 2;
64 bw_index
= (virt_dev
->real_port
- 1) * 2 + 1;
66 /* add one more for each SS port */
67 bw_index
= virt_dev
->real_port
+ xhci
->usb3_rhub
.num_ports
- 1;
73 static u32
get_esit(struct xhci_ep_ctx
*ep_ctx
)
77 esit
= 1 << CTX_TO_EP_INTERVAL(le32_to_cpu(ep_ctx
->ep_info
));
78 if (esit
> XHCI_MTK_MAX_ESIT
)
79 esit
= XHCI_MTK_MAX_ESIT
;
84 static struct mu3h_sch_tt
*find_tt(struct usb_device
*udev
)
86 struct usb_tt
*utt
= udev
->tt
;
87 struct mu3h_sch_tt
*tt
, **tt_index
, **ptt
;
89 bool allocated_index
= false;
92 return NULL
; /* Not below a TT */
95 * Find/create our data structure.
96 * For hubs with a single TT, we get it directly.
97 * For hubs with multiple TTs, there's an extra level of pointers.
101 tt_index
= utt
->hcpriv
;
102 if (!tt_index
) { /* Create the index array */
103 tt_index
= kcalloc(utt
->hub
->maxchild
,
104 sizeof(*tt_index
), GFP_KERNEL
);
106 return ERR_PTR(-ENOMEM
);
107 utt
->hcpriv
= tt_index
;
108 allocated_index
= true;
110 port
= udev
->ttport
- 1;
111 ptt
= &tt_index
[port
];
114 ptt
= (struct mu3h_sch_tt
**) &utt
->hcpriv
;
118 if (!tt
) { /* Create the mu3h_sch_tt */
119 tt
= kzalloc(sizeof(*tt
), GFP_KERNEL
);
121 if (allocated_index
) {
125 return ERR_PTR(-ENOMEM
);
127 INIT_LIST_HEAD(&tt
->ep_list
);
136 /* Release the TT above udev, if it's not in use */
137 static void drop_tt(struct usb_device
*udev
)
139 struct usb_tt
*utt
= udev
->tt
;
140 struct mu3h_sch_tt
*tt
, **tt_index
, **ptt
;
143 if (!utt
|| !utt
->hcpriv
)
144 return; /* Not below a TT, or never allocated */
148 tt_index
= utt
->hcpriv
;
149 ptt
= &tt_index
[udev
->ttport
- 1];
150 /* How many entries are left in tt_index? */
151 for (i
= 0; i
< utt
->hub
->maxchild
; ++i
)
152 cnt
+= !!tt_index
[i
];
155 ptt
= (struct mu3h_sch_tt
**)&utt
->hcpriv
;
159 if (!tt
|| !list_empty(&tt
->ep_list
))
160 return; /* never allocated , or still in use*/
171 static struct mu3h_sch_ep_info
*create_sch_ep(struct usb_device
*udev
,
172 struct usb_host_endpoint
*ep
, struct xhci_ep_ctx
*ep_ctx
)
174 struct mu3h_sch_ep_info
*sch_ep
;
175 struct mu3h_sch_tt
*tt
= NULL
;
176 u32 len_bw_budget_table
;
179 if (is_fs_or_ls(udev
->speed
))
180 len_bw_budget_table
= TT_MICROFRAMES_MAX
;
181 else if ((udev
->speed
>= USB_SPEED_SUPER
)
182 && usb_endpoint_xfer_isoc(&ep
->desc
))
183 len_bw_budget_table
= get_esit(ep_ctx
);
185 len_bw_budget_table
= 1;
187 mem_size
= sizeof(struct mu3h_sch_ep_info
) +
188 len_bw_budget_table
* sizeof(u32
);
189 sch_ep
= kzalloc(mem_size
, GFP_KERNEL
);
191 return ERR_PTR(-ENOMEM
);
193 if (is_fs_or_ls(udev
->speed
)) {
197 return ERR_PTR(-ENOMEM
);
207 static void setup_sch_info(struct usb_device
*udev
,
208 struct xhci_ep_ctx
*ep_ctx
, struct mu3h_sch_ep_info
*sch_ep
)
215 u32 max_esit_payload
;
216 u32
*bwb_table
= sch_ep
->bw_budget_table
;
219 ep_type
= CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx
->ep_info2
));
220 maxpkt
= MAX_PACKET_DECODED(le32_to_cpu(ep_ctx
->ep_info2
));
221 max_burst
= CTX_TO_MAX_BURST(le32_to_cpu(ep_ctx
->ep_info2
));
222 mult
= CTX_TO_EP_MULT(le32_to_cpu(ep_ctx
->ep_info
));
224 (CTX_TO_MAX_ESIT_PAYLOAD_HI(
225 le32_to_cpu(ep_ctx
->ep_info
)) << 16) |
226 CTX_TO_MAX_ESIT_PAYLOAD(le32_to_cpu(ep_ctx
->tx_info
));
228 sch_ep
->esit
= get_esit(ep_ctx
);
229 sch_ep
->ep_type
= ep_type
;
230 sch_ep
->maxpkt
= maxpkt
;
232 sch_ep
->burst_mode
= 0;
235 if (udev
->speed
== USB_SPEED_HIGH
) {
236 sch_ep
->cs_count
= 0;
239 * usb_20 spec section5.9
240 * a single microframe is enough for HS synchromous endpoints
243 sch_ep
->num_budget_microframes
= 1;
246 * xHCI spec section6.2.3.4
247 * @max_burst is the number of additional transactions
248 * opportunities per microframe
250 sch_ep
->pkts
= max_burst
+ 1;
251 sch_ep
->bw_cost_per_microframe
= maxpkt
* sch_ep
->pkts
;
252 bwb_table
[0] = sch_ep
->bw_cost_per_microframe
;
253 } else if (udev
->speed
>= USB_SPEED_SUPER
) {
254 /* usb3_r1 spec section4.4.7 & 4.4.8 */
255 sch_ep
->cs_count
= 0;
256 sch_ep
->burst_mode
= 1;
258 * some device's (d)wBytesPerInterval is set as 0,
259 * then max_esit_payload is 0, so evaluate esit_pkts from
262 esit_pkts
= DIV_ROUND_UP(max_esit_payload
, maxpkt
);
264 esit_pkts
= (mult
+ 1) * (max_burst
+ 1);
266 if (ep_type
== INT_IN_EP
|| ep_type
== INT_OUT_EP
) {
267 sch_ep
->pkts
= esit_pkts
;
268 sch_ep
->num_budget_microframes
= 1;
269 bwb_table
[0] = maxpkt
* sch_ep
->pkts
;
272 if (ep_type
== ISOC_IN_EP
|| ep_type
== ISOC_OUT_EP
) {
275 if (sch_ep
->esit
== 1)
276 sch_ep
->pkts
= esit_pkts
;
277 else if (esit_pkts
<= sch_ep
->esit
)
280 sch_ep
->pkts
= roundup_pow_of_two(esit_pkts
)
283 sch_ep
->num_budget_microframes
=
284 DIV_ROUND_UP(esit_pkts
, sch_ep
->pkts
);
286 sch_ep
->repeat
= !!(sch_ep
->num_budget_microframes
> 1);
287 sch_ep
->bw_cost_per_microframe
= maxpkt
* sch_ep
->pkts
;
289 remainder
= sch_ep
->bw_cost_per_microframe
;
290 remainder
*= sch_ep
->num_budget_microframes
;
291 remainder
-= (maxpkt
* esit_pkts
);
292 for (i
= 0; i
< sch_ep
->num_budget_microframes
- 1; i
++)
293 bwb_table
[i
] = sch_ep
->bw_cost_per_microframe
;
295 /* last one <= bw_cost_per_microframe */
296 bwb_table
[i
] = remainder
;
298 } else if (is_fs_or_ls(udev
->speed
)) {
299 sch_ep
->pkts
= 1; /* at most one packet for each microframe */
302 * num_budget_microframes and cs_count will be updated when
303 * check TT for INT_OUT_EP, ISOC/INT_IN_EP type
305 sch_ep
->cs_count
= DIV_ROUND_UP(maxpkt
, FS_PAYLOAD_MAX
);
306 sch_ep
->num_budget_microframes
= sch_ep
->cs_count
;
307 sch_ep
->bw_cost_per_microframe
=
308 (maxpkt
< FS_PAYLOAD_MAX
) ? maxpkt
: FS_PAYLOAD_MAX
;
310 /* init budget table */
311 if (ep_type
== ISOC_OUT_EP
) {
312 for (i
= 0; i
< sch_ep
->num_budget_microframes
; i
++)
313 bwb_table
[i
] = sch_ep
->bw_cost_per_microframe
;
314 } else if (ep_type
== INT_OUT_EP
) {
315 /* only first one consumes bandwidth, others as zero */
316 bwb_table
[0] = sch_ep
->bw_cost_per_microframe
;
317 } else { /* INT_IN_EP or ISOC_IN_EP */
318 bwb_table
[0] = 0; /* start split */
319 bwb_table
[1] = 0; /* idle */
321 * due to cs_count will be updated according to cs
322 * position, assign all remainder budget array
323 * elements as @bw_cost_per_microframe, but only first
324 * @num_budget_microframes elements will be used later
326 for (i
= 2; i
< TT_MICROFRAMES_MAX
; i
++)
327 bwb_table
[i
] = sch_ep
->bw_cost_per_microframe
;
332 /* Get maximum bandwidth when we schedule at offset slot. */
333 static u32
get_max_bw(struct mu3h_sch_bw_info
*sch_bw
,
334 struct mu3h_sch_ep_info
*sch_ep
, u32 offset
)
342 num_esit
= XHCI_MTK_MAX_ESIT
/ sch_ep
->esit
;
343 for (i
= 0; i
< num_esit
; i
++) {
344 u32 base
= offset
+ i
* sch_ep
->esit
;
346 for (j
= 0; j
< sch_ep
->num_budget_microframes
; j
++) {
347 bw
= sch_bw
->bus_bw
[base
+ j
] +
348 sch_ep
->bw_budget_table
[j
];
356 static void update_bus_bw(struct mu3h_sch_bw_info
*sch_bw
,
357 struct mu3h_sch_ep_info
*sch_ep
, bool used
)
364 num_esit
= XHCI_MTK_MAX_ESIT
/ sch_ep
->esit
;
365 for (i
= 0; i
< num_esit
; i
++) {
366 base
= sch_ep
->offset
+ i
* sch_ep
->esit
;
367 for (j
= 0; j
< sch_ep
->num_budget_microframes
; j
++) {
369 sch_bw
->bus_bw
[base
+ j
] +=
370 sch_ep
->bw_budget_table
[j
];
372 sch_bw
->bus_bw
[base
+ j
] -=
373 sch_ep
->bw_budget_table
[j
];
378 static int check_sch_tt(struct usb_device
*udev
,
379 struct mu3h_sch_ep_info
*sch_ep
, u32 offset
)
381 struct mu3h_sch_tt
*tt
= sch_ep
->sch_tt
;
384 u32 start_ss
, last_ss
;
385 u32 start_cs
, last_cs
;
388 start_ss
= offset
% 8;
389 fs_budget_start
= (start_ss
+ 1) % 8;
391 if (sch_ep
->ep_type
== ISOC_OUT_EP
) {
392 last_ss
= start_ss
+ sch_ep
->cs_count
- 1;
395 * usb_20 spec section11.18:
396 * must never schedule Start-Split in Y6
398 if (!(start_ss
== 7 || last_ss
< 6))
401 for (i
= 0; i
< sch_ep
->cs_count
; i
++)
402 if (test_bit(offset
+ i
, tt
->split_bit_map
))
406 u32 cs_count
= DIV_ROUND_UP(sch_ep
->maxpkt
, FS_PAYLOAD_MAX
);
409 * usb_20 spec section11.18:
410 * must never schedule Start-Split in Y6
415 /* one uframe for ss + one uframe for idle */
416 start_cs
= (start_ss
+ 2) % 8;
417 last_cs
= start_cs
+ cs_count
- 1;
422 if (sch_ep
->ep_type
== ISOC_IN_EP
)
423 extra_cs_count
= (last_cs
== 7) ? 1 : 2;
424 else /* ep_type : INTR IN / INTR OUT */
425 extra_cs_count
= (fs_budget_start
== 6) ? 1 : 2;
427 cs_count
+= extra_cs_count
;
429 cs_count
= 7; /* HW limit */
431 for (i
= 0; i
< cs_count
+ 2; i
++) {
432 if (test_bit(offset
+ i
, tt
->split_bit_map
))
436 sch_ep
->cs_count
= cs_count
;
437 /* one for ss, the other for idle */
438 sch_ep
->num_budget_microframes
= cs_count
+ 2;
441 * if interval=1, maxp >752, num_budge_micoframe is larger
442 * than sch_ep->esit, will overstep boundary
444 if (sch_ep
->num_budget_microframes
> sch_ep
->esit
)
445 sch_ep
->num_budget_microframes
= sch_ep
->esit
;
451 static void update_sch_tt(struct usb_device
*udev
,
452 struct mu3h_sch_ep_info
*sch_ep
)
454 struct mu3h_sch_tt
*tt
= sch_ep
->sch_tt
;
458 num_esit
= XHCI_MTK_MAX_ESIT
/ sch_ep
->esit
;
459 for (i
= 0; i
< num_esit
; i
++) {
460 base
= sch_ep
->offset
+ i
* sch_ep
->esit
;
461 for (j
= 0; j
< sch_ep
->num_budget_microframes
; j
++)
462 set_bit(base
+ j
, tt
->split_bit_map
);
465 list_add_tail(&sch_ep
->tt_endpoint
, &tt
->ep_list
);
468 static int check_sch_bw(struct usb_device
*udev
,
469 struct mu3h_sch_bw_info
*sch_bw
, struct mu3h_sch_ep_info
*sch_ep
)
479 bool tt_offset_ok
= false;
485 * Search through all possible schedule microframes.
486 * and find a microframe where its worst bandwidth is minimum.
490 min_cs_count
= sch_ep
->cs_count
;
491 min_num_budget
= sch_ep
->num_budget_microframes
;
492 for (offset
= 0; offset
< esit
; offset
++) {
493 if (is_fs_or_ls(udev
->speed
)) {
494 ret
= check_sch_tt(udev
, sch_ep
, offset
);
501 if ((offset
+ sch_ep
->num_budget_microframes
) > sch_ep
->esit
)
504 worst_bw
= get_max_bw(sch_bw
, sch_ep
, offset
);
505 if (min_bw
> worst_bw
) {
508 min_cs_count
= sch_ep
->cs_count
;
509 min_num_budget
= sch_ep
->num_budget_microframes
;
515 if (udev
->speed
== USB_SPEED_SUPER_PLUS
)
516 bw_boundary
= SSP_BW_BOUNDARY
;
517 else if (udev
->speed
== USB_SPEED_SUPER
)
518 bw_boundary
= SS_BW_BOUNDARY
;
520 bw_boundary
= HS_BW_BOUNDARY
;
522 /* check bandwidth */
523 if (min_bw
> bw_boundary
)
526 sch_ep
->offset
= min_index
;
527 sch_ep
->cs_count
= min_cs_count
;
528 sch_ep
->num_budget_microframes
= min_num_budget
;
530 if (is_fs_or_ls(udev
->speed
)) {
531 /* all offset for tt is not ok*/
535 update_sch_tt(udev
, sch_ep
);
538 /* update bus bandwidth info */
539 update_bus_bw(sch_bw
, sch_ep
, 1);
544 static bool need_bw_sch(struct usb_host_endpoint
*ep
,
545 enum usb_device_speed speed
, int has_tt
)
547 /* only for periodic endpoints */
548 if (usb_endpoint_xfer_control(&ep
->desc
)
549 || usb_endpoint_xfer_bulk(&ep
->desc
))
553 * for LS & FS periodic endpoints which its device is not behind
554 * a TT are also ignored, root-hub will schedule them directly,
555 * but need set @bpkts field of endpoint context to 1.
557 if (is_fs_or_ls(speed
) && !has_tt
)
563 int xhci_mtk_sch_init(struct xhci_hcd_mtk
*mtk
)
565 struct xhci_hcd
*xhci
= hcd_to_xhci(mtk
->hcd
);
566 struct mu3h_sch_bw_info
*sch_array
;
570 /* ss IN and OUT are separated */
571 num_usb_bus
= xhci
->usb3_rhub
.num_ports
* 2 + xhci
->usb2_rhub
.num_ports
;
573 sch_array
= kcalloc(num_usb_bus
, sizeof(*sch_array
), GFP_KERNEL
);
574 if (sch_array
== NULL
)
577 for (i
= 0; i
< num_usb_bus
; i
++)
578 INIT_LIST_HEAD(&sch_array
[i
].bw_ep_list
);
580 mtk
->sch_array
= sch_array
;
584 EXPORT_SYMBOL_GPL(xhci_mtk_sch_init
);
586 void xhci_mtk_sch_exit(struct xhci_hcd_mtk
*mtk
)
588 kfree(mtk
->sch_array
);
590 EXPORT_SYMBOL_GPL(xhci_mtk_sch_exit
);
592 int xhci_mtk_add_ep_quirk(struct usb_hcd
*hcd
, struct usb_device
*udev
,
593 struct usb_host_endpoint
*ep
)
595 struct xhci_hcd_mtk
*mtk
= hcd_to_mtk(hcd
);
596 struct xhci_hcd
*xhci
;
597 struct xhci_ep_ctx
*ep_ctx
;
598 struct xhci_slot_ctx
*slot_ctx
;
599 struct xhci_virt_device
*virt_dev
;
600 struct mu3h_sch_bw_info
*sch_bw
;
601 struct mu3h_sch_ep_info
*sch_ep
;
602 struct mu3h_sch_bw_info
*sch_array
;
603 unsigned int ep_index
;
607 xhci
= hcd_to_xhci(hcd
);
608 virt_dev
= xhci
->devs
[udev
->slot_id
];
609 ep_index
= xhci_get_endpoint_index(&ep
->desc
);
610 slot_ctx
= xhci_get_slot_ctx(xhci
, virt_dev
->in_ctx
);
611 ep_ctx
= xhci_get_ep_ctx(xhci
, virt_dev
->in_ctx
, ep_index
);
612 sch_array
= mtk
->sch_array
;
614 xhci_dbg(xhci
, "%s() type:%d, speed:%d, mpkt:%d, dir:%d, ep:%p\n",
615 __func__
, usb_endpoint_type(&ep
->desc
), udev
->speed
,
616 usb_endpoint_maxp(&ep
->desc
),
617 usb_endpoint_dir_in(&ep
->desc
), ep
);
619 if (!need_bw_sch(ep
, udev
->speed
, slot_ctx
->tt_info
& TT_SLOT
)) {
621 * set @bpkts to 1 if it is LS or FS periodic endpoint, and its
622 * device does not connected through an external HS hub
624 if (usb_endpoint_xfer_int(&ep
->desc
)
625 || usb_endpoint_xfer_isoc(&ep
->desc
))
626 ep_ctx
->reserved
[0] |= cpu_to_le32(EP_BPKTS(1));
631 bw_index
= get_bw_index(xhci
, udev
, ep
);
632 sch_bw
= &sch_array
[bw_index
];
634 sch_ep
= create_sch_ep(udev
, ep
, ep_ctx
);
635 if (IS_ERR_OR_NULL(sch_ep
))
638 setup_sch_info(udev
, ep_ctx
, sch_ep
);
640 ret
= check_sch_bw(udev
, sch_bw
, sch_ep
);
642 xhci_err(xhci
, "Not enough bandwidth!\n");
643 if (is_fs_or_ls(udev
->speed
))
650 list_add_tail(&sch_ep
->endpoint
, &sch_bw
->bw_ep_list
);
652 ep_ctx
->reserved
[0] |= cpu_to_le32(EP_BPKTS(sch_ep
->pkts
)
653 | EP_BCSCOUNT(sch_ep
->cs_count
) | EP_BBM(sch_ep
->burst_mode
));
654 ep_ctx
->reserved
[1] |= cpu_to_le32(EP_BOFFSET(sch_ep
->offset
)
655 | EP_BREPEAT(sch_ep
->repeat
));
657 xhci_dbg(xhci
, " PKTS:%x, CSCOUNT:%x, BM:%x, OFFSET:%x, REPEAT:%x\n",
658 sch_ep
->pkts
, sch_ep
->cs_count
, sch_ep
->burst_mode
,
659 sch_ep
->offset
, sch_ep
->repeat
);
663 EXPORT_SYMBOL_GPL(xhci_mtk_add_ep_quirk
);
665 void xhci_mtk_drop_ep_quirk(struct usb_hcd
*hcd
, struct usb_device
*udev
,
666 struct usb_host_endpoint
*ep
)
668 struct xhci_hcd_mtk
*mtk
= hcd_to_mtk(hcd
);
669 struct xhci_hcd
*xhci
;
670 struct xhci_slot_ctx
*slot_ctx
;
671 struct xhci_virt_device
*virt_dev
;
672 struct mu3h_sch_bw_info
*sch_array
;
673 struct mu3h_sch_bw_info
*sch_bw
;
674 struct mu3h_sch_ep_info
*sch_ep
;
677 xhci
= hcd_to_xhci(hcd
);
678 virt_dev
= xhci
->devs
[udev
->slot_id
];
679 slot_ctx
= xhci_get_slot_ctx(xhci
, virt_dev
->in_ctx
);
680 sch_array
= mtk
->sch_array
;
682 xhci_dbg(xhci
, "%s() type:%d, speed:%d, mpks:%d, dir:%d, ep:%p\n",
683 __func__
, usb_endpoint_type(&ep
->desc
), udev
->speed
,
684 usb_endpoint_maxp(&ep
->desc
),
685 usb_endpoint_dir_in(&ep
->desc
), ep
);
687 if (!need_bw_sch(ep
, udev
->speed
, slot_ctx
->tt_info
& TT_SLOT
))
690 bw_index
= get_bw_index(xhci
, udev
, ep
);
691 sch_bw
= &sch_array
[bw_index
];
693 list_for_each_entry(sch_ep
, &sch_bw
->bw_ep_list
, endpoint
) {
694 if (sch_ep
->ep
== ep
) {
695 update_bus_bw(sch_bw
, sch_ep
, 0);
696 list_del(&sch_ep
->endpoint
);
697 if (is_fs_or_ls(udev
->speed
)) {
698 list_del(&sch_ep
->tt_endpoint
);
706 EXPORT_SYMBOL_GPL(xhci_mtk_drop_ep_quirk
);