Commit 1645eee0 authored by Chunfeng Yun's avatar Chunfeng Yun Committed by Greg Kroah-Hartman

usb: xhci-mtk: remove bandwidth budget table

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: default avatarChunfeng Yun <chunfeng.yun@mediatek.com>
Link: https://lore.kernel.org/r/20220512064931.31670-2-chunfeng.yun@mediatek.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent c237566b
...@@ -19,11 +19,6 @@ ...@@ -19,11 +19,6 @@
#define HS_BW_BOUNDARY 6144 #define HS_BW_BOUNDARY 6144
/* usb2 spec section11.18.1: at most 188 FS bytes per microframe */ /* usb2 spec section11.18.1: at most 188 FS bytes per microframe */
#define FS_PAYLOAD_MAX 188 #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 #define DBG_BUF_EN 64
...@@ -242,28 +237,17 @@ static void drop_tt(struct usb_device *udev) ...@@ -242,28 +237,17 @@ static void drop_tt(struct usb_device *udev)
static struct mu3h_sch_ep_info * static struct mu3h_sch_ep_info *
create_sch_ep(struct xhci_hcd_mtk *mtk, struct usb_device *udev, 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_ep_info *sch_ep;
struct mu3h_sch_bw_info *bw_info; struct mu3h_sch_bw_info *bw_info;
struct mu3h_sch_tt *tt = NULL; struct mu3h_sch_tt *tt = NULL;
u32 len_bw_budget_table;
bw_info = get_bw_info(mtk, udev, ep); bw_info = get_bw_info(mtk, udev, ep);
if (!bw_info) if (!bw_info)
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
if (is_fs_or_ls(udev->speed)) sch_ep = kzalloc(sizeof(*sch_ep), GFP_KERNEL);
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);
if (!sch_ep) if (!sch_ep)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
...@@ -295,8 +279,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx, ...@@ -295,8 +279,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
u32 mult; u32 mult;
u32 esit_pkts; u32 esit_pkts;
u32 max_esit_payload; 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)); ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2));
maxpkt = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2)); maxpkt = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
...@@ -332,7 +314,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx, ...@@ -332,7 +314,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
*/ */
sch_ep->pkts = max_burst + 1; sch_ep->pkts = max_burst + 1;
sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts; 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) { } else if (sch_ep->speed >= USB_SPEED_SUPER) {
/* usb3_r1 spec section4.4.7 & 4.4.8 */ /* usb3_r1 spec section4.4.7 & 4.4.8 */
sch_ep->cs_count = 0; sch_ep->cs_count = 0;
...@@ -349,7 +330,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx, ...@@ -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) { if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) {
sch_ep->pkts = esit_pkts; sch_ep->pkts = esit_pkts;
sch_ep->num_budget_microframes = 1; sch_ep->num_budget_microframes = 1;
bwb_table[0] = maxpkt * sch_ep->pkts;
} }
if (ep_type == ISOC_IN_EP || ep_type == ISOC_OUT_EP) { if (ep_type == ISOC_IN_EP || ep_type == ISOC_OUT_EP) {
...@@ -366,15 +346,8 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx, ...@@ -366,15 +346,8 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
DIV_ROUND_UP(esit_pkts, sch_ep->pkts); DIV_ROUND_UP(esit_pkts, sch_ep->pkts);
sch_ep->repeat = !!(sch_ep->num_budget_microframes > 1); 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)) { } else if (is_fs_or_ls(sch_ep->speed)) {
sch_ep->pkts = 1; /* at most one packet for each microframe */ sch_ep->pkts = 1; /* at most one packet for each microframe */
...@@ -384,28 +357,7 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx, ...@@ -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->cs_count = DIV_ROUND_UP(maxpkt, FS_PAYLOAD_MAX);
sch_ep->num_budget_microframes = sch_ep->cs_count; sch_ep->num_budget_microframes = sch_ep->cs_count;
sch_ep->bw_cost_per_microframe = sch_ep->bw_cost_per_microframe = min_t(u32, maxpkt, FS_PAYLOAD_MAX);
(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;
}
} }
} }
...@@ -422,7 +374,7 @@ static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw, ...@@ -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++) { for (j = 0; j < sch_ep->num_budget_microframes; j++) {
k = XHCI_MTK_BW_INDEX(base + 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) if (bw > max_bw)
max_bw = bw; max_bw = bw;
} }
...@@ -433,18 +385,16 @@ static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw, ...@@ -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, static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw,
struct mu3h_sch_ep_info *sch_ep, bool used) struct mu3h_sch_ep_info *sch_ep, bool used)
{ {
int bw_updated;
u32 base; 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++) { for (i = 0; i < sch_ep->num_esit; i++) {
base = sch_ep->offset + i * sch_ep->esit; base = sch_ep->offset + i * sch_ep->esit;
for (j = 0; j < sch_ep->num_budget_microframes; j++) { for (j = 0; j < sch_ep->num_budget_microframes; j++)
k = XHCI_MTK_BW_INDEX(base + j); sch_bw->bus_bw[XHCI_MTK_BW_INDEX(base + j)] += bw_updated;
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];
}
} }
} }
...@@ -708,7 +658,7 @@ static int add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev, ...@@ -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)); 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)) if (IS_ERR_OR_NULL(sch_ep))
return -ENOMEM; return -ENOMEM;
......
...@@ -83,7 +83,6 @@ struct mu3h_sch_bw_info { ...@@ -83,7 +83,6 @@ struct mu3h_sch_bw_info {
* times; 1: distribute the (bMaxBurst+1)*(Mult+1) packets * times; 1: distribute the (bMaxBurst+1)*(Mult+1) packets
* according to @pkts and @repeat. normal mode is used by * according to @pkts and @repeat. normal mode is used by
* default * default
* @bw_budget_table: table to record bandwidth budget per microframe
*/ */
struct mu3h_sch_ep_info { struct mu3h_sch_ep_info {
u32 esit; u32 esit;
...@@ -109,7 +108,6 @@ struct mu3h_sch_ep_info { ...@@ -109,7 +108,6 @@ struct mu3h_sch_ep_info {
u32 pkts; u32 pkts;
u32 cs_count; u32 cs_count;
u32 burst_mode; u32 burst_mode;
u32 bw_budget_table[];
}; };
#define MU3C_U3_PORT_MAX 4 #define MU3C_U3_PORT_MAX 4
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment