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()
130 struct xhci_hcd *xhci = hcd_to_xhci(mtk->hcd); in get_bw_info()
134 virt_dev = xhci->devs[udev->slot_id]; in get_bw_info()
135 if (!virt_dev->rhub_port) { in get_bw_info()
136 WARN_ONCE(1, "%s invalid rhub port\n", dev_name(&udev->dev)); in get_bw_info()
140 if (udev->speed >= USB_SPEED_SUPER) { in get_bw_info()
141 if (usb_endpoint_dir_out(&ep->desc)) in get_bw_info()
142 bw_index = (virt_dev->rhub_port->hw_portnum) * 2; in get_bw_info()
144 bw_index = (virt_dev->rhub_port->hw_portnum) * 2 + 1; in get_bw_info()
147 bw_index = virt_dev->rhub_port->hw_portnum + xhci->usb3_rhub.num_ports; in get_bw_info()
150 return &mtk->sch_array[bw_index]; in get_bw_info()
157 esit = 1 << CTX_TO_EP_INTERVAL(le32_to_cpu(ep_ctx->ep_info)); in get_esit()
166 struct usb_tt *utt = udev->tt; in find_tt()
167 struct mu3h_sch_tt *tt, **tt_index, **ptt; in find_tt() local
171 return NULL; /* Not below a TT */ in find_tt()
175 * For hubs with a single TT, we get it directly. in find_tt()
179 if (utt->multi) { in find_tt()
180 tt_index = utt->hcpriv; in find_tt()
182 tt_index = kcalloc(utt->hub->maxchild, in find_tt()
185 return ERR_PTR(-ENOMEM); in find_tt()
186 utt->hcpriv = tt_index; in find_tt()
189 ptt = &tt_index[udev->ttport - 1]; in find_tt()
191 ptt = (struct mu3h_sch_tt **) &utt->hcpriv; in find_tt()
194 tt = *ptt; in find_tt()
195 if (!tt) { /* Create the mu3h_sch_tt */ in find_tt()
196 tt = kzalloc(sizeof(*tt), GFP_KERNEL); in find_tt()
197 if (!tt) { in find_tt()
199 utt->hcpriv = NULL; in find_tt()
202 return ERR_PTR(-ENOMEM); in find_tt()
204 INIT_LIST_HEAD(&tt->ep_list); in find_tt()
205 *ptt = tt; in find_tt()
208 return tt; in find_tt()
211 /* Release the TT above udev, if it's not in use */
214 struct usb_tt *utt = udev->tt; in drop_tt()
215 struct mu3h_sch_tt *tt, **tt_index, **ptt; in drop_tt() local
218 if (!utt || !utt->hcpriv) in drop_tt()
219 return; /* Not below a TT, or never allocated */ in drop_tt()
222 if (utt->multi) { in drop_tt()
223 tt_index = utt->hcpriv; in drop_tt()
224 ptt = &tt_index[udev->ttport - 1]; in drop_tt()
226 for (i = 0; i < utt->hub->maxchild; ++i) in drop_tt()
230 ptt = (struct mu3h_sch_tt **)&utt->hcpriv; in drop_tt()
233 tt = *ptt; in drop_tt()
234 if (!tt || !list_empty(&tt->ep_list)) in drop_tt()
238 kfree(tt); in drop_tt()
241 utt->hcpriv = NULL; in drop_tt()
252 struct mu3h_sch_tt *tt = NULL; in create_sch_ep() local
257 return ERR_PTR(-ENODEV); in create_sch_ep()
259 if (is_fs_or_ls(udev->speed)) in create_sch_ep()
261 else if ((udev->speed >= USB_SPEED_SUPER) && in create_sch_ep()
262 usb_endpoint_xfer_isoc(&ep->desc)) in create_sch_ep()
269 return ERR_PTR(-ENOMEM); in create_sch_ep()
271 if (is_fs_or_ls(udev->speed)) { in create_sch_ep()
272 tt = find_tt(udev); in create_sch_ep()
273 if (IS_ERR(tt)) { in create_sch_ep()
275 return ERR_PTR(-ENOMEM); in create_sch_ep()
279 sch_ep->bw_info = bw_info; in create_sch_ep()
280 sch_ep->sch_tt = tt; in create_sch_ep()
281 sch_ep->ep = ep; in create_sch_ep()
282 sch_ep->speed = udev->speed; in create_sch_ep()
283 INIT_LIST_HEAD(&sch_ep->endpoint); in create_sch_ep()
284 INIT_LIST_HEAD(&sch_ep->tt_endpoint); in create_sch_ep()
285 INIT_HLIST_NODE(&sch_ep->hentry); in create_sch_ep()
303 bwb_table = sch_ep->bw_budget_table; in setup_sch_info()
304 ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2)); in setup_sch_info()
305 maxpkt = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2)); in setup_sch_info()
306 max_burst = CTX_TO_MAX_BURST(le32_to_cpu(ep_ctx->ep_info2)); in setup_sch_info()
307 mult = CTX_TO_EP_MULT(le32_to_cpu(ep_ctx->ep_info)); in setup_sch_info()
310 le32_to_cpu(ep_ctx->ep_info)) << 16) | in setup_sch_info()
311 CTX_TO_MAX_ESIT_PAYLOAD(le32_to_cpu(ep_ctx->tx_info)); in setup_sch_info()
313 sch_ep->esit = get_esit(ep_ctx); in setup_sch_info()
314 sch_ep->num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit; in setup_sch_info()
315 sch_ep->ep_type = ep_type; in setup_sch_info()
316 sch_ep->maxpkt = maxpkt; in setup_sch_info()
317 sch_ep->offset = 0; in setup_sch_info()
318 sch_ep->burst_mode = 0; in setup_sch_info()
319 sch_ep->repeat = 0; in setup_sch_info()
321 if (sch_ep->speed == USB_SPEED_HIGH) { in setup_sch_info()
322 sch_ep->cs_count = 0; in setup_sch_info()
329 sch_ep->num_budget_microframes = 1; in setup_sch_info()
336 sch_ep->pkts = max_burst + 1; in setup_sch_info()
337 bwb_table[0] = maxpkt * sch_ep->pkts; in setup_sch_info()
338 } else if (sch_ep->speed >= USB_SPEED_SUPER) { in setup_sch_info()
340 sch_ep->cs_count = 0; in setup_sch_info()
341 sch_ep->burst_mode = 1; in setup_sch_info()
352 sch_ep->pkts = esit_pkts; in setup_sch_info()
353 sch_ep->num_budget_microframes = 1; in setup_sch_info()
354 bwb_table[0] = maxpkt * sch_ep->pkts; in setup_sch_info()
359 if (sch_ep->esit == 1) in setup_sch_info()
360 sch_ep->pkts = esit_pkts; in setup_sch_info()
361 else if (esit_pkts <= sch_ep->esit) in setup_sch_info()
362 sch_ep->pkts = 1; in setup_sch_info()
364 sch_ep->pkts = roundup_pow_of_two(esit_pkts) in setup_sch_info()
365 / sch_ep->esit; in setup_sch_info()
367 sch_ep->num_budget_microframes = in setup_sch_info()
368 DIV_ROUND_UP(esit_pkts, sch_ep->pkts); in setup_sch_info()
370 sch_ep->repeat = !!(sch_ep->num_budget_microframes > 1); in setup_sch_info()
371 bw_per_microframe = maxpkt * sch_ep->pkts; in setup_sch_info()
373 for (i = 0; i < sch_ep->num_budget_microframes - 1; i++) in setup_sch_info()
377 bwb_table[i] = maxpkt * esit_pkts - i * bw_per_microframe; in setup_sch_info()
379 } else if (is_fs_or_ls(sch_ep->speed)) { in setup_sch_info()
380 sch_ep->pkts = 1; /* at most one packet for each microframe */ in setup_sch_info()
383 * @cs_count will be updated to add extra-cs when in setup_sch_info()
384 * check TT for INT_OUT_EP, ISOC/INT_IN_EP type in setup_sch_info()
387 sch_ep->cs_count = DIV_ROUND_UP(maxpkt, FS_PAYLOAD_MAX); in setup_sch_info()
388 sch_ep->num_budget_microframes = sch_ep->cs_count; in setup_sch_info()
392 for (i = 0; i < sch_ep->cs_count - 1; i++) in setup_sch_info()
395 bwb_table[i] = maxpkt - i * FS_PAYLOAD_MAX; in setup_sch_info()
404 * (add 1 or 2 extra-cs), but assume only first in setup_sch_info()
406 * although in fact it does not (extra-cs budget many receive in setup_sch_info()
410 for (i = 0; i < sch_ep->cs_count - 1; i++) in setup_sch_info()
413 bwb_table[i + CS_OFFSET] = maxpkt - i * FS_PAYLOAD_MAX; in setup_sch_info()
415 sch_ep->num_budget_microframes += CS_OFFSET; in setup_sch_info()
428 for (i = 0; i < sch_ep->num_esit; i++) { in get_max_bw()
429 u32 base = offset + i * sch_ep->esit; in get_max_bw()
431 for (j = 0; j < sch_ep->num_budget_microframes; j++) { in get_max_bw()
433 bw = sch_bw->bus_bw[k] + sch_ep->bw_budget_table[j]; in get_max_bw()
447 struct mu3h_sch_tt *tt = sch_ep->sch_tt; in get_fs_bw() local
450 if (sch_ep->ep_type == ISOC_OUT_EP || sch_ep->ep_type == INT_OUT_EP) in get_fs_bw()
451 fs_bw = tt->fs_bus_bw_out[XHCI_MTK_BW_INDEX(offset)]; in get_fs_bw()
453 fs_bw = tt->fs_bus_bw_in[XHCI_MTK_BW_INDEX(offset + CS_OFFSET)]; in get_fs_bw()
464 for (i = 0; i < sch_ep->num_esit; i++) { in update_bus_bw()
465 base = sch_ep->offset + i * sch_ep->esit; in update_bus_bw()
466 for (j = 0; j < sch_ep->num_budget_microframes; j++) { in update_bus_bw()
469 sch_bw->bus_bw[k] += sch_ep->bw_budget_table[j]; in update_bus_bw()
471 sch_bw->bus_bw[k] -= sch_ep->bw_budget_table[j]; in update_bus_bw()
478 struct mu3h_sch_tt *tt = sch_ep->sch_tt; in check_ls_budget_microframes() local
481 if (sch_ep->speed != USB_SPEED_LOW) in check_ls_budget_microframes()
484 if (sch_ep->ep_type == INT_OUT_EP) in check_ls_budget_microframes()
486 else if (sch_ep->ep_type == INT_IN_EP) in check_ls_budget_microframes()
489 return -EINVAL; in check_ls_budget_microframes()
491 if (tt->ls_bus_bw[i] + sch_ep->maxpkt > LS_PAYLOAD_MAX) in check_ls_budget_microframes()
492 return -ESCH_BW_OVERFLOW; in check_ls_budget_microframes()
499 struct mu3h_sch_tt *tt = sch_ep->sch_tt; in check_fs_budget_microframes() local
510 for (i = 0; i < sch_ep->num_budget_microframes; i++) { in check_fs_budget_microframes()
512 if (sch_ep->ep_type == ISOC_OUT_EP || sch_ep->ep_type == INT_OUT_EP) in check_fs_budget_microframes()
513 tmp = tt->fs_bus_bw_out[k] + sch_ep->bw_budget_table[i]; in check_fs_budget_microframes()
515 tmp = tt->fs_bus_bw_in[k]; in check_fs_budget_microframes()
518 return -ESCH_BW_OVERFLOW; in check_fs_budget_microframes()
526 struct mu3h_sch_tt *tt = sch_ep->sch_tt; in check_fs_budget_frames() local
532 k = XHCI_MTK_BW_INDEX(offset + sch_ep->num_budget_microframes - 1) / UFRAMES_PER_FRAME; in check_fs_budget_frames()
535 head = tt->fs_frame_bw[j]; in check_fs_budget_frames()
536 tail = tt->fs_frame_bw[k]; in check_fs_budget_frames()
538 head = tt->fs_frame_bw[j]; in check_fs_budget_frames()
543 for (i = 0; i < sch_ep->num_budget_microframes; i++) { in check_fs_budget_frames()
545 head += sch_ep->bw_budget_table[i]; in check_fs_budget_frames()
547 tail += sch_ep->bw_budget_table[i]; in check_fs_budget_frames()
551 return -ESCH_BW_OVERFLOW; in check_fs_budget_frames()
561 for (i = 0; i < sch_ep->num_esit; i++) { in check_fs_bus_bw()
562 base = offset + i * sch_ep->esit; in check_fs_bus_bw()
588 if (sch_ep->ep_type == ISOC_OUT_EP) { in check_ss_and_cs()
589 last_ss = start_ss + sch_ep->cs_count - 1; in check_ss_and_cs()
593 * must never schedule Start-Split in Y6 in check_ss_and_cs()
596 return -ESCH_SS_Y6; in check_ss_and_cs()
600 u32 cs_count = DIV_ROUND_UP(sch_ep->maxpkt, FS_PAYLOAD_MAX); in check_ss_and_cs()
604 * must never schedule Start-Split in Y6 in check_ss_and_cs()
607 return -ESCH_SS_Y6; in check_ss_and_cs()
611 last_cs = start_cs + cs_count - 1; in check_ss_and_cs()
613 return -ESCH_CS_OVERFLOW; in check_ss_and_cs()
615 /* add extra-cs */ in check_ss_and_cs()
620 sch_ep->cs_count = cs_count; in check_ss_and_cs()
628 * when isoc-out transfers 188 bytes in a uframe, and send isoc/intr's
631 * when isoc-out transfer less than 188 bytes in a uframe, shall send
632 * isoc-in's ss after isoc-out's ss (but hw can't ensure the sequence,
637 struct mu3h_sch_tt *tt = sch_ep->sch_tt; in check_isoc_ss_overlap() local
641 if (!tt) in check_isoc_ss_overlap()
644 for (i = 0; i < sch_ep->num_esit; i++) { in check_isoc_ss_overlap()
645 base = offset + i * sch_ep->esit; in check_isoc_ss_overlap()
647 if (sch_ep->ep_type == ISOC_OUT_EP) { in check_isoc_ss_overlap()
648 for (j = 0; j < sch_ep->num_budget_microframes; j++) { in check_isoc_ss_overlap()
650 if (tt->in_ss_cnt[k]) in check_isoc_ss_overlap()
651 return -ESCH_SS_OVERLAP; in check_isoc_ss_overlap()
653 } else if (sch_ep->ep_type == ISOC_IN_EP || sch_ep->ep_type == INT_IN_EP) { in check_isoc_ss_overlap()
656 if (tt->fs_bus_bw_out[k]) in check_isoc_ss_overlap()
657 return -ESCH_SS_OVERLAP; in check_isoc_ss_overlap()
682 struct mu3h_sch_bw_info *sch_bw = sch_ep->bw_info; in alloc_sch_portion_of_frame()
683 const u32 bw_boundary = get_bw_boundary(sch_ep->speed); in alloc_sch_portion_of_frame()
691 frames = sch_ep->esit / UFRAMES_PER_FRAME; in alloc_sch_portion_of_frame()
698 offset = (i + j * UFRAMES_PER_FRAME) % sch_ep->esit; in alloc_sch_portion_of_frame()
707 ret = -ESCH_BW_OVERFLOW; in alloc_sch_portion_of_frame()
711 /* use best-fit between frames */ in alloc_sch_portion_of_frame()
722 /* use first-fit between microframes in a frame */ in alloc_sch_portion_of_frame()
728 return -ESCH_BW_OVERFLOW; in alloc_sch_portion_of_frame()
730 sch_ep->offset = offset_min; in alloc_sch_portion_of_frame()
737 struct mu3h_sch_tt *tt = sch_ep->sch_tt; in update_sch_tt() local
742 if (sch_ep->ep_type == ISOC_OUT_EP || sch_ep->ep_type == INT_OUT_EP) in update_sch_tt()
743 fs_bus_bw = tt->fs_bus_bw_out; in update_sch_tt()
745 fs_bus_bw = tt->fs_bus_bw_in; in update_sch_tt()
747 for (i = 0; i < sch_ep->num_esit; i++) { in update_sch_tt()
748 base = sch_ep->offset + i * sch_ep->esit; in update_sch_tt()
750 for (j = 0; j < sch_ep->num_budget_microframes; j++) { in update_sch_tt()
754 if (sch_ep->speed == USB_SPEED_LOW) in update_sch_tt()
755 tt->ls_bus_bw[k] += (u8)sch_ep->bw_budget_table[j]; in update_sch_tt()
757 fs_bus_bw[k] += (u16)sch_ep->bw_budget_table[j]; in update_sch_tt()
758 tt->fs_frame_bw[f] += (u16)sch_ep->bw_budget_table[j]; in update_sch_tt()
760 if (sch_ep->speed == USB_SPEED_LOW) in update_sch_tt()
761 tt->ls_bus_bw[k] -= (u8)sch_ep->bw_budget_table[j]; in update_sch_tt()
763 fs_bus_bw[k] -= (u16)sch_ep->bw_budget_table[j]; in update_sch_tt()
764 tt->fs_frame_bw[f] -= (u16)sch_ep->bw_budget_table[j]; in update_sch_tt()
768 if (sch_ep->ep_type == ISOC_IN_EP || sch_ep->ep_type == INT_IN_EP) { in update_sch_tt()
771 tt->in_ss_cnt[k]++; in update_sch_tt()
773 tt->in_ss_cnt[k]--; in update_sch_tt()
778 list_add_tail(&sch_ep->tt_endpoint, &tt->ep_list); in update_sch_tt()
780 list_del(&sch_ep->tt_endpoint); in update_sch_tt()
786 if (sch_ep->sch_tt) in load_ep_bw()
791 sch_ep->allocated = loaded; in load_ep_bw()
799 struct mu3h_sch_bw_info *sch_bw = sch_ep->bw_info; in alloc_sch_microframes()
800 const u32 bw_boundary = get_bw_boundary(sch_ep->speed); in alloc_sch_microframes()
804 int min_index = -1; in alloc_sch_microframes()
810 for (offset = 0; offset < sch_ep->esit; offset++) { in alloc_sch_microframes()
823 return -ESCH_BW_OVERFLOW; in alloc_sch_microframes()
825 sch_ep->offset = min_index; in alloc_sch_microframes()
834 if (sch_ep->sch_tt) in check_sch_bw()
842 return load_ep_bw(sch_ep->bw_info, sch_ep, true); in check_sch_bw()
849 if (sch_ep->allocated) in destroy_sch_ep()
850 load_ep_bw(sch_ep->bw_info, sch_ep, false); in destroy_sch_ep()
852 if (sch_ep->sch_tt) in destroy_sch_ep()
855 list_del(&sch_ep->endpoint); in destroy_sch_ep()
856 hlist_del(&sch_ep->hentry); in destroy_sch_ep()
863 bool has_tt = udev->tt && udev->tt->hub->parent; in need_bw_sch()
866 if (usb_endpoint_xfer_control(&ep->desc) in need_bw_sch()
867 || usb_endpoint_xfer_bulk(&ep->desc)) in need_bw_sch()
872 * a TT are also ignored, root-hub will schedule them directly, in need_bw_sch()
875 if (is_fs_or_ls(udev->speed) && !has_tt) in need_bw_sch()
879 if (usb_endpoint_maxp(&ep->desc) == 0) in need_bw_sch()
887 struct xhci_hcd *xhci = hcd_to_xhci(mtk->hcd); in xhci_mtk_sch_init()
892 num_usb_bus = xhci->usb3_rhub.num_ports * 2 + xhci->usb2_rhub.num_ports; in xhci_mtk_sch_init()
896 return -ENOMEM; in xhci_mtk_sch_init()
898 mtk->sch_array = sch_array; in xhci_mtk_sch_init()
900 INIT_LIST_HEAD(&mtk->bw_ep_chk_list); in xhci_mtk_sch_init()
901 hash_init(mtk->sch_ep_hash); in xhci_mtk_sch_init()
908 kfree(mtk->sch_array); in xhci_mtk_sch_exit()
921 virt_dev = xhci->devs[udev->slot_id]; in add_ep_quirk()
922 ep_index = xhci_get_endpoint_index(&ep->desc); in add_ep_quirk()
923 ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); in add_ep_quirk()
930 if (usb_endpoint_xfer_int(&ep->desc) in add_ep_quirk()
931 || usb_endpoint_xfer_isoc(&ep->desc)) in add_ep_quirk()
932 ep_ctx->reserved[0] = cpu_to_le32(EP_BPKTS(1)); in add_ep_quirk()
937 xhci_dbg(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed)); in add_ep_quirk()
941 return -ENOMEM; in add_ep_quirk()
945 list_add_tail(&sch_ep->endpoint, &mtk->bw_ep_chk_list); in add_ep_quirk()
946 hash_add(mtk->sch_ep_hash, &sch_ep->hentry, (unsigned long)ep); in add_ep_quirk()
962 xhci_dbg(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed)); in drop_ep_quirk()
964 hash_for_each_possible_safe(mtk->sch_ep_hash, sch_ep, in drop_ep_quirk()
966 if (sch_ep->ep == ep) { in drop_ep_quirk()
977 struct xhci_virt_device *virt_dev = xhci->devs[udev->slot_id]; in xhci_mtk_check_bandwidth()
981 xhci_dbg(xhci, "%s() udev %s\n", __func__, dev_name(&udev->dev)); in xhci_mtk_check_bandwidth()
983 list_for_each_entry(sch_ep, &mtk->bw_ep_chk_list, endpoint) { in xhci_mtk_check_bandwidth()
985 struct usb_host_endpoint *ep = sch_ep->ep; in xhci_mtk_check_bandwidth()
986 unsigned int ep_index = xhci_get_endpoint_index(&ep->desc); in xhci_mtk_check_bandwidth()
991 sch_error_string(-ret)); in xhci_mtk_check_bandwidth()
992 return -ENOSPC; in xhci_mtk_check_bandwidth()
995 ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); in xhci_mtk_check_bandwidth()
996 ep_ctx->reserved[0] = cpu_to_le32(EP_BPKTS(sch_ep->pkts) in xhci_mtk_check_bandwidth()
997 | EP_BCSCOUNT(sch_ep->cs_count) in xhci_mtk_check_bandwidth()
998 | EP_BBM(sch_ep->burst_mode)); in xhci_mtk_check_bandwidth()
999 ep_ctx->reserved[1] = cpu_to_le32(EP_BOFFSET(sch_ep->offset) in xhci_mtk_check_bandwidth()
1000 | EP_BREPEAT(sch_ep->repeat)); in xhci_mtk_check_bandwidth()
1003 sch_ep->pkts, sch_ep->cs_count, sch_ep->burst_mode, in xhci_mtk_check_bandwidth()
1004 sch_ep->offset, sch_ep->repeat); in xhci_mtk_check_bandwidth()
1009 list_del_init(&mtk->bw_ep_chk_list); in xhci_mtk_check_bandwidth()
1020 xhci_dbg(xhci, "%s() udev %s\n", __func__, dev_name(&udev->dev)); in xhci_mtk_reset_bandwidth()
1022 list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_chk_list, endpoint) in xhci_mtk_reset_bandwidth()
1037 if (ep->hcpriv) in xhci_mtk_add_ep()
1052 /* needn't check @ep->hcpriv, xhci_endpoint_disable set it NULL */ in xhci_mtk_drop_ep()