Lines Matching +full:multi +full:- +full:tt

1 // SPDX-License-Identifier: GPL-2.0
14 #include "xhci-mtk.h"
18 /* table 5-5. High-speed Isoc Transaction Limits in usb_20 spec */
28 * max number of microframes for split transfer, assume extra-cs budget is 0
55 return "Can't schedule Start-Split in Y6"; in sch_error_string()
57 return "Can't find a suitable Start-Split location"; in sch_error_string()
59 return "The last Complete-Split is greater than 7"; in sch_error_string()
78 struct usb_endpoint_descriptor *epd = &ep->desc; in decode_ep()
94 usb_endpoint_maxp(epd), epd->bInterval, interval, unit); in decode_ep()
128 * SSport0-OUT, SSport0-IN, ..., SSportX-OUT, SSportX-IN, HSport0, ..., HSportY
134 struct xhci_hcd *xhci = hcd_to_xhci(mtk->hcd); in get_bw_info()
138 virt_dev = xhci->devs[udev->slot_id]; in get_bw_info()
139 if (!virt_dev->real_port) { in get_bw_info()
140 WARN_ONCE(1, "%s invalid real_port\n", dev_name(&udev->dev)); in get_bw_info()
144 if (udev->speed >= USB_SPEED_SUPER) { in get_bw_info()
145 if (usb_endpoint_dir_out(&ep->desc)) in get_bw_info()
146 bw_index = (virt_dev->real_port - 1) * 2; in get_bw_info()
148 bw_index = (virt_dev->real_port - 1) * 2 + 1; in get_bw_info()
151 bw_index = virt_dev->real_port + xhci->usb3_rhub.num_ports - 1; in get_bw_info()
154 return &mtk->sch_array[bw_index]; in get_bw_info()
161 esit = 1 << CTX_TO_EP_INTERVAL(le32_to_cpu(ep_ctx->ep_info)); in get_esit()
170 struct usb_tt *utt = udev->tt; in find_tt()
171 struct mu3h_sch_tt *tt, **tt_index, **ptt; in find_tt() local
175 return NULL; /* Not below a TT */ in find_tt()
179 * For hubs with a single TT, we get it directly. in find_tt()
183 if (utt->multi) { in find_tt()
184 tt_index = utt->hcpriv; in find_tt()
186 tt_index = kcalloc(utt->hub->maxchild, in find_tt()
189 return ERR_PTR(-ENOMEM); in find_tt()
190 utt->hcpriv = tt_index; in find_tt()
193 ptt = &tt_index[udev->ttport - 1]; in find_tt()
195 ptt = (struct mu3h_sch_tt **) &utt->hcpriv; in find_tt()
198 tt = *ptt; in find_tt()
199 if (!tt) { /* Create the mu3h_sch_tt */ in find_tt()
200 tt = kzalloc(sizeof(*tt), GFP_KERNEL); in find_tt()
201 if (!tt) { in find_tt()
203 utt->hcpriv = NULL; in find_tt()
206 return ERR_PTR(-ENOMEM); in find_tt()
208 INIT_LIST_HEAD(&tt->ep_list); in find_tt()
209 *ptt = tt; in find_tt()
212 return tt; in find_tt()
215 /* Release the TT above udev, if it's not in use */
218 struct usb_tt *utt = udev->tt; in drop_tt()
219 struct mu3h_sch_tt *tt, **tt_index, **ptt; in drop_tt() local
222 if (!utt || !utt->hcpriv) in drop_tt()
223 return; /* Not below a TT, or never allocated */ in drop_tt()
226 if (utt->multi) { in drop_tt()
227 tt_index = utt->hcpriv; in drop_tt()
228 ptt = &tt_index[udev->ttport - 1]; in drop_tt()
230 for (i = 0; i < utt->hub->maxchild; ++i) in drop_tt()
234 ptt = (struct mu3h_sch_tt **)&utt->hcpriv; in drop_tt()
237 tt = *ptt; in drop_tt()
238 if (!tt || !list_empty(&tt->ep_list)) in drop_tt()
242 kfree(tt); in drop_tt()
245 utt->hcpriv = NULL; in drop_tt()
256 struct mu3h_sch_tt *tt = NULL; in create_sch_ep() local
261 return ERR_PTR(-ENODEV); in create_sch_ep()
263 if (is_fs_or_ls(udev->speed)) in create_sch_ep()
265 else if ((udev->speed >= USB_SPEED_SUPER) && in create_sch_ep()
266 usb_endpoint_xfer_isoc(&ep->desc)) in create_sch_ep()
273 return ERR_PTR(-ENOMEM); in create_sch_ep()
275 if (is_fs_or_ls(udev->speed)) { in create_sch_ep()
276 tt = find_tt(udev); in create_sch_ep()
277 if (IS_ERR(tt)) { in create_sch_ep()
279 return ERR_PTR(-ENOMEM); in create_sch_ep()
283 sch_ep->bw_info = bw_info; in create_sch_ep()
284 sch_ep->sch_tt = tt; in create_sch_ep()
285 sch_ep->ep = ep; in create_sch_ep()
286 sch_ep->speed = udev->speed; in create_sch_ep()
287 INIT_LIST_HEAD(&sch_ep->endpoint); in create_sch_ep()
288 INIT_LIST_HEAD(&sch_ep->tt_endpoint); in create_sch_ep()
289 INIT_HLIST_NODE(&sch_ep->hentry); in create_sch_ep()
307 bwb_table = sch_ep->bw_budget_table; in setup_sch_info()
308 ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2)); in setup_sch_info()
309 maxpkt = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2)); in setup_sch_info()
310 max_burst = CTX_TO_MAX_BURST(le32_to_cpu(ep_ctx->ep_info2)); in setup_sch_info()
311 mult = CTX_TO_EP_MULT(le32_to_cpu(ep_ctx->ep_info)); in setup_sch_info()
314 le32_to_cpu(ep_ctx->ep_info)) << 16) | in setup_sch_info()
315 CTX_TO_MAX_ESIT_PAYLOAD(le32_to_cpu(ep_ctx->tx_info)); in setup_sch_info()
317 sch_ep->esit = get_esit(ep_ctx); in setup_sch_info()
318 sch_ep->num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit; in setup_sch_info()
319 sch_ep->ep_type = ep_type; in setup_sch_info()
320 sch_ep->maxpkt = maxpkt; in setup_sch_info()
321 sch_ep->offset = 0; in setup_sch_info()
322 sch_ep->burst_mode = 0; in setup_sch_info()
323 sch_ep->repeat = 0; in setup_sch_info()
325 if (sch_ep->speed == USB_SPEED_HIGH) { in setup_sch_info()
326 sch_ep->cs_count = 0; in setup_sch_info()
333 sch_ep->num_budget_microframes = 1; in setup_sch_info()
340 sch_ep->pkts = max_burst + 1; in setup_sch_info()
341 bwb_table[0] = maxpkt * sch_ep->pkts; in setup_sch_info()
342 } else if (sch_ep->speed >= USB_SPEED_SUPER) { in setup_sch_info()
344 sch_ep->cs_count = 0; in setup_sch_info()
345 sch_ep->burst_mode = 1; in setup_sch_info()
356 sch_ep->pkts = esit_pkts; in setup_sch_info()
357 sch_ep->num_budget_microframes = 1; in setup_sch_info()
358 bwb_table[0] = maxpkt * sch_ep->pkts; in setup_sch_info()
363 if (sch_ep->esit == 1) in setup_sch_info()
364 sch_ep->pkts = esit_pkts; in setup_sch_info()
365 else if (esit_pkts <= sch_ep->esit) in setup_sch_info()
366 sch_ep->pkts = 1; in setup_sch_info()
368 sch_ep->pkts = roundup_pow_of_two(esit_pkts) in setup_sch_info()
369 / sch_ep->esit; in setup_sch_info()
371 sch_ep->num_budget_microframes = in setup_sch_info()
372 DIV_ROUND_UP(esit_pkts, sch_ep->pkts); in setup_sch_info()
374 sch_ep->repeat = !!(sch_ep->num_budget_microframes > 1); in setup_sch_info()
375 bw_per_microframe = maxpkt * sch_ep->pkts; in setup_sch_info()
377 for (i = 0; i < sch_ep->num_budget_microframes - 1; i++) in setup_sch_info()
381 bwb_table[i] = maxpkt * esit_pkts - i * bw_per_microframe; in setup_sch_info()
383 } else if (is_fs_or_ls(sch_ep->speed)) { in setup_sch_info()
384 sch_ep->pkts = 1; /* at most one packet for each microframe */ in setup_sch_info()
387 * @cs_count will be updated to add extra-cs when in setup_sch_info()
388 * check TT for INT_OUT_EP, ISOC/INT_IN_EP type in setup_sch_info()
391 sch_ep->cs_count = DIV_ROUND_UP(maxpkt, FS_PAYLOAD_MAX); in setup_sch_info()
392 sch_ep->num_budget_microframes = sch_ep->cs_count; in setup_sch_info()
396 for (i = 0; i < sch_ep->cs_count - 1; i++) in setup_sch_info()
399 bwb_table[i] = maxpkt - i * FS_PAYLOAD_MAX; in setup_sch_info()
408 * (add 1 or 2 extra-cs), but assume only first in setup_sch_info()
410 * although in fact it does not (extra-cs budget many receive in setup_sch_info()
414 for (i = 0; i < sch_ep->cs_count - 1; i++) in setup_sch_info()
417 bwb_table[i + CS_OFFSET] = maxpkt - i * FS_PAYLOAD_MAX; in setup_sch_info()
419 sch_ep->num_budget_microframes += CS_OFFSET; in setup_sch_info()
432 for (i = 0; i < sch_ep->num_esit; i++) { in get_max_bw()
433 u32 base = offset + i * sch_ep->esit; in get_max_bw()
435 for (j = 0; j < sch_ep->num_budget_microframes; j++) { in get_max_bw()
437 bw = sch_bw->bus_bw[k] + sch_ep->bw_budget_table[j]; in get_max_bw()
451 struct mu3h_sch_tt *tt = sch_ep->sch_tt; in get_fs_bw() local
454 if (sch_ep->ep_type == ISOC_OUT_EP || sch_ep->ep_type == INT_OUT_EP) in get_fs_bw()
455 fs_bw = tt->fs_bus_bw_out[XHCI_MTK_BW_INDEX(offset)]; in get_fs_bw()
457 fs_bw = tt->fs_bus_bw_in[XHCI_MTK_BW_INDEX(offset + CS_OFFSET)]; in get_fs_bw()
468 for (i = 0; i < sch_ep->num_esit; i++) { in update_bus_bw()
469 base = sch_ep->offset + i * sch_ep->esit; in update_bus_bw()
470 for (j = 0; j < sch_ep->num_budget_microframes; j++) { in update_bus_bw()
473 sch_bw->bus_bw[k] += sch_ep->bw_budget_table[j]; in update_bus_bw()
475 sch_bw->bus_bw[k] -= sch_ep->bw_budget_table[j]; in update_bus_bw()
482 struct mu3h_sch_tt *tt = sch_ep->sch_tt; in check_ls_budget_microframes() local
485 if (sch_ep->speed != USB_SPEED_LOW) in check_ls_budget_microframes()
488 if (sch_ep->ep_type == INT_OUT_EP) in check_ls_budget_microframes()
490 else if (sch_ep->ep_type == INT_IN_EP) in check_ls_budget_microframes()
493 return -EINVAL; in check_ls_budget_microframes()
495 if (tt->ls_bus_bw[i] + sch_ep->maxpkt > LS_PAYLOAD_MAX) in check_ls_budget_microframes()
496 return -ESCH_BW_OVERFLOW; in check_ls_budget_microframes()
503 struct mu3h_sch_tt *tt = sch_ep->sch_tt; in check_fs_budget_microframes() local
514 for (i = 0; i < sch_ep->num_budget_microframes; i++) { in check_fs_budget_microframes()
516 if (sch_ep->ep_type == ISOC_OUT_EP || sch_ep->ep_type == INT_OUT_EP) in check_fs_budget_microframes()
517 tmp = tt->fs_bus_bw_out[k] + sch_ep->bw_budget_table[i]; in check_fs_budget_microframes()
519 tmp = tt->fs_bus_bw_in[k]; in check_fs_budget_microframes()
522 return -ESCH_BW_OVERFLOW; in check_fs_budget_microframes()
530 struct mu3h_sch_tt *tt = sch_ep->sch_tt; in check_fs_budget_frames() local
536 k = XHCI_MTK_BW_INDEX(offset + sch_ep->num_budget_microframes - 1) / UFRAMES_PER_FRAME; in check_fs_budget_frames()
539 head = tt->fs_frame_bw[j]; in check_fs_budget_frames()
540 tail = tt->fs_frame_bw[k]; in check_fs_budget_frames()
542 head = tt->fs_frame_bw[j]; in check_fs_budget_frames()
547 for (i = 0; i < sch_ep->num_budget_microframes; i++) { in check_fs_budget_frames()
549 head += sch_ep->bw_budget_table[i]; in check_fs_budget_frames()
551 tail += sch_ep->bw_budget_table[i]; in check_fs_budget_frames()
555 return -ESCH_BW_OVERFLOW; in check_fs_budget_frames()
565 for (i = 0; i < sch_ep->num_esit; i++) { in check_fs_bus_bw()
566 base = offset + i * sch_ep->esit; in check_fs_bus_bw()
592 if (sch_ep->ep_type == ISOC_OUT_EP) { in check_ss_and_cs()
593 last_ss = start_ss + sch_ep->cs_count - 1; in check_ss_and_cs()
597 * must never schedule Start-Split in Y6 in check_ss_and_cs()
600 return -ESCH_SS_Y6; in check_ss_and_cs()
604 u32 cs_count = DIV_ROUND_UP(sch_ep->maxpkt, FS_PAYLOAD_MAX); in check_ss_and_cs()
608 * must never schedule Start-Split in Y6 in check_ss_and_cs()
611 return -ESCH_SS_Y6; in check_ss_and_cs()
615 last_cs = start_cs + cs_count - 1; in check_ss_and_cs()
617 return -ESCH_CS_OVERFLOW; in check_ss_and_cs()
619 /* add extra-cs */ in check_ss_and_cs()
624 sch_ep->cs_count = cs_count; in check_ss_and_cs()
632 * when isoc-out transfers 188 bytes in a uframe, and send isoc/intr's
635 * when isoc-out transfer less than 188 bytes in a uframe, shall send
636 * isoc-in's ss after isoc-out's ss (but hw can't ensure the sequence,
641 struct mu3h_sch_tt *tt = sch_ep->sch_tt; in check_isoc_ss_overlap() local
645 if (!tt) in check_isoc_ss_overlap()
648 for (i = 0; i < sch_ep->num_esit; i++) { in check_isoc_ss_overlap()
649 base = offset + i * sch_ep->esit; in check_isoc_ss_overlap()
651 if (sch_ep->ep_type == ISOC_OUT_EP) { in check_isoc_ss_overlap()
652 for (j = 0; j < sch_ep->num_budget_microframes; j++) { in check_isoc_ss_overlap()
654 if (tt->in_ss_cnt[k]) in check_isoc_ss_overlap()
655 return -ESCH_SS_OVERLAP; in check_isoc_ss_overlap()
657 } else if (sch_ep->ep_type == ISOC_IN_EP || sch_ep->ep_type == INT_IN_EP) { in check_isoc_ss_overlap()
660 if (tt->fs_bus_bw_out[k]) in check_isoc_ss_overlap()
661 return -ESCH_SS_OVERLAP; in check_isoc_ss_overlap()
686 struct mu3h_sch_bw_info *sch_bw = sch_ep->bw_info; in alloc_sch_portion_of_frame()
687 const u32 bw_boundary = get_bw_boundary(sch_ep->speed); in alloc_sch_portion_of_frame()
695 frames = sch_ep->esit / UFRAMES_PER_FRAME; in alloc_sch_portion_of_frame()
702 offset = (i + j * UFRAMES_PER_FRAME) % sch_ep->esit; in alloc_sch_portion_of_frame()
711 ret = -ESCH_BW_OVERFLOW; in alloc_sch_portion_of_frame()
715 /* use best-fit between frames */ in alloc_sch_portion_of_frame()
726 /* use first-fit between microframes in a frame */ in alloc_sch_portion_of_frame()
732 return -ESCH_BW_OVERFLOW; in alloc_sch_portion_of_frame()
734 sch_ep->offset = offset_min; in alloc_sch_portion_of_frame()
741 struct mu3h_sch_tt *tt = sch_ep->sch_tt; in update_sch_tt() local
746 if (sch_ep->ep_type == ISOC_OUT_EP || sch_ep->ep_type == INT_OUT_EP) in update_sch_tt()
747 fs_bus_bw = tt->fs_bus_bw_out; in update_sch_tt()
749 fs_bus_bw = tt->fs_bus_bw_in; in update_sch_tt()
751 for (i = 0; i < sch_ep->num_esit; i++) { in update_sch_tt()
752 base = sch_ep->offset + i * sch_ep->esit; in update_sch_tt()
754 for (j = 0; j < sch_ep->num_budget_microframes; j++) { in update_sch_tt()
758 if (sch_ep->speed == USB_SPEED_LOW) in update_sch_tt()
759 tt->ls_bus_bw[k] += (u8)sch_ep->bw_budget_table[j]; in update_sch_tt()
761 fs_bus_bw[k] += (u16)sch_ep->bw_budget_table[j]; in update_sch_tt()
762 tt->fs_frame_bw[f] += (u16)sch_ep->bw_budget_table[j]; in update_sch_tt()
764 if (sch_ep->speed == USB_SPEED_LOW) in update_sch_tt()
765 tt->ls_bus_bw[k] -= (u8)sch_ep->bw_budget_table[j]; in update_sch_tt()
767 fs_bus_bw[k] -= (u16)sch_ep->bw_budget_table[j]; in update_sch_tt()
768 tt->fs_frame_bw[f] -= (u16)sch_ep->bw_budget_table[j]; in update_sch_tt()
772 if (sch_ep->ep_type == ISOC_IN_EP || sch_ep->ep_type == INT_IN_EP) { in update_sch_tt()
775 tt->in_ss_cnt[k]++; in update_sch_tt()
777 tt->in_ss_cnt[k]--; in update_sch_tt()
782 list_add_tail(&sch_ep->tt_endpoint, &tt->ep_list); in update_sch_tt()
784 list_del(&sch_ep->tt_endpoint); in update_sch_tt()
790 if (sch_ep->sch_tt) in load_ep_bw()
795 sch_ep->allocated = loaded; in load_ep_bw()
803 struct mu3h_sch_bw_info *sch_bw = sch_ep->bw_info; in alloc_sch_microframes()
804 const u32 bw_boundary = get_bw_boundary(sch_ep->speed); in alloc_sch_microframes()
808 int min_index = -1; in alloc_sch_microframes()
814 for (offset = 0; offset < sch_ep->esit; offset++) { in alloc_sch_microframes()
827 return -ESCH_BW_OVERFLOW; in alloc_sch_microframes()
829 sch_ep->offset = min_index; in alloc_sch_microframes()
838 if (sch_ep->sch_tt) in check_sch_bw()
846 return load_ep_bw(sch_ep->bw_info, sch_ep, true); in check_sch_bw()
853 if (sch_ep->allocated) in destroy_sch_ep()
854 load_ep_bw(sch_ep->bw_info, sch_ep, false); in destroy_sch_ep()
856 if (sch_ep->sch_tt) in destroy_sch_ep()
859 list_del(&sch_ep->endpoint); in destroy_sch_ep()
860 hlist_del(&sch_ep->hentry); in destroy_sch_ep()
867 bool has_tt = udev->tt && udev->tt->hub->parent; in need_bw_sch()
870 if (usb_endpoint_xfer_control(&ep->desc) in need_bw_sch()
871 || usb_endpoint_xfer_bulk(&ep->desc)) in need_bw_sch()
876 * a TT are also ignored, root-hub will schedule them directly, in need_bw_sch()
879 if (is_fs_or_ls(udev->speed) && !has_tt) in need_bw_sch()
883 if (usb_endpoint_maxp(&ep->desc) == 0) in need_bw_sch()
891 struct xhci_hcd *xhci = hcd_to_xhci(mtk->hcd); in xhci_mtk_sch_init()
896 num_usb_bus = xhci->usb3_rhub.num_ports * 2 + xhci->usb2_rhub.num_ports; in xhci_mtk_sch_init()
900 return -ENOMEM; in xhci_mtk_sch_init()
902 mtk->sch_array = sch_array; in xhci_mtk_sch_init()
904 INIT_LIST_HEAD(&mtk->bw_ep_chk_list); in xhci_mtk_sch_init()
905 hash_init(mtk->sch_ep_hash); in xhci_mtk_sch_init()
912 kfree(mtk->sch_array); in xhci_mtk_sch_exit()
925 virt_dev = xhci->devs[udev->slot_id]; in add_ep_quirk()
926 ep_index = xhci_get_endpoint_index(&ep->desc); in add_ep_quirk()
927 ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); in add_ep_quirk()
934 if (usb_endpoint_xfer_int(&ep->desc) in add_ep_quirk()
935 || usb_endpoint_xfer_isoc(&ep->desc)) in add_ep_quirk()
936 ep_ctx->reserved[0] = cpu_to_le32(EP_BPKTS(1)); in add_ep_quirk()
941 xhci_dbg(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed)); in add_ep_quirk()
945 return -ENOMEM; in add_ep_quirk()
949 list_add_tail(&sch_ep->endpoint, &mtk->bw_ep_chk_list); in add_ep_quirk()
950 hash_add(mtk->sch_ep_hash, &sch_ep->hentry, (unsigned long)ep); in add_ep_quirk()
966 xhci_dbg(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed)); in drop_ep_quirk()
968 hash_for_each_possible_safe(mtk->sch_ep_hash, sch_ep, in drop_ep_quirk()
970 if (sch_ep->ep == ep) { in drop_ep_quirk()
981 struct xhci_virt_device *virt_dev = xhci->devs[udev->slot_id]; in xhci_mtk_check_bandwidth()
985 xhci_dbg(xhci, "%s() udev %s\n", __func__, dev_name(&udev->dev)); in xhci_mtk_check_bandwidth()
987 list_for_each_entry(sch_ep, &mtk->bw_ep_chk_list, endpoint) { in xhci_mtk_check_bandwidth()
989 struct usb_host_endpoint *ep = sch_ep->ep; in xhci_mtk_check_bandwidth()
990 unsigned int ep_index = xhci_get_endpoint_index(&ep->desc); in xhci_mtk_check_bandwidth()
995 sch_error_string(-ret)); in xhci_mtk_check_bandwidth()
996 return -ENOSPC; in xhci_mtk_check_bandwidth()
999 ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); in xhci_mtk_check_bandwidth()
1000 ep_ctx->reserved[0] = cpu_to_le32(EP_BPKTS(sch_ep->pkts) in xhci_mtk_check_bandwidth()
1001 | EP_BCSCOUNT(sch_ep->cs_count) in xhci_mtk_check_bandwidth()
1002 | EP_BBM(sch_ep->burst_mode)); in xhci_mtk_check_bandwidth()
1003 ep_ctx->reserved[1] = cpu_to_le32(EP_BOFFSET(sch_ep->offset) in xhci_mtk_check_bandwidth()
1004 | EP_BREPEAT(sch_ep->repeat)); in xhci_mtk_check_bandwidth()
1007 sch_ep->pkts, sch_ep->cs_count, sch_ep->burst_mode, in xhci_mtk_check_bandwidth()
1008 sch_ep->offset, sch_ep->repeat); in xhci_mtk_check_bandwidth()
1013 list_del_init(&mtk->bw_ep_chk_list); in xhci_mtk_check_bandwidth()
1024 xhci_dbg(xhci, "%s() udev %s\n", __func__, dev_name(&udev->dev)); in xhci_mtk_reset_bandwidth()
1026 list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_chk_list, endpoint) in xhci_mtk_reset_bandwidth()
1041 if (ep->hcpriv) in xhci_mtk_add_ep()
1056 /* needn't check @ep->hcpriv, xhci_endpoint_disable set it NULL */ in xhci_mtk_drop_ep()