]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 8 Feb 2021 10:09:33 +0000 (11:09 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 8 Feb 2021 10:09:33 +0000 (11:09 +0100)
added patches:
usb-dwc2-fix-endpoint-direction-check-in-ep_from_windex.patch
usb-dwc3-fix-clock-issue-during-resume-in-otg-mode.patch
usb-gadget-aspeed-add-missing-of_node_put.patch
usb-gadget-legacy-fix-an-error-code-in-eth_bind.patch
usb-renesas_usbhs-clear-pipe-running-flag-in-usbhs_pkt_pop.patch
usb-usblp-don-t-call-usb_set_interface-if-there-s-a-single-alt.patch
usb-xhci-mtk-break-loop-when-find-the-endpoint-to-drop.patch
usb-xhci-mtk-fix-unreleased-bandwidth-data.patch
usb-xhci-mtk-skip-dropping-bandwidth-of-unchecked-endpoints.patch

queue-5.10/series
queue-5.10/usb-dwc2-fix-endpoint-direction-check-in-ep_from_windex.patch [new file with mode: 0644]
queue-5.10/usb-dwc3-fix-clock-issue-during-resume-in-otg-mode.patch [new file with mode: 0644]
queue-5.10/usb-gadget-aspeed-add-missing-of_node_put.patch [new file with mode: 0644]
queue-5.10/usb-gadget-legacy-fix-an-error-code-in-eth_bind.patch [new file with mode: 0644]
queue-5.10/usb-host-xhci-mvebu-make-usb-3.0-phy-optional-for-ar.patch [deleted file]
queue-5.10/usb-renesas_usbhs-clear-pipe-running-flag-in-usbhs_pkt_pop.patch [new file with mode: 0644]
queue-5.10/usb-usblp-don-t-call-usb_set_interface-if-there-s-a-single-alt.patch [new file with mode: 0644]
queue-5.10/usb-xhci-mtk-break-loop-when-find-the-endpoint-to-drop.patch [new file with mode: 0644]
queue-5.10/usb-xhci-mtk-fix-unreleased-bandwidth-data.patch [new file with mode: 0644]
queue-5.10/usb-xhci-mtk-skip-dropping-bandwidth-of-unchecked-endpoints.patch [new file with mode: 0644]

index 79f397536577bd85ec0131b79cfba5a5ae89f8b8..6514a3f4b5f082aed2838bdbcaea7707b238a4da 100644 (file)
@@ -2,7 +2,15 @@ usb-serial-cp210x-add-pid-vid-for-wsda-200-usb.patch
 usb-serial-cp210x-add-new-vid-pid-for-supporting-teraoka-ad2000.patch
 usb-serial-option-adding-support-for-cinterion-mv31.patch
 usb-host-xhci-mvebu-make-usb-3.0-phy-optional-for-armada-3720.patch
-usb-host-xhci-mvebu-make-usb-3.0-phy-optional-for-ar.patch
+usb-gadget-legacy-fix-an-error-code-in-eth_bind.patch
+usb-gadget-aspeed-add-missing-of_node_put.patch
+usb-usblp-don-t-call-usb_set_interface-if-there-s-a-single-alt.patch
+usb-renesas_usbhs-clear-pipe-running-flag-in-usbhs_pkt_pop.patch
+usb-dwc2-fix-endpoint-direction-check-in-ep_from_windex.patch
+usb-dwc3-fix-clock-issue-during-resume-in-otg-mode.patch
+usb-xhci-mtk-fix-unreleased-bandwidth-data.patch
+usb-xhci-mtk-skip-dropping-bandwidth-of-unchecked-endpoints.patch
+usb-xhci-mtk-break-loop-when-find-the-endpoint-to-drop.patch
 arm-omap1-osk-fix-ohci-omap-breakage.patch
 arm64-dts-qcom-c630-keep-both-touchpad-devices-enabl.patch
 input-i8042-unbreak-pegatron-c15b.patch
diff --git a/queue-5.10/usb-dwc2-fix-endpoint-direction-check-in-ep_from_windex.patch b/queue-5.10/usb-dwc2-fix-endpoint-direction-check-in-ep_from_windex.patch
new file mode 100644 (file)
index 0000000..e5418f4
--- /dev/null
@@ -0,0 +1,74 @@
+From f670e9f9c8cac716c3506c6bac9e997b27ad441a Mon Sep 17 00:00:00 2001
+From: Heiko Stuebner <heiko.stuebner@theobroma-systems.com>
+Date: Wed, 27 Jan 2021 11:39:19 +0100
+Subject: usb: dwc2: Fix endpoint direction check in ep_from_windex
+
+From: Heiko Stuebner <heiko.stuebner@theobroma-systems.com>
+
+commit f670e9f9c8cac716c3506c6bac9e997b27ad441a upstream.
+
+dwc2_hsotg_process_req_status uses ep_from_windex() to retrieve
+the endpoint for the index provided in the wIndex request param.
+
+In a test-case with a rndis gadget running and sending a malformed
+packet to it like:
+    dev.ctrl_transfer(
+        0x82,      # bmRequestType
+        0x00,       # bRequest
+        0x0000,     # wValue
+        0x0001,     # wIndex
+        0x00       # wLength
+    )
+it is possible to cause a crash:
+
+[  217.533022] dwc2 ff300000.usb: dwc2_hsotg_process_req_status: USB_REQ_GET_STATUS
+[  217.559003] Unable to handle kernel read from unreadable memory at virtual address 0000000000000088
+...
+[  218.313189] Call trace:
+[  218.330217]  ep_from_windex+0x3c/0x54
+[  218.348565]  usb_gadget_giveback_request+0x10/0x20
+[  218.368056]  dwc2_hsotg_complete_request+0x144/0x184
+
+This happens because ep_from_windex wants to compare the endpoint
+direction even if index_to_ep() didn't return an endpoint due to
+the direction not matching.
+
+The fix is easy insofar that the actual direction check is already
+happening when calling index_to_ep() which will return NULL if there
+is no endpoint for the targeted direction, so the offending check
+can go away completely.
+
+Fixes: c6f5c050e2a7 ("usb: dwc2: gadget: add bi-directional endpoint support")
+Cc: stable@vger.kernel.org
+Reported-by: Gerhard Klostermeier <gerhard.klostermeier@syss.de>
+Signed-off-by: Heiko Stuebner <heiko.stuebner@theobroma-systems.com>
+Link: https://lore.kernel.org/r/20210127103919.58215-1-heiko@sntech.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc2/gadget.c |    8 +-------
+ 1 file changed, 1 insertion(+), 7 deletions(-)
+
+--- a/drivers/usb/dwc2/gadget.c
++++ b/drivers/usb/dwc2/gadget.c
+@@ -1543,7 +1543,6 @@ static void dwc2_hsotg_complete_oursetup
+ static struct dwc2_hsotg_ep *ep_from_windex(struct dwc2_hsotg *hsotg,
+                                           u32 windex)
+ {
+-      struct dwc2_hsotg_ep *ep;
+       int dir = (windex & USB_DIR_IN) ? 1 : 0;
+       int idx = windex & 0x7F;
+@@ -1553,12 +1552,7 @@ static struct dwc2_hsotg_ep *ep_from_win
+       if (idx > hsotg->num_of_eps)
+               return NULL;
+-      ep = index_to_ep(hsotg, idx, dir);
+-
+-      if (idx && ep->dir_in != dir)
+-              return NULL;
+-
+-      return ep;
++      return index_to_ep(hsotg, idx, dir);
+ }
+ /**
diff --git a/queue-5.10/usb-dwc3-fix-clock-issue-during-resume-in-otg-mode.patch b/queue-5.10/usb-dwc3-fix-clock-issue-during-resume-in-otg-mode.patch
new file mode 100644 (file)
index 0000000..783220e
--- /dev/null
@@ -0,0 +1,41 @@
+From 0e5a3c8284a30f4c43fd81d7285528ece74563b5 Mon Sep 17 00:00:00 2001
+From: Gary Bisson <gary.bisson@boundarydevices.com>
+Date: Mon, 25 Jan 2021 17:19:34 +0100
+Subject: usb: dwc3: fix clock issue during resume in OTG mode
+
+From: Gary Bisson <gary.bisson@boundarydevices.com>
+
+commit 0e5a3c8284a30f4c43fd81d7285528ece74563b5 upstream.
+
+Commit fe8abf332b8f ("usb: dwc3: support clocks and resets for DWC3
+core") introduced clock support and a new function named
+dwc3_core_init_for_resume() which enables the clock before calling
+dwc3_core_init() during resume as clocks get disabled during suspend.
+
+Unfortunately in this commit the DWC3_GCTL_PRTCAP_OTG case was forgotten
+and therefore during resume, a platform could call dwc3_core_init()
+without re-enabling the clocks first, preventing to resume properly.
+
+So update the resume path to call dwc3_core_init_for_resume() as it
+should.
+
+Fixes: fe8abf332b8f ("usb: dwc3: support clocks and resets for DWC3 core")
+Cc: stable@vger.kernel.org
+Signed-off-by: Gary Bisson <gary.bisson@boundarydevices.com>
+Link: https://lore.kernel.org/r/20210125161934.527820-1-gary.bisson@boundarydevices.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/core.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/dwc3/core.c
++++ b/drivers/usb/dwc3/core.c
+@@ -1758,7 +1758,7 @@ static int dwc3_resume_common(struct dwc
+               if (PMSG_IS_AUTO(msg))
+                       break;
+-              ret = dwc3_core_init(dwc);
++              ret = dwc3_core_init_for_resume(dwc);
+               if (ret)
+                       return ret;
diff --git a/queue-5.10/usb-gadget-aspeed-add-missing-of_node_put.patch b/queue-5.10/usb-gadget-aspeed-add-missing-of_node_put.patch
new file mode 100644 (file)
index 0000000..72c05d2
--- /dev/null
@@ -0,0 +1,40 @@
+From a55a9a4c5c6253f6e4dea268af728664ac997790 Mon Sep 17 00:00:00 2001
+From: kernel test robot <lkp@intel.com>
+Date: Thu, 21 Jan 2021 19:12:54 +0100
+Subject: usb: gadget: aspeed: add missing of_node_put
+
+From: kernel test robot <lkp@intel.com>
+
+commit a55a9a4c5c6253f6e4dea268af728664ac997790 upstream.
+
+Breaking out of for_each_child_of_node requires a put on the
+child value.
+
+Generated by: scripts/coccinelle/iterators/for_each_child.cocci
+
+Fixes: 82c2d81361ec ("coccinelle: iterators: Add for_each_child.cocci script")
+CC: Sumera Priyadarsini <sylphrenadin@gmail.com>
+Reported-by: kernel test robot <lkp@intel.com>
+Signed-off-by: kernel test robot <lkp@intel.com>
+Signed-off-by: Julia Lawall <julia.lawall@inria.fr>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/alpine.DEB.2.22.394.2101211907060.14700@hadrien
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/udc/aspeed-vhub/hub.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/udc/aspeed-vhub/hub.c
++++ b/drivers/usb/gadget/udc/aspeed-vhub/hub.c
+@@ -999,8 +999,10 @@ static int ast_vhub_of_parse_str_desc(st
+               str_array[offset].s = NULL;
+               ret = ast_vhub_str_alloc_add(vhub, &lang_str);
+-              if (ret)
++              if (ret) {
++                      of_node_put(child);
+                       break;
++              }
+       }
+       return ret;
diff --git a/queue-5.10/usb-gadget-legacy-fix-an-error-code-in-eth_bind.patch b/queue-5.10/usb-gadget-legacy-fix-an-error-code-in-eth_bind.patch
new file mode 100644 (file)
index 0000000..b17f71a
--- /dev/null
@@ -0,0 +1,35 @@
+From 3e1f4a2e1184ae6ad7f4caf682ced9554141a0f4 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Thu, 28 Jan 2021 12:33:42 +0300
+Subject: USB: gadget: legacy: fix an error code in eth_bind()
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit 3e1f4a2e1184ae6ad7f4caf682ced9554141a0f4 upstream.
+
+This code should return -ENOMEM if the allocation fails but it currently
+returns success.
+
+Fixes: 9b95236eebdb ("usb: gadget: ether: allocate and init otg descriptor by otg capabilities")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Link: https://lore.kernel.org/r/YBKE9rqVuJEOUWpW@mwanda
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/legacy/ether.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/legacy/ether.c
++++ b/drivers/usb/gadget/legacy/ether.c
+@@ -403,8 +403,10 @@ static int eth_bind(struct usb_composite
+               struct usb_descriptor_header *usb_desc;
+               usb_desc = usb_otg_descriptor_alloc(gadget);
+-              if (!usb_desc)
++              if (!usb_desc) {
++                      status = -ENOMEM;
+                       goto fail1;
++              }
+               usb_otg_descriptor_init(gadget, usb_desc);
+               otg_desc[0] = usb_desc;
+               otg_desc[1] = NULL;
diff --git a/queue-5.10/usb-host-xhci-mvebu-make-usb-3.0-phy-optional-for-ar.patch b/queue-5.10/usb-host-xhci-mvebu-make-usb-3.0-phy-optional-for-ar.patch
deleted file mode 100644 (file)
index 31c0cd2..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-From bec5fbb439c63738153b186dea9e487db9b5259b Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 1 Feb 2021 16:08:03 +0100
-Subject: usb: host: xhci: mvebu: make USB 3.0 PHY optional for Armada 3720
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-From: Pali Rohár <pali@kernel.org>
-
-commit 3241929b67d28c83945d3191c6816a3271fd6b85 upstream.
-
-Older ATF does not provide SMC call for USB 3.0 phy power on functionality
-and therefore initialization of xhci-hcd is failing when older version of
-ATF is used. In this case phy_power_on() function returns -EOPNOTSUPP.
-
-[    3.108467] mvebu-a3700-comphy d0018300.phy: unsupported SMC call, try updating your firmware
-[    3.117250] phy phy-d0018300.phy.0: phy poweron failed --> -95
-[    3.123465] xhci-hcd: probe of d0058000.usb failed with error -95
-
-This patch introduces a new plat_setup callback for xhci platform drivers
-which is called prior calling usb_add_hcd() function. This function at its
-beginning skips PHY init if hcd->skip_phy_initialization is set.
-
-Current init_quirk callback for xhci platform drivers is called from
-xhci_plat_setup() function which is called after chip reset completes.
-It happens in the middle of the usb_add_hcd() function and therefore this
-callback cannot be used for setting if PHY init should be skipped or not.
-
-For Armada 3720 this patch introduce a new xhci_mvebu_a3700_plat_setup()
-function configured as a xhci platform plat_setup callback. This new
-function calls phy_power_on() and in case it returns -EOPNOTSUPP then
-XHCI_SKIP_PHY_INIT quirk is set to instruct xhci-plat to skip PHY
-initialization.
-
-This patch fixes above failure by ignoring 'not supported' error in
-xhci-hcd driver. In this case it is expected that phy is already power on.
-
-It fixes initialization of xhci-hcd on Espressobin boards where is older
-Marvell's Arm Trusted Firmware without SMC call for USB 3.0 phy power.
-
-This is regression introduced in commit bd3d25b07342 ("arm64: dts: marvell:
-armada-37xx: link USB hosts with their PHYs") where USB 3.0 phy was defined
-and therefore xhci-hcd on Espressobin with older ATF started failing.
-
-Fixes: bd3d25b07342 ("arm64: dts: marvell: armada-37xx: link USB hosts with their PHYs")
-Cc: <stable@vger.kernel.org> # 5.1+: ea17a0f153af: phy: marvell: comphy: Convert internal SMCC firmware return codes to errno
-Cc: <stable@vger.kernel.org> # 5.1+: f768e718911e: usb: host: xhci-plat: add priv quirk for skip PHY initialization
-Tested-by: Tomasz Maciej Nowak <tmn505@gmail.com>
-Tested-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> # On R-Car
-Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> # xhci-plat
-Acked-by: Mathias Nyman <mathias.nyman@linux.intel.com>
-Signed-off-by: Pali Rohár <pali@kernel.org>
-Link: https://lore.kernel.org/r/20210201150803.7305-1-pali@kernel.org
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/usb/host/xhci-mvebu.c | 42 +++++++++++++++++++++++++++++++++++
- drivers/usb/host/xhci-mvebu.h |  6 +++++
- drivers/usb/host/xhci-plat.c  | 20 ++++++++++++++++-
- drivers/usb/host/xhci-plat.h  |  1 +
- 4 files changed, 68 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/usb/host/xhci-mvebu.c b/drivers/usb/host/xhci-mvebu.c
-index 60651a50770f9..8ca1a235d1645 100644
---- a/drivers/usb/host/xhci-mvebu.c
-+++ b/drivers/usb/host/xhci-mvebu.c
-@@ -8,6 +8,7 @@
- #include <linux/mbus.h>
- #include <linux/of.h>
- #include <linux/platform_device.h>
-+#include <linux/phy/phy.h>
- #include <linux/usb.h>
- #include <linux/usb/hcd.h>
-@@ -74,6 +75,47 @@ int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd)
-       return 0;
- }
-+int xhci_mvebu_a3700_plat_setup(struct usb_hcd *hcd)
-+{
-+      struct xhci_hcd *xhci = hcd_to_xhci(hcd);
-+      struct device *dev = hcd->self.controller;
-+      struct phy *phy;
-+      int ret;
-+
-+      /* Old bindings miss the PHY handle */
-+      phy = of_phy_get(dev->of_node, "usb3-phy");
-+      if (IS_ERR(phy) && PTR_ERR(phy) == -EPROBE_DEFER)
-+              return -EPROBE_DEFER;
-+      else if (IS_ERR(phy))
-+              goto phy_out;
-+
-+      ret = phy_init(phy);
-+      if (ret)
-+              goto phy_put;
-+
-+      ret = phy_set_mode(phy, PHY_MODE_USB_HOST_SS);
-+      if (ret)
-+              goto phy_exit;
-+
-+      ret = phy_power_on(phy);
-+      if (ret == -EOPNOTSUPP) {
-+              /* Skip initializatin of XHCI PHY when it is unsupported by firmware */
-+              dev_warn(dev, "PHY unsupported by firmware\n");
-+              xhci->quirks |= XHCI_SKIP_PHY_INIT;
-+      }
-+      if (ret)
-+              goto phy_exit;
-+
-+      phy_power_off(phy);
-+phy_exit:
-+      phy_exit(phy);
-+phy_put:
-+      of_phy_put(phy);
-+phy_out:
-+
-+      return 0;
-+}
-+
- int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd)
- {
-       struct xhci_hcd *xhci = hcd_to_xhci(hcd);
-diff --git a/drivers/usb/host/xhci-mvebu.h b/drivers/usb/host/xhci-mvebu.h
-index 3be021793cc8b..01bf3fcb3eca5 100644
---- a/drivers/usb/host/xhci-mvebu.h
-+++ b/drivers/usb/host/xhci-mvebu.h
-@@ -12,6 +12,7 @@ struct usb_hcd;
- #if IS_ENABLED(CONFIG_USB_XHCI_MVEBU)
- int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd);
-+int xhci_mvebu_a3700_plat_setup(struct usb_hcd *hcd);
- int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd);
- #else
- static inline int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd)
-@@ -19,6 +20,11 @@ static inline int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd)
-       return 0;
- }
-+static inline int xhci_mvebu_a3700_plat_setup(struct usb_hcd *hcd)
-+{
-+      return 0;
-+}
-+
- static inline int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd)
- {
-       return 0;
-diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
-index 4d34f6005381e..c1edcc9b13cec 100644
---- a/drivers/usb/host/xhci-plat.c
-+++ b/drivers/usb/host/xhci-plat.c
-@@ -44,6 +44,16 @@ static void xhci_priv_plat_start(struct usb_hcd *hcd)
-               priv->plat_start(hcd);
- }
-+static int xhci_priv_plat_setup(struct usb_hcd *hcd)
-+{
-+      struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
-+
-+      if (!priv->plat_setup)
-+              return 0;
-+
-+      return priv->plat_setup(hcd);
-+}
-+
- static int xhci_priv_init_quirk(struct usb_hcd *hcd)
- {
-       struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
-@@ -111,6 +121,7 @@ static const struct xhci_plat_priv xhci_plat_marvell_armada = {
- };
- static const struct xhci_plat_priv xhci_plat_marvell_armada3700 = {
-+      .plat_setup = xhci_mvebu_a3700_plat_setup,
-       .init_quirk = xhci_mvebu_a3700_init_quirk,
- };
-@@ -330,7 +341,14 @@ static int xhci_plat_probe(struct platform_device *pdev)
-       hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node);
-       xhci->shared_hcd->tpl_support = hcd->tpl_support;
--      if (priv && (priv->quirks & XHCI_SKIP_PHY_INIT))
-+
-+      if (priv) {
-+              ret = xhci_priv_plat_setup(hcd);
-+              if (ret)
-+                      goto disable_usb_phy;
-+      }
-+
-+      if ((xhci->quirks & XHCI_SKIP_PHY_INIT) || (priv && (priv->quirks & XHCI_SKIP_PHY_INIT)))
-               hcd->skip_phy_initialization = 1;
-       if (priv && (priv->quirks & XHCI_SG_TRB_CACHE_SIZE_QUIRK))
-diff --git a/drivers/usb/host/xhci-plat.h b/drivers/usb/host/xhci-plat.h
-index 1fb149d1fbcea..561d0b7bce098 100644
---- a/drivers/usb/host/xhci-plat.h
-+++ b/drivers/usb/host/xhci-plat.h
-@@ -13,6 +13,7 @@
- struct xhci_plat_priv {
-       const char *firmware_name;
-       unsigned long long quirks;
-+      int (*plat_setup)(struct usb_hcd *);
-       void (*plat_start)(struct usb_hcd *);
-       int (*init_quirk)(struct usb_hcd *);
-       int (*suspend_quirk)(struct usb_hcd *);
--- 
-2.27.0
-
diff --git a/queue-5.10/usb-renesas_usbhs-clear-pipe-running-flag-in-usbhs_pkt_pop.patch b/queue-5.10/usb-renesas_usbhs-clear-pipe-running-flag-in-usbhs_pkt_pop.patch
new file mode 100644 (file)
index 0000000..92aa805
--- /dev/null
@@ -0,0 +1,33 @@
+From 9917f0e3cdba7b9f1a23f70e3f70b1a106be54a8 Mon Sep 17 00:00:00 2001
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Date: Mon, 1 Feb 2021 21:47:20 +0900
+Subject: usb: renesas_usbhs: Clear pipe running flag in usbhs_pkt_pop()
+
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+
+commit 9917f0e3cdba7b9f1a23f70e3f70b1a106be54a8 upstream.
+
+Should clear the pipe running flag in usbhs_pkt_pop(). Otherwise,
+we cannot use this pipe after dequeue was called while the pipe was
+running.
+
+Fixes: 8355b2b3082d ("usb: renesas_usbhs: fix the behavior of some usbhs_pkt_handle")
+Reported-by: Tho Vu <tho.vu.wh@renesas.com>
+Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Link: https://lore.kernel.org/r/1612183640-8898-1-git-send-email-yoshihiro.shimoda.uh@renesas.com
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/renesas_usbhs/fifo.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/usb/renesas_usbhs/fifo.c
++++ b/drivers/usb/renesas_usbhs/fifo.c
+@@ -126,6 +126,7 @@ struct usbhs_pkt *usbhs_pkt_pop(struct u
+               }
+               usbhs_pipe_clear_without_sequence(pipe, 0, 0);
++              usbhs_pipe_running(pipe, 0);
+               __usbhsf_pkt_del(pkt);
+       }
diff --git a/queue-5.10/usb-usblp-don-t-call-usb_set_interface-if-there-s-a-single-alt.patch b/queue-5.10/usb-usblp-don-t-call-usb_set_interface-if-there-s-a-single-alt.patch
new file mode 100644 (file)
index 0000000..0af5510
--- /dev/null
@@ -0,0 +1,51 @@
+From d8c6edfa3f4ee0d45d7ce5ef18d1245b78774b9d Mon Sep 17 00:00:00 2001
+From: Jeremy Figgins <kernel@jeremyfiggins.com>
+Date: Sat, 23 Jan 2021 18:21:36 -0600
+Subject: USB: usblp: don't call usb_set_interface if there's a single alt
+
+From: Jeremy Figgins <kernel@jeremyfiggins.com>
+
+commit d8c6edfa3f4ee0d45d7ce5ef18d1245b78774b9d upstream.
+
+Some devices, such as the Winbond Electronics Corp. Virtual Com Port
+(Vendor=0416, ProdId=5011), lockup when usb_set_interface() or
+usb_clear_halt() are called. This device has only a single
+altsetting, so it should not be necessary to call usb_set_interface().
+
+Acked-by: Pete Zaitcev <zaitcev@redhat.com>
+Signed-off-by: Jeremy Figgins <kernel@jeremyfiggins.com>
+Link: https://lore.kernel.org/r/YAy9kJhM/rG8EQXC@watson
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/class/usblp.c |   19 +++++++++++--------
+ 1 file changed, 11 insertions(+), 8 deletions(-)
+
+--- a/drivers/usb/class/usblp.c
++++ b/drivers/usb/class/usblp.c
+@@ -1329,14 +1329,17 @@ static int usblp_set_protocol(struct usb
+       if (protocol < USBLP_FIRST_PROTOCOL || protocol > USBLP_LAST_PROTOCOL)
+               return -EINVAL;
+-      alts = usblp->protocol[protocol].alt_setting;
+-      if (alts < 0)
+-              return -EINVAL;
+-      r = usb_set_interface(usblp->dev, usblp->ifnum, alts);
+-      if (r < 0) {
+-              printk(KERN_ERR "usblp: can't set desired altsetting %d on interface %d\n",
+-                      alts, usblp->ifnum);
+-              return r;
++      /* Don't unnecessarily set the interface if there's a single alt. */
++      if (usblp->intf->num_altsetting > 1) {
++              alts = usblp->protocol[protocol].alt_setting;
++              if (alts < 0)
++                      return -EINVAL;
++              r = usb_set_interface(usblp->dev, usblp->ifnum, alts);
++              if (r < 0) {
++                      printk(KERN_ERR "usblp: can't set desired altsetting %d on interface %d\n",
++                              alts, usblp->ifnum);
++                      return r;
++              }
+       }
+       usblp->bidir = (usblp->protocol[protocol].epread != NULL);
diff --git a/queue-5.10/usb-xhci-mtk-break-loop-when-find-the-endpoint-to-drop.patch b/queue-5.10/usb-xhci-mtk-break-loop-when-find-the-endpoint-to-drop.patch
new file mode 100644 (file)
index 0000000..2c84e36
--- /dev/null
@@ -0,0 +1,36 @@
+From a50ea34d6dd00a12c9cd29cf7b0fa72816bffbcb Mon Sep 17 00:00:00 2001
+From: Chunfeng Yun <chunfeng.yun@mediatek.com>
+Date: Tue, 2 Feb 2021 16:38:24 +0800
+Subject: usb: xhci-mtk: break loop when find the endpoint to drop
+
+From: Chunfeng Yun <chunfeng.yun@mediatek.com>
+
+commit a50ea34d6dd00a12c9cd29cf7b0fa72816bffbcb upstream.
+
+No need to check the following endpoints after finding the endpoint
+wanted to drop.
+
+Fixes: 54f6a8af3722 ("usb: xhci-mtk: skip dropping bandwidth of unchecked endpoints")
+Cc: stable <stable@vger.kernel.org>
+Reported-by: Ikjoon Jang <ikjn@chromium.org>
+Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
+Link: https://lore.kernel.org/r/1612255104-5363-1-git-send-email-chunfeng.yun@mediatek.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/xhci-mtk-sch.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci-mtk-sch.c
++++ b/drivers/usb/host/xhci-mtk-sch.c
+@@ -689,8 +689,10 @@ void xhci_mtk_drop_ep_quirk(struct usb_h
+       sch_bw = &sch_array[bw_index];
+       list_for_each_entry_safe(sch_ep, tmp, &sch_bw->bw_ep_list, endpoint) {
+-              if (sch_ep->ep == ep)
++              if (sch_ep->ep == ep) {
+                       destroy_sch_ep(udev, sch_bw, sch_ep);
++                      break;
++              }
+       }
+ }
+ EXPORT_SYMBOL_GPL(xhci_mtk_drop_ep_quirk);
diff --git a/queue-5.10/usb-xhci-mtk-fix-unreleased-bandwidth-data.patch b/queue-5.10/usb-xhci-mtk-fix-unreleased-bandwidth-data.patch
new file mode 100644 (file)
index 0000000..1896cea
--- /dev/null
@@ -0,0 +1,321 @@
+From 1d69f9d901ef14d81c3b004e3282b8cc7b456280 Mon Sep 17 00:00:00 2001
+From: Ikjoon Jang <ikjn@chromium.org>
+Date: Wed, 13 Jan 2021 18:05:11 +0800
+Subject: usb: xhci-mtk: fix unreleased bandwidth data
+
+From: Ikjoon Jang <ikjn@chromium.org>
+
+commit 1d69f9d901ef14d81c3b004e3282b8cc7b456280 upstream.
+
+xhci-mtk needs XHCI_MTK_HOST quirk functions in add_endpoint() and
+drop_endpoint() to handle its own sw bandwidth management.
+
+It stores bandwidth data into an internal table every time
+add_endpoint() is called, and drops those in drop_endpoint().
+But when bandwidth allocation fails at one endpoint, all earlier
+allocation from the same interface could still remain at the table.
+
+This patch moves bandwidth management codes to check_bandwidth() and
+reset_bandwidth() path. To do so, this patch also adds those functions
+to xhci_driver_overrides and lets mtk-xhci to release all failed
+endpoints in reset_bandwidth() path.
+
+Fixes: 08e469de87a2 ("usb: xhci-mtk: supports bandwidth scheduling with multi-TT")
+Signed-off-by: Ikjoon Jang <ikjn@chromium.org>
+Link: https://lore.kernel.org/r/20210113180444.v6.1.Id0d31b5f3ddf5e734d2ab11161ac5821921b1e1e@changeid
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/xhci-mtk-sch.c |  123 +++++++++++++++++++++++++++-------------
+ drivers/usb/host/xhci-mtk.c     |    2 
+ drivers/usb/host/xhci-mtk.h     |   13 ++++
+ drivers/usb/host/xhci.c         |    8 +-
+ drivers/usb/host/xhci.h         |    4 +
+ 5 files changed, 111 insertions(+), 39 deletions(-)
+
+--- a/drivers/usb/host/xhci-mtk-sch.c
++++ b/drivers/usb/host/xhci-mtk-sch.c
+@@ -200,6 +200,7 @@ static struct mu3h_sch_ep_info *create_s
+       sch_ep->sch_tt = tt;
+       sch_ep->ep = ep;
++      INIT_LIST_HEAD(&sch_ep->tt_endpoint);
+       return sch_ep;
+ }
+@@ -583,6 +584,8 @@ int xhci_mtk_sch_init(struct xhci_hcd_mt
+       mtk->sch_array = sch_array;
++      INIT_LIST_HEAD(&mtk->bw_ep_list_new);
++
+       return 0;
+ }
+ EXPORT_SYMBOL_GPL(xhci_mtk_sch_init);
+@@ -601,19 +604,14 @@ int xhci_mtk_add_ep_quirk(struct usb_hcd
+       struct xhci_ep_ctx *ep_ctx;
+       struct xhci_slot_ctx *slot_ctx;
+       struct xhci_virt_device *virt_dev;
+-      struct mu3h_sch_bw_info *sch_bw;
+       struct mu3h_sch_ep_info *sch_ep;
+-      struct mu3h_sch_bw_info *sch_array;
+       unsigned int ep_index;
+-      int bw_index;
+-      int ret = 0;
+       xhci = hcd_to_xhci(hcd);
+       virt_dev = xhci->devs[udev->slot_id];
+       ep_index = xhci_get_endpoint_index(&ep->desc);
+       slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
+       ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
+-      sch_array = mtk->sch_array;
+       xhci_dbg(xhci, "%s() type:%d, speed:%d, mpkt:%d, dir:%d, ep:%p\n",
+               __func__, usb_endpoint_type(&ep->desc), udev->speed,
+@@ -632,39 +630,34 @@ int xhci_mtk_add_ep_quirk(struct usb_hcd
+               return 0;
+       }
+-      bw_index = get_bw_index(xhci, udev, ep);
+-      sch_bw = &sch_array[bw_index];
+-
+       sch_ep = create_sch_ep(udev, ep, ep_ctx);
+       if (IS_ERR_OR_NULL(sch_ep))
+               return -ENOMEM;
+       setup_sch_info(udev, ep_ctx, sch_ep);
+-      ret = check_sch_bw(udev, sch_bw, sch_ep);
+-      if (ret) {
+-              xhci_err(xhci, "Not enough bandwidth!\n");
+-              if (is_fs_or_ls(udev->speed))
+-                      drop_tt(udev);
+-
+-              kfree(sch_ep);
+-              return -ENOSPC;
+-      }
++      list_add_tail(&sch_ep->endpoint, &mtk->bw_ep_list_new);
+-      list_add_tail(&sch_ep->endpoint, &sch_bw->bw_ep_list);
++      return 0;
++}
++EXPORT_SYMBOL_GPL(xhci_mtk_add_ep_quirk);
+-      ep_ctx->reserved[0] |= cpu_to_le32(EP_BPKTS(sch_ep->pkts)
+-              | EP_BCSCOUNT(sch_ep->cs_count) | EP_BBM(sch_ep->burst_mode));
+-      ep_ctx->reserved[1] |= cpu_to_le32(EP_BOFFSET(sch_ep->offset)
+-              | EP_BREPEAT(sch_ep->repeat));
++static void xhci_mtk_drop_ep(struct xhci_hcd_mtk *mtk, struct usb_device *udev,
++                           struct mu3h_sch_ep_info *sch_ep)
++{
++      struct xhci_hcd *xhci = hcd_to_xhci(mtk->hcd);
++      int bw_index = get_bw_index(xhci, udev, sch_ep->ep);
++      struct mu3h_sch_bw_info *sch_bw = &mtk->sch_array[bw_index];
+-      xhci_dbg(xhci, " PKTS:%x, CSCOUNT:%x, BM:%x, OFFSET:%x, REPEAT:%x\n",
+-                      sch_ep->pkts, sch_ep->cs_count, sch_ep->burst_mode,
+-                      sch_ep->offset, sch_ep->repeat);
++      update_bus_bw(sch_bw, sch_ep, 0);
++      list_del(&sch_ep->endpoint);
+-      return 0;
++      if (sch_ep->sch_tt) {
++              list_del(&sch_ep->tt_endpoint);
++              drop_tt(udev);
++      }
++      kfree(sch_ep);
+ }
+-EXPORT_SYMBOL_GPL(xhci_mtk_add_ep_quirk);
+ void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
+               struct usb_host_endpoint *ep)
+@@ -675,7 +668,7 @@ void xhci_mtk_drop_ep_quirk(struct usb_h
+       struct xhci_virt_device *virt_dev;
+       struct mu3h_sch_bw_info *sch_array;
+       struct mu3h_sch_bw_info *sch_bw;
+-      struct mu3h_sch_ep_info *sch_ep;
++      struct mu3h_sch_ep_info *sch_ep, *tmp;
+       int bw_index;
+       xhci = hcd_to_xhci(hcd);
+@@ -694,17 +687,73 @@ void xhci_mtk_drop_ep_quirk(struct usb_h
+       bw_index = get_bw_index(xhci, udev, ep);
+       sch_bw = &sch_array[bw_index];
+-      list_for_each_entry(sch_ep, &sch_bw->bw_ep_list, endpoint) {
++      list_for_each_entry_safe(sch_ep, tmp, &sch_bw->bw_ep_list, endpoint) {
+               if (sch_ep->ep == ep) {
+-                      update_bus_bw(sch_bw, sch_ep, 0);
+-                      list_del(&sch_ep->endpoint);
+-                      if (is_fs_or_ls(udev->speed)) {
+-                              list_del(&sch_ep->tt_endpoint);
+-                              drop_tt(udev);
+-                      }
+-                      kfree(sch_ep);
+-                      break;
++                      xhci_mtk_drop_ep(mtk, udev, sch_ep);
+               }
+       }
+ }
+ EXPORT_SYMBOL_GPL(xhci_mtk_drop_ep_quirk);
++
++int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
++{
++      struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
++      struct xhci_hcd *xhci = hcd_to_xhci(hcd);
++      struct xhci_virt_device *virt_dev = xhci->devs[udev->slot_id];
++      struct mu3h_sch_bw_info *sch_bw;
++      struct mu3h_sch_ep_info *sch_ep, *tmp;
++      int bw_index, ret;
++
++      dev_dbg(&udev->dev, "%s\n", __func__);
++
++      list_for_each_entry(sch_ep, &mtk->bw_ep_list_new, endpoint) {
++              bw_index = get_bw_index(xhci, udev, sch_ep->ep);
++              sch_bw = &mtk->sch_array[bw_index];
++
++              ret = check_sch_bw(udev, sch_bw, sch_ep);
++              if (ret) {
++                      xhci_err(xhci, "Not enough bandwidth!\n");
++                      return -ENOSPC;
++              }
++      }
++
++      list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_list_new, endpoint) {
++              struct xhci_ep_ctx *ep_ctx;
++              struct usb_host_endpoint *ep = sch_ep->ep;
++              unsigned int ep_index = xhci_get_endpoint_index(&ep->desc);
++
++              bw_index = get_bw_index(xhci, udev, ep);
++              sch_bw = &mtk->sch_array[bw_index];
++
++              list_move_tail(&sch_ep->endpoint, &sch_bw->bw_ep_list);
++
++              ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
++              ep_ctx->reserved[0] |= cpu_to_le32(EP_BPKTS(sch_ep->pkts)
++                      | EP_BCSCOUNT(sch_ep->cs_count)
++                      | EP_BBM(sch_ep->burst_mode));
++              ep_ctx->reserved[1] |= cpu_to_le32(EP_BOFFSET(sch_ep->offset)
++                      | EP_BREPEAT(sch_ep->repeat));
++
++              xhci_dbg(xhci, " PKTS:%x, CSCOUNT:%x, BM:%x, OFFSET:%x, REPEAT:%x\n",
++                      sch_ep->pkts, sch_ep->cs_count, sch_ep->burst_mode,
++                      sch_ep->offset, sch_ep->repeat);
++      }
++
++      return xhci_check_bandwidth(hcd, udev);
++}
++EXPORT_SYMBOL_GPL(xhci_mtk_check_bandwidth);
++
++void xhci_mtk_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
++{
++      struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
++      struct mu3h_sch_ep_info *sch_ep, *tmp;
++
++      dev_dbg(&udev->dev, "%s\n", __func__);
++
++      list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_list_new, endpoint) {
++              xhci_mtk_drop_ep(mtk, udev, sch_ep);
++      }
++
++      xhci_reset_bandwidth(hcd, udev);
++}
++EXPORT_SYMBOL_GPL(xhci_mtk_reset_bandwidth);
+--- a/drivers/usb/host/xhci-mtk.c
++++ b/drivers/usb/host/xhci-mtk.c
+@@ -347,6 +347,8 @@ static void usb_wakeup_set(struct xhci_h
+ static int xhci_mtk_setup(struct usb_hcd *hcd);
+ static const struct xhci_driver_overrides xhci_mtk_overrides __initconst = {
+       .reset = xhci_mtk_setup,
++      .check_bandwidth = xhci_mtk_check_bandwidth,
++      .reset_bandwidth = xhci_mtk_reset_bandwidth,
+ };
+ static struct hc_driver __read_mostly xhci_mtk_hc_driver;
+--- a/drivers/usb/host/xhci-mtk.h
++++ b/drivers/usb/host/xhci-mtk.h
+@@ -130,6 +130,7 @@ struct mu3c_ippc_regs {
+ struct xhci_hcd_mtk {
+       struct device *dev;
+       struct usb_hcd *hcd;
++      struct list_head bw_ep_list_new;
+       struct mu3h_sch_bw_info *sch_array;
+       struct mu3c_ippc_regs __iomem *ippc_regs;
+       bool has_ippc;
+@@ -166,6 +167,8 @@ int xhci_mtk_add_ep_quirk(struct usb_hcd
+               struct usb_host_endpoint *ep);
+ void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
+               struct usb_host_endpoint *ep);
++int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
++void xhci_mtk_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
+ #else
+ static inline int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd,
+@@ -179,6 +182,16 @@ static inline void xhci_mtk_drop_ep_quir
+ {
+ }
++static inline int xhci_mtk_check_bandwidth(struct usb_hcd *hcd,
++              struct usb_device *udev)
++{
++      return 0;
++}
++
++static inline void xhci_mtk_reset_bandwidth(struct usb_hcd *hcd,
++              struct usb_device *udev)
++{
++}
+ #endif
+ #endif                /* _XHCI_MTK_H_ */
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -2861,7 +2861,7 @@ static void xhci_check_bw_drop_ep_stream
+  * else should be touching the xhci->devs[slot_id] structure, so we
+  * don't need to take the xhci->lock for manipulating that.
+  */
+-static int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
++int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
+ {
+       int i;
+       int ret = 0;
+@@ -2959,7 +2959,7 @@ command_cleanup:
+       return ret;
+ }
+-static void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
++void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
+ {
+       struct xhci_hcd *xhci;
+       struct xhci_virt_device *virt_dev;
+@@ -5385,6 +5385,10 @@ void xhci_init_driver(struct hc_driver *
+                       drv->reset = over->reset;
+               if (over->start)
+                       drv->start = over->start;
++              if (over->check_bandwidth)
++                      drv->check_bandwidth = over->check_bandwidth;
++              if (over->reset_bandwidth)
++                      drv->reset_bandwidth = over->reset_bandwidth;
+       }
+ }
+ EXPORT_SYMBOL_GPL(xhci_init_driver);
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1916,6 +1916,8 @@ struct xhci_driver_overrides {
+       size_t extra_priv_size;
+       int (*reset)(struct usb_hcd *hcd);
+       int (*start)(struct usb_hcd *hcd);
++      int (*check_bandwidth)(struct usb_hcd *, struct usb_device *);
++      void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *);
+ };
+ #define       XHCI_CFC_DELAY          10
+@@ -2070,6 +2072,8 @@ int xhci_gen_setup(struct usb_hcd *hcd,
+ void xhci_shutdown(struct usb_hcd *hcd);
+ void xhci_init_driver(struct hc_driver *drv,
+                     const struct xhci_driver_overrides *over);
++int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
++void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
+ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id);
+ int xhci_ext_cap_init(struct xhci_hcd *xhci);
diff --git a/queue-5.10/usb-xhci-mtk-skip-dropping-bandwidth-of-unchecked-endpoints.patch b/queue-5.10/usb-xhci-mtk-skip-dropping-bandwidth-of-unchecked-endpoints.patch
new file mode 100644 (file)
index 0000000..01f02d2
--- /dev/null
@@ -0,0 +1,189 @@
+From 54f6a8af372213a254af6609758d99f7c0b6b5ad Mon Sep 17 00:00:00 2001
+From: Chunfeng Yun <chunfeng.yun@mediatek.com>
+Date: Mon, 1 Feb 2021 13:57:44 +0800
+Subject: usb: xhci-mtk: skip dropping bandwidth of unchecked endpoints
+
+From: Chunfeng Yun <chunfeng.yun@mediatek.com>
+
+commit 54f6a8af372213a254af6609758d99f7c0b6b5ad upstream.
+
+For those unchecked endpoints, we don't allocate bandwidth for
+them, so no need free the bandwidth, otherwise will decrease
+the allocated bandwidth.
+Meanwhile use xhci_dbg() instead of dev_dbg() to print logs and
+rename bw_ep_list_new as bw_ep_chk_list.
+
+Fixes: 1d69f9d901ef ("usb: xhci-mtk: fix unreleased bandwidth data")
+Cc: stable <stable@vger.kernel.org>
+Reviewed-and-tested-by: Ikjoon Jang <ikjn@chromium.org>
+Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
+Link: https://lore.kernel.org/r/1612159064-28413-1-git-send-email-chunfeng.yun@mediatek.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/xhci-mtk-sch.c |   61 +++++++++++++++++++++-------------------
+ drivers/usb/host/xhci-mtk.h     |    4 +-
+ 2 files changed, 36 insertions(+), 29 deletions(-)
+
+--- a/drivers/usb/host/xhci-mtk-sch.c
++++ b/drivers/usb/host/xhci-mtk-sch.c
+@@ -200,6 +200,7 @@ static struct mu3h_sch_ep_info *create_s
+       sch_ep->sch_tt = tt;
+       sch_ep->ep = ep;
++      INIT_LIST_HEAD(&sch_ep->endpoint);
+       INIT_LIST_HEAD(&sch_ep->tt_endpoint);
+       return sch_ep;
+@@ -374,6 +375,7 @@ static void update_bus_bw(struct mu3h_sc
+                                       sch_ep->bw_budget_table[j];
+               }
+       }
++      sch_ep->allocated = used;
+ }
+ static int check_sch_tt(struct usb_device *udev,
+@@ -542,6 +544,22 @@ static int check_sch_bw(struct usb_devic
+       return 0;
+ }
++static void destroy_sch_ep(struct usb_device *udev,
++      struct mu3h_sch_bw_info *sch_bw, struct mu3h_sch_ep_info *sch_ep)
++{
++      /* only release ep bw check passed by check_sch_bw() */
++      if (sch_ep->allocated)
++              update_bus_bw(sch_bw, sch_ep, 0);
++
++      list_del(&sch_ep->endpoint);
++
++      if (sch_ep->sch_tt) {
++              list_del(&sch_ep->tt_endpoint);
++              drop_tt(udev);
++      }
++      kfree(sch_ep);
++}
++
+ static bool need_bw_sch(struct usb_host_endpoint *ep,
+       enum usb_device_speed speed, int has_tt)
+ {
+@@ -584,7 +602,7 @@ int xhci_mtk_sch_init(struct xhci_hcd_mt
+       mtk->sch_array = sch_array;
+-      INIT_LIST_HEAD(&mtk->bw_ep_list_new);
++      INIT_LIST_HEAD(&mtk->bw_ep_chk_list);
+       return 0;
+ }
+@@ -636,29 +654,12 @@ int xhci_mtk_add_ep_quirk(struct usb_hcd
+       setup_sch_info(udev, ep_ctx, sch_ep);
+-      list_add_tail(&sch_ep->endpoint, &mtk->bw_ep_list_new);
++      list_add_tail(&sch_ep->endpoint, &mtk->bw_ep_chk_list);
+       return 0;
+ }
+ EXPORT_SYMBOL_GPL(xhci_mtk_add_ep_quirk);
+-static void xhci_mtk_drop_ep(struct xhci_hcd_mtk *mtk, struct usb_device *udev,
+-                           struct mu3h_sch_ep_info *sch_ep)
+-{
+-      struct xhci_hcd *xhci = hcd_to_xhci(mtk->hcd);
+-      int bw_index = get_bw_index(xhci, udev, sch_ep->ep);
+-      struct mu3h_sch_bw_info *sch_bw = &mtk->sch_array[bw_index];
+-
+-      update_bus_bw(sch_bw, sch_ep, 0);
+-      list_del(&sch_ep->endpoint);
+-
+-      if (sch_ep->sch_tt) {
+-              list_del(&sch_ep->tt_endpoint);
+-              drop_tt(udev);
+-      }
+-      kfree(sch_ep);
+-}
+-
+ void xhci_mtk_drop_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
+               struct usb_host_endpoint *ep)
+ {
+@@ -688,9 +689,8 @@ void xhci_mtk_drop_ep_quirk(struct usb_h
+       sch_bw = &sch_array[bw_index];
+       list_for_each_entry_safe(sch_ep, tmp, &sch_bw->bw_ep_list, endpoint) {
+-              if (sch_ep->ep == ep) {
+-                      xhci_mtk_drop_ep(mtk, udev, sch_ep);
+-              }
++              if (sch_ep->ep == ep)
++                      destroy_sch_ep(udev, sch_bw, sch_ep);
+       }
+ }
+ EXPORT_SYMBOL_GPL(xhci_mtk_drop_ep_quirk);
+@@ -704,9 +704,9 @@ int xhci_mtk_check_bandwidth(struct usb_
+       struct mu3h_sch_ep_info *sch_ep, *tmp;
+       int bw_index, ret;
+-      dev_dbg(&udev->dev, "%s\n", __func__);
++      xhci_dbg(xhci, "%s() udev %s\n", __func__, dev_name(&udev->dev));
+-      list_for_each_entry(sch_ep, &mtk->bw_ep_list_new, endpoint) {
++      list_for_each_entry(sch_ep, &mtk->bw_ep_chk_list, endpoint) {
+               bw_index = get_bw_index(xhci, udev, sch_ep->ep);
+               sch_bw = &mtk->sch_array[bw_index];
+@@ -717,7 +717,7 @@ int xhci_mtk_check_bandwidth(struct usb_
+               }
+       }
+-      list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_list_new, endpoint) {
++      list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_chk_list, endpoint) {
+               struct xhci_ep_ctx *ep_ctx;
+               struct usb_host_endpoint *ep = sch_ep->ep;
+               unsigned int ep_index = xhci_get_endpoint_index(&ep->desc);
+@@ -746,12 +746,17 @@ EXPORT_SYMBOL_GPL(xhci_mtk_check_bandwid
+ void xhci_mtk_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
+ {
+       struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
++      struct xhci_hcd *xhci = hcd_to_xhci(hcd);
++      struct mu3h_sch_bw_info *sch_bw;
+       struct mu3h_sch_ep_info *sch_ep, *tmp;
++      int bw_index;
+-      dev_dbg(&udev->dev, "%s\n", __func__);
++      xhci_dbg(xhci, "%s() udev %s\n", __func__, dev_name(&udev->dev));
+-      list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_list_new, endpoint) {
+-              xhci_mtk_drop_ep(mtk, udev, sch_ep);
++      list_for_each_entry_safe(sch_ep, tmp, &mtk->bw_ep_chk_list, endpoint) {
++              bw_index = get_bw_index(xhci, udev, sch_ep->ep);
++              sch_bw = &mtk->sch_array[bw_index];
++              destroy_sch_ep(udev, sch_bw, sch_ep);
+       }
+       xhci_reset_bandwidth(hcd, udev);
+--- a/drivers/usb/host/xhci-mtk.h
++++ b/drivers/usb/host/xhci-mtk.h
+@@ -59,6 +59,7 @@ struct mu3h_sch_bw_info {
+  * @ep_type: endpoint type
+  * @maxpkt: max packet size of endpoint
+  * @ep: address of usb_host_endpoint struct
++ * @allocated: the bandwidth is aready allocated from bus_bw
+  * @offset: which uframe of the interval that transfer should be
+  *            scheduled first time within the interval
+  * @repeat: the time gap between two uframes that transfers are
+@@ -86,6 +87,7 @@ struct mu3h_sch_ep_info {
+       u32 ep_type;
+       u32 maxpkt;
+       void *ep;
++      bool allocated;
+       /*
+        * mtk xHCI scheduling information put into reserved DWs
+        * in ep context
+@@ -130,8 +132,8 @@ struct mu3c_ippc_regs {
+ struct xhci_hcd_mtk {
+       struct device *dev;
+       struct usb_hcd *hcd;
+-      struct list_head bw_ep_list_new;
+       struct mu3h_sch_bw_info *sch_array;
++      struct list_head bw_ep_chk_list;
+       struct mu3c_ippc_regs __iomem *ippc_regs;
+       bool has_ippc;
+       int num_u2_ports;