On Thu, 2021-08-05 at 13:39 +0800, Ikjoon Jang wrote: > Currently xhci-mtk needs software-managed bandwidth allocation for > periodic endpoints, it allocates the microframe index for the first > start-split packet for each endpoint. As this index allocation logic > should avoid the conflicts with other full/low-speed periodic > endpoints, > it uses the worst case byte budgets on high-speed bus bandwidth > For example, for an isochronos IN endpoint with 192 bytes budget, > it will consume the whole 4 u-frames(188 * 4) while the actual > full-speed bus budget should be just 192bytes. > > This patch changes the low/full-speed bandwidth allocation logic > to use "approximate" best case budget for lower speed bandwidth > management. For the same endpoint from the above example, the > approximate best case budget is now reduced to (188 * 2) bytes. > > Without this patch, many usb audio headsets with 3 interfaces > (audio input, audio output, and HID) cannot be configured > on xhci-mtk. > > Signed-off-by: Ikjoon Jang <ikjn@xxxxxxxxxxxx> > --- > > drivers/usb/host/xhci-mtk-sch.c | 20 +++++++++++++------- > 1 file changed, 13 insertions(+), 7 deletions(-) > > diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci- > mtk-sch.c > index f9b4d27ce449..46cbf5d54f4f 100644 > --- a/drivers/usb/host/xhci-mtk-sch.c > +++ b/drivers/usb/host/xhci-mtk-sch.c > @@ -459,16 +459,17 @@ static int check_fs_bus_bw(struct > mu3h_sch_ep_info *sch_ep, int offset) > u32 num_esit, tmp; > int base; > int i, j; > + u8 uframes = DIV_ROUND_UP(sch_ep->maxpkt, FS_PAYLOAD_MAX); > > num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit; > + > + if (sch_ep->ep_type == INT_IN_EP || sch_ep->ep_type == > ISOC_IN_EP) > + offset++; > + > 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++) { > + for (j = 0; j < uframes; j++) { Please don't calculate new value, should use the value calculated by check_sch_tt(). See usb2.0 spec Figure 11-64, sometime will use 2 extra CS. > tmp = tt->fs_bus_bw[base + j] + sch_ep- > >bw_cost_per_microframe; > if (tmp > FS_PAYLOAD_MAX) > return -ESCH_BW_OVERFLOW; > @@ -546,6 +547,8 @@ static void update_sch_tt(struct mu3h_sch_ep_info > *sch_ep, bool used) > u32 base, num_esit; > int bw_updated; > int i, j; > + int offset = sch_ep->offset; > + u8 uframes = DIV_ROUND_UP(sch_ep->maxpkt, FS_PAYLOAD_MAX); > > num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit; > > @@ -554,10 +557,13 @@ static void update_sch_tt(struct > mu3h_sch_ep_info *sch_ep, bool used) > else > bw_updated = -sch_ep->bw_cost_per_microframe; > > + if (sch_ep->ep_type == INT_IN_EP || sch_ep->ep_type == > ISOC_IN_EP) > + offset++; > + > for (i = 0; i < num_esit; i++) { > - base = sch_ep->offset + i * sch_ep->esit; > + base = offset + i * sch_ep->esit; > > - for (j = 0; j < sch_ep->cs_count; j++) > + for (j = 0; j < uframes; j++) > tt->fs_bus_bw[base + j] += bw_updated; > } >