--- /dev/null
+From 739d0959fbed23838a96c48fbce01dd2f6fb2c5f Mon Sep 17 00:00:00 2001
+From: Luke D Jones <luke@ljones.dev>
+Date: Sat, 7 Aug 2021 14:58:05 +1200
+Subject: ALSA: hda: Add quirk for ASUS Flow x13
+
+From: Luke D Jones <luke@ljones.dev>
+
+commit 739d0959fbed23838a96c48fbce01dd2f6fb2c5f upstream.
+
+The ASUS GV301QH sound appears to work well with the quirk for
+ALC294_FIXUP_ASUS_DUAL_SPK.
+
+Signed-off-by: Luke D Jones <luke@ljones.dev>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20210807025805.27321-1-luke@ljones.dev
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/pci/hda/patch_realtek.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -8122,6 +8122,7 @@ static const struct snd_pci_quirk alc269
+ SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
+ SND_PCI_QUIRK(0x1043, 0x1740, "ASUS UX430UA", ALC295_FIXUP_ASUS_DACS),
+ SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK),
++ SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK),
+ SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS),
+ SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1043, 0x18f1, "Asus FX505DT", ALC256_FIXUP_ASUS_HEADSET_MIC),
--- /dev/null
+From b1bd5cba3306691c771d558e94baa73e8b0b96b7 Mon Sep 17 00:00:00 2001
+From: Lai Jiangshan <laijs@linux.alibaba.com>
+Date: Thu, 3 Jun 2021 13:24:55 +0800
+Subject: KVM: X86: MMU: Use the correct inherited permissions to get shadow page
+
+From: Lai Jiangshan <laijs@linux.alibaba.com>
+
+commit b1bd5cba3306691c771d558e94baa73e8b0b96b7 upstream.
+
+When computing the access permissions of a shadow page, use the effective
+permissions of the walk up to that point, i.e. the logic AND of its parents'
+permissions. Two guest PxE entries that point at the same table gfn need to
+be shadowed with different shadow pages if their parents' permissions are
+different. KVM currently uses the effective permissions of the last
+non-leaf entry for all non-leaf entries. Because all non-leaf SPTEs have
+full ("uwx") permissions, and the effective permissions are recorded only
+in role.access and merged into the leaves, this can lead to incorrect
+reuse of a shadow page and eventually to a missing guest protection page
+fault.
+
+For example, here is a shared pagetable:
+
+ pgd[] pud[] pmd[] virtual address pointers
+ /->pmd1(u--)->pte1(uw-)->page1 <- ptr1 (u--)
+ /->pud1(uw-)--->pmd2(uw-)->pte2(uw-)->page2 <- ptr2 (uw-)
+ pgd-| (shared pmd[] as above)
+ \->pud2(u--)--->pmd1(u--)->pte1(uw-)->page1 <- ptr3 (u--)
+ \->pmd2(uw-)->pte2(uw-)->page2 <- ptr4 (u--)
+
+ pud1 and pud2 point to the same pmd table, so:
+ - ptr1 and ptr3 points to the same page.
+ - ptr2 and ptr4 points to the same page.
+
+(pud1 and pud2 here are pud entries, while pmd1 and pmd2 here are pmd entries)
+
+- First, the guest reads from ptr1 first and KVM prepares a shadow
+ page table with role.access=u--, from ptr1's pud1 and ptr1's pmd1.
+ "u--" comes from the effective permissions of pgd, pud1 and
+ pmd1, which are stored in pt->access. "u--" is used also to get
+ the pagetable for pud1, instead of "uw-".
+
+- Then the guest writes to ptr2 and KVM reuses pud1 which is present.
+ The hypervisor set up a shadow page for ptr2 with pt->access is "uw-"
+ even though the pud1 pmd (because of the incorrect argument to
+ kvm_mmu_get_page in the previous step) has role.access="u--".
+
+- Then the guest reads from ptr3. The hypervisor reuses pud1's
+ shadow pmd for pud2, because both use "u--" for their permissions.
+ Thus, the shadow pmd already includes entries for both pmd1 and pmd2.
+
+- At last, the guest writes to ptr4. This causes no vmexit or pagefault,
+ because pud1's shadow page structures included an "uw-" page even though
+ its role.access was "u--".
+
+Any kind of shared pagetable might have the similar problem when in
+virtual machine without TDP enabled if the permissions are different
+from different ancestors.
+
+In order to fix the problem, we change pt->access to be an array, and
+any access in it will not include permissions ANDed from child ptes.
+
+The test code is: https://lore.kernel.org/kvm/20210603050537.19605-1-jiangshanlai@gmail.com/
+Remember to test it with TDP disabled.
+
+The problem had existed long before the commit 41074d07c78b ("KVM: MMU:
+Fix inherited permissions for emulated guest pte updates"), and it
+is hard to find which is the culprit. So there is no fixes tag here.
+
+Signed-off-by: Lai Jiangshan <laijs@linux.alibaba.com>
+Message-Id: <20210603052455.21023-1-jiangshanlai@gmail.com>
+Cc: stable@vger.kernel.org
+Fixes: cea0f0e7ea54 ("[PATCH] KVM: MMU: Shadow page table caching")
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+[OP: - apply arch/x86/kvm/mmu/* changes to arch/x86/kvm
+ - apply documentation changes to Documentation/virt/kvm/mmu.txt
+ - adjusted context in arch/x86/kvm/paging_tmpl.h]
+Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/virt/kvm/mmu.txt | 4 ++--
+ arch/x86/kvm/paging_tmpl.h | 14 +++++++++-----
+ 2 files changed, 11 insertions(+), 7 deletions(-)
+
+--- a/Documentation/virt/kvm/mmu.txt
++++ b/Documentation/virt/kvm/mmu.txt
+@@ -152,8 +152,8 @@ Shadow pages contain the following infor
+ shadow pages) so role.quadrant takes values in the range 0..3. Each
+ quadrant maps 1GB virtual address space.
+ role.access:
+- Inherited guest access permissions in the form uwx. Note execute
+- permission is positive, not negative.
++ Inherited guest access permissions from the parent ptes in the form uwx.
++ Note execute permission is positive, not negative.
+ role.invalid:
+ The page is invalid and should not be used. It is a root page that is
+ currently pinned (by a cpu hardware register pointing to it); once it is
+--- a/arch/x86/kvm/paging_tmpl.h
++++ b/arch/x86/kvm/paging_tmpl.h
+@@ -90,8 +90,8 @@ struct guest_walker {
+ gpa_t pte_gpa[PT_MAX_FULL_LEVELS];
+ pt_element_t __user *ptep_user[PT_MAX_FULL_LEVELS];
+ bool pte_writable[PT_MAX_FULL_LEVELS];
+- unsigned pt_access;
+- unsigned pte_access;
++ unsigned int pt_access[PT_MAX_FULL_LEVELS];
++ unsigned int pte_access;
+ gfn_t gfn;
+ struct x86_exception fault;
+ };
+@@ -406,13 +406,15 @@ retry_walk:
+ }
+
+ walker->ptes[walker->level - 1] = pte;
++
++ /* Convert to ACC_*_MASK flags for struct guest_walker. */
++ walker->pt_access[walker->level - 1] = FNAME(gpte_access)(pt_access ^ walk_nx_mask);
+ } while (!is_last_gpte(mmu, walker->level, pte));
+
+ pte_pkey = FNAME(gpte_pkeys)(vcpu, pte);
+ accessed_dirty = have_ad ? pte_access & PT_GUEST_ACCESSED_MASK : 0;
+
+ /* Convert to ACC_*_MASK flags for struct guest_walker. */
+- walker->pt_access = FNAME(gpte_access)(pt_access ^ walk_nx_mask);
+ walker->pte_access = FNAME(gpte_access)(pte_access ^ walk_nx_mask);
+ errcode = permission_fault(vcpu, mmu, walker->pte_access, pte_pkey, access);
+ if (unlikely(errcode))
+@@ -451,7 +453,8 @@ retry_walk:
+ }
+
+ pgprintk("%s: pte %llx pte_access %x pt_access %x\n",
+- __func__, (u64)pte, walker->pte_access, walker->pt_access);
++ __func__, (u64)pte, walker->pte_access,
++ walker->pt_access[walker->level - 1]);
+ return 1;
+
+ error:
+@@ -620,7 +623,7 @@ static int FNAME(fetch)(struct kvm_vcpu
+ {
+ struct kvm_mmu_page *sp = NULL;
+ struct kvm_shadow_walk_iterator it;
+- unsigned direct_access, access = gw->pt_access;
++ unsigned int direct_access, access;
+ int top_level, ret;
+ gfn_t gfn, base_gfn;
+
+@@ -652,6 +655,7 @@ static int FNAME(fetch)(struct kvm_vcpu
+ sp = NULL;
+ if (!is_shadow_present_pte(*it.sptep)) {
+ table_gfn = gw->table_gfn[it.level - 2];
++ access = gw->pt_access[it.level - 2];
+ sp = kvm_mmu_get_page(vcpu, table_gfn, addr, it.level-1,
+ false, access);
+ }
--- /dev/null
+From 427215d85e8d1476da1a86b8d67aceb485eb3631 Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <mszeredi@redhat.com>
+Date: Mon, 9 Aug 2021 10:19:47 +0200
+Subject: ovl: prevent private clone if bind mount is not allowed
+
+From: Miklos Szeredi <mszeredi@redhat.com>
+
+commit 427215d85e8d1476da1a86b8d67aceb485eb3631 upstream.
+
+Add the following checks from __do_loopback() to clone_private_mount() as
+well:
+
+ - verify that the mount is in the current namespace
+
+ - verify that there are no locked children
+
+Reported-by: Alois Wohlschlager <alois1@gmx-topmail.de>
+Fixes: c771d683a62e ("vfs: introduce clone_private_mount()")
+Cc: <stable@vger.kernel.org> # v3.18
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/namespace.c | 42 ++++++++++++++++++++++++++++--------------
+ 1 file changed, 28 insertions(+), 14 deletions(-)
+
+--- a/fs/namespace.c
++++ b/fs/namespace.c
+@@ -1861,6 +1861,20 @@ void drop_collected_mounts(struct vfsmou
+ namespace_unlock();
+ }
+
++static bool has_locked_children(struct mount *mnt, struct dentry *dentry)
++{
++ struct mount *child;
++
++ list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
++ if (!is_subdir(child->mnt_mountpoint, dentry))
++ continue;
++
++ if (child->mnt.mnt_flags & MNT_LOCKED)
++ return true;
++ }
++ return false;
++}
++
+ /**
+ * clone_private_mount - create a private clone of a path
+ *
+@@ -1875,14 +1889,27 @@ struct vfsmount *clone_private_mount(con
+ struct mount *old_mnt = real_mount(path->mnt);
+ struct mount *new_mnt;
+
++ down_read(&namespace_sem);
+ if (IS_MNT_UNBINDABLE(old_mnt))
+- return ERR_PTR(-EINVAL);
++ goto invalid;
++
++ if (!check_mnt(old_mnt))
++ goto invalid;
++
++ if (has_locked_children(old_mnt, path->dentry))
++ goto invalid;
+
+ new_mnt = clone_mnt(old_mnt, path->dentry, CL_PRIVATE);
++ up_read(&namespace_sem);
++
+ if (IS_ERR(new_mnt))
+ return ERR_CAST(new_mnt);
+
+ return &new_mnt->mnt;
++
++invalid:
++ up_read(&namespace_sem);
++ return ERR_PTR(-EINVAL);
+ }
+ EXPORT_SYMBOL_GPL(clone_private_mount);
+
+@@ -2234,19 +2261,6 @@ static int do_change_type(struct path *p
+ return err;
+ }
+
+-static bool has_locked_children(struct mount *mnt, struct dentry *dentry)
+-{
+- struct mount *child;
+- list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
+- if (!is_subdir(child->mnt_mountpoint, dentry))
+- continue;
+-
+- if (child->mnt.mnt_flags & MNT_LOCKED)
+- return true;
+- }
+- return false;
+-}
+-
+ static struct mount *__do_loopback(struct path *old_path, int recurse)
+ {
+ struct mount *mnt = ERR_PTR(-EINVAL), *old = real_mount(old_path->mnt);
--- /dev/null
+From 3125f26c514826077f2a4490b75e9b1c7a644c42 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Sat, 7 Aug 2021 18:00:50 +0200
+Subject: ppp: Fix generating ppp unit id when ifname is not specified
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 3125f26c514826077f2a4490b75e9b1c7a644c42 upstream.
+
+When registering new ppp interface via PPPIOCNEWUNIT ioctl then kernel has
+to choose interface name as this ioctl API does not support specifying it.
+
+Kernel in this case register new interface with name "ppp<id>" where <id>
+is the ppp unit id, which can be obtained via PPPIOCGUNIT ioctl. This
+applies also in the case when registering new ppp interface via rtnl
+without supplying IFLA_IFNAME.
+
+PPPIOCNEWUNIT ioctl allows to specify own ppp unit id which will kernel
+assign to ppp interface, in case this ppp id is not already used by other
+ppp interface.
+
+In case user does not specify ppp unit id then kernel choose the first free
+ppp unit id. This applies also for case when creating ppp interface via
+rtnl method as it does not provide a way for specifying own ppp unit id.
+
+If some network interface (does not have to be ppp) has name "ppp<id>"
+with this first free ppp id then PPPIOCNEWUNIT ioctl or rtnl call fails.
+
+And registering new ppp interface is not possible anymore, until interface
+which holds conflicting name is renamed. Or when using rtnl method with
+custom interface name in IFLA_IFNAME.
+
+As list of allocated / used ppp unit ids is not possible to retrieve from
+kernel to userspace, userspace has no idea what happens nor which interface
+is doing this conflict.
+
+So change the algorithm how ppp unit id is generated. And choose the first
+number which is not neither used as ppp unit id nor in some network
+interface with pattern "ppp<id>".
+
+This issue can be simply reproduced by following pppd call when there is no
+ppp interface registered and also no interface with name pattern "ppp<id>":
+
+ pppd ifname ppp1 +ipv6 noip noauth nolock local nodetach pty "pppd +ipv6 noip noauth nolock local nodetach notty"
+
+Or by creating the one ppp interface (which gets assigned ppp unit id 0),
+renaming it to "ppp1" and then trying to create a new ppp interface (which
+will always fails as next free ppp unit id is 1, but network interface with
+name "ppp1" exists).
+
+This patch fixes above described issue by generating new and new ppp unit
+id until some non-conflicting id with network interfaces is generated.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ppp/ppp_generic.c | 19 +++++++++++++++----
+ 1 file changed, 15 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/ppp/ppp_generic.c
++++ b/drivers/net/ppp/ppp_generic.c
+@@ -283,7 +283,7 @@ static struct channel *ppp_find_channel(
+ static int ppp_connect_channel(struct channel *pch, int unit);
+ static int ppp_disconnect_channel(struct channel *pch);
+ static void ppp_destroy_channel(struct channel *pch);
+-static int unit_get(struct idr *p, void *ptr);
++static int unit_get(struct idr *p, void *ptr, int min);
+ static int unit_set(struct idr *p, void *ptr, int n);
+ static void unit_put(struct idr *p, int n);
+ static void *unit_find(struct idr *p, int n);
+@@ -959,9 +959,20 @@ static int ppp_unit_register(struct ppp
+ mutex_lock(&pn->all_ppp_mutex);
+
+ if (unit < 0) {
+- ret = unit_get(&pn->units_idr, ppp);
++ ret = unit_get(&pn->units_idr, ppp, 0);
+ if (ret < 0)
+ goto err;
++ if (!ifname_is_set) {
++ while (1) {
++ snprintf(ppp->dev->name, IFNAMSIZ, "ppp%i", ret);
++ if (!__dev_get_by_name(ppp->ppp_net, ppp->dev->name))
++ break;
++ unit_put(&pn->units_idr, ret);
++ ret = unit_get(&pn->units_idr, ppp, ret + 1);
++ if (ret < 0)
++ goto err;
++ }
++ }
+ } else {
+ /* Caller asked for a specific unit number. Fail with -EEXIST
+ * if unavailable. For backward compatibility, return -EEXIST
+@@ -3294,9 +3305,9 @@ static int unit_set(struct idr *p, void
+ }
+
+ /* get new free unit number and associate pointer with it */
+-static int unit_get(struct idr *p, void *ptr)
++static int unit_get(struct idr *p, void *ptr, int min)
+ {
+- return idr_alloc(p, ptr, 0, 0, GFP_KERNEL);
++ return idr_alloc(p, ptr, min, 0, GFP_KERNEL);
+ }
+
+ /* put unit number back to a pool */
kvm-svm-fix-off-by-one-indexing-when-nullifying-last.patch
tee-correct-inappropriate-usage-of-tee_shm_dma_buf-f.patch
-usb-dwc3-gadget-use-list_replace_init-before-travers.patch
media-v4l2-mem2mem-always-consider-output-queue-during-poll.patch
+tracing-reject-string-operand-in-the-histogram-expression.patch
+usb-dwc3-stop-active-transfers-before-halting-the-controller.patch
+usb-dwc3-gadget-allow-runtime-suspend-if-udc-unbinded.patch
+usb-dwc3-gadget-restart-dwc3-gadget-when-enabling-pullup.patch
+usb-dwc3-gadget-prevent-ep-queuing-while-stopping-transfers.patch
+usb-dwc3-gadget-clear-dep-flags-after-stop-transfers-in-ep-disable.patch
+usb-dwc3-gadget-disable-gadget-irq-during-pullup-disable.patch
+usb-dwc3-gadget-avoid-runtime-resume-if-disabling-pullup.patch
+kvm-x86-mmu-use-the-correct-inherited-permissions-to-get-shadow-page.patch
+usb-ehci-fix-kunpeng920-ehci-hardware-problem.patch
+alsa-hda-add-quirk-for-asus-flow-x13.patch
+ppp-fix-generating-ppp-unit-id-when-ifname-is-not-specified.patch
+ovl-prevent-private-clone-if-bind-mount-is-not-allowed.patch
--- /dev/null
+From a9d10ca4986571bffc19778742d508cc8dd13e02 Mon Sep 17 00:00:00 2001
+From: Masami Hiramatsu <mhiramat@kernel.org>
+Date: Wed, 28 Jul 2021 07:55:43 +0900
+Subject: tracing: Reject string operand in the histogram expression
+
+From: Masami Hiramatsu <mhiramat@kernel.org>
+
+commit a9d10ca4986571bffc19778742d508cc8dd13e02 upstream.
+
+Since the string type can not be the target of the addition / subtraction
+operation, it must be rejected. Without this fix, the string type silently
+converted to digits.
+
+Link: https://lkml.kernel.org/r/162742654278.290973.1523000673366456634.stgit@devnote2
+
+Cc: stable@vger.kernel.org
+Fixes: 100719dcef447 ("tracing: Add simple expression support to hist triggers")
+Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
+Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/trace_events_hist.c | 20 +++++++++++++++++++-
+ 1 file changed, 19 insertions(+), 1 deletion(-)
+
+--- a/kernel/trace/trace_events_hist.c
++++ b/kernel/trace/trace_events_hist.c
+@@ -66,7 +66,8 @@
+ C(INVALID_SUBSYS_EVENT, "Invalid subsystem or event name"), \
+ C(INVALID_REF_KEY, "Using variable references in keys not supported"), \
+ C(VAR_NOT_FOUND, "Couldn't find variable"), \
+- C(FIELD_NOT_FOUND, "Couldn't find field"),
++ C(FIELD_NOT_FOUND, "Couldn't find field"), \
++ C(INVALID_STR_OPERAND, "String type can not be an operand in expression"),
+
+ #undef C
+ #define C(a, b) HIST_ERR_##a
+@@ -3038,6 +3039,13 @@ static struct hist_field *parse_unary(st
+ ret = PTR_ERR(operand1);
+ goto free;
+ }
++ if (operand1->flags & HIST_FIELD_FL_STRING) {
++ /* String type can not be the operand of unary operator. */
++ hist_err(file->tr, HIST_ERR_INVALID_STR_OPERAND, errpos(str));
++ destroy_hist_field(operand1, 0);
++ ret = -EINVAL;
++ goto free;
++ }
+
+ expr->flags |= operand1->flags &
+ (HIST_FIELD_FL_TIMESTAMP | HIST_FIELD_FL_TIMESTAMP_USECS);
+@@ -3139,6 +3147,11 @@ static struct hist_field *parse_expr(str
+ operand1 = NULL;
+ goto free;
+ }
++ if (operand1->flags & HIST_FIELD_FL_STRING) {
++ hist_err(file->tr, HIST_ERR_INVALID_STR_OPERAND, errpos(operand1_str));
++ ret = -EINVAL;
++ goto free;
++ }
+
+ /* rest of string could be another expression e.g. b+c in a+b+c */
+ operand_flags = 0;
+@@ -3148,6 +3161,11 @@ static struct hist_field *parse_expr(str
+ operand2 = NULL;
+ goto free;
+ }
++ if (operand2->flags & HIST_FIELD_FL_STRING) {
++ hist_err(file->tr, HIST_ERR_INVALID_STR_OPERAND, errpos(str));
++ ret = -EINVAL;
++ goto free;
++ }
+
+ ret = check_expr_operands(file->tr, operand1, operand2);
+ if (ret)
--- /dev/null
+From foo@baz Fri Aug 13 10:48:08 AM CEST 2021
+From: Sam Protsenko <semen.protsenko@linaro.org>
+Date: Thu, 12 Aug 2021 20:16:47 +0300
+Subject: usb: dwc3: gadget: Allow runtime suspend if UDC unbinded
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: stable@vger.kernel.org, Wesley Cheng <wcheng@codeaurora.org>
+Message-ID: <20210812171652.23803-3-semen.protsenko@linaro.org>
+
+From: Wesley Cheng <wcheng@codeaurora.org>
+
+[ Upstream commit 77adb8bdf4227257e26b7ff67272678e66a0b250 ]
+
+The DWC3 runtime suspend routine checks for the USB connected parameter to
+determine if the controller can enter into a low power state. The
+connected state is only set to false after receiving a disconnect event.
+However, in the case of a device initiated disconnect (i.e. UDC unbind),
+the controller is halted and a disconnect event is never generated. Set
+the connected flag to false if issuing a device initiated disconnect to
+allow the controller to be suspended.
+
+Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
+Link: https://lore.kernel.org/r/1609283136-22140-2-git-send-email-wcheng@codeaurora.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/gadget.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -2018,6 +2018,17 @@ static int dwc3_gadget_pullup(struct usb
+ }
+
+ /*
++ * Check the return value for successful resume, or error. For a
++ * successful resume, the DWC3 runtime PM resume routine will handle
++ * the run stop sequence, so avoid duplicate operations here.
++ */
++ ret = pm_runtime_get_sync(dwc->dev);
++ if (!ret || ret < 0) {
++ pm_runtime_put(dwc->dev);
++ return 0;
++ }
++
++ /*
+ * Synchronize any pending event handling before executing the controller
+ * halt routine.
+ */
+@@ -2055,10 +2066,12 @@ static int dwc3_gadget_pullup(struct usb
+ dwc->ev_buf->lpos = (dwc->ev_buf->lpos + count) %
+ dwc->ev_buf->length;
+ }
++ dwc->connected = false;
+ }
+
+ ret = dwc3_gadget_run_stop(dwc, is_on, false);
+ spin_unlock_irqrestore(&dwc->lock, flags);
++ pm_runtime_put(dwc->dev);
+
+ return ret;
+ }
--- /dev/null
+From foo@baz Fri Aug 13 10:48:08 AM CEST 2021
+From: Sam Protsenko <semen.protsenko@linaro.org>
+Date: Thu, 12 Aug 2021 20:16:52 +0300
+Subject: usb: dwc3: gadget: Avoid runtime resume if disabling pullup
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: stable@vger.kernel.org, Wesley Cheng <wcheng@codeaurora.org>
+Message-ID: <20210812171652.23803-8-semen.protsenko@linaro.org>
+
+From: Wesley Cheng <wcheng@codeaurora.org>
+
+[ Upstream commit cb10f68ad8150f243964b19391711aaac5e8ff42 ]
+
+If the device is already in the runtime suspended state, any call to
+the pullup routine will issue a runtime resume on the DWC3 core
+device. If the USB gadget is disabling the pullup, then avoid having
+to issue a runtime resume, as DWC3 gadget has already been
+halted/stopped.
+
+This fixes an issue where the following condition occurs:
+
+usb_gadget_remove_driver()
+-->usb_gadget_disconnect()
+ -->dwc3_gadget_pullup(0)
+ -->pm_runtime_get_sync() -> ret = 0
+ -->pm_runtime_put() [async]
+-->usb_gadget_udc_stop()
+ -->dwc3_gadget_stop()
+ -->dwc->gadget_driver = NULL
+...
+
+dwc3_suspend_common()
+-->dwc3_gadget_suspend()
+ -->DWC3 halt/stop routine skipped, driver_data == NULL
+
+This leads to a situation where the DWC3 gadget is not properly
+stopped, as the runtime resume would have re-enabled EP0 and event
+interrupts, and since we avoided the DWC3 gadget suspend, these
+resources were never disabled.
+
+Fixes: 77adb8bdf422 ("usb: dwc3: gadget: Allow runtime suspend if UDC unbinded")
+Cc: stable <stable@vger.kernel.org>
+Acked-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
+Link: https://lore.kernel.org/r/1628058245-30692-1-git-send-email-wcheng@codeaurora.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/gadget.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -2019,6 +2019,17 @@ static int dwc3_gadget_pullup(struct usb
+ }
+
+ /*
++ * Avoid issuing a runtime resume if the device is already in the
++ * suspended state during gadget disconnect. DWC3 gadget was already
++ * halted/stopped during runtime suspend.
++ */
++ if (!is_on) {
++ pm_runtime_barrier(dwc->dev);
++ if (pm_runtime_suspended(dwc->dev))
++ return 0;
++ }
++
++ /*
+ * Check the return value for successful resume, or error. For a
+ * successful resume, the DWC3 runtime PM resume routine will handle
+ * the run stop sequence, so avoid duplicate operations here.
--- /dev/null
+From foo@baz Fri Aug 13 10:48:08 AM CEST 2021
+From: Sam Protsenko <semen.protsenko@linaro.org>
+Date: Thu, 12 Aug 2021 20:16:50 +0300
+Subject: usb: dwc3: gadget: Clear DEP flags after stop transfers in ep disable
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: stable@vger.kernel.org, Wesley Cheng <wcheng@codeaurora.org>
+Message-ID: <20210812171652.23803-6-semen.protsenko@linaro.org>
+
+From: Wesley Cheng <wcheng@codeaurora.org>
+
+[ Upstream commit 5aef629704ad4d983ecf5c8a25840f16e45b6d59 ]
+
+Ensure that dep->flags are cleared until after stop active transfers
+is completed. Otherwise, the ENDXFER command will not be executed
+during ep disable.
+
+Fixes: f09ddcfcb8c5 ("usb: dwc3: gadget: Prevent EP queuing while stopping transfers")
+Cc: stable <stable@vger.kernel.org>
+Reported-and-tested-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
+Link: https://lore.kernel.org/r/1616610664-16495-1-git-send-email-wcheng@codeaurora.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/gadget.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -754,10 +754,6 @@ static int __dwc3_gadget_ep_disable(stru
+ reg &= ~DWC3_DALEPENA_EP(dep->number);
+ dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
+
+- dep->stream_capable = false;
+- dep->type = 0;
+- dep->flags = 0;
+-
+ /* Clear out the ep descriptors for non-ep0 */
+ if (dep->number > 1) {
+ dep->endpoint.comp_desc = NULL;
+@@ -766,6 +762,10 @@ static int __dwc3_gadget_ep_disable(stru
+
+ dwc3_remove_requests(dwc, dep);
+
++ dep->stream_capable = false;
++ dep->type = 0;
++ dep->flags = 0;
++
+ return 0;
+ }
+
--- /dev/null
+From foo@baz Fri Aug 13 10:48:08 AM CEST 2021
+From: Sam Protsenko <semen.protsenko@linaro.org>
+Date: Thu, 12 Aug 2021 20:16:51 +0300
+Subject: usb: dwc3: gadget: Disable gadget IRQ during pullup disable
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: stable@vger.kernel.org, Wesley Cheng <wcheng@codeaurora.org>
+Message-ID: <20210812171652.23803-7-semen.protsenko@linaro.org>
+
+From: Wesley Cheng <wcheng@codeaurora.org>
+
+[ Upstream commit 8212937305f84ef73ea81036dafb80c557583d4b ]
+
+Current sequence utilizes dwc3_gadget_disable_irq() alongside
+synchronize_irq() to ensure that no further DWC3 events are generated.
+However, the dwc3_gadget_disable_irq() API only disables device
+specific events. Endpoint events can still be generated. Briefly
+disable the interrupt line, so that the cleanup code can run to
+prevent device and endpoint events. (i.e. __dwc3_gadget_stop() and
+dwc3_stop_active_transfers() respectively)
+
+Without doing so, it can lead to both the interrupt handler and the
+pullup disable routine both writing to the GEVNTCOUNT register, which
+will cause an incorrect count being read from future interrupts.
+
+Fixes: ae7e86108b12 ("usb: dwc3: Stop active transfers before halting the controller")
+Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
+Link: https://lore.kernel.org/r/1621571037-1424-1-git-send-email-wcheng@codeaurora.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/gadget.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -2030,13 +2030,10 @@ static int dwc3_gadget_pullup(struct usb
+ }
+
+ /*
+- * Synchronize any pending event handling before executing the controller
+- * halt routine.
++ * Synchronize and disable any further event handling while controller
++ * is being enabled/disabled.
+ */
+- if (!is_on) {
+- dwc3_gadget_disable_irq(dwc);
+- synchronize_irq(dwc->irq_gadget);
+- }
++ disable_irq(dwc->irq_gadget);
+
+ spin_lock_irqsave(&dwc->lock, flags);
+
+@@ -2074,6 +2071,8 @@ static int dwc3_gadget_pullup(struct usb
+
+ ret = dwc3_gadget_run_stop(dwc, is_on, false);
+ spin_unlock_irqrestore(&dwc->lock, flags);
++ enable_irq(dwc->irq_gadget);
++
+ pm_runtime_put(dwc->dev);
+
+ return ret;
--- /dev/null
+From foo@baz Fri Aug 13 10:48:08 AM CEST 2021
+From: Sam Protsenko <semen.protsenko@linaro.org>
+Date: Thu, 12 Aug 2021 20:16:49 +0300
+Subject: usb: dwc3: gadget: Prevent EP queuing while stopping transfers
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: stable@vger.kernel.org, Wesley Cheng <wcheng@codeaurora.org>
+Message-ID: <20210812171652.23803-5-semen.protsenko@linaro.org>
+
+From: Wesley Cheng <wcheng@codeaurora.org>
+
+[ Upstream commit f09ddcfcb8c569675066337adac2ac205113471f ]
+
+In the situations where the DWC3 gadget stops active transfers, once
+calling the dwc3_gadget_giveback(), there is a chance where a function
+driver can queue a new USB request in between the time where the dwc3
+lock has been released and re-aquired. This occurs after we've already
+issued an ENDXFER command. When the stop active transfers continues
+to remove USB requests from all dep lists, the newly added request will
+also be removed, while controller still has an active TRB for it.
+This can lead to the controller accessing an unmapped memory address.
+
+Fix this by ensuring parameters to prevent EP queuing are set before
+calling the stop active transfers API.
+
+Fixes: ae7e86108b12 ("usb: dwc3: Stop active transfers before halting the controller")
+Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
+Link: https://lore.kernel.org/r/1615507142-23097-1-git-send-email-wcheng@codeaurora.org
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/gadget.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -746,8 +746,6 @@ static int __dwc3_gadget_ep_disable(stru
+
+ trace_dwc3_gadget_ep_disable(dep);
+
+- dwc3_remove_requests(dwc, dep);
+-
+ /* make sure HW endpoint isn't stalled */
+ if (dep->flags & DWC3_EP_STALL)
+ __dwc3_gadget_ep_set_halt(dep, 0, false);
+@@ -766,6 +764,8 @@ static int __dwc3_gadget_ep_disable(stru
+ dep->endpoint.desc = NULL;
+ }
+
++ dwc3_remove_requests(dwc, dep);
++
+ return 0;
+ }
+
+@@ -1511,7 +1511,7 @@ static int __dwc3_gadget_ep_queue(struct
+ {
+ struct dwc3 *dwc = dep->dwc;
+
+- if (!dep->endpoint.desc || !dwc->pullups_connected) {
++ if (!dep->endpoint.desc || !dwc->pullups_connected || !dwc->connected) {
+ dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
+ dep->name);
+ return -ESHUTDOWN;
+@@ -2043,6 +2043,7 @@ static int dwc3_gadget_pullup(struct usb
+ if (!is_on) {
+ u32 count;
+
++ dwc->connected = false;
+ /*
+ * In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a
+ * Section 4.1.8 Table 4-7, it states that for a device-initiated
+@@ -2067,7 +2068,6 @@ static int dwc3_gadget_pullup(struct usb
+ dwc->ev_buf->lpos = (dwc->ev_buf->lpos + count) %
+ dwc->ev_buf->length;
+ }
+- dwc->connected = false;
+ } else {
+ __dwc3_gadget_start(dwc);
+ }
+@@ -3057,8 +3057,6 @@ static void dwc3_gadget_reset_interrupt(
+ {
+ u32 reg;
+
+- dwc->connected = true;
+-
+ /*
+ * Ideally, dwc3_reset_gadget() would trigger the function
+ * drivers to stop any active transfers through ep disable.
+@@ -3107,6 +3105,7 @@ static void dwc3_gadget_reset_interrupt(
+ * transfers."
+ */
+ dwc3_stop_active_transfers(dwc);
++ dwc->connected = true;
+
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+ reg &= ~DWC3_DCTL_TSTCTRL_MASK;
--- /dev/null
+From foo@baz Fri Aug 13 10:48:08 AM CEST 2021
+From: Sam Protsenko <semen.protsenko@linaro.org>
+Date: Thu, 12 Aug 2021 20:16:48 +0300
+Subject: usb: dwc3: gadget: Restart DWC3 gadget when enabling pullup
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: stable@vger.kernel.org, Wesley Cheng <wcheng@codeaurora.org>
+Message-ID: <20210812171652.23803-4-semen.protsenko@linaro.org>
+
+From: Wesley Cheng <wcheng@codeaurora.org>
+
+[ Upstream commit a1383b3537a7bea1c213baa7878ccc4ecf4413b5 ]
+
+usb_gadget_deactivate/usb_gadget_activate does not execute the UDC start
+operation, which may leave EP0 disabled and event IRQs disabled when
+re-activating the function. Move the enabling/disabling of USB EP0 and
+device event IRQs to be performed in the pullup routine.
+
+Fixes: ae7e86108b12 ("usb: dwc3: Stop active transfers before halting the controller")
+Tested-by: Michael Tretter <m.tretter@pengutronix.de>
+Cc: stable <stable@vger.kernel.org>
+Reported-by: Michael Tretter <m.tretter@pengutronix.de>
+Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
+Link: https://lore.kernel.org/r/1609282837-21666-1-git-send-email-wcheng@codeaurora.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/gadget.c | 14 +++-----------
+ 1 file changed, 3 insertions(+), 11 deletions(-)
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -1993,6 +1993,7 @@ static int dwc3_gadget_run_stop(struct d
+
+ static void dwc3_gadget_disable_irq(struct dwc3 *dwc);
+ static void __dwc3_gadget_stop(struct dwc3 *dwc);
++static int __dwc3_gadget_start(struct dwc3 *dwc);
+
+ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
+ {
+@@ -2067,6 +2068,8 @@ static int dwc3_gadget_pullup(struct usb
+ dwc->ev_buf->length;
+ }
+ dwc->connected = false;
++ } else {
++ __dwc3_gadget_start(dwc);
+ }
+
+ ret = dwc3_gadget_run_stop(dwc, is_on, false);
+@@ -2244,10 +2247,6 @@ static int dwc3_gadget_start(struct usb_
+ }
+
+ dwc->gadget_driver = driver;
+-
+- if (pm_runtime_active(dwc->dev))
+- __dwc3_gadget_start(dwc);
+-
+ spin_unlock_irqrestore(&dwc->lock, flags);
+
+ return 0;
+@@ -2273,13 +2272,6 @@ static int dwc3_gadget_stop(struct usb_g
+ unsigned long flags;
+
+ spin_lock_irqsave(&dwc->lock, flags);
+-
+- if (pm_runtime_suspended(dwc->dev))
+- goto out;
+-
+- __dwc3_gadget_stop(dwc);
+-
+-out:
+ dwc->gadget_driver = NULL;
+ spin_unlock_irqrestore(&dwc->lock, flags);
+
+++ /dev/null
-From 3b6405938fd74df7b35ae997af0f481e0ce80d52 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 29 Jul 2021 00:33:14 -0700
-Subject: usb: dwc3: gadget: Use list_replace_init() before traversing lists
-
-From: Wesley Cheng <wcheng@codeaurora.org>
-
-[ Upstream commit d25d85061bd856d6be221626605319154f9b5043 ]
-
-The list_for_each_entry_safe() macro saves the current item (n) and
-the item after (n+1), so that n can be safely removed without
-corrupting the list. However, when traversing the list and removing
-items using gadget giveback, the DWC3 lock is briefly released,
-allowing other routines to execute. There is a situation where, while
-items are being removed from the cancelled_list using
-dwc3_gadget_ep_cleanup_cancelled_requests(), the pullup disable
-routine is running in parallel (due to UDC unbind). As the cleanup
-routine removes n, and the pullup disable removes n+1, once the
-cleanup retakes the DWC3 lock, it references a request who was already
-removed/handled. With list debug enabled, this leads to a panic.
-Ensure all instances of the macro are replaced where gadget giveback
-is used.
-
-Example call stack:
-
-Thread#1:
-__dwc3_gadget_ep_set_halt() - CLEAR HALT
- -> dwc3_gadget_ep_cleanup_cancelled_requests()
- ->list_for_each_entry_safe()
- ->dwc3_gadget_giveback(n)
- ->dwc3_gadget_del_and_unmap_request()- n deleted[cancelled_list]
- ->spin_unlock
- ->Thread#2 executes
- ...
- ->dwc3_gadget_giveback(n+1)
- ->Already removed!
-
-Thread#2:
-dwc3_gadget_pullup()
- ->waiting for dwc3 spin_lock
- ...
- ->Thread#1 released lock
- ->dwc3_stop_active_transfers()
- ->dwc3_remove_requests()
- ->fetches n+1 item from cancelled_list (n removed by Thread#1)
- ->dwc3_gadget_giveback()
- ->dwc3_gadget_del_and_unmap_request()- n+1
-deleted[cancelled_list]
- ->spin_unlock
-
-Fix this condition by utilizing list_replace_init(), and traversing
-through a local copy of the current elements in the endpoint lists.
-This will also set the parent list as empty, so if another thread is
-also looping through the list, it will be empty on the next iteration.
-
-Fixes: d4f1afe5e896 ("usb: dwc3: gadget: move requests to cancelled_list")
-Cc: stable <stable@vger.kernel.org>
-Acked-by: Felipe Balbi <balbi@kernel.org>
-Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
-Link: https://lore.kernel.org/r/1627543994-20327-1-git-send-email-wcheng@codeaurora.org
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/usb/dwc3/gadget.c | 18 ++++++++++++++++--
- 1 file changed, 16 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
-index 9cf66636b19d..dd0aff33c7ca 100644
---- a/drivers/usb/dwc3/gadget.c
-+++ b/drivers/usb/dwc3/gadget.c
-@@ -1623,11 +1623,18 @@ static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep)
- {
- struct dwc3_request *req;
- struct dwc3_request *tmp;
-+ struct list_head local;
-
-- list_for_each_entry_safe(req, tmp, &dep->cancelled_list, list) {
-+restart:
-+ list_replace_init(&dep->cancelled_list, &local);
-+
-+ list_for_each_entry_safe(req, tmp, &local, list) {
- dwc3_gadget_ep_skip_trbs(dep, req);
- dwc3_gadget_giveback(dep, req, -ECONNRESET);
- }
-+
-+ if (!list_empty(&dep->cancelled_list))
-+ goto restart;
- }
-
- static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
-@@ -2684,8 +2691,12 @@ static void dwc3_gadget_ep_cleanup_completed_requests(struct dwc3_ep *dep,
- {
- struct dwc3_request *req;
- struct dwc3_request *tmp;
-+ struct list_head local;
-
-- list_for_each_entry_safe(req, tmp, &dep->started_list, list) {
-+restart:
-+ list_replace_init(&dep->started_list, &local);
-+
-+ list_for_each_entry_safe(req, tmp, &local, list) {
- int ret;
-
- ret = dwc3_gadget_ep_cleanup_completed_request(dep, event,
-@@ -2693,6 +2704,9 @@ static void dwc3_gadget_ep_cleanup_completed_requests(struct dwc3_ep *dep,
- if (ret)
- break;
- }
-+
-+ if (!list_empty(&dep->started_list))
-+ goto restart;
- }
-
- static bool dwc3_gadget_ep_should_continue(struct dwc3_ep *dep)
---
-2.30.2
-
--- /dev/null
+From foo@baz Fri Aug 13 10:48:40 AM CEST 2021
+From: Sam Protsenko <semen.protsenko@linaro.org>
+Date: Thu, 12 Aug 2021 20:16:46 +0300
+Subject: usb: dwc3: Stop active transfers before halting the controller
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: stable@vger.kernel.org, Wesley Cheng <wcheng@codeaurora.org>
+Message-ID: <20210812171652.23803-2-semen.protsenko@linaro.org>
+
+From: Wesley Cheng <wcheng@codeaurora.org>
+
+[ Upstream commit ae7e86108b12351028fa7e8796a59f9b2d9e1774 ]
+
+In the DWC3 databook, for a device initiated disconnect or bus reset, the
+driver is required to send dependxfer commands for any pending transfers.
+In addition, before the controller can move to the halted state, the SW
+needs to acknowledge any pending events. If the controller is not halted
+properly, there is a chance the controller will continue accessing stale or
+freed TRBs and buffers.
+
+Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
+Reviewed-by: Thinh Nguyen <thinhn@synopsys.com>
+Signed-off-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/ep0.c | 2 -
+ drivers/usb/dwc3/gadget.c | 66 +++++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 66 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/dwc3/ep0.c
++++ b/drivers/usb/dwc3/ep0.c
+@@ -197,7 +197,7 @@ int dwc3_gadget_ep0_queue(struct usb_ep
+ int ret;
+
+ spin_lock_irqsave(&dwc->lock, flags);
+- if (!dep->endpoint.desc) {
++ if (!dep->endpoint.desc || !dwc->pullups_connected) {
+ dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
+ dep->name);
+ ret = -ESHUTDOWN;
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -1511,7 +1511,7 @@ static int __dwc3_gadget_ep_queue(struct
+ {
+ struct dwc3 *dwc = dep->dwc;
+
+- if (!dep->endpoint.desc) {
++ if (!dep->endpoint.desc || !dwc->pullups_connected) {
+ dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
+ dep->name);
+ return -ESHUTDOWN;
+@@ -1931,6 +1931,21 @@ static int dwc3_gadget_set_selfpowered(s
+ return 0;
+ }
+
++static void dwc3_stop_active_transfers(struct dwc3 *dwc)
++{
++ u32 epnum;
++
++ for (epnum = 2; epnum < dwc->num_eps; epnum++) {
++ struct dwc3_ep *dep;
++
++ dep = dwc->eps[epnum];
++ if (!dep)
++ continue;
++
++ dwc3_remove_requests(dwc, dep);
++ }
++}
++
+ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
+ {
+ u32 reg;
+@@ -1976,6 +1991,9 @@ static int dwc3_gadget_run_stop(struct d
+ return 0;
+ }
+
++static void dwc3_gadget_disable_irq(struct dwc3 *dwc);
++static void __dwc3_gadget_stop(struct dwc3 *dwc);
++
+ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
+ {
+ struct dwc3 *dwc = gadget_to_dwc(g);
+@@ -1999,7 +2017,46 @@ static int dwc3_gadget_pullup(struct usb
+ }
+ }
+
++ /*
++ * Synchronize any pending event handling before executing the controller
++ * halt routine.
++ */
++ if (!is_on) {
++ dwc3_gadget_disable_irq(dwc);
++ synchronize_irq(dwc->irq_gadget);
++ }
++
+ spin_lock_irqsave(&dwc->lock, flags);
++
++ if (!is_on) {
++ u32 count;
++
++ /*
++ * In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a
++ * Section 4.1.8 Table 4-7, it states that for a device-initiated
++ * disconnect, the SW needs to ensure that it sends "a DEPENDXFER
++ * command for any active transfers" before clearing the RunStop
++ * bit.
++ */
++ dwc3_stop_active_transfers(dwc);
++ __dwc3_gadget_stop(dwc);
++
++ /*
++ * In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a
++ * Section 1.3.4, it mentions that for the DEVCTRLHLT bit, the
++ * "software needs to acknowledge the events that are generated
++ * (by writing to GEVNTCOUNTn) while it is waiting for this bit
++ * to be set to '1'."
++ */
++ count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0));
++ count &= DWC3_GEVNTCOUNT_MASK;
++ if (count > 0) {
++ dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count);
++ dwc->ev_buf->lpos = (dwc->ev_buf->lpos + count) %
++ dwc->ev_buf->length;
++ }
++ }
++
+ ret = dwc3_gadget_run_stop(dwc, is_on, false);
+ spin_unlock_irqrestore(&dwc->lock, flags);
+
+@@ -3038,6 +3095,13 @@ static void dwc3_gadget_reset_interrupt(
+ }
+
+ dwc3_reset_gadget(dwc);
++ /*
++ * In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a
++ * Section 4.1.2 Table 4-2, it states that during a USB reset, the SW
++ * needs to ensure that it sends "a DEPENDXFER command for any active
++ * transfers."
++ */
++ dwc3_stop_active_transfers(dwc);
+
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+ reg &= ~DWC3_DCTL_TSTCTRL_MASK;
--- /dev/null
+From 26b75952ca0b8b4b3050adb9582c8e2f44d49687 Mon Sep 17 00:00:00 2001
+From: Longfang Liu <liulongfang@huawei.com>
+Date: Fri, 9 Apr 2021 16:48:01 +0800
+Subject: USB:ehci:fix Kunpeng920 ehci hardware problem
+
+From: Longfang Liu <liulongfang@huawei.com>
+
+commit 26b75952ca0b8b4b3050adb9582c8e2f44d49687 upstream.
+
+Kunpeng920's EHCI controller does not have SBRN register.
+Reading the SBRN register when the controller driver is
+initialized will get 0.
+
+When rebooting the EHCI driver, ehci_shutdown() will be called.
+if the sbrn flag is 0, ehci_shutdown() will return directly.
+The sbrn flag being 0 will cause the EHCI interrupt signal to
+not be turned off after reboot. this interrupt that is not closed
+will cause an exception to the device sharing the interrupt.
+
+Therefore, the EHCI controller of Kunpeng920 needs to skip
+the read operation of the SBRN register.
+
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Longfang Liu <liulongfang@huawei.com>
+Link: https://lore.kernel.org/r/1617958081-17999-1-git-send-email-liulongfang@huawei.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/ehci-pci.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/usb/host/ehci-pci.c
++++ b/drivers/usb/host/ehci-pci.c
+@@ -298,6 +298,9 @@ static int ehci_pci_setup(struct usb_hcd
+ if (pdev->vendor == PCI_VENDOR_ID_STMICRO
+ && pdev->device == PCI_DEVICE_ID_STMICRO_USB_HOST)
+ ; /* ConneXT has no sbrn register */
++ else if (pdev->vendor == PCI_VENDOR_ID_HUAWEI
++ && pdev->device == 0xa239)
++ ; /* HUAWEI Kunpeng920 USB EHCI has no sbrn register */
+ else
+ pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
+