usb: xhci-mtk: allow bandwidth table rollover

xhci-mtk has 64 slots for periodic bandwidth calculations and each
slot represents byte budgets on a microframe. When an endpoint's
allocation sits on the boundary of the table, byte budgets' slot
can be rolled over but the current implementation doesn't.

This patch allows the microframe index rollover and prevent
out-of-bounds array access.

Signed-off-by: Ikjoon Jang <ikjn@chromium.org>
Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
Link: https://lore.kernel.org/r/20210827033105.26595-1-chunfeng.yun@mediatek.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Chunfeng Yun 2021-08-27 11:31:05 +08:00 committed by Greg Kroah-Hartman
parent 452d1ea55c
commit b7d509a92b
2 changed files with 18 additions and 39 deletions

View File

@ -416,15 +416,14 @@ static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw,
{
u32 max_bw = 0;
u32 bw;
int i;
int j;
int i, j, k;
for (i = 0; i < sch_ep->num_esit; i++) {
u32 base = offset + i * sch_ep->esit;
for (j = 0; j < sch_ep->num_budget_microframes; j++) {
bw = sch_bw->bus_bw[base + j] +
sch_ep->bw_budget_table[j];
k = XHCI_MTK_BW_INDEX(base + j);
bw = sch_bw->bus_bw[k] + sch_ep->bw_budget_table[j];
if (bw > max_bw)
max_bw = bw;
}
@ -436,18 +435,16 @@ static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw,
struct mu3h_sch_ep_info *sch_ep, bool used)
{
u32 base;
int i;
int j;
int i, j, k;
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[base + j] +=
sch_ep->bw_budget_table[j];
sch_bw->bus_bw[k] += sch_ep->bw_budget_table[j];
else
sch_bw->bus_bw[base + j] -=
sch_ep->bw_budget_table[j];
sch_bw->bus_bw[k] -= sch_ep->bw_budget_table[j];
}
}
}
@ -457,7 +454,7 @@ 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 tmp;
int base;
int i, j;
int i, j, k;
for (i = 0; i < sch_ep->num_esit; i++) {
base = offset + i * sch_ep->esit;
@ -467,7 +464,8 @@ static int check_fs_bus_bw(struct mu3h_sch_ep_info *sch_ep, int offset)
* the hub will always delay one uframe to send data
*/
for (j = 0; j < sch_ep->num_budget_microframes; j++) {
tmp = tt->fs_bus_bw[base + j] + sch_ep->bw_budget_table[j];
k = XHCI_MTK_BW_INDEX(base + j);
tmp = tt->fs_bus_bw[k] + sch_ep->bw_budget_table[j];
if (tmp > FS_PAYLOAD_MAX)
return -ESCH_BW_OVERFLOW;
}
@ -542,16 +540,18 @@ 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;
int i, j;
int i, j, k;
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++)
for (j = 0; j < sch_ep->num_budget_microframes; j++) {
k = XHCI_MTK_BW_INDEX(base + j);
if (used)
tt->fs_bus_bw[base + j] += sch_ep->bw_budget_table[j];
tt->fs_bus_bw[k] += sch_ep->bw_budget_table[j];
else
tt->fs_bus_bw[base + j] -= sch_ep->bw_budget_table[j];
tt->fs_bus_bw[k] -= sch_ep->bw_budget_table[j];
}
}
if (used)
@ -573,27 +573,9 @@ static int load_ep_bw(struct mu3h_sch_bw_info *sch_bw,
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, normally esit >= 8 for FS/LS,
* not add one for other types to avoid access array
* out of boundary
*/
if (sch_ep->ep_type == ISOC_OUT_EP && boundary > 1)
boundary--;
}
return boundary;
}
static int check_sch_bw(struct mu3h_sch_ep_info *sch_ep)
{
struct mu3h_sch_bw_info *sch_bw = sch_ep->bw_info;
const u32 esit_boundary = get_esit_boundary(sch_ep);
const u32 bw_boundary = get_bw_boundary(sch_ep->speed);
u32 offset;
u32 worst_bw;
@ -606,10 +588,6 @@ static int check_sch_bw(struct mu3h_sch_ep_info *sch_ep)
* and find a microframe where its worst bandwidth is minimum.
*/
for (offset = 0; offset < sch_ep->esit; offset++) {
if ((offset + sch_ep->num_budget_microframes) > esit_boundary)
break;
ret = check_sch_tt(sch_ep, offset);
if (ret)
continue;

View File

@ -25,7 +25,8 @@
* round down to the limit value, that means allocating more
* bandwidth to it.
*/
#define XHCI_MTK_MAX_ESIT 64
#define XHCI_MTK_MAX_ESIT (1 << 6)
#define XHCI_MTK_BW_INDEX(x) ((x) & (XHCI_MTK_MAX_ESIT - 1))
/**
* @fs_bus_bw: array to keep track of bandwidth already used for FS