From: Ikjoon Jang <ikjn@chromium.org>
To: linux-usb@vger.kernel.org, Chunfeng Yun <chunfeng.yun@mediatek.com>
Cc: linux-mediatek@lists.infradead.org,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Matthias Brugger <matthias.bgg@gmail.com>,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
Mathias Nyman <mathias.nyman@intel.com>,
Ikjoon Jang <ikjn@chromium.org>
Subject: [RFC PATCH] usb: xhci-mtk: handle bandwidth table rollover
Date: Mon, 9 Aug 2021 16:59:29 +0800 [thread overview]
Message-ID: <20210809165904.RFC.1.I5165a4a8da5cac23c9928b1ec3c3a1a7383b7c23@changeid> (raw)
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
should be rolled over but the current implementation doesn't.
This patch applies a 6 bits mask to the microframe index to handle
its rollover 64 slots and prevent out-of-bounds array access.
Signed-off-by: Ikjoon Jang <ikjn@chromium.org>
---
drivers/usb/host/xhci-mtk-sch.c | 79 +++++++++------------------------
drivers/usb/host/xhci-mtk.h | 1 +
2 files changed, 23 insertions(+), 57 deletions(-)
diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c
index 46cbf5d54f4f..ef16cd124343 100644
--- a/drivers/usb/host/xhci-mtk-sch.c
+++ b/drivers/usb/host/xhci-mtk-sch.c
@@ -411,18 +411,13 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw,
struct mu3h_sch_ep_info *sch_ep, u32 offset)
{
- u32 num_esit;
- u32 max_bw = 0;
- u32 bw;
- int i;
- int j;
-
- num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
- for (i = 0; i < num_esit; i++) {
- u32 base = offset + i * sch_ep->esit;
+ u32 bw, max_bw = 0;
+ int i, j, idx;
+ for (i = 0; i < XHCI_MTK_MAX_ESIT; i += sch_ep->esit) {
for (j = 0; j < sch_ep->num_budget_microframes; j++) {
- bw = sch_bw->bus_bw[base + j] +
+ idx = XHCI_MTK_BW_IDX(i + offset + j);
+ bw = sch_bw->bus_bw[idx] +
sch_ep->bw_budget_table[j];
if (bw > max_bw)
max_bw = bw;
@@ -434,20 +429,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)
{
- u32 num_esit;
- u32 base;
- int i;
- int j;
+ int i, j, idx;
- num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
- for (i = 0; i < num_esit; i++) {
- base = sch_ep->offset + i * sch_ep->esit;
+ for (i = 0; i < XHCI_MTK_MAX_ESIT; i += sch_ep->esit) {
for (j = 0; j < sch_ep->num_budget_microframes; j++) {
+ idx = XHCI_MTK_BW_IDX(i + sch_ep->offset + j);
if (used)
- sch_bw->bus_bw[base + j] +=
+ sch_bw->bus_bw[idx] +=
sch_ep->bw_budget_table[j];
else
- sch_bw->bus_bw[base + j] -=
+ sch_bw->bus_bw[idx] -=
sch_ep->bw_budget_table[j];
}
}
@@ -456,22 +447,18 @@ static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw,
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 num_esit, tmp;
- int base;
- int i, j;
+ u32 bw;
+ int i, j, idx;
u8 uframes = DIV_ROUND_UP(sch_ep->maxpkt, FS_PAYLOAD_MAX);
- num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
-
if (sch_ep->ep_type == INT_IN_EP || sch_ep->ep_type == ISOC_IN_EP)
offset++;
- for (i = 0; i < num_esit; i++) {
- base = offset + i * sch_ep->esit;
-
+ for (i = 0; i < XHCI_MTK_MAX_ESIT; i += sch_ep->esit) {
for (j = 0; j < uframes; j++) {
- tmp = tt->fs_bus_bw[base + j] + sch_ep->bw_cost_per_microframe;
- if (tmp > FS_PAYLOAD_MAX)
+ idx = XHCI_MTK_BW_IDX(i + offset + j);
+ bw = tt->fs_bus_bw[idx] + sch_ep->bw_cost_per_microframe;
+ if (bw > FS_PAYLOAD_MAX)
return -ESCH_BW_OVERFLOW;
}
}
@@ -544,14 +531,11 @@ static int check_sch_tt(struct mu3h_sch_ep_info *sch_ep, u32 offset)
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, num_esit;
int bw_updated;
- int i, j;
+ int i, j, idx;
int offset = sch_ep->offset;
u8 uframes = DIV_ROUND_UP(sch_ep->maxpkt, FS_PAYLOAD_MAX);
- num_esit = XHCI_MTK_MAX_ESIT / sch_ep->esit;
-
if (used)
bw_updated = sch_ep->bw_cost_per_microframe;
else
@@ -560,11 +544,11 @@ static void update_sch_tt(struct mu3h_sch_ep_info *sch_ep, bool used)
if (sch_ep->ep_type == INT_IN_EP || sch_ep->ep_type == ISOC_IN_EP)
offset++;
- for (i = 0; i < num_esit; i++) {
- base = offset + i * sch_ep->esit;
-
- for (j = 0; j < uframes; j++)
- tt->fs_bus_bw[base + j] += bw_updated;
+ for (i = 0; i < XHCI_MTK_MAX_ESIT; i += sch_ep->esit) {
+ for (j = 0; j < uframes; j++) {
+ idx = XHCI_MTK_BW_IDX(i + offset + j);
+ tt->fs_bus_bw[idx] += bw_updated;
+ }
}
if (used)
@@ -586,25 +570,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 */
- if (sch_ep->ep_type != ISOC_OUT_EP)
- boundary++;
- else if (boundary > 1) /* normally esit >= 8 for FS/LS */
- 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;
@@ -621,9 +589,6 @@ static int check_sch_bw(struct mu3h_sch_ep_info *sch_ep)
if (ret)
continue;
- if ((offset + sch_ep->num_budget_microframes) > esit_boundary)
- break;
-
worst_bw = get_max_bw(sch_bw, sch_ep, offset);
if (worst_bw > bw_boundary)
continue;
diff --git a/drivers/usb/host/xhci-mtk.h b/drivers/usb/host/xhci-mtk.h
index ddcf25524f67..f627941c4860 100644
--- a/drivers/usb/host/xhci-mtk.h
+++ b/drivers/usb/host/xhci-mtk.h
@@ -23,6 +23,7 @@
* bandwidth to it.
*/
#define XHCI_MTK_MAX_ESIT 64
+#define XHCI_MTK_BW_IDX(idx) ((idx) & 63)
/**
* @fs_bus_bw: array to keep track of bandwidth already used for FS
--
2.32.0.605.g8dce9f2422-goog
next reply other threads:[~2021-08-09 8:59 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-08-09 8:59 Ikjoon Jang [this message]
2021-08-09 9:11 ` [RFC PATCH] usb: xhci-mtk: handle bandwidth table rollover Greg Kroah-Hartman
2021-08-09 9:42 ` Ikjoon Jang
2021-08-11 9:01 ` Chunfeng Yun (云春峰)
2021-08-12 9:31 ` Ikjoon Jang
2021-08-12 11:49 ` Chunfeng Yun (云春峰)
2021-08-12 13:47 ` Ikjoon Jang
2021-08-18 2:43 ` Ikjoon Jang
2021-08-20 3:37 ` Chunfeng Yun (云春峰)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210809165904.RFC.1.I5165a4a8da5cac23c9928b1ec3c3a1a7383b7c23@changeid \
--to=ikjn@chromium.org \
--cc=chunfeng.yun@mediatek.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mediatek@lists.infradead.org \
--cc=linux-usb@vger.kernel.org \
--cc=mathias.nyman@intel.com \
--cc=matthias.bgg@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).