Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Chunfeng Yun and committed by
Greg Kroah-Hartman
b7d509a9 452d1ea5

+18 -39
+16 -38
drivers/usb/host/xhci-mtk-sch.c
··· 416 416 { 417 417 u32 max_bw = 0; 418 418 u32 bw; 419 - int i; 420 - int j; 419 + int i, j, k; 421 420 422 421 for (i = 0; i < sch_ep->num_esit; i++) { 423 422 u32 base = offset + i * sch_ep->esit; 424 423 425 424 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]; 428 427 if (bw > max_bw) 429 428 max_bw = bw; 430 429 } ··· 435 436 struct mu3h_sch_ep_info *sch_ep, bool used) 436 437 { 437 438 u32 base; 438 - int i; 439 - int j; 439 + int i, j, k; 440 440 441 441 for (i = 0; i < sch_ep->num_esit; i++) { 442 442 base = sch_ep->offset + i * sch_ep->esit; 443 443 for (j = 0; j < sch_ep->num_budget_microframes; j++) { 444 + k = XHCI_MTK_BW_INDEX(base + j); 444 445 if (used) 445 - sch_bw->bus_bw[base + j] += 446 - sch_ep->bw_budget_table[j]; 446 + sch_bw->bus_bw[k] += sch_ep->bw_budget_table[j]; 447 447 else 448 - sch_bw->bus_bw[base + j] -= 449 - sch_ep->bw_budget_table[j]; 448 + sch_bw->bus_bw[k] -= sch_ep->bw_budget_table[j]; 450 449 } 451 450 } 452 451 } ··· 454 457 struct mu3h_sch_tt *tt = sch_ep->sch_tt; 455 458 u32 tmp; 456 459 int base; 457 - int i, j; 460 + int i, j, k; 458 461 459 462 for (i = 0; i < sch_ep->num_esit; i++) { 460 463 base = offset + i * sch_ep->esit; ··· 464 467 * the hub will always delay one uframe to send data 465 468 */ 466 469 for (j = 0; j < sch_ep->num_budget_microframes; j++) { 467 - tmp = tt->fs_bus_bw[base + j] + sch_ep->bw_budget_table[j]; 470 + k = XHCI_MTK_BW_INDEX(base + j); 471 + tmp = tt->fs_bus_bw[k] + sch_ep->bw_budget_table[j]; 468 472 if (tmp > FS_PAYLOAD_MAX) 469 473 return -ESCH_BW_OVERFLOW; 470 474 } ··· 540 542 { 541 543 struct mu3h_sch_tt *tt = sch_ep->sch_tt; 542 544 u32 base; 543 - int i, j; 545 + int i, j, k; 544 546 545 547 for (i = 0; i < sch_ep->num_esit; i++) { 546 548 base = sch_ep->offset + i * sch_ep->esit; 547 549 548 - for (j = 0; j < sch_ep->num_budget_microframes; j++) 550 + for (j = 0; j < sch_ep->num_budget_microframes; j++) { 551 + k = XHCI_MTK_BW_INDEX(base + j); 549 552 if (used) 550 - tt->fs_bus_bw[base + j] += sch_ep->bw_budget_table[j]; 553 + tt->fs_bus_bw[k] += sch_ep->bw_budget_table[j]; 551 554 else 552 - tt->fs_bus_bw[base + j] -= sch_ep->bw_budget_table[j]; 555 + tt->fs_bus_bw[k] -= sch_ep->bw_budget_table[j]; 556 + } 553 557 } 554 558 555 559 if (used) ··· 573 573 return 0; 574 574 } 575 575 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 - 593 576 static int check_sch_bw(struct mu3h_sch_ep_info *sch_ep) 594 577 { 595 578 struct mu3h_sch_bw_info *sch_bw = sch_ep->bw_info; 596 - const u32 esit_boundary = get_esit_boundary(sch_ep); 597 579 const u32 bw_boundary = get_bw_boundary(sch_ep->speed); 598 580 u32 offset; 599 581 u32 worst_bw; ··· 588 606 * and find a microframe where its worst bandwidth is minimum. 589 607 */ 590 608 for (offset = 0; offset < sch_ep->esit; offset++) { 591 - 592 - if ((offset + sch_ep->num_budget_microframes) > esit_boundary) 593 - break; 594 - 595 609 ret = check_sch_tt(sch_ep, offset); 596 610 if (ret) 597 611 continue;
+2 -1
drivers/usb/host/xhci-mtk.h
··· 25 25 * round down to the limit value, that means allocating more 26 26 * bandwidth to it. 27 27 */ 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)) 29 30 30 31 /** 31 32 * @fs_bus_bw: array to keep track of bandwidth already used for FS