diff options
Diffstat (limited to 'drivers/usb/host/xhci-mtk-sch.c')
-rw-r--r-- | drivers/usb/host/xhci-mtk-sch.c | 369 |
1 files changed, 241 insertions, 128 deletions
diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c index b45e5bf08997..8b90da5a6ed1 100644 --- a/drivers/usb/host/xhci-mtk-sch.c +++ b/drivers/usb/host/xhci-mtk-sch.c @@ -25,6 +25,15 @@ */ #define TT_MICROFRAMES_MAX 9 +#define DBG_BUF_EN 64 + +/* schedule error type */ +#define ESCH_SS_Y6 1001 +#define ESCH_SS_OVERLAP 1002 +#define ESCH_CS_OVERFLOW 1003 +#define ESCH_BW_OVERFLOW 1004 +#define ESCH_FIXME 1005 + /* mtk scheduler bitmasks */ #define EP_BPKTS(p) ((p) & 0x7f) #define EP_BCSCOUNT(p) (((p) & 0x7) << 8) @@ -32,13 +41,75 @@ #define EP_BOFFSET(p) ((p) & 0x3fff) #define EP_BREPEAT(p) (((p) & 0x7fff) << 16) +static char *sch_error_string(int err_num) +{ + switch (err_num) { + case ESCH_SS_Y6: + return "Can't schedule Start-Split in Y6"; + case ESCH_SS_OVERLAP: + return "Can't find a suitable Start-Split location"; + case ESCH_CS_OVERFLOW: + return "The last Complete-Split is greater than 7"; + case ESCH_BW_OVERFLOW: + return "Bandwidth exceeds the maximum limit"; + case ESCH_FIXME: + return "FIXME, to be resolved"; + default: + return "Unknown"; + } +} + static int is_fs_or_ls(enum usb_device_speed speed) { return speed == USB_SPEED_FULL || speed == USB_SPEED_LOW; } +static const char * +decode_ep(struct usb_host_endpoint *ep, enum usb_device_speed speed) +{ + static char buf[DBG_BUF_EN]; + struct usb_endpoint_descriptor *epd = &ep->desc; + unsigned int interval; + const char *unit; + + interval = usb_decode_interval(epd, speed); + if (interval % 1000) { + unit = "us"; + } else { + unit = "ms"; + interval /= 1000; + } + + snprintf(buf, DBG_BUF_EN, "%s ep%d%s %s, mpkt:%d, interval:%d/%d%s\n", + usb_speed_string(speed), usb_endpoint_num(epd), + usb_endpoint_dir_in(epd) ? "in" : "out", + usb_ep_type_string(usb_endpoint_type(epd)), + usb_endpoint_maxp(epd), epd->bInterval, interval, unit); + + return buf; +} + +static u32 get_bw_boundary(enum usb_device_speed speed) +{ + u32 boundary; + + switch (speed) { + case USB_SPEED_SUPER_PLUS: + boundary = SSP_BW_BOUNDARY; + break; + case USB_SPEED_SUPER: + boundary = SS_BW_BOUNDARY; + break; + default: + boundary = HS_BW_BOUNDARY; + break; + } + + return boundary; +} + /* -* get the index of bandwidth domains array which @ep belongs to. +* get the bandwidth domain which @ep belongs to. * * the bandwidth domain array is saved to @sch_array of struct xhci_hcd_mtk, * each HS root port is treated as a single bandwidth domain, @@ -49,9 +120,11 @@ static int is_fs_or_ls(enum usb_device_speed speed) * so the bandwidth domain array is organized as follow for simplification: * SSport0-OUT, SSport0-IN, ..., SSportX-OUT, SSportX-IN, HSport0, ..., HSportY */ -static int get_bw_index(struct xhci_hcd *xhci, struct usb_device *udev, - struct usb_host_endpoint *ep) +static struct mu3h_sch_bw_info * +get_bw_info(struct xhci_hcd_mtk *mtk, struct usb_device *udev, + struct usb_host_endpoint *ep) { + struct xhci_hcd *xhci = hcd_to_xhci(mtk->hcd); struct xhci_virt_device *virt_dev; int bw_index; @@ -67,7 +140,7 @@ static int get_bw_index(struct xhci_hcd *xhci, struct usb_device *udev, bw_index = virt_dev->real_port + xhci->usb3_rhub.num_ports - 1; } - return bw_index; + return &mtk->sch_array[bw_index]; } static u32 get_esit(struct xhci_ep_ctx *ep_ctx) @@ -85,7 +158,6 @@ static struct mu3h_sch_tt *find_tt(struct usb_device *udev) { struct usb_tt *utt = udev->tt; struct mu3h_sch_tt *tt, **tt_index, **ptt; - unsigned int port; bool allocated_index = false; if (!utt) @@ -107,10 +179,8 @@ static struct mu3h_sch_tt *find_tt(struct usb_device *udev) utt->hcpriv = tt_index; allocated_index = true; } - port = udev->ttport - 1; - ptt = &tt_index[port]; + ptt = &tt_index[udev->ttport - 1]; } else { - port = 0; ptt = (struct mu3h_sch_tt **) &utt->hcpriv; } @@ -125,8 +195,6 @@ static struct mu3h_sch_tt *find_tt(struct usb_device *udev) return ERR_PTR(-ENOMEM); } INIT_LIST_HEAD(&tt->ep_list); - tt->usb_tt = utt; - tt->tt_port = port; *ptt = tt; } @@ -200,14 +268,15 @@ static struct mu3h_sch_ep_info *create_sch_ep(struct usb_device *udev, sch_ep->sch_tt = tt; sch_ep->ep = ep; + sch_ep->speed = udev->speed; INIT_LIST_HEAD(&sch_ep->endpoint); INIT_LIST_HEAD(&sch_ep->tt_endpoint); return sch_ep; } -static void setup_sch_info(struct usb_device *udev, - struct xhci_ep_ctx *ep_ctx, struct mu3h_sch_ep_info *sch_ep) +static void setup_sch_info(struct xhci_ep_ctx *ep_ctx, + struct mu3h_sch_ep_info *sch_ep) { u32 ep_type; u32 maxpkt; @@ -234,7 +303,7 @@ static void setup_sch_info(struct usb_device *udev, sch_ep->burst_mode = 0; sch_ep->repeat = 0; - if (udev->speed == USB_SPEED_HIGH) { + if (sch_ep->speed == USB_SPEED_HIGH) { sch_ep->cs_count = 0; /* @@ -252,7 +321,7 @@ static void setup_sch_info(struct usb_device *udev, sch_ep->pkts = max_burst + 1; sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts; bwb_table[0] = sch_ep->bw_cost_per_microframe; - } else if (udev->speed >= USB_SPEED_SUPER) { + } else if (sch_ep->speed >= USB_SPEED_SUPER) { /* usb3_r1 spec section4.4.7 & 4.4.8 */ sch_ep->cs_count = 0; sch_ep->burst_mode = 1; @@ -272,7 +341,6 @@ static void setup_sch_info(struct usb_device *udev, } if (ep_type == ISOC_IN_EP || ep_type == ISOC_OUT_EP) { - u32 remainder; if (sch_ep->esit == 1) sch_ep->pkts = esit_pkts; @@ -288,16 +356,14 @@ static void setup_sch_info(struct usb_device *udev, sch_ep->repeat = !!(sch_ep->num_budget_microframes > 1); sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts; - remainder = sch_ep->bw_cost_per_microframe; - remainder *= sch_ep->num_budget_microframes; - remainder -= (maxpkt * esit_pkts); for (i = 0; i < sch_ep->num_budget_microframes - 1; i++) bwb_table[i] = sch_ep->bw_cost_per_microframe; /* last one <= bw_cost_per_microframe */ - bwb_table[i] = remainder; + bwb_table[i] = maxpkt * esit_pkts + - i * sch_ep->bw_cost_per_microframe; } - } else if (is_fs_or_ls(udev->speed)) { + } else if (is_fs_or_ls(sch_ep->speed)) { sch_ep->pkts = 1; /* at most one packet for each microframe */ /* @@ -375,21 +441,42 @@ static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw, sch_ep->bw_budget_table[j]; } } - sch_ep->allocated = used; } -static int check_sch_tt(struct usb_device *udev, - struct mu3h_sch_ep_info *sch_ep, u32 offset) +static int check_fs_bus_bw(struct mu3h_sch_ep_info *sch_ep, int offset) +{ + struct mu3h_sch_tt *tt = sch_ep->sch_tt; + u32 num_esit, tmp; + int base; + int i, j; + + num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit; + for (i = 0; i < num_esit; i++) { + base = offset + i * sch_ep->esit; + + /* + * Compared with hs bus, no matter what ep type, + * the hub will always delay one uframe to send data + */ + for (j = 0; j < sch_ep->cs_count; j++) { + tmp = tt->fs_bus_bw[base + j] + sch_ep->bw_cost_per_microframe; + if (tmp > FS_PAYLOAD_MAX) + return -ESCH_BW_OVERFLOW; + } + } + + return 0; +} + +static int check_sch_tt(struct mu3h_sch_ep_info *sch_ep, u32 offset) { struct mu3h_sch_tt *tt = sch_ep->sch_tt; u32 extra_cs_count; - u32 fs_budget_start; u32 start_ss, last_ss; u32 start_cs, last_cs; int i; start_ss = offset % 8; - fs_budget_start = (start_ss + 1) % 8; if (sch_ep->ep_type == ISOC_OUT_EP) { last_ss = start_ss + sch_ep->cs_count - 1; @@ -399,11 +486,11 @@ static int check_sch_tt(struct usb_device *udev, * must never schedule Start-Split in Y6 */ if (!(start_ss == 7 || last_ss < 6)) - return -ERANGE; + return -ESCH_SS_Y6; for (i = 0; i < sch_ep->cs_count; i++) - if (test_bit(offset + i, tt->split_bit_map)) - return -ERANGE; + if (test_bit(offset + i, tt->ss_bit_map)) + return -ESCH_SS_OVERLAP; } else { u32 cs_count = DIV_ROUND_UP(sch_ep->maxpkt, FS_PAYLOAD_MAX); @@ -413,28 +500,26 @@ static int check_sch_tt(struct usb_device *udev, * must never schedule Start-Split in Y6 */ if (start_ss == 6) - return -ERANGE; + return -ESCH_SS_Y6; /* one uframe for ss + one uframe for idle */ start_cs = (start_ss + 2) % 8; last_cs = start_cs + cs_count - 1; if (last_cs > 7) - return -ERANGE; + return -ESCH_CS_OVERFLOW; if (sch_ep->ep_type == ISOC_IN_EP) extra_cs_count = (last_cs == 7) ? 1 : 2; else /* ep_type : INTR IN / INTR OUT */ - extra_cs_count = (fs_budget_start == 6) ? 1 : 2; + extra_cs_count = 1; cs_count += extra_cs_count; if (cs_count > 7) cs_count = 7; /* HW limit */ - for (i = 0; i < cs_count + 2; i++) { - if (test_bit(offset + i, tt->split_bit_map)) - return -ERANGE; - } + if (test_bit(offset, tt->ss_bit_map)) + return -ESCH_SS_OVERLAP; sch_ep->cs_count = cs_count; /* one for ss, the other for idle */ @@ -448,41 +533,85 @@ static int check_sch_tt(struct usb_device *udev, sch_ep->num_budget_microframes = sch_ep->esit; } - return 0; + return check_fs_bus_bw(sch_ep, offset); } -static void update_sch_tt(struct usb_device *udev, - struct mu3h_sch_ep_info *sch_ep) +static void update_sch_tt(struct mu3h_sch_ep_info *sch_ep, bool used) { struct mu3h_sch_tt *tt = sch_ep->sch_tt; u32 base, num_esit; + int bw_updated; + int bits; int i, j; num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit; + bits = (sch_ep->ep_type == ISOC_OUT_EP) ? sch_ep->cs_count : 1; + + if (used) + bw_updated = sch_ep->bw_cost_per_microframe; + else + bw_updated = -sch_ep->bw_cost_per_microframe; + for (i = 0; i < num_esit; i++) { base = sch_ep->offset + i * sch_ep->esit; - for (j = 0; j < sch_ep->num_budget_microframes; j++) - set_bit(base + j, tt->split_bit_map); + + for (j = 0; j < bits; j++) { + if (used) + set_bit(base + j, tt->ss_bit_map); + else + clear_bit(base + j, tt->ss_bit_map); + } + + for (j = 0; j < sch_ep->cs_count; j++) + tt->fs_bus_bw[base + j] += bw_updated; } - list_add_tail(&sch_ep->tt_endpoint, &tt->ep_list); + if (used) + list_add_tail(&sch_ep->tt_endpoint, &tt->ep_list); + else + list_del(&sch_ep->tt_endpoint); } -static int check_sch_bw(struct usb_device *udev, - struct mu3h_sch_bw_info *sch_bw, struct mu3h_sch_ep_info *sch_ep) +static int load_ep_bw(struct mu3h_sch_bw_info *sch_bw, + struct mu3h_sch_ep_info *sch_ep, bool loaded) +{ + if (sch_ep->sch_tt) + update_sch_tt(sch_ep, loaded); + + /* update bus bandwidth info */ + update_bus_bw(sch_bw, sch_ep, loaded); + sch_ep->allocated = loaded; + + return 0; +} + +static u32 get_esit_boundary(struct mu3h_sch_ep_info *sch_ep) +{ + u32 boundary = sch_ep->esit; + + if (sch_ep->sch_tt) { /* LS/FS with TT */ + /* tune for CS */ + if (sch_ep->ep_type != ISOC_OUT_EP) + boundary++; + else if (boundary > 1) /* normally esit >= 8 for FS/LS */ + boundary--; + } + + return boundary; +} + +static int check_sch_bw(struct mu3h_sch_bw_info *sch_bw, + struct mu3h_sch_ep_info *sch_ep) { u32 offset; - u32 esit; u32 min_bw; u32 min_index; u32 worst_bw; u32 bw_boundary; + u32 esit_boundary; u32 min_num_budget; u32 min_cs_count; - bool tt_offset_ok = false; - int ret; - - esit = sch_ep->esit; + int ret = 0; /* * Search through all possible schedule microframes. @@ -492,16 +621,15 @@ static int check_sch_bw(struct usb_device *udev, min_index = 0; min_cs_count = sch_ep->cs_count; min_num_budget = sch_ep->num_budget_microframes; - for (offset = 0; offset < esit; offset++) { - if (is_fs_or_ls(udev->speed)) { - ret = check_sch_tt(udev, sch_ep, offset); + esit_boundary = get_esit_boundary(sch_ep); + for (offset = 0; offset < sch_ep->esit; offset++) { + if (sch_ep->sch_tt) { + ret = check_sch_tt(sch_ep, offset); if (ret) continue; - else - tt_offset_ok = true; } - if ((offset + sch_ep->num_budget_microframes) > sch_ep->esit) + if ((offset + sch_ep->num_budget_microframes) > esit_boundary) break; worst_bw = get_max_bw(sch_bw, sch_ep, offset); @@ -515,33 +643,16 @@ static int check_sch_bw(struct usb_device *udev, break; } - if (udev->speed == USB_SPEED_SUPER_PLUS) - bw_boundary = SSP_BW_BOUNDARY; - else if (udev->speed == USB_SPEED_SUPER) - bw_boundary = SS_BW_BOUNDARY; - else - bw_boundary = HS_BW_BOUNDARY; - + bw_boundary = get_bw_boundary(sch_ep->speed); /* check bandwidth */ if (min_bw > bw_boundary) - return -ERANGE; + return ret ? ret : -ESCH_BW_OVERFLOW; sch_ep->offset = min_index; sch_ep->cs_count = min_cs_count; sch_ep->num_budget_microframes = min_num_budget; - if (is_fs_or_ls(udev->speed)) { - /* all offset for tt is not ok*/ - if (!tt_offset_ok) - return -ERANGE; - - update_sch_tt(udev, sch_ep); - } - - /* update bus bandwidth info */ - update_bus_bw(sch_bw, sch_ep, 1); - - return 0; + return load_ep_bw(sch_bw, sch_ep, true); } static void destroy_sch_ep(struct usb_device *udev, @@ -549,14 +660,12 @@ static void destroy_sch_ep(struct usb_device *udev, { /* only release ep bw check passed by check_sch_bw() */ if (sch_ep->allocated) - update_bus_bw(sch_bw, sch_ep, 0); + load_ep_bw(sch_bw, sch_ep, false); - list_del(&sch_ep->endpoint); - - if (sch_ep->sch_tt) { - list_del(&sch_ep->tt_endpoint); + if (sch_ep->sch_tt) drop_tt(udev); - } + + list_del(&sch_ep->endpoint); kfree(sch_ep); } @@ -606,44 +715,36 @@ int xhci_mtk_sch_init(struct xhci_hcd_mtk *mtk) return 0; } -EXPORT_SYMBOL_GPL(xhci_mtk_sch_init); void xhci_mtk_sch_exit(struct xhci_hcd_mtk *mtk) { kfree(mtk->sch_array); } -EXPORT_SYMBOL_GPL(xhci_mtk_sch_exit); -int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev, - struct usb_host_endpoint *ep) +static int add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev, + struct usb_host_endpoint *ep) { struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd); - struct xhci_hcd *xhci; + struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_ep_ctx *ep_ctx; - struct xhci_slot_ctx *slot_ctx; struct xhci_virt_device *virt_dev; struct mu3h_sch_ep_info *sch_ep; unsigned int ep_index; - xhci = hcd_to_xhci(hcd); virt_dev = xhci->devs[udev->slot_id]; ep_index = xhci_get_endpoint_index(&ep->desc); - slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx); ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); - xhci_dbg(xhci, "%s() type:%d, speed:%d, mpkt:%d, dir:%d, ep:%p\n", - __func__, usb_endpoint_type(&ep->desc), udev->speed, - usb_endpoint_maxp(&ep->desc), - usb_endpoint_dir_in(&ep->desc), ep); + xhci_dbg(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed)); - if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT)) { + if (!need_bw_sch(ep, udev->speed, !!virt_dev->tt_info)) { /* * set @bpkts to 1 if it is LS or FS periodic endpoint, and its * device does not connected through an external HS hub */ if (usb_endpoint_xfer_int(&ep->desc) || usb_endpoint_xfer_isoc(&ep->desc)) - ep_ctx->reserved[0] |= cpu_to_le32(EP_BPKTS(1)); + ep_ctx->reserved[0] = cpu_to_le32(EP_BPKTS(1)); return 0; } @@ -652,41 +753,30 @@ int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev, if (IS_ERR_OR_NULL(sch_ep)) return -ENOMEM; - setup_sch_info(udev, ep_ctx, sch_ep); + setup_sch_info(ep_ctx, sch_ep); list_add_tail(&sch_ep->endpoint, &mtk->bw_ep_chk_list); return 0; } -EXPORT_SYMBOL_GPL(xhci_mtk_add_ep_quirk); -void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev, - struct usb_host_endpoint *ep) +static void drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev, + struct usb_host_endpoint *ep) { struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd); - struct xhci_hcd *xhci; - struct xhci_slot_ctx *slot_ctx; + struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_virt_device *virt_dev; - struct mu3h_sch_bw_info *sch_array; struct mu3h_sch_bw_info *sch_bw; struct mu3h_sch_ep_info *sch_ep, *tmp; - int bw_index; - xhci = hcd_to_xhci(hcd); virt_dev = xhci->devs[udev->slot_id]; - slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx); - sch_array = mtk->sch_array; - xhci_dbg(xhci, "%s() type:%d, speed:%d, mpks:%d, dir:%d, ep:%p\n", - __func__, usb_endpoint_type(&ep->desc), udev->speed, - usb_endpoint_maxp(&ep->desc), - usb_endpoint_dir_in(&ep->desc), ep); + xhci_dbg(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed)); - if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT)) + if (!need_bw_sch(ep, udev->speed, !!virt_dev->tt_info)) return; - bw_index = get_bw_index(xhci, udev, ep); - sch_bw = &sch_array[bw_index]; + sch_bw = get_bw_info(mtk, udev, ep); list_for_each_entry_safe(sch_ep, tmp, &sch_bw->bw_ep_list, endpoint) { if (sch_ep->ep == ep) { @@ -695,7 +785,6 @@ void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev, } } } -EXPORT_SYMBOL_GPL(xhci_mtk_drop_ep_quirk); int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) { @@ -704,17 +793,17 @@ int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) struct xhci_virt_device *virt_dev = xhci->devs[udev->slot_id]; struct mu3h_sch_bw_info *sch_bw; struct mu3h_sch_ep_info *sch_ep, *tmp; - int bw_index, ret; + int ret; xhci_dbg(xhci, "%s() udev %s\n", __func__, dev_name(&udev->dev)); list_for_each_entry(sch_ep, &mtk->bw_ep_chk_list, endpoint) { - bw_index = get_bw_index(xhci, udev, sch_ep->ep); - sch_bw = &mtk->sch_array[bw_index]; + sch_bw = get_bw_info(mtk, udev, sch_ep->ep); - ret = check_sch_bw(udev, sch_bw, sch_ep); + ret = check_sch_bw(sch_bw, sch_ep); if (ret) { - xhci_err(xhci, "Not enough bandwidth!\n"); + xhci_err(xhci, "Not enough bandwidth! (%s)\n", + sch_error_string(-ret)); return -ENOSPC; } } @@ -724,16 +813,14 @@ int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) struct usb_host_endpoint *ep = sch_ep->ep; unsigned int ep_index = xhci_get_endpoint_index(&ep->desc); - bw_index = get_bw_index(xhci, udev, ep); - sch_bw = &mtk->sch_array[bw_index]; - + sch_bw = get_bw_info(mtk, udev, ep); list_move_tail(&sch_ep->endpoint, &sch_bw->bw_ep_list); ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); - ep_ctx->reserved[0] |= cpu_to_le32(EP_BPKTS(sch_ep->pkts) + ep_ctx->reserved[0] = cpu_to_le32(EP_BPKTS(sch_ep->pkts) | EP_BCSCOUNT(sch_ep->cs_count) | EP_BBM(sch_ep->burst_mode)); - ep_ctx->reserved[1] |= cpu_to_le32(EP_BOFFSET(sch_ep->offset) + ep_ctx->reserved[1] = cpu_to_le32(EP_BOFFSET(sch_ep->offset) | EP_BREPEAT(sch_ep->repeat)); xhci_dbg(xhci, " PKTS:%x, CSCOUNT:%x, BM:%x, OFFSET:%x, REPEAT:%x\n", @@ -743,7 +830,6 @@ int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) return xhci_check_bandwidth(hcd, udev); } -EXPORT_SYMBOL_GPL(xhci_mtk_check_bandwidth); void xhci_mtk_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) { @@ -751,16 +837,43 @@ void xhci_mtk_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct mu3h_sch_bw_info *sch_bw; struct mu3h_sch_ep_info *sch_ep, *tmp; - int bw_index; xhci_dbg(xhci, "%s() udev %s\n", __func__, dev_name(&udev->dev)); list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_chk_list, endpoint) { - bw_index = get_bw_index(xhci, udev, sch_ep->ep); - sch_bw = &mtk->sch_array[bw_index]; + sch_bw = get_bw_info(mtk, udev, sch_ep->ep); destroy_sch_ep(udev, sch_bw, sch_ep); } xhci_reset_bandwidth(hcd, udev); } -EXPORT_SYMBOL_GPL(xhci_mtk_reset_bandwidth); + +int xhci_mtk_add_ep(struct usb_hcd *hcd, struct usb_device *udev, + struct usb_host_endpoint *ep) +{ + int ret; + + ret = xhci_add_endpoint(hcd, udev, ep); + if (ret) + return ret; + + if (ep->hcpriv) + ret = add_ep_quirk(hcd, udev, ep); + + return ret; +} + +int xhci_mtk_drop_ep(struct usb_hcd *hcd, struct usb_device *udev, + struct usb_host_endpoint *ep) +{ + int ret; + + ret = xhci_drop_endpoint(hcd, udev, ep); + if (ret) + return ret; + + if (ep->hcpriv) + drop_ep_quirk(hcd, udev, ep); + + return 0; +} |