Skip to content

Commit b7d509a

Browse files
Chunfeng Yungregkh
authored andcommitted
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 <[email protected]> Signed-off-by: Chunfeng Yun <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 452d1ea commit b7d509a

File tree

2 files changed

+18
-39
lines changed

2 files changed

+18
-39
lines changed

drivers/usb/host/xhci-mtk-sch.c

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -416,15 +416,14 @@ static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw,
416416
{
417417
u32 max_bw = 0;
418418
u32 bw;
419-
int i;
420-
int j;
419+
int i, j, k;
421420

422421
for (i = 0; i < sch_ep->num_esit; i++) {
423422
u32 base = offset + i * sch_ep->esit;
424423

425424
for (j = 0; j < sch_ep->num_budget_microframes; j++) {
426-
bw = sch_bw->bus_bw[base + j] +
427-
sch_ep->bw_budget_table[j];
425+
k = XHCI_MTK_BW_INDEX(base + j);
426+
bw = sch_bw->bus_bw[k] + sch_ep->bw_budget_table[j];
428427
if (bw > max_bw)
429428
max_bw = bw;
430429
}
@@ -436,18 +435,16 @@ static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw,
436435
struct mu3h_sch_ep_info *sch_ep, bool used)
437436
{
438437
u32 base;
439-
int i;
440-
int j;
438+
int i, j, k;
441439

442440
for (i = 0; i < sch_ep->num_esit; i++) {
443441
base = sch_ep->offset + i * sch_ep->esit;
444442
for (j = 0; j < sch_ep->num_budget_microframes; j++) {
443+
k = XHCI_MTK_BW_INDEX(base + j);
445444
if (used)
446-
sch_bw->bus_bw[base + j] +=
447-
sch_ep->bw_budget_table[j];
445+
sch_bw->bus_bw[k] += sch_ep->bw_budget_table[j];
448446
else
449-
sch_bw->bus_bw[base + j] -=
450-
sch_ep->bw_budget_table[j];
447+
sch_bw->bus_bw[k] -= sch_ep->bw_budget_table[j];
451448
}
452449
}
453450
}
@@ -457,7 +454,7 @@ static int check_fs_bus_bw(struct mu3h_sch_ep_info *sch_ep, int offset)
457454
struct mu3h_sch_tt *tt = sch_ep->sch_tt;
458455
u32 tmp;
459456
int base;
460-
int i, j;
457+
int i, j, k;
461458

462459
for (i = 0; i < sch_ep->num_esit; i++) {
463460
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)
467464
* the hub will always delay one uframe to send data
468465
*/
469466
for (j = 0; j < sch_ep->num_budget_microframes; j++) {
470-
tmp = tt->fs_bus_bw[base + j] + sch_ep->bw_budget_table[j];
467+
k = XHCI_MTK_BW_INDEX(base + j);
468+
tmp = tt->fs_bus_bw[k] + sch_ep->bw_budget_table[j];
471469
if (tmp > FS_PAYLOAD_MAX)
472470
return -ESCH_BW_OVERFLOW;
473471
}
@@ -542,16 +540,18 @@ static void update_sch_tt(struct mu3h_sch_ep_info *sch_ep, bool used)
542540
{
543541
struct mu3h_sch_tt *tt = sch_ep->sch_tt;
544542
u32 base;
545-
int i, j;
543+
int i, j, k;
546544

547545
for (i = 0; i < sch_ep->num_esit; i++) {
548546
base = sch_ep->offset + i * sch_ep->esit;
549547

550-
for (j = 0; j < sch_ep->num_budget_microframes; j++)
548+
for (j = 0; j < sch_ep->num_budget_microframes; j++) {
549+
k = XHCI_MTK_BW_INDEX(base + j);
551550
if (used)
552-
tt->fs_bus_bw[base + j] += sch_ep->bw_budget_table[j];
551+
tt->fs_bus_bw[k] += sch_ep->bw_budget_table[j];
553552
else
554-
tt->fs_bus_bw[base + j] -= sch_ep->bw_budget_table[j];
553+
tt->fs_bus_bw[k] -= sch_ep->bw_budget_table[j];
554+
}
555555
}
556556

557557
if (used)
@@ -573,27 +573,9 @@ static int load_ep_bw(struct mu3h_sch_bw_info *sch_bw,
573573
return 0;
574574
}
575575

576-
static u32 get_esit_boundary(struct mu3h_sch_ep_info *sch_ep)
577-
{
578-
u32 boundary = sch_ep->esit;
579-
580-
if (sch_ep->sch_tt) { /* LS/FS with TT */
581-
/*
582-
* tune for CS, normally esit >= 8 for FS/LS,
583-
* not add one for other types to avoid access array
584-
* out of boundary
585-
*/
586-
if (sch_ep->ep_type == ISOC_OUT_EP && boundary > 1)
587-
boundary--;
588-
}
589-
590-
return boundary;
591-
}
592-
593576
static int check_sch_bw(struct mu3h_sch_ep_info *sch_ep)
594577
{
595578
struct mu3h_sch_bw_info *sch_bw = sch_ep->bw_info;
596-
const u32 esit_boundary = get_esit_boundary(sch_ep);
597579
const u32 bw_boundary = get_bw_boundary(sch_ep->speed);
598580
u32 offset;
599581
u32 worst_bw;
@@ -606,10 +588,6 @@ static int check_sch_bw(struct mu3h_sch_ep_info *sch_ep)
606588
* and find a microframe where its worst bandwidth is minimum.
607589
*/
608590
for (offset = 0; offset < sch_ep->esit; offset++) {
609-
610-
if ((offset + sch_ep->num_budget_microframes) > esit_boundary)
611-
break;
612-
613591
ret = check_sch_tt(sch_ep, offset);
614592
if (ret)
615593
continue;

drivers/usb/host/xhci-mtk.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
* round down to the limit value, that means allocating more
2626
* bandwidth to it.
2727
*/
28-
#define XHCI_MTK_MAX_ESIT 64
28+
#define XHCI_MTK_MAX_ESIT (1 << 6)
29+
#define XHCI_MTK_BW_INDEX(x) ((x) & (XHCI_MTK_MAX_ESIT - 1))
2930

3031
/**
3132
* @fs_bus_bw: array to keep track of bandwidth already used for FS

0 commit comments

Comments
 (0)