linux-usb.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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


             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).