Skip to content

Commit

Permalink
usb: xhci-mtk: remove bandwidth budget table
Browse files Browse the repository at this point in the history
The bandwidth budget table is introduced to trace ideal bandwidth used
by each INT/ISOC endpoint, but in fact the endpoint may consume more
bandwidth and cause data transfer error, so it's better to leave some
margin. Obviously it's difficult to find the best margin for all cases,
instead take use of the worst-case scenario.

Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
Link: https://lore.kernel.org/r/20220512064931.31670-2-chunfeng.yun@mediatek.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Chunfeng Yun authored and Greg Kroah-Hartman committed May 12, 2022
1 parent c237566 commit 1645eee
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 64 deletions.
74 changes: 12 additions & 62 deletions drivers/usb/host/xhci-mtk-sch.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,6 @@
#define HS_BW_BOUNDARY 6144
/* usb2 spec section11.18.1: at most 188 FS bytes per microframe */
#define FS_PAYLOAD_MAX 188
/*
* max number of microframes for split transfer,
* for fs isoc in : 1 ss + 1 idle + 7 cs
*/
#define TT_MICROFRAMES_MAX 9

#define DBG_BUF_EN 64

Expand Down Expand Up @@ -242,28 +237,17 @@ static void drop_tt(struct usb_device *udev)

static struct mu3h_sch_ep_info *
create_sch_ep(struct xhci_hcd_mtk *mtk, struct usb_device *udev,
struct usb_host_endpoint *ep, struct xhci_ep_ctx *ep_ctx)
struct usb_host_endpoint *ep)
{
struct mu3h_sch_ep_info *sch_ep;
struct mu3h_sch_bw_info *bw_info;
struct mu3h_sch_tt *tt = NULL;
u32 len_bw_budget_table;

bw_info = get_bw_info(mtk, udev, ep);
if (!bw_info)
return ERR_PTR(-ENODEV);

if (is_fs_or_ls(udev->speed))
len_bw_budget_table = TT_MICROFRAMES_MAX;
else if ((udev->speed >= USB_SPEED_SUPER)
&& usb_endpoint_xfer_isoc(&ep->desc))
len_bw_budget_table = get_esit(ep_ctx);
else
len_bw_budget_table = 1;

sch_ep = kzalloc(struct_size(sch_ep, bw_budget_table,
len_bw_budget_table),
GFP_KERNEL);
sch_ep = kzalloc(sizeof(*sch_ep), GFP_KERNEL);
if (!sch_ep)
return ERR_PTR(-ENOMEM);

Expand Down Expand Up @@ -295,8 +279,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
u32 mult;
u32 esit_pkts;
u32 max_esit_payload;
u32 *bwb_table = sch_ep->bw_budget_table;
int i;

ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2));
maxpkt = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
Expand Down Expand Up @@ -332,7 +314,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
*/
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 (sch_ep->speed >= USB_SPEED_SUPER) {
/* usb3_r1 spec section4.4.7 & 4.4.8 */
sch_ep->cs_count = 0;
Expand All @@ -349,7 +330,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) {
sch_ep->pkts = esit_pkts;
sch_ep->num_budget_microframes = 1;
bwb_table[0] = maxpkt * sch_ep->pkts;
}

if (ep_type == ISOC_IN_EP || ep_type == ISOC_OUT_EP) {
Expand All @@ -366,15 +346,8 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
DIV_ROUND_UP(esit_pkts, sch_ep->pkts);

sch_ep->repeat = !!(sch_ep->num_budget_microframes > 1);
sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->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] = maxpkt * esit_pkts
- i * sch_ep->bw_cost_per_microframe;
}
sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts;
} else if (is_fs_or_ls(sch_ep->speed)) {
sch_ep->pkts = 1; /* at most one packet for each microframe */

Expand All @@ -384,28 +357,7 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
*/
sch_ep->cs_count = DIV_ROUND_UP(maxpkt, FS_PAYLOAD_MAX);
sch_ep->num_budget_microframes = sch_ep->cs_count;
sch_ep->bw_cost_per_microframe =
(maxpkt < FS_PAYLOAD_MAX) ? maxpkt : FS_PAYLOAD_MAX;

/* init budget table */
if (ep_type == ISOC_OUT_EP) {
for (i = 0; i < sch_ep->num_budget_microframes; i++)
bwb_table[i] = sch_ep->bw_cost_per_microframe;
} else if (ep_type == INT_OUT_EP) {
/* only first one consumes bandwidth, others as zero */
bwb_table[0] = sch_ep->bw_cost_per_microframe;
} else { /* INT_IN_EP or ISOC_IN_EP */
bwb_table[0] = 0; /* start split */
bwb_table[1] = 0; /* idle */
/*
* due to cs_count will be updated according to cs
* position, assign all remainder budget array
* elements as @bw_cost_per_microframe, but only first
* @num_budget_microframes elements will be used later
*/
for (i = 2; i < TT_MICROFRAMES_MAX; i++)
bwb_table[i] = sch_ep->bw_cost_per_microframe;
}
sch_ep->bw_cost_per_microframe = min_t(u32, maxpkt, FS_PAYLOAD_MAX);
}
}

Expand All @@ -422,7 +374,7 @@ static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw,

for (j = 0; j < sch_ep->num_budget_microframes; j++) {
k = XHCI_MTK_BW_INDEX(base + j);
bw = sch_bw->bus_bw[k] + sch_ep->bw_budget_table[j];
bw = sch_bw->bus_bw[k] + sch_ep->bw_cost_per_microframe;
if (bw > max_bw)
max_bw = bw;
}
Expand All @@ -433,18 +385,16 @@ static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw,
static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw,
struct mu3h_sch_ep_info *sch_ep, bool used)
{
int bw_updated;
u32 base;
int i, j, k;
int i, j;

bw_updated = sch_ep->bw_cost_per_microframe * (used ? 1 : -1);

for (i = 0; i < sch_ep->num_esit; i++) {
base = sch_ep->offset + i * sch_ep->esit;
for (j = 0; j < sch_ep->num_budget_microframes; j++) {
k = XHCI_MTK_BW_INDEX(base + j);
if (used)
sch_bw->bus_bw[k] += sch_ep->bw_budget_table[j];
else
sch_bw->bus_bw[k] -= sch_ep->bw_budget_table[j];
}
for (j = 0; j < sch_ep->num_budget_microframes; j++)
sch_bw->bus_bw[XHCI_MTK_BW_INDEX(base + j)] += bw_updated;
}
}

Expand Down Expand Up @@ -708,7 +658,7 @@ static int add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,

xhci_dbg(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed));

sch_ep = create_sch_ep(mtk, udev, ep, ep_ctx);
sch_ep = create_sch_ep(mtk, udev, ep);
if (IS_ERR_OR_NULL(sch_ep))
return -ENOMEM;

Expand Down
2 changes: 0 additions & 2 deletions drivers/usb/host/xhci-mtk.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ struct mu3h_sch_bw_info {
* times; 1: distribute the (bMaxBurst+1)*(Mult+1) packets
* according to @pkts and @repeat. normal mode is used by
* default
* @bw_budget_table: table to record bandwidth budget per microframe
*/
struct mu3h_sch_ep_info {
u32 esit;
Expand All @@ -109,7 +108,6 @@ struct mu3h_sch_ep_info {
u32 pkts;
u32 cs_count;
u32 burst_mode;
u32 bw_budget_table[];
};

#define MU3C_U3_PORT_MAX 4
Expand Down

0 comments on commit 1645eee

Please sign in to comment.