]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 8 Feb 2021 10:27:01 +0000 (11:27 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 8 Feb 2021 10:27:01 +0000 (11:27 +0100)
added patches:
cifs-report-error-instead-of-invalid-when-revalidating-a-dentry-fails.patch
fgraph-initialize-tracing_graph_pause-at-task-creation.patch
genirq-msi-activate-multi-msi-early-when-msi_flag_activate_early-is-set.patch
kretprobe-avoid-re-registration-of-the-same-kretprobe-earlier.patch
libnvdimm-dimm-avoid-race-between-probe-and-available_slots_show.patch
mac80211-fix-station-rate-table-updates-on-assoc.patch
ovl-fix-dentry-leak-in-ovl_get_redirect.patch
usb-dwc2-fix-endpoint-direction-check-in-ep_from_windex.patch
usb-dwc3-fix-clock-issue-during-resume-in-otg-mode.patch
usb-gadget-legacy-fix-an-error-code-in-eth_bind.patch
usb-host-xhci-plat-add-priv-quirk-for-skip-phy-initialization.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
xhci-fix-bounce-buffer-usage-for-non-sg-list-case.patch

18 files changed:
queue-5.4/cifs-report-error-instead-of-invalid-when-revalidating-a-dentry-fails.patch [new file with mode: 0644]
queue-5.4/fgraph-initialize-tracing_graph_pause-at-task-creation.patch [new file with mode: 0644]
queue-5.4/genirq-msi-activate-multi-msi-early-when-msi_flag_activate_early-is-set.patch [new file with mode: 0644]
queue-5.4/kretprobe-avoid-re-registration-of-the-same-kretprobe-earlier.patch [new file with mode: 0644]
queue-5.4/libnvdimm-dimm-avoid-race-between-probe-and-available_slots_show.patch [new file with mode: 0644]
queue-5.4/mac80211-fix-station-rate-table-updates-on-assoc.patch [new file with mode: 0644]
queue-5.4/ovl-fix-dentry-leak-in-ovl_get_redirect.patch [new file with mode: 0644]
queue-5.4/series
queue-5.4/usb-dwc2-fix-endpoint-direction-check-in-ep_from_windex.patch [new file with mode: 0644]
queue-5.4/usb-dwc3-fix-clock-issue-during-resume-in-otg-mode.patch [new file with mode: 0644]
queue-5.4/usb-gadget-legacy-fix-an-error-code-in-eth_bind.patch [new file with mode: 0644]
queue-5.4/usb-host-xhci-plat-add-priv-quirk-for-skip-phy-initialization.patch [new file with mode: 0644]
queue-5.4/usb-renesas_usbhs-clear-pipe-running-flag-in-usbhs_pkt_pop.patch [new file with mode: 0644]
queue-5.4/usb-usblp-don-t-call-usb_set_interface-if-there-s-a-single-alt.patch [new file with mode: 0644]
queue-5.4/usb-xhci-mtk-break-loop-when-find-the-endpoint-to-drop.patch [new file with mode: 0644]
queue-5.4/usb-xhci-mtk-fix-unreleased-bandwidth-data.patch [new file with mode: 0644]
queue-5.4/usb-xhci-mtk-skip-dropping-bandwidth-of-unchecked-endpoints.patch [new file with mode: 0644]
queue-5.4/xhci-fix-bounce-buffer-usage-for-non-sg-list-case.patch [new file with mode: 0644]

diff --git a/queue-5.4/cifs-report-error-instead-of-invalid-when-revalidating-a-dentry-fails.patch b/queue-5.4/cifs-report-error-instead-of-invalid-when-revalidating-a-dentry-fails.patch
new file mode 100644 (file)
index 0000000..4015a11
--- /dev/null
@@ -0,0 +1,74 @@
+From 21b200d091826a83aafc95d847139b2b0582f6d1 Mon Sep 17 00:00:00 2001
+From: Aurelien Aptel <aaptel@suse.com>
+Date: Fri, 5 Feb 2021 15:42:48 +0100
+Subject: cifs: report error instead of invalid when revalidating a dentry fails
+
+From: Aurelien Aptel <aaptel@suse.com>
+
+commit 21b200d091826a83aafc95d847139b2b0582f6d1 upstream.
+
+Assuming
+- //HOST/a is mounted on /mnt
+- //HOST/b is mounted on /mnt/b
+
+On a slow connection, running 'df' and killing it while it's
+processing /mnt/b can make cifs_get_inode_info() returns -ERESTARTSYS.
+
+This triggers the following chain of events:
+=> the dentry revalidation fail
+=> dentry is put and released
+=> superblock associated with the dentry is put
+=> /mnt/b is unmounted
+
+This patch makes cifs_d_revalidate() return the error instead of 0
+(invalid) when cifs_revalidate_dentry() fails, except for ENOENT (file
+deleted) and ESTALE (file recreated).
+
+Signed-off-by: Aurelien Aptel <aaptel@suse.com>
+Suggested-by: Shyam Prasad N <nspmangalore@gmail.com>
+Reviewed-by: Shyam Prasad N <nspmangalore@gmail.com>
+CC: stable@vger.kernel.org
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/cifs/dir.c |   22 ++++++++++++++++++++--
+ 1 file changed, 20 insertions(+), 2 deletions(-)
+
+--- a/fs/cifs/dir.c
++++ b/fs/cifs/dir.c
+@@ -738,6 +738,7 @@ static int
+ cifs_d_revalidate(struct dentry *direntry, unsigned int flags)
+ {
+       struct inode *inode;
++      int rc;
+       if (flags & LOOKUP_RCU)
+               return -ECHILD;
+@@ -747,8 +748,25 @@ cifs_d_revalidate(struct dentry *direntr
+               if ((flags & LOOKUP_REVAL) && !CIFS_CACHE_READ(CIFS_I(inode)))
+                       CIFS_I(inode)->time = 0; /* force reval */
+-              if (cifs_revalidate_dentry(direntry))
+-                      return 0;
++              rc = cifs_revalidate_dentry(direntry);
++              if (rc) {
++                      cifs_dbg(FYI, "cifs_revalidate_dentry failed with rc=%d", rc);
++                      switch (rc) {
++                      case -ENOENT:
++                      case -ESTALE:
++                              /*
++                               * Those errors mean the dentry is invalid
++                               * (file was deleted or recreated)
++                               */
++                              return 0;
++                      default:
++                              /*
++                               * Otherwise some unexpected error happened
++                               * report it as-is to VFS layer
++                               */
++                              return rc;
++                      }
++              }
+               else {
+                       /*
+                        * If the inode wasn't known to be a dfs entry when
diff --git a/queue-5.4/fgraph-initialize-tracing_graph_pause-at-task-creation.patch b/queue-5.4/fgraph-initialize-tracing_graph_pause-at-task-creation.patch
new file mode 100644 (file)
index 0000000..ba5717a
--- /dev/null
@@ -0,0 +1,82 @@
+From 7e0a9220467dbcfdc5bc62825724f3e52e50ab31 Mon Sep 17 00:00:00 2001
+From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>
+Date: Fri, 29 Jan 2021 10:13:53 -0500
+Subject: fgraph: Initialize tracing_graph_pause at task creation
+
+From: Steven Rostedt (VMware) <rostedt@goodmis.org>
+
+commit 7e0a9220467dbcfdc5bc62825724f3e52e50ab31 upstream.
+
+On some archs, the idle task can call into cpu_suspend(). The cpu_suspend()
+will disable or pause function graph tracing, as there's some paths in
+bringing down the CPU that can have issues with its return address being
+modified. The task_struct structure has a "tracing_graph_pause" atomic
+counter, that when set to something other than zero, the function graph
+tracer will not modify the return address.
+
+The problem is that the tracing_graph_pause counter is initialized when the
+function graph tracer is enabled. This can corrupt the counter for the idle
+task if it is suspended in these architectures.
+
+   CPU 1                               CPU 2
+   -----                               -----
+  do_idle()
+    cpu_suspend()
+      pause_graph_tracing()
+          task_struct->tracing_graph_pause++ (0 -> 1)
+
+                               start_graph_tracing()
+                                 for_each_online_cpu(cpu) {
+                                   ftrace_graph_init_idle_task(cpu)
+                                     task-struct->tracing_graph_pause = 0 (1 -> 0)
+
+      unpause_graph_tracing()
+          task_struct->tracing_graph_pause-- (0 -> -1)
+
+The above should have gone from 1 to zero, and enabled function graph
+tracing again. But instead, it is set to -1, which keeps it disabled.
+
+There's no reason that the field tracing_graph_pause on the task_struct can
+not be initialized at boot up.
+
+Cc: stable@vger.kernel.org
+Fixes: 380c4b1411ccd ("tracing/function-graph-tracer: append the tracing_graph_flag")
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=211339
+Reported-by: pierre.gondois@arm.com
+Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ init/init_task.c      |    3 ++-
+ kernel/trace/fgraph.c |    2 --
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+--- a/init/init_task.c
++++ b/init/init_task.c
+@@ -171,7 +171,8 @@ struct task_struct init_task
+       .lockdep_recursion = 0,
+ #endif
+ #ifdef CONFIG_FUNCTION_GRAPH_TRACER
+-      .ret_stack      = NULL,
++      .ret_stack              = NULL,
++      .tracing_graph_pause    = ATOMIC_INIT(0),
+ #endif
+ #if defined(CONFIG_TRACING) && defined(CONFIG_PREEMPTION)
+       .trace_recursion = 0,
+--- a/kernel/trace/fgraph.c
++++ b/kernel/trace/fgraph.c
+@@ -367,7 +367,6 @@ static int alloc_retstack_tasklist(struc
+               }
+               if (t->ret_stack == NULL) {
+-                      atomic_set(&t->tracing_graph_pause, 0);
+                       atomic_set(&t->trace_overrun, 0);
+                       t->curr_ret_stack = -1;
+                       t->curr_ret_depth = -1;
+@@ -462,7 +461,6 @@ static DEFINE_PER_CPU(struct ftrace_ret_
+ static void
+ graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack)
+ {
+-      atomic_set(&t->tracing_graph_pause, 0);
+       atomic_set(&t->trace_overrun, 0);
+       t->ftrace_timestamp = 0;
+       /* make curr_ret_stack visible before we add the ret_stack */
diff --git a/queue-5.4/genirq-msi-activate-multi-msi-early-when-msi_flag_activate_early-is-set.patch b/queue-5.4/genirq-msi-activate-multi-msi-early-when-msi_flag_activate_early-is-set.patch
new file mode 100644 (file)
index 0000000..453be01
--- /dev/null
@@ -0,0 +1,123 @@
+From 4c457e8cb75eda91906a4f89fc39bde3f9a43922 Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <maz@kernel.org>
+Date: Sat, 23 Jan 2021 12:27:59 +0000
+Subject: genirq/msi: Activate Multi-MSI early when MSI_FLAG_ACTIVATE_EARLY is set
+
+From: Marc Zyngier <maz@kernel.org>
+
+commit 4c457e8cb75eda91906a4f89fc39bde3f9a43922 upstream.
+
+When MSI_FLAG_ACTIVATE_EARLY is set (which is the case for PCI),
+__msi_domain_alloc_irqs() performs the activation of the interrupt (which
+in the case of PCI results in the endpoint being programmed) as soon as the
+interrupt is allocated.
+
+But it appears that this is only done for the first vector, introducing an
+inconsistent behaviour for PCI Multi-MSI.
+
+Fix it by iterating over the number of vectors allocated to each MSI
+descriptor. This is easily achieved by introducing a new
+"for_each_msi_vector" iterator, together with a tiny bit of refactoring.
+
+Fixes: f3b0946d629c ("genirq/msi: Make sure PCI MSIs are activated early")
+Reported-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Tested-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20210123122759.1781359-1-maz@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/msi.h |    6 ++++++
+ kernel/irq/msi.c    |   44 ++++++++++++++++++++------------------------
+ 2 files changed, 26 insertions(+), 24 deletions(-)
+
+--- a/include/linux/msi.h
++++ b/include/linux/msi.h
+@@ -139,6 +139,12 @@ struct msi_desc {
+       list_for_each_entry((desc), dev_to_msi_list((dev)), list)
+ #define for_each_msi_entry_safe(desc, tmp, dev)       \
+       list_for_each_entry_safe((desc), (tmp), dev_to_msi_list((dev)), list)
++#define for_each_msi_vector(desc, __irq, dev)                         \
++      for_each_msi_entry((desc), (dev))                               \
++              if ((desc)->irq)                                        \
++                      for (__irq = (desc)->irq;                       \
++                           __irq < ((desc)->irq + (desc)->nvec_used); \
++                           __irq++)
+ #ifdef CONFIG_IRQ_MSI_IOMMU
+ static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
+--- a/kernel/irq/msi.c
++++ b/kernel/irq/msi.c
+@@ -437,22 +437,22 @@ int msi_domain_alloc_irqs(struct irq_dom
+       can_reserve = msi_check_reservation_mode(domain, info, dev);
+-      for_each_msi_entry(desc, dev) {
+-              virq = desc->irq;
+-              if (desc->nvec_used == 1)
+-                      dev_dbg(dev, "irq %d for MSI\n", virq);
+-              else
++      /*
++       * This flag is set by the PCI layer as we need to activate
++       * the MSI entries before the PCI layer enables MSI in the
++       * card. Otherwise the card latches a random msi message.
++       */
++      if (!(info->flags & MSI_FLAG_ACTIVATE_EARLY))
++              goto skip_activate;
++
++      for_each_msi_vector(desc, i, dev) {
++              if (desc->irq == i) {
++                      virq = desc->irq;
+                       dev_dbg(dev, "irq [%d-%d] for MSI\n",
+                               virq, virq + desc->nvec_used - 1);
+-              /*
+-               * This flag is set by the PCI layer as we need to activate
+-               * the MSI entries before the PCI layer enables MSI in the
+-               * card. Otherwise the card latches a random msi message.
+-               */
+-              if (!(info->flags & MSI_FLAG_ACTIVATE_EARLY))
+-                      continue;
++              }
+-              irq_data = irq_domain_get_irq_data(domain, desc->irq);
++              irq_data = irq_domain_get_irq_data(domain, i);
+               if (!can_reserve) {
+                       irqd_clr_can_reserve(irq_data);
+                       if (domain->flags & IRQ_DOMAIN_MSI_NOMASK_QUIRK)
+@@ -463,28 +463,24 @@ int msi_domain_alloc_irqs(struct irq_dom
+                       goto cleanup;
+       }
++skip_activate:
+       /*
+        * If these interrupts use reservation mode, clear the activated bit
+        * so request_irq() will assign the final vector.
+        */
+       if (can_reserve) {
+-              for_each_msi_entry(desc, dev) {
+-                      irq_data = irq_domain_get_irq_data(domain, desc->irq);
++              for_each_msi_vector(desc, i, dev) {
++                      irq_data = irq_domain_get_irq_data(domain, i);
+                       irqd_clr_activated(irq_data);
+               }
+       }
+       return 0;
+ cleanup:
+-      for_each_msi_entry(desc, dev) {
+-              struct irq_data *irqd;
+-
+-              if (desc->irq == virq)
+-                      break;
+-
+-              irqd = irq_domain_get_irq_data(domain, desc->irq);
+-              if (irqd_is_activated(irqd))
+-                      irq_domain_deactivate_irq(irqd);
++      for_each_msi_vector(desc, i, dev) {
++              irq_data = irq_domain_get_irq_data(domain, i);
++              if (irqd_is_activated(irq_data))
++                      irq_domain_deactivate_irq(irq_data);
+       }
+       msi_domain_free_irqs(domain, dev);
+       return ret;
diff --git a/queue-5.4/kretprobe-avoid-re-registration-of-the-same-kretprobe-earlier.patch b/queue-5.4/kretprobe-avoid-re-registration-of-the-same-kretprobe-earlier.patch
new file mode 100644 (file)
index 0000000..b37f075
--- /dev/null
@@ -0,0 +1,52 @@
+From 0188b87899ffc4a1d36a0badbe77d56c92fd91dc Mon Sep 17 00:00:00 2001
+From: Wang ShaoBo <bobo.shaobowang@huawei.com>
+Date: Thu, 28 Jan 2021 20:44:27 +0800
+Subject: kretprobe: Avoid re-registration of the same kretprobe earlier
+
+From: Wang ShaoBo <bobo.shaobowang@huawei.com>
+
+commit 0188b87899ffc4a1d36a0badbe77d56c92fd91dc upstream.
+
+Our system encountered a re-init error when re-registering same kretprobe,
+where the kretprobe_instance in rp->free_instances is illegally accessed
+after re-init.
+
+Implementation to avoid re-registration has been introduced for kprobe
+before, but lags for register_kretprobe(). We must check if kprobe has
+been re-registered before re-initializing kretprobe, otherwise it will
+destroy the data struct of kretprobe registered, which can lead to memory
+leak, system crash, also some unexpected behaviors.
+
+We use check_kprobe_rereg() to check if kprobe has been re-registered
+before running register_kretprobe()'s body, for giving a warning message
+and terminate registration process.
+
+Link: https://lkml.kernel.org/r/20210128124427.2031088-1-bobo.shaobowang@huawei.com
+
+Cc: stable@vger.kernel.org
+Fixes: 1f0ab40976460 ("kprobes: Prevent re-registration of the same kprobe")
+[ The above commit should have been done for kretprobes too ]
+Acked-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
+Acked-by: Ananth N Mavinakayanahalli <ananth@linux.ibm.com>
+Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
+Signed-off-by: Wang ShaoBo <bobo.shaobowang@huawei.com>
+Signed-off-by: Cheng Jian <cj.chengjian@huawei.com>
+Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/kprobes.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/kernel/kprobes.c
++++ b/kernel/kprobes.c
+@@ -1972,6 +1972,10 @@ int register_kretprobe(struct kretprobe
+       if (!kprobe_on_func_entry(rp->kp.addr, rp->kp.symbol_name, rp->kp.offset))
+               return -EINVAL;
++      /* If only rp->kp.addr is specified, check reregistering kprobes */
++      if (rp->kp.addr && check_kprobe_rereg(&rp->kp))
++              return -EINVAL;
++
+       if (kretprobe_blacklist_size) {
+               addr = kprobe_addr(&rp->kp);
+               if (IS_ERR(addr))
diff --git a/queue-5.4/libnvdimm-dimm-avoid-race-between-probe-and-available_slots_show.patch b/queue-5.4/libnvdimm-dimm-avoid-race-between-probe-and-available_slots_show.patch
new file mode 100644 (file)
index 0000000..6be11ce
--- /dev/null
@@ -0,0 +1,96 @@
+From 7018c897c2f243d4b5f1b94bc6b4831a7eab80fb Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Mon, 1 Feb 2021 16:20:40 -0800
+Subject: libnvdimm/dimm: Avoid race between probe and available_slots_show()
+
+From: Dan Williams <dan.j.williams@intel.com>
+
+commit 7018c897c2f243d4b5f1b94bc6b4831a7eab80fb upstream.
+
+Richard reports that the following test:
+
+(while true; do
+     cat /sys/bus/nd/devices/nmem*/available_slots 2>&1 > /dev/null
+ done) &
+
+while true; do
+     for i in $(seq 0 4); do
+         echo nmem$i > /sys/bus/nd/drivers/nvdimm/bind
+     done
+     for i in $(seq 0 4); do
+         echo nmem$i > /sys/bus/nd/drivers/nvdimm/unbind
+     done
+ done
+
+...fails with a crash signature like:
+
+    divide error: 0000 [#1] SMP KASAN PTI
+    RIP: 0010:nd_label_nfree+0x134/0x1a0 [libnvdimm]
+    [..]
+    Call Trace:
+     available_slots_show+0x4e/0x120 [libnvdimm]
+     dev_attr_show+0x42/0x80
+     ? memset+0x20/0x40
+     sysfs_kf_seq_show+0x218/0x410
+
+The root cause is that available_slots_show() consults driver-data, but
+fails to synchronize against device-unbind setting up a TOCTOU race to
+access uninitialized memory.
+
+Validate driver-data under the device-lock.
+
+Fixes: 4d88a97aa9e8 ("libnvdimm, nvdimm: dimm driver and base libnvdimm device-driver infrastructure")
+Cc: <stable@vger.kernel.org>
+Cc: Vishal Verma <vishal.l.verma@intel.com>
+Cc: Dave Jiang <dave.jiang@intel.com>
+Cc: Ira Weiny <ira.weiny@intel.com>
+Cc: Coly Li <colyli@suse.com>
+Reported-by: Richard Palethorpe <rpalethorpe@suse.com>
+Acked-by: Richard Palethorpe <rpalethorpe@suse.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvdimm/dimm_devs.c |   18 +++++++++++++++---
+ 1 file changed, 15 insertions(+), 3 deletions(-)
+
+--- a/drivers/nvdimm/dimm_devs.c
++++ b/drivers/nvdimm/dimm_devs.c
+@@ -344,16 +344,16 @@ static ssize_t state_show(struct device
+ }
+ static DEVICE_ATTR_RO(state);
+-static ssize_t available_slots_show(struct device *dev,
+-              struct device_attribute *attr, char *buf)
++static ssize_t __available_slots_show(struct nvdimm_drvdata *ndd, char *buf)
+ {
+-      struct nvdimm_drvdata *ndd = dev_get_drvdata(dev);
++      struct device *dev;
+       ssize_t rc;
+       u32 nfree;
+       if (!ndd)
+               return -ENXIO;
++      dev = ndd->dev;
+       nvdimm_bus_lock(dev);
+       nfree = nd_label_nfree(ndd);
+       if (nfree - 1 > nfree) {
+@@ -365,6 +365,18 @@ static ssize_t available_slots_show(stru
+       nvdimm_bus_unlock(dev);
+       return rc;
+ }
++
++static ssize_t available_slots_show(struct device *dev,
++                                  struct device_attribute *attr, char *buf)
++{
++      ssize_t rc;
++
++      nd_device_lock(dev);
++      rc = __available_slots_show(dev_get_drvdata(dev), buf);
++      nd_device_unlock(dev);
++
++      return rc;
++}
+ static DEVICE_ATTR_RO(available_slots);
+ __weak ssize_t security_show(struct device *dev,
diff --git a/queue-5.4/mac80211-fix-station-rate-table-updates-on-assoc.patch b/queue-5.4/mac80211-fix-station-rate-table-updates-on-assoc.patch
new file mode 100644 (file)
index 0000000..b03d4b3
--- /dev/null
@@ -0,0 +1,51 @@
+From 18fe0fae61252b5ae6e26553e2676b5fac555951 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@nbd.name>
+Date: Mon, 1 Feb 2021 09:33:24 +0100
+Subject: mac80211: fix station rate table updates on assoc
+
+From: Felix Fietkau <nbd@nbd.name>
+
+commit 18fe0fae61252b5ae6e26553e2676b5fac555951 upstream.
+
+If the driver uses .sta_add, station entries are only uploaded after the sta
+is in assoc state. Fix early station rate table updates by deferring them
+until the sta has been uploaded.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Link: https://lore.kernel.org/r/20210201083324.3134-1-nbd@nbd.name
+[use rcu_access_pointer() instead since we won't dereference here]
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mac80211/driver-ops.c |    5 ++++-
+ net/mac80211/rate.c       |    3 ++-
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+--- a/net/mac80211/driver-ops.c
++++ b/net/mac80211/driver-ops.c
+@@ -125,8 +125,11 @@ int drv_sta_state(struct ieee80211_local
+       } else if (old_state == IEEE80211_STA_AUTH &&
+                  new_state == IEEE80211_STA_ASSOC) {
+               ret = drv_sta_add(local, sdata, &sta->sta);
+-              if (ret == 0)
++              if (ret == 0) {
+                       sta->uploaded = true;
++                      if (rcu_access_pointer(sta->sta.rates))
++                              drv_sta_rate_tbl_update(local, sdata, &sta->sta);
++              }
+       } else if (old_state == IEEE80211_STA_ASSOC &&
+                  new_state == IEEE80211_STA_AUTH) {
+               drv_sta_remove(local, sdata, &sta->sta);
+--- a/net/mac80211/rate.c
++++ b/net/mac80211/rate.c
+@@ -934,7 +934,8 @@ int rate_control_set_rates(struct ieee80
+       if (old)
+               kfree_rcu(old, rcu_head);
+-      drv_sta_rate_tbl_update(hw_to_local(hw), sta->sdata, pubsta);
++      if (sta->uploaded)
++              drv_sta_rate_tbl_update(hw_to_local(hw), sta->sdata, pubsta);
+       ieee80211_sta_set_expected_throughput(pubsta, sta_get_expected_throughput(sta));
diff --git a/queue-5.4/ovl-fix-dentry-leak-in-ovl_get_redirect.patch b/queue-5.4/ovl-fix-dentry-leak-in-ovl_get_redirect.patch
new file mode 100644 (file)
index 0000000..778729a
--- /dev/null
@@ -0,0 +1,91 @@
+From e04527fefba6e4e66492f122cf8cc6314f3cf3bf Mon Sep 17 00:00:00 2001
+From: Liangyan <liangyan.peng@linux.alibaba.com>
+Date: Tue, 22 Dec 2020 11:06:26 +0800
+Subject: ovl: fix dentry leak in ovl_get_redirect
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Liangyan <liangyan.peng@linux.alibaba.com>
+
+commit e04527fefba6e4e66492f122cf8cc6314f3cf3bf upstream.
+
+We need to lock d_parent->d_lock before dget_dlock, or this may
+have d_lockref updated parallelly like calltrace below which will
+cause dentry->d_lockref leak and risk a crash.
+
+     CPU 0                                CPU 1
+ovl_set_redirect                       lookup_fast
+  ovl_get_redirect                       __d_lookup
+    dget_dlock
+      //no lock protection here            spin_lock(&dentry->d_lock)
+      dentry->d_lockref.count++            dentry->d_lockref.count++
+
+[ Â  49.799059] PGD 800000061fed7067 P4D 800000061fed7067 PUD 61fec5067 PMD 0
+[ Â  49.799689] Oops: 0002 [#1] SMP PTI
+[ Â  49.800019] CPU: 2 PID: 2332 Comm: node Not tainted 4.19.24-7.20.al7.x86_64 #1
+[ Â  49.800678] Hardware name: Alibaba Cloud Alibaba Cloud ECS, BIOS 8a46cfe 04/01/2014
+[ Â  49.801380] RIP: 0010:_raw_spin_lock+0xc/0x20
+[ Â  49.803470] RSP: 0018:ffffac6fc5417e98 EFLAGS: 00010246
+[ Â  49.803949] RAX: 0000000000000000 RBX: ffff93b8da3446c0 RCX: 0000000a00000000
+[ Â  49.804600] RDX: 0000000000000001 RSI: 000000000000000a RDI: 0000000000000088
+[ Â  49.805252] RBP: 0000000000000000 R08: 0000000000000000 R09: ffffffff993cf040
+[ Â  49.805898] R10: ffff93b92292e580 R11: ffffd27f188a4b80 R12: 0000000000000000
+[ Â  49.806548] R13: 00000000ffffff9c R14: 00000000fffffffe R15: ffff93b8da3446c0
+[ Â  49.807200] FS: Â 00007ffbedffb700(0000) GS:ffff93b927880000(0000) knlGS:0000000000000000
+[ Â  49.807935] CS: Â 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ Â  49.808461] CR2: 0000000000000088 CR3: 00000005e3f74006 CR4: 00000000003606a0
+[ Â  49.809113] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+[ Â  49.809758] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+[ Â  49.810410] Call Trace:
+[ Â  49.810653] Â d_delete+0x2c/0xb0
+[ Â  49.810951] Â vfs_rmdir+0xfd/0x120
+[ Â  49.811264] Â do_rmdir+0x14f/0x1a0
+[ Â  49.811573] Â do_syscall_64+0x5b/0x190
+[ Â  49.811917] Â entry_SYSCALL_64_after_hwframe+0x44/0xa9
+[ Â  49.812385] RIP: 0033:0x7ffbf505ffd7
+[ Â  49.814404] RSP: 002b:00007ffbedffada8 EFLAGS: 00000297 ORIG_RAX: 0000000000000054
+[ Â  49.815098] RAX: ffffffffffffffda RBX: 00007ffbedffb640 RCX: 00007ffbf505ffd7
+[ Â  49.815744] RDX: 0000000004449700 RSI: 0000000000000000 RDI: 0000000006c8cd50
+[ Â  49.816394] RBP: 00007ffbedffaea0 R08: 0000000000000000 R09: 0000000000017d0b
+[ Â  49.817038] R10: 0000000000000000 R11: 0000000000000297 R12: 0000000000000012
+[ Â  49.817687] R13: 00000000072823d8 R14: 00007ffbedffb700 R15: 00000000072823d8
+[ Â  49.818338] Modules linked in: pvpanic cirrusfb button qemu_fw_cfg atkbd libps2 i8042
+[ Â  49.819052] CR2: 0000000000000088
+[ Â  49.819368] ---[ end trace 4e652b8aa299aa2d ]---
+[ Â  49.819796] RIP: 0010:_raw_spin_lock+0xc/0x20
+[ Â  49.821880] RSP: 0018:ffffac6fc5417e98 EFLAGS: 00010246
+[ Â  49.822363] RAX: 0000000000000000 RBX: ffff93b8da3446c0 RCX: 0000000a00000000
+[ Â  49.823008] RDX: 0000000000000001 RSI: 000000000000000a RDI: 0000000000000088
+[ Â  49.823658] RBP: 0000000000000000 R08: 0000000000000000 R09: ffffffff993cf040
+[ Â  49.825404] R10: ffff93b92292e580 R11: ffffd27f188a4b80 R12: 0000000000000000
+[ Â  49.827147] R13: 00000000ffffff9c R14: 00000000fffffffe R15: ffff93b8da3446c0
+[ Â  49.828890] FS: Â 00007ffbedffb700(0000) GS:ffff93b927880000(0000) knlGS:0000000000000000
+[ Â  49.830725] CS: Â 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ Â  49.832359] CR2: 0000000000000088 CR3: 00000005e3f74006 CR4: 00000000003606a0
+[ Â  49.834085] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+[ Â  49.835792] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+
+Cc: <stable@vger.kernel.org>
+Fixes: a6c606551141 ("ovl: redirect on rename-dir")
+Signed-off-by: Liangyan <liangyan.peng@linux.alibaba.com>
+Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
+Suggested-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/overlayfs/dir.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/overlayfs/dir.c
++++ b/fs/overlayfs/dir.c
+@@ -940,8 +940,8 @@ static char *ovl_get_redirect(struct den
+               buflen -= thislen;
+               memcpy(&buf[buflen], name, thislen);
+-              tmp = dget_dlock(d->d_parent);
+               spin_unlock(&d->d_lock);
++              tmp = dget_parent(d);
+               dput(d);
+               d = tmp;
index 285dae03115c6350e959d7fdb2c0d77ceea3c0fb..e3f30cc18d3ca1c928c4f707e12f0d917bd3fb13 100644 (file)
@@ -20,3 +20,20 @@ r8169-fix-wol-on-shutdown-if-config_debug_shirq-is-s.patch
 arm-dts-sun7i-a20-bananapro-fix-ethernet-phy-mode.patch
 nvmet-tcp-fix-out-of-bounds-access-when-receiving-mu.patch
 memblock-do-not-start-bottom-up-allocations-with-ker.patch
+usb-gadget-legacy-fix-an-error-code-in-eth_bind.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
+usb-host-xhci-plat-add-priv-quirk-for-skip-phy-initialization.patch
+ovl-fix-dentry-leak-in-ovl_get_redirect.patch
+mac80211-fix-station-rate-table-updates-on-assoc.patch
+fgraph-initialize-tracing_graph_pause-at-task-creation.patch
+kretprobe-avoid-re-registration-of-the-same-kretprobe-earlier.patch
+libnvdimm-dimm-avoid-race-between-probe-and-available_slots_show.patch
+genirq-msi-activate-multi-msi-early-when-msi_flag_activate_early-is-set.patch
+xhci-fix-bounce-buffer-usage-for-non-sg-list-case.patch
+cifs-report-error-instead-of-invalid-when-revalidating-a-dentry-fails.patch
diff --git a/queue-5.4/usb-dwc2-fix-endpoint-direction-check-in-ep_from_windex.patch b/queue-5.4/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.4/usb-dwc3-fix-clock-issue-during-resume-in-otg-mode.patch b/queue-5.4/usb-dwc3-fix-clock-issue-during-resume-in-otg-mode.patch
new file mode 100644 (file)
index 0000000..977a599
--- /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
+@@ -1718,7 +1718,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.4/usb-gadget-legacy-fix-an-error-code-in-eth_bind.patch b/queue-5.4/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.4/usb-host-xhci-plat-add-priv-quirk-for-skip-phy-initialization.patch b/queue-5.4/usb-host-xhci-plat-add-priv-quirk-for-skip-phy-initialization.patch
new file mode 100644 (file)
index 0000000..08ff8e6
--- /dev/null
@@ -0,0 +1,64 @@
+From f768e718911e03a4a20b65f984eaa9b09045e4cd Mon Sep 17 00:00:00 2001
+From: Peter Chen <peter.chen@nxp.com>
+Date: Fri, 18 Sep 2020 16:17:46 +0300
+Subject: usb: host: xhci-plat: add priv quirk for skip PHY initialization
+
+From: Peter Chen <peter.chen@nxp.com>
+
+commit f768e718911e03a4a20b65f984eaa9b09045e4cd upstream.
+
+Some DRD controllers (eg, dwc3 & cdns3) have PHY management at
+their own driver to cover both device and host mode, so add one
+priv quirk for such users to skip PHY management from HCD core.
+
+Reviewed-by: Jun Li <jun.li@nxp.com>
+Signed-off-by: Peter Chen <peter.chen@nxp.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20200918131752.16488-5-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/xhci-plat.c |    8 ++++++--
+ drivers/usb/host/xhci.h      |    1 +
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/xhci-plat.c
++++ b/drivers/usb/host/xhci-plat.c
+@@ -163,6 +163,8 @@ static int xhci_plat_probe(struct platfo
+       struct usb_hcd          *hcd;
+       int                     ret;
+       int                     irq;
++      struct xhci_plat_priv   *priv = NULL;
++
+       if (usb_disabled())
+               return -ENODEV;
+@@ -257,8 +259,7 @@ static int xhci_plat_probe(struct platfo
+       priv_match = of_device_get_match_data(&pdev->dev);
+       if (priv_match) {
+-              struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
+-
++              priv = hcd_to_xhci_priv(hcd);
+               /* Just copy data for now */
+               if (priv_match)
+                       *priv = *priv_match;
+@@ -307,6 +308,9 @@ static int xhci_plat_probe(struct platfo
+       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))
++              hcd->skip_phy_initialization = 1;
++
+       ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+       if (ret)
+               goto disable_usb_phy;
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1873,6 +1873,7 @@ struct xhci_hcd {
+ #define XHCI_DEFAULT_PM_RUNTIME_ALLOW BIT_ULL(33)
+ #define XHCI_RESET_PLL_ON_DISCONNECT  BIT_ULL(34)
+ #define XHCI_SNPS_BROKEN_SUSPEND    BIT_ULL(35)
++#define XHCI_SKIP_PHY_INIT    BIT_ULL(37)
+ #define XHCI_DISABLE_SPARSE   BIT_ULL(38)
+       unsigned int            num_active_eps;
diff --git a/queue-5.4/usb-renesas_usbhs-clear-pipe-running-flag-in-usbhs_pkt_pop.patch b/queue-5.4/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.4/usb-usblp-don-t-call-usb_set_interface-if-there-s-a-single-alt.patch b/queue-5.4/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.4/usb-xhci-mtk-break-loop-when-find-the-endpoint-to-drop.patch b/queue-5.4/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.4/usb-xhci-mtk-fix-unreleased-bandwidth-data.patch b/queue-5.4/usb-xhci-mtk-fix-unreleased-bandwidth-data.patch
new file mode 100644 (file)
index 0000000..a15894d
--- /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;
+@@ -5380,6 +5380,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
+@@ -1911,6 +1911,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
+@@ -2063,6 +2065,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.4/usb-xhci-mtk-skip-dropping-bandwidth-of-unchecked-endpoints.patch b/queue-5.4/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;
diff --git a/queue-5.4/xhci-fix-bounce-buffer-usage-for-non-sg-list-case.patch b/queue-5.4/xhci-fix-bounce-buffer-usage-for-non-sg-list-case.patch
new file mode 100644 (file)
index 0000000..6410e1f
--- /dev/null
@@ -0,0 +1,82 @@
+From d4a610635400ccc382792f6be69427078541c678 Mon Sep 17 00:00:00 2001
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Wed, 3 Feb 2021 13:37:02 +0200
+Subject: xhci: fix bounce buffer usage for non-sg list case
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit d4a610635400ccc382792f6be69427078541c678 upstream.
+
+xhci driver may in some special cases need to copy small amounts
+of payload data to a bounce buffer in order to meet the boundary
+and alignment restrictions set by the xHCI specification.
+
+In the majority of these cases the data is in a sg list, and
+driver incorrectly assumed data is always in urb->sg when using
+the bounce buffer.
+
+If data instead is contiguous, and in urb->transfer_buffer, we may still
+need to bounce buffer a small part if data starts very close (less than
+packet size) to a 64k boundary.
+
+Check if sg list is used before copying data to/from it.
+
+Fixes: f9c589e142d0 ("xhci: TD-fragment, align the unsplittable case with a bounce buffer")
+Cc: stable@vger.kernel.org
+Reported-by: Andreas Hartmann <andihartmann@01019freenet.de>
+Tested-by: Andreas Hartmann <andihartmann@01019freenet.de>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20210203113702.436762-2-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/xhci-ring.c |   31 ++++++++++++++++++++-----------
+ 1 file changed, 20 insertions(+), 11 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -695,11 +695,16 @@ static void xhci_unmap_td_bounce_buffer(
+       dma_unmap_single(dev, seg->bounce_dma, ring->bounce_buf_len,
+                        DMA_FROM_DEVICE);
+       /* for in tranfers we need to copy the data from bounce to sg */
+-      len = sg_pcopy_from_buffer(urb->sg, urb->num_sgs, seg->bounce_buf,
+-                           seg->bounce_len, seg->bounce_offs);
+-      if (len != seg->bounce_len)
+-              xhci_warn(xhci, "WARN Wrong bounce buffer read length: %zu != %d\n",
+-                              len, seg->bounce_len);
++      if (urb->num_sgs) {
++              len = sg_pcopy_from_buffer(urb->sg, urb->num_sgs, seg->bounce_buf,
++                                         seg->bounce_len, seg->bounce_offs);
++              if (len != seg->bounce_len)
++                      xhci_warn(xhci, "WARN Wrong bounce buffer read length: %zu != %d\n",
++                                len, seg->bounce_len);
++      } else {
++              memcpy(urb->transfer_buffer + seg->bounce_offs, seg->bounce_buf,
++                     seg->bounce_len);
++      }
+       seg->bounce_len = 0;
+       seg->bounce_offs = 0;
+ }
+@@ -3263,12 +3268,16 @@ static int xhci_align_td(struct xhci_hcd
+       /* create a max max_pkt sized bounce buffer pointed to by last trb */
+       if (usb_urb_dir_out(urb)) {
+-              len = sg_pcopy_to_buffer(urb->sg, urb->num_sgs,
+-                                 seg->bounce_buf, new_buff_len, enqd_len);
+-              if (len != new_buff_len)
+-                      xhci_warn(xhci,
+-                              "WARN Wrong bounce buffer write length: %zu != %d\n",
+-                              len, new_buff_len);
++              if (urb->num_sgs) {
++                      len = sg_pcopy_to_buffer(urb->sg, urb->num_sgs,
++                                               seg->bounce_buf, new_buff_len, enqd_len);
++                      if (len != new_buff_len)
++                              xhci_warn(xhci, "WARN Wrong bounce buffer write length: %zu != %d\n",
++                                        len, new_buff_len);
++              } else {
++                      memcpy(seg->bounce_buf, urb->transfer_buffer + enqd_len, new_buff_len);
++              }
++
+               seg->bounce_dma = dma_map_single(dev, seg->bounce_buf,
+                                                max_pkt, DMA_TO_DEVICE);
+       } else {