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 SS_BW_BOUNDARY 51000
17 /* table 5-5. High-speed Isoc Transaction Limits in usb_20 spec */
18 #define HS_BW_BOUNDARY 6144
19 /* usb2 spec section11.18.1: at most 188 FS bytes per microframe */
20 #define FS_PAYLOAD_MAX 188
22 /* mtk scheduler bitmasks */
23 #define EP_BPKTS(p) ((p) & 0x3f)
24 #define EP_BCSCOUNT(p) (((p) & 0x7) << 8)
25 #define EP_BBM(p) ((p) << 11)
26 #define EP_BOFFSET(p) ((p) & 0x3fff)
27 #define EP_BREPEAT(p) (((p) & 0x7fff) << 16)
29 static int is_fs_or_ls(enum usb_device_speed speed
)
31 return speed
== USB_SPEED_FULL
|| speed
== USB_SPEED_LOW
;
35 * get the index of bandwidth domains array which @ep belongs to.
37 * the bandwidth domain array is saved to @sch_array of struct xhci_hcd_mtk,
38 * each HS root port is treated as a single bandwidth domain,
39 * but each SS root port is treated as two bandwidth domains, one for IN eps,
41 * @real_port value is defined as follow according to xHCI spec:
42 * 1 for SSport0, ..., N+1 for SSportN, N+2 for HSport0, N+3 for HSport1, etc
43 * so the bandwidth domain array is organized as follow for simplification:
44 * SSport0-OUT, SSport0-IN, ..., SSportX-OUT, SSportX-IN, HSport0, ..., HSportY
46 static int get_bw_index(struct xhci_hcd
*xhci
, struct usb_device
*udev
,
47 struct usb_host_endpoint
*ep
)
49 struct xhci_virt_device
*virt_dev
;
52 virt_dev
= xhci
->devs
[udev
->slot_id
];
54 if (udev
->speed
== USB_SPEED_SUPER
) {
55 if (usb_endpoint_dir_out(&ep
->desc
))
56 bw_index
= (virt_dev
->real_port
- 1) * 2;
58 bw_index
= (virt_dev
->real_port
- 1) * 2 + 1;
60 /* add one more for each SS port */
61 bw_index
= virt_dev
->real_port
+ xhci
->usb3_rhub
.num_ports
- 1;
67 static void setup_sch_info(struct usb_device
*udev
,
68 struct xhci_ep_ctx
*ep_ctx
, struct mu3h_sch_ep_info
*sch_ep
)
77 ep_type
= CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx
->ep_info2
));
78 ep_interval
= CTX_TO_EP_INTERVAL(le32_to_cpu(ep_ctx
->ep_info
));
79 max_packet_size
= MAX_PACKET_DECODED(le32_to_cpu(ep_ctx
->ep_info2
));
80 max_burst
= CTX_TO_MAX_BURST(le32_to_cpu(ep_ctx
->ep_info2
));
81 mult
= CTX_TO_EP_MULT(le32_to_cpu(ep_ctx
->ep_info
));
83 sch_ep
->esit
= 1 << ep_interval
;
85 sch_ep
->burst_mode
= 0;
87 if (udev
->speed
== USB_SPEED_HIGH
) {
91 * usb_20 spec section5.9
92 * a single microframe is enough for HS synchromous endpoints
95 sch_ep
->num_budget_microframes
= 1;
99 * xHCI spec section6.2.3.4
100 * @max_burst is the number of additional transactions
101 * opportunities per microframe
103 sch_ep
->pkts
= max_burst
+ 1;
104 sch_ep
->bw_cost_per_microframe
= max_packet_size
* sch_ep
->pkts
;
105 } else if (udev
->speed
== USB_SPEED_SUPER
) {
106 /* usb3_r1 spec section4.4.7 & 4.4.8 */
107 sch_ep
->cs_count
= 0;
108 esit_pkts
= (mult
+ 1) * (max_burst
+ 1);
109 if (ep_type
== INT_IN_EP
|| ep_type
== INT_OUT_EP
) {
110 sch_ep
->pkts
= esit_pkts
;
111 sch_ep
->num_budget_microframes
= 1;
115 if (ep_type
== ISOC_IN_EP
|| ep_type
== ISOC_OUT_EP
) {
116 if (esit_pkts
<= sch_ep
->esit
)
119 sch_ep
->pkts
= roundup_pow_of_two(esit_pkts
)
122 sch_ep
->num_budget_microframes
=
123 DIV_ROUND_UP(esit_pkts
, sch_ep
->pkts
);
125 if (sch_ep
->num_budget_microframes
> 1)
130 sch_ep
->bw_cost_per_microframe
= max_packet_size
* sch_ep
->pkts
;
131 } else if (is_fs_or_ls(udev
->speed
)) {
134 * usb_20 spec section11.18.4
138 sch_ep
->pkts
= 1; /* at most one packet for each microframe */
139 if (ep_type
== INT_IN_EP
|| ep_type
== INT_OUT_EP
) {
140 sch_ep
->cs_count
= 3; /* at most need 3 CS*/
141 /* one for SS and one for budgeted transaction */
142 sch_ep
->num_budget_microframes
= sch_ep
->cs_count
+ 2;
143 sch_ep
->bw_cost_per_microframe
= max_packet_size
;
145 if (ep_type
== ISOC_OUT_EP
) {
148 * the best case FS budget assumes that 188 FS bytes
149 * occur in each microframe
151 sch_ep
->num_budget_microframes
= DIV_ROUND_UP(
152 max_packet_size
, FS_PAYLOAD_MAX
);
153 sch_ep
->bw_cost_per_microframe
= FS_PAYLOAD_MAX
;
154 sch_ep
->cs_count
= sch_ep
->num_budget_microframes
;
156 if (ep_type
== ISOC_IN_EP
) {
157 /* at most need additional two CS. */
158 sch_ep
->cs_count
= DIV_ROUND_UP(
159 max_packet_size
, FS_PAYLOAD_MAX
) + 2;
160 sch_ep
->num_budget_microframes
= sch_ep
->cs_count
+ 2;
161 sch_ep
->bw_cost_per_microframe
= FS_PAYLOAD_MAX
;
166 /* Get maximum bandwidth when we schedule at offset slot. */
167 static u32
get_max_bw(struct mu3h_sch_bw_info
*sch_bw
,
168 struct mu3h_sch_ep_info
*sch_ep
, u32 offset
)
175 num_esit
= XHCI_MTK_MAX_ESIT
/ sch_ep
->esit
;
176 for (i
= 0; i
< num_esit
; i
++) {
177 u32 base
= offset
+ i
* sch_ep
->esit
;
179 for (j
= 0; j
< sch_ep
->num_budget_microframes
; j
++) {
180 if (sch_bw
->bus_bw
[base
+ j
] > max_bw
)
181 max_bw
= sch_bw
->bus_bw
[base
+ j
];
187 static void update_bus_bw(struct mu3h_sch_bw_info
*sch_bw
,
188 struct mu3h_sch_ep_info
*sch_ep
, int bw_cost
)
195 num_esit
= XHCI_MTK_MAX_ESIT
/ sch_ep
->esit
;
196 for (i
= 0; i
< num_esit
; i
++) {
197 base
= sch_ep
->offset
+ i
* sch_ep
->esit
;
198 for (j
= 0; j
< sch_ep
->num_budget_microframes
; j
++)
199 sch_bw
->bus_bw
[base
+ j
] += bw_cost
;
203 static int check_sch_bw(struct usb_device
*udev
,
204 struct mu3h_sch_bw_info
*sch_bw
, struct mu3h_sch_ep_info
*sch_ep
)
208 u32 num_budget_microframes
;
214 if (sch_ep
->esit
> XHCI_MTK_MAX_ESIT
)
215 sch_ep
->esit
= XHCI_MTK_MAX_ESIT
;
218 num_budget_microframes
= sch_ep
->num_budget_microframes
;
221 * Search through all possible schedule microframes.
222 * and find a microframe where its worst bandwidth is minimum.
226 for (offset
= 0; offset
< esit
; offset
++) {
227 if ((offset
+ num_budget_microframes
) > sch_ep
->esit
)
231 * usb_20 spec section11.18:
232 * must never schedule Start-Split in Y6
234 if (is_fs_or_ls(udev
->speed
) && (offset
% 8 == 6))
237 worst_bw
= get_max_bw(sch_bw
, sch_ep
, offset
);
238 if (min_bw
> worst_bw
) {
245 sch_ep
->offset
= min_index
;
247 bw_boundary
= (udev
->speed
== USB_SPEED_SUPER
)
248 ? SS_BW_BOUNDARY
: HS_BW_BOUNDARY
;
250 /* check bandwidth */
251 if (min_bw
+ sch_ep
->bw_cost_per_microframe
> bw_boundary
)
254 /* update bus bandwidth info */
255 update_bus_bw(sch_bw
, sch_ep
, sch_ep
->bw_cost_per_microframe
);
260 static bool need_bw_sch(struct usb_host_endpoint
*ep
,
261 enum usb_device_speed speed
, int has_tt
)
263 /* only for periodic endpoints */
264 if (usb_endpoint_xfer_control(&ep
->desc
)
265 || usb_endpoint_xfer_bulk(&ep
->desc
))
269 * for LS & FS periodic endpoints which its device is not behind
270 * a TT are also ignored, root-hub will schedule them directly,
271 * but need set @bpkts field of endpoint context to 1.
273 if (is_fs_or_ls(speed
) && !has_tt
)
279 int xhci_mtk_sch_init(struct xhci_hcd_mtk
*mtk
)
281 struct xhci_hcd
*xhci
= hcd_to_xhci(mtk
->hcd
);
282 struct mu3h_sch_bw_info
*sch_array
;
286 /* ss IN and OUT are separated */
287 num_usb_bus
= xhci
->usb3_rhub
.num_ports
* 2 + xhci
->usb2_rhub
.num_ports
;
289 sch_array
= kcalloc(num_usb_bus
, sizeof(*sch_array
), GFP_KERNEL
);
290 if (sch_array
== NULL
)
293 for (i
= 0; i
< num_usb_bus
; i
++)
294 INIT_LIST_HEAD(&sch_array
[i
].bw_ep_list
);
296 mtk
->sch_array
= sch_array
;
300 EXPORT_SYMBOL_GPL(xhci_mtk_sch_init
);
302 void xhci_mtk_sch_exit(struct xhci_hcd_mtk
*mtk
)
304 kfree(mtk
->sch_array
);
306 EXPORT_SYMBOL_GPL(xhci_mtk_sch_exit
);
308 int xhci_mtk_add_ep_quirk(struct usb_hcd
*hcd
, struct usb_device
*udev
,
309 struct usb_host_endpoint
*ep
)
311 struct xhci_hcd_mtk
*mtk
= hcd_to_mtk(hcd
);
312 struct xhci_hcd
*xhci
;
313 struct xhci_ep_ctx
*ep_ctx
;
314 struct xhci_slot_ctx
*slot_ctx
;
315 struct xhci_virt_device
*virt_dev
;
316 struct mu3h_sch_bw_info
*sch_bw
;
317 struct mu3h_sch_ep_info
*sch_ep
;
318 struct mu3h_sch_bw_info
*sch_array
;
319 unsigned int ep_index
;
323 xhci
= hcd_to_xhci(hcd
);
324 virt_dev
= xhci
->devs
[udev
->slot_id
];
325 ep_index
= xhci_get_endpoint_index(&ep
->desc
);
326 slot_ctx
= xhci_get_slot_ctx(xhci
, virt_dev
->in_ctx
);
327 ep_ctx
= xhci_get_ep_ctx(xhci
, virt_dev
->in_ctx
, ep_index
);
328 sch_array
= mtk
->sch_array
;
330 xhci_dbg(xhci
, "%s() type:%d, speed:%d, mpkt:%d, dir:%d, ep:%p\n",
331 __func__
, usb_endpoint_type(&ep
->desc
), udev
->speed
,
332 usb_endpoint_maxp(&ep
->desc
),
333 usb_endpoint_dir_in(&ep
->desc
), ep
);
335 if (!need_bw_sch(ep
, udev
->speed
, slot_ctx
->tt_info
& TT_SLOT
)) {
337 * set @bpkts to 1 if it is LS or FS periodic endpoint, and its
338 * device does not connected through an external HS hub
340 if (usb_endpoint_xfer_int(&ep
->desc
)
341 || usb_endpoint_xfer_isoc(&ep
->desc
))
342 ep_ctx
->reserved
[0] |= cpu_to_le32(EP_BPKTS(1));
347 bw_index
= get_bw_index(xhci
, udev
, ep
);
348 sch_bw
= &sch_array
[bw_index
];
350 sch_ep
= kzalloc(sizeof(struct mu3h_sch_ep_info
), GFP_NOIO
);
354 setup_sch_info(udev
, ep_ctx
, sch_ep
);
356 ret
= check_sch_bw(udev
, sch_bw
, sch_ep
);
358 xhci_err(xhci
, "Not enough bandwidth!\n");
363 list_add_tail(&sch_ep
->endpoint
, &sch_bw
->bw_ep_list
);
366 ep_ctx
->reserved
[0] |= cpu_to_le32(EP_BPKTS(sch_ep
->pkts
)
367 | EP_BCSCOUNT(sch_ep
->cs_count
) | EP_BBM(sch_ep
->burst_mode
));
368 ep_ctx
->reserved
[1] |= cpu_to_le32(EP_BOFFSET(sch_ep
->offset
)
369 | EP_BREPEAT(sch_ep
->repeat
));
371 xhci_dbg(xhci
, " PKTS:%x, CSCOUNT:%x, BM:%x, OFFSET:%x, REPEAT:%x\n",
372 sch_ep
->pkts
, sch_ep
->cs_count
, sch_ep
->burst_mode
,
373 sch_ep
->offset
, sch_ep
->repeat
);
377 EXPORT_SYMBOL_GPL(xhci_mtk_add_ep_quirk
);
379 void xhci_mtk_drop_ep_quirk(struct usb_hcd
*hcd
, struct usb_device
*udev
,
380 struct usb_host_endpoint
*ep
)
382 struct xhci_hcd_mtk
*mtk
= hcd_to_mtk(hcd
);
383 struct xhci_hcd
*xhci
;
384 struct xhci_slot_ctx
*slot_ctx
;
385 struct xhci_virt_device
*virt_dev
;
386 struct mu3h_sch_bw_info
*sch_array
;
387 struct mu3h_sch_bw_info
*sch_bw
;
388 struct mu3h_sch_ep_info
*sch_ep
;
391 xhci
= hcd_to_xhci(hcd
);
392 virt_dev
= xhci
->devs
[udev
->slot_id
];
393 slot_ctx
= xhci_get_slot_ctx(xhci
, virt_dev
->in_ctx
);
394 sch_array
= mtk
->sch_array
;
396 xhci_dbg(xhci
, "%s() type:%d, speed:%d, mpks:%d, dir:%d, ep:%p\n",
397 __func__
, usb_endpoint_type(&ep
->desc
), udev
->speed
,
398 usb_endpoint_maxp(&ep
->desc
),
399 usb_endpoint_dir_in(&ep
->desc
), ep
);
401 if (!need_bw_sch(ep
, udev
->speed
, slot_ctx
->tt_info
& TT_SLOT
))
404 bw_index
= get_bw_index(xhci
, udev
, ep
);
405 sch_bw
= &sch_array
[bw_index
];
407 list_for_each_entry(sch_ep
, &sch_bw
->bw_ep_list
, endpoint
) {
408 if (sch_ep
->ep
== ep
) {
409 update_bus_bw(sch_bw
, sch_ep
,
410 -sch_ep
->bw_cost_per_microframe
);
411 list_del(&sch_ep
->endpoint
);
417 EXPORT_SYMBOL_GPL(xhci_mtk_drop_ep_quirk
);