Lines Matching +full:mtk +full:- +full:xhci

1 // SPDX-License-Identifier: GPL-2.0
13 #include "xhci.h"
14 #include "xhci-mtk.h"
18 /* table 5-5. High-speed Isoc Transaction Limits in usb_20 spec */
32 /* mtk scheduler bitmasks */
43 return "Can't schedule Start-Split in Y6"; in sch_error_string()
45 return "Can't find a suitable Start-Split location"; in sch_error_string()
47 return "The last Complete-Split is greater than 7"; in sch_error_string()
66 struct usb_endpoint_descriptor *epd = &ep->desc; in decode_ep()
82 usb_endpoint_maxp(epd), epd->bInterval, interval, unit); in decode_ep()
113 * @real_port value is defined as follow according to xHCI spec:
116 * SSport0-OUT, SSport0-IN, ..., SSportX-OUT, SSportX-IN, HSport0, ..., HSportY
119 get_bw_info(struct xhci_hcd_mtk *mtk, struct usb_device *udev, in get_bw_info() argument
122 struct xhci_hcd *xhci = hcd_to_xhci(mtk->hcd); in get_bw_info() local
126 virt_dev = xhci->devs[udev->slot_id]; in get_bw_info()
127 if (!virt_dev->real_port) { in get_bw_info()
128 WARN_ONCE(1, "%s invalid real_port\n", dev_name(&udev->dev)); in get_bw_info()
132 if (udev->speed >= USB_SPEED_SUPER) { in get_bw_info()
133 if (usb_endpoint_dir_out(&ep->desc)) in get_bw_info()
134 bw_index = (virt_dev->real_port - 1) * 2; in get_bw_info()
136 bw_index = (virt_dev->real_port - 1) * 2 + 1; in get_bw_info()
139 bw_index = virt_dev->real_port + xhci->usb3_rhub.num_ports - 1; in get_bw_info()
142 return &mtk->sch_array[bw_index]; in get_bw_info()
149 esit = 1 << CTX_TO_EP_INTERVAL(le32_to_cpu(ep_ctx->ep_info)); in get_esit()
158 struct usb_tt *utt = udev->tt; in find_tt()
171 if (utt->multi) { in find_tt()
172 tt_index = utt->hcpriv; in find_tt()
174 tt_index = kcalloc(utt->hub->maxchild, in find_tt()
177 return ERR_PTR(-ENOMEM); in find_tt()
178 utt->hcpriv = tt_index; in find_tt()
181 ptt = &tt_index[udev->ttport - 1]; in find_tt()
183 ptt = (struct mu3h_sch_tt **) &utt->hcpriv; in find_tt()
191 utt->hcpriv = NULL; in find_tt()
194 return ERR_PTR(-ENOMEM); in find_tt()
196 INIT_LIST_HEAD(&tt->ep_list); in find_tt()
206 struct usb_tt *utt = udev->tt; in drop_tt()
210 if (!utt || !utt->hcpriv) in drop_tt()
214 if (utt->multi) { in drop_tt()
215 tt_index = utt->hcpriv; in drop_tt()
216 ptt = &tt_index[udev->ttport - 1]; in drop_tt()
218 for (i = 0; i < utt->hub->maxchild; ++i) in drop_tt()
222 ptt = (struct mu3h_sch_tt **)&utt->hcpriv; in drop_tt()
226 if (!tt || !list_empty(&tt->ep_list)) in drop_tt()
233 utt->hcpriv = NULL; in drop_tt()
239 create_sch_ep(struct xhci_hcd_mtk *mtk, struct usb_device *udev, in create_sch_ep() argument
246 bw_info = get_bw_info(mtk, udev, ep); in create_sch_ep()
248 return ERR_PTR(-ENODEV); in create_sch_ep()
252 return ERR_PTR(-ENOMEM); in create_sch_ep()
254 if (is_fs_or_ls(udev->speed)) { in create_sch_ep()
258 return ERR_PTR(-ENOMEM); in create_sch_ep()
262 sch_ep->bw_info = bw_info; in create_sch_ep()
263 sch_ep->sch_tt = tt; in create_sch_ep()
264 sch_ep->ep = ep; in create_sch_ep()
265 sch_ep->speed = udev->speed; in create_sch_ep()
266 INIT_LIST_HEAD(&sch_ep->endpoint); in create_sch_ep()
267 INIT_LIST_HEAD(&sch_ep->tt_endpoint); in create_sch_ep()
268 INIT_HLIST_NODE(&sch_ep->hentry); in create_sch_ep()
283 ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2)); in setup_sch_info()
284 maxpkt = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2)); in setup_sch_info()
285 max_burst = CTX_TO_MAX_BURST(le32_to_cpu(ep_ctx->ep_info2)); in setup_sch_info()
286 mult = CTX_TO_EP_MULT(le32_to_cpu(ep_ctx->ep_info)); in setup_sch_info()
289 le32_to_cpu(ep_ctx->ep_info)) << 16) | in setup_sch_info()
290 CTX_TO_MAX_ESIT_PAYLOAD(le32_to_cpu(ep_ctx->tx_info)); in setup_sch_info()
292 sch_ep->esit = get_esit(ep_ctx); in setup_sch_info()
293 sch_ep->num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit; in setup_sch_info()
294 sch_ep->ep_type = ep_type; in setup_sch_info()
295 sch_ep->maxpkt = maxpkt; in setup_sch_info()
296 sch_ep->offset = 0; in setup_sch_info()
297 sch_ep->burst_mode = 0; in setup_sch_info()
298 sch_ep->repeat = 0; in setup_sch_info()
300 if (sch_ep->speed == USB_SPEED_HIGH) { in setup_sch_info()
301 sch_ep->cs_count = 0; in setup_sch_info()
308 sch_ep->num_budget_microframes = 1; in setup_sch_info()
311 * xHCI spec section6.2.3.4 in setup_sch_info()
315 sch_ep->pkts = max_burst + 1; in setup_sch_info()
316 sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts; in setup_sch_info()
317 } else if (sch_ep->speed >= USB_SPEED_SUPER) { in setup_sch_info()
319 sch_ep->cs_count = 0; in setup_sch_info()
320 sch_ep->burst_mode = 1; in setup_sch_info()
331 sch_ep->pkts = esit_pkts; in setup_sch_info()
332 sch_ep->num_budget_microframes = 1; in setup_sch_info()
337 if (sch_ep->esit == 1) in setup_sch_info()
338 sch_ep->pkts = esit_pkts; in setup_sch_info()
339 else if (esit_pkts <= sch_ep->esit) in setup_sch_info()
340 sch_ep->pkts = 1; in setup_sch_info()
342 sch_ep->pkts = roundup_pow_of_two(esit_pkts) in setup_sch_info()
343 / sch_ep->esit; in setup_sch_info()
345 sch_ep->num_budget_microframes = in setup_sch_info()
346 DIV_ROUND_UP(esit_pkts, sch_ep->pkts); in setup_sch_info()
348 sch_ep->repeat = !!(sch_ep->num_budget_microframes > 1); in setup_sch_info()
350 sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts; in setup_sch_info()
351 } else if (is_fs_or_ls(sch_ep->speed)) { in setup_sch_info()
352 sch_ep->pkts = 1; /* at most one packet for each microframe */ in setup_sch_info()
358 sch_ep->cs_count = DIV_ROUND_UP(maxpkt, FS_PAYLOAD_MAX); in setup_sch_info()
359 sch_ep->num_budget_microframes = sch_ep->cs_count; in setup_sch_info()
360 sch_ep->bw_cost_per_microframe = min_t(u32, maxpkt, FS_PAYLOAD_MAX); in setup_sch_info()
372 for (i = 0; i < sch_ep->num_esit; i++) { in get_max_bw()
373 u32 base = offset + i * sch_ep->esit; in get_max_bw()
375 for (j = 0; j < sch_ep->num_budget_microframes; j++) { in get_max_bw()
377 bw = sch_bw->bus_bw[k] + sch_ep->bw_cost_per_microframe; in get_max_bw()
392 bw_updated = sch_ep->bw_cost_per_microframe * (used ? 1 : -1); in update_bus_bw()
394 for (i = 0; i < sch_ep->num_esit; i++) { in update_bus_bw()
395 base = sch_ep->offset + i * sch_ep->esit; in update_bus_bw()
396 for (j = 0; j < sch_ep->num_budget_microframes; j++) in update_bus_bw()
397 sch_bw->bus_bw[XHCI_MTK_BW_INDEX(base + j)] += bw_updated; in update_bus_bw()
403 struct mu3h_sch_tt *tt = sch_ep->sch_tt; in check_fs_bus_bw()
408 for (i = 0; i < sch_ep->num_esit; i++) { in check_fs_bus_bw()
409 base = offset + i * sch_ep->esit; in check_fs_bus_bw()
415 for (j = 0; j < sch_ep->num_budget_microframes; j++) { in check_fs_bus_bw()
417 tmp = tt->fs_bus_bw[k] + sch_ep->bw_cost_per_microframe; in check_fs_bus_bw()
419 return -ESCH_BW_OVERFLOW; in check_fs_bus_bw()
431 if (!sch_ep->sch_tt) in check_sch_tt()
436 if (sch_ep->ep_type == ISOC_OUT_EP) { in check_sch_tt()
437 last_ss = start_ss + sch_ep->cs_count - 1; in check_sch_tt()
441 * must never schedule Start-Split in Y6 in check_sch_tt()
444 return -ESCH_SS_Y6; in check_sch_tt()
447 u32 cs_count = DIV_ROUND_UP(sch_ep->maxpkt, FS_PAYLOAD_MAX); in check_sch_tt()
451 * must never schedule Start-Split in Y6 in check_sch_tt()
454 return -ESCH_SS_Y6; in check_sch_tt()
458 last_cs = start_cs + cs_count - 1; in check_sch_tt()
461 return -ESCH_CS_OVERFLOW; in check_sch_tt()
466 sch_ep->cs_count = cs_count; in check_sch_tt()
468 sch_ep->num_budget_microframes = cs_count; in check_sch_tt()
472 * than sch_ep->esit, will overstep boundary in check_sch_tt()
474 if (sch_ep->num_budget_microframes > sch_ep->esit) in check_sch_tt()
475 sch_ep->num_budget_microframes = sch_ep->esit; in check_sch_tt()
483 struct mu3h_sch_tt *tt = sch_ep->sch_tt; in update_sch_tt()
488 bw_updated = sch_ep->bw_cost_per_microframe * (used ? 1 : -1); in update_sch_tt()
490 for (i = 0; i < sch_ep->num_esit; i++) { in update_sch_tt()
491 base = sch_ep->offset + i * sch_ep->esit; in update_sch_tt()
493 for (j = 0; j < sch_ep->num_budget_microframes; j++) in update_sch_tt()
494 tt->fs_bus_bw[XHCI_MTK_BW_INDEX(base + j)] += bw_updated; in update_sch_tt()
498 list_add_tail(&sch_ep->tt_endpoint, &tt->ep_list); in update_sch_tt()
500 list_del(&sch_ep->tt_endpoint); in update_sch_tt()
506 if (sch_ep->sch_tt) in load_ep_bw()
511 sch_ep->allocated = loaded; in load_ep_bw()
518 struct mu3h_sch_bw_info *sch_bw = sch_ep->bw_info; in check_sch_bw()
519 const u32 bw_boundary = get_bw_boundary(sch_ep->speed); in check_sch_bw()
523 int min_index = -1; in check_sch_bw()
530 for (offset = 0; offset < sch_ep->esit; offset++) { in check_sch_bw()
544 /* use first-fit for LS/FS */ in check_sch_bw()
545 if (sch_ep->sch_tt && min_index >= 0) in check_sch_bw()
553 return ret ? ret : -ESCH_BW_OVERFLOW; in check_sch_bw()
555 sch_ep->offset = min_index; in check_sch_bw()
560 static void destroy_sch_ep(struct xhci_hcd_mtk *mtk, struct usb_device *udev, in destroy_sch_ep() argument
564 if (sch_ep->allocated) in destroy_sch_ep()
565 load_ep_bw(sch_ep->bw_info, sch_ep, false); in destroy_sch_ep()
567 if (sch_ep->sch_tt) in destroy_sch_ep()
570 list_del(&sch_ep->endpoint); in destroy_sch_ep()
571 hlist_del(&sch_ep->hentry); in destroy_sch_ep()
578 bool has_tt = udev->tt && udev->tt->hub->parent; in need_bw_sch()
581 if (usb_endpoint_xfer_control(&ep->desc) in need_bw_sch()
582 || usb_endpoint_xfer_bulk(&ep->desc)) in need_bw_sch()
587 * a TT are also ignored, root-hub will schedule them directly, in need_bw_sch()
590 if (is_fs_or_ls(udev->speed) && !has_tt) in need_bw_sch()
594 if (usb_endpoint_maxp(&ep->desc) == 0) in need_bw_sch()
600 int xhci_mtk_sch_init(struct xhci_hcd_mtk *mtk) in xhci_mtk_sch_init() argument
602 struct xhci_hcd *xhci = hcd_to_xhci(mtk->hcd); in xhci_mtk_sch_init() local
607 num_usb_bus = xhci->usb3_rhub.num_ports * 2 + xhci->usb2_rhub.num_ports; in xhci_mtk_sch_init()
611 return -ENOMEM; in xhci_mtk_sch_init()
613 mtk->sch_array = sch_array; in xhci_mtk_sch_init()
615 INIT_LIST_HEAD(&mtk->bw_ep_chk_list); in xhci_mtk_sch_init()
616 hash_init(mtk->sch_ep_hash); in xhci_mtk_sch_init()
621 void xhci_mtk_sch_exit(struct xhci_hcd_mtk *mtk) in xhci_mtk_sch_exit() argument
623 kfree(mtk->sch_array); in xhci_mtk_sch_exit()
629 struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd); in add_ep_quirk() local
630 struct xhci_hcd *xhci = hcd_to_xhci(hcd); in add_ep_quirk() local
636 virt_dev = xhci->devs[udev->slot_id]; in add_ep_quirk()
637 ep_index = xhci_get_endpoint_index(&ep->desc); in add_ep_quirk()
638 ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); in add_ep_quirk()
645 if (usb_endpoint_xfer_int(&ep->desc) in add_ep_quirk()
646 || usb_endpoint_xfer_isoc(&ep->desc)) in add_ep_quirk()
647 ep_ctx->reserved[0] = cpu_to_le32(EP_BPKTS(1)); in add_ep_quirk()
652 xhci_dbg(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed)); in add_ep_quirk()
654 sch_ep = create_sch_ep(mtk, udev, ep); in add_ep_quirk()
656 return -ENOMEM; in add_ep_quirk()
660 list_add_tail(&sch_ep->endpoint, &mtk->bw_ep_chk_list); in add_ep_quirk()
661 hash_add(mtk->sch_ep_hash, &sch_ep->hentry, (unsigned long)ep); in add_ep_quirk()
669 struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd); in drop_ep_quirk() local
670 struct xhci_hcd *xhci = hcd_to_xhci(hcd); in drop_ep_quirk() local
677 xhci_dbg(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed)); in drop_ep_quirk()
679 hash_for_each_possible_safe(mtk->sch_ep_hash, sch_ep, in drop_ep_quirk()
681 if (sch_ep->ep == ep) { in drop_ep_quirk()
682 destroy_sch_ep(mtk, udev, sch_ep); in drop_ep_quirk()
690 struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd); in xhci_mtk_check_bandwidth() local
691 struct xhci_hcd *xhci = hcd_to_xhci(hcd); in xhci_mtk_check_bandwidth() local
692 struct xhci_virt_device *virt_dev = xhci->devs[udev->slot_id]; in xhci_mtk_check_bandwidth()
696 xhci_dbg(xhci, "%s() udev %s\n", __func__, dev_name(&udev->dev)); in xhci_mtk_check_bandwidth()
698 list_for_each_entry(sch_ep, &mtk->bw_ep_chk_list, endpoint) { in xhci_mtk_check_bandwidth()
700 struct usb_host_endpoint *ep = sch_ep->ep; in xhci_mtk_check_bandwidth()
701 unsigned int ep_index = xhci_get_endpoint_index(&ep->desc); in xhci_mtk_check_bandwidth()
705 xhci_err(xhci, "Not enough bandwidth! (%s)\n", in xhci_mtk_check_bandwidth()
706 sch_error_string(-ret)); in xhci_mtk_check_bandwidth()
707 return -ENOSPC; in xhci_mtk_check_bandwidth()
710 ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); in xhci_mtk_check_bandwidth()
711 ep_ctx->reserved[0] = cpu_to_le32(EP_BPKTS(sch_ep->pkts) in xhci_mtk_check_bandwidth()
712 | EP_BCSCOUNT(sch_ep->cs_count) in xhci_mtk_check_bandwidth()
713 | EP_BBM(sch_ep->burst_mode)); in xhci_mtk_check_bandwidth()
714 ep_ctx->reserved[1] = cpu_to_le32(EP_BOFFSET(sch_ep->offset) in xhci_mtk_check_bandwidth()
715 | EP_BREPEAT(sch_ep->repeat)); in xhci_mtk_check_bandwidth()
717 xhci_dbg(xhci, " PKTS:%x, CSCOUNT:%x, BM:%x, OFFSET:%x, REPEAT:%x\n", in xhci_mtk_check_bandwidth()
718 sch_ep->pkts, sch_ep->cs_count, sch_ep->burst_mode, in xhci_mtk_check_bandwidth()
719 sch_ep->offset, sch_ep->repeat); in xhci_mtk_check_bandwidth()
724 list_del_init(&mtk->bw_ep_chk_list); in xhci_mtk_check_bandwidth()
731 struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd); in xhci_mtk_reset_bandwidth() local
732 struct xhci_hcd *xhci = hcd_to_xhci(hcd); in xhci_mtk_reset_bandwidth() local
735 xhci_dbg(xhci, "%s() udev %s\n", __func__, dev_name(&udev->dev)); in xhci_mtk_reset_bandwidth()
737 list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_chk_list, endpoint) in xhci_mtk_reset_bandwidth()
738 destroy_sch_ep(mtk, udev, sch_ep); in xhci_mtk_reset_bandwidth()
752 if (ep->hcpriv) in xhci_mtk_add_ep()
767 /* needn't check @ep->hcpriv, xhci_endpoint_disable set it NULL */ in xhci_mtk_drop_ep()