From: Greg Kroah-Hartman Date: Fri, 13 Aug 2021 09:03:58 +0000 (+0200) Subject: 5.4-stable patches X-Git-Tag: v4.4.281~13 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b6caa8d751d8ad21adadc215d768ed3bc2e56b10;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: alsa-hda-add-quirk-for-asus-flow-x13.patch kvm-x86-mmu-use-the-correct-inherited-permissions-to-get-shadow-page.patch ovl-prevent-private-clone-if-bind-mount-is-not-allowed.patch ppp-fix-generating-ppp-unit-id-when-ifname-is-not-specified.patch tracing-reject-string-operand-in-the-histogram-expression.patch usb-dwc3-gadget-allow-runtime-suspend-if-udc-unbinded.patch usb-dwc3-gadget-avoid-runtime-resume-if-disabling-pullup.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-prevent-ep-queuing-while-stopping-transfers.patch usb-dwc3-gadget-restart-dwc3-gadget-when-enabling-pullup.patch usb-dwc3-stop-active-transfers-before-halting-the-controller.patch usb-ehci-fix-kunpeng920-ehci-hardware-problem.patch --- diff --git a/queue-5.4/alsa-hda-add-quirk-for-asus-flow-x13.patch b/queue-5.4/alsa-hda-add-quirk-for-asus-flow-x13.patch new file mode 100644 index 00000000000..9bbae3906eb --- /dev/null +++ b/queue-5.4/alsa-hda-add-quirk-for-asus-flow-x13.patch @@ -0,0 +1,31 @@ +From 739d0959fbed23838a96c48fbce01dd2f6fb2c5f Mon Sep 17 00:00:00 2001 +From: Luke D Jones +Date: Sat, 7 Aug 2021 14:58:05 +1200 +Subject: ALSA: hda: Add quirk for ASUS Flow x13 + +From: Luke D Jones + +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 +Cc: +Link: https://lore.kernel.org/r/20210807025805.27321-1-luke@ljones.dev +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + 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), diff --git a/queue-5.4/kvm-x86-mmu-use-the-correct-inherited-permissions-to-get-shadow-page.patch b/queue-5.4/kvm-x86-mmu-use-the-correct-inherited-permissions-to-get-shadow-page.patch new file mode 100644 index 00000000000..57d26acc8b8 --- /dev/null +++ b/queue-5.4/kvm-x86-mmu-use-the-correct-inherited-permissions-to-get-shadow-page.patch @@ -0,0 +1,153 @@ +From b1bd5cba3306691c771d558e94baa73e8b0b96b7 Mon Sep 17 00:00:00 2001 +From: Lai Jiangshan +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 + +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 +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 +[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 +Signed-off-by: Greg Kroah-Hartman +--- + 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); + } diff --git a/queue-5.4/ovl-prevent-private-clone-if-bind-mount-is-not-allowed.patch b/queue-5.4/ovl-prevent-private-clone-if-bind-mount-is-not-allowed.patch new file mode 100644 index 00000000000..751a9f156b4 --- /dev/null +++ b/queue-5.4/ovl-prevent-private-clone-if-bind-mount-is-not-allowed.patch @@ -0,0 +1,97 @@ +From 427215d85e8d1476da1a86b8d67aceb485eb3631 Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Mon, 9 Aug 2021 10:19:47 +0200 +Subject: ovl: prevent private clone if bind mount is not allowed + +From: Miklos Szeredi + +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 +Fixes: c771d683a62e ("vfs: introduce clone_private_mount()") +Cc: # v3.18 +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-5.4/ppp-fix-generating-ppp-unit-id-when-ifname-is-not-specified.patch b/queue-5.4/ppp-fix-generating-ppp-unit-id-when-ifname-is-not-specified.patch new file mode 100644 index 00000000000..39fccf2c3c9 --- /dev/null +++ b/queue-5.4/ppp-fix-generating-ppp-unit-id-when-ifname-is-not-specified.patch @@ -0,0 +1,109 @@ +From 3125f26c514826077f2a4490b75e9b1c7a644c42 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +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 + +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" where +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" +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". + +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": + + 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 +Cc: stable@vger.kernel.org +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 */ diff --git a/queue-5.4/series b/queue-5.4/series index 42173c2be13..139939da977 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -1,4 +1,16 @@ 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 diff --git a/queue-5.4/tracing-reject-string-operand-in-the-histogram-expression.patch b/queue-5.4/tracing-reject-string-operand-in-the-histogram-expression.patch new file mode 100644 index 00000000000..0342f712a47 --- /dev/null +++ b/queue-5.4/tracing-reject-string-operand-in-the-histogram-expression.patch @@ -0,0 +1,74 @@ +From a9d10ca4986571bffc19778742d508cc8dd13e02 Mon Sep 17 00:00:00 2001 +From: Masami Hiramatsu +Date: Wed, 28 Jul 2021 07:55:43 +0900 +Subject: tracing: Reject string operand in the histogram expression + +From: Masami Hiramatsu + +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 +Signed-off-by: Steven Rostedt (VMware) +Signed-off-by: Greg Kroah-Hartman +--- + 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) diff --git a/queue-5.4/usb-dwc3-gadget-allow-runtime-suspend-if-udc-unbinded.patch b/queue-5.4/usb-dwc3-gadget-allow-runtime-suspend-if-udc-unbinded.patch new file mode 100644 index 00000000000..0e0778a20a8 --- /dev/null +++ b/queue-5.4/usb-dwc3-gadget-allow-runtime-suspend-if-udc-unbinded.patch @@ -0,0 +1,60 @@ +From foo@baz Fri Aug 13 10:48:08 AM CEST 2021 +From: Sam Protsenko +Date: Thu, 12 Aug 2021 20:16:47 +0300 +Subject: usb: dwc3: gadget: Allow runtime suspend if UDC unbinded +To: Greg Kroah-Hartman +Cc: stable@vger.kernel.org, Wesley Cheng +Message-ID: <20210812171652.23803-3-semen.protsenko@linaro.org> + +From: Wesley Cheng + +[ 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 +Link: https://lore.kernel.org/r/1609283136-22140-2-git-send-email-wcheng@codeaurora.org +Signed-off-by: Greg Kroah-Hartman +--- + 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; + } diff --git a/queue-5.4/usb-dwc3-gadget-avoid-runtime-resume-if-disabling-pullup.patch b/queue-5.4/usb-dwc3-gadget-avoid-runtime-resume-if-disabling-pullup.patch new file mode 100644 index 00000000000..428044eb2e6 --- /dev/null +++ b/queue-5.4/usb-dwc3-gadget-avoid-runtime-resume-if-disabling-pullup.patch @@ -0,0 +1,69 @@ +From foo@baz Fri Aug 13 10:48:08 AM CEST 2021 +From: Sam Protsenko +Date: Thu, 12 Aug 2021 20:16:52 +0300 +Subject: usb: dwc3: gadget: Avoid runtime resume if disabling pullup +To: Greg Kroah-Hartman +Cc: stable@vger.kernel.org, Wesley Cheng +Message-ID: <20210812171652.23803-8-semen.protsenko@linaro.org> + +From: Wesley Cheng + +[ 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 +Acked-by: Felipe Balbi +Signed-off-by: Wesley Cheng +Link: https://lore.kernel.org/r/1628058245-30692-1-git-send-email-wcheng@codeaurora.org +Signed-off-by: Greg Kroah-Hartman +--- + 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. diff --git a/queue-5.4/usb-dwc3-gadget-clear-dep-flags-after-stop-transfers-in-ep-disable.patch b/queue-5.4/usb-dwc3-gadget-clear-dep-flags-after-stop-transfers-in-ep-disable.patch new file mode 100644 index 00000000000..b5eb053f733 --- /dev/null +++ b/queue-5.4/usb-dwc3-gadget-clear-dep-flags-after-stop-transfers-in-ep-disable.patch @@ -0,0 +1,51 @@ +From foo@baz Fri Aug 13 10:48:08 AM CEST 2021 +From: Sam Protsenko +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 +Cc: stable@vger.kernel.org, Wesley Cheng +Message-ID: <20210812171652.23803-6-semen.protsenko@linaro.org> + +From: Wesley Cheng + +[ 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 +Reported-and-tested-by: Andy Shevchenko +Tested-by: Marek Szyprowski +Signed-off-by: Wesley Cheng +Link: https://lore.kernel.org/r/1616610664-16495-1-git-send-email-wcheng@codeaurora.org +Signed-off-by: Greg Kroah-Hartman +--- + 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; + } + diff --git a/queue-5.4/usb-dwc3-gadget-disable-gadget-irq-during-pullup-disable.patch b/queue-5.4/usb-dwc3-gadget-disable-gadget-irq-during-pullup-disable.patch new file mode 100644 index 00000000000..d8e80b5f8a0 --- /dev/null +++ b/queue-5.4/usb-dwc3-gadget-disable-gadget-irq-during-pullup-disable.patch @@ -0,0 +1,60 @@ +From foo@baz Fri Aug 13 10:48:08 AM CEST 2021 +From: Sam Protsenko +Date: Thu, 12 Aug 2021 20:16:51 +0300 +Subject: usb: dwc3: gadget: Disable gadget IRQ during pullup disable +To: Greg Kroah-Hartman +Cc: stable@vger.kernel.org, Wesley Cheng +Message-ID: <20210812171652.23803-7-semen.protsenko@linaro.org> + +From: Wesley Cheng + +[ 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 +Link: https://lore.kernel.org/r/1621571037-1424-1-git-send-email-wcheng@codeaurora.org +Signed-off-by: Greg Kroah-Hartman +--- + 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; diff --git a/queue-5.4/usb-dwc3-gadget-prevent-ep-queuing-while-stopping-transfers.patch b/queue-5.4/usb-dwc3-gadget-prevent-ep-queuing-while-stopping-transfers.patch new file mode 100644 index 00000000000..fb8c605d1db --- /dev/null +++ b/queue-5.4/usb-dwc3-gadget-prevent-ep-queuing-while-stopping-transfers.patch @@ -0,0 +1,95 @@ +From foo@baz Fri Aug 13 10:48:08 AM CEST 2021 +From: Sam Protsenko +Date: Thu, 12 Aug 2021 20:16:49 +0300 +Subject: usb: dwc3: gadget: Prevent EP queuing while stopping transfers +To: Greg Kroah-Hartman +Cc: stable@vger.kernel.org, Wesley Cheng +Message-ID: <20210812171652.23803-5-semen.protsenko@linaro.org> + +From: Wesley Cheng + +[ 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 +Link: https://lore.kernel.org/r/1615507142-23097-1-git-send-email-wcheng@codeaurora.org +Cc: stable +Signed-off-by: Greg Kroah-Hartman +--- + 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; diff --git a/queue-5.4/usb-dwc3-gadget-restart-dwc3-gadget-when-enabling-pullup.patch b/queue-5.4/usb-dwc3-gadget-restart-dwc3-gadget-when-enabling-pullup.patch new file mode 100644 index 00000000000..fd5c3f3452f --- /dev/null +++ b/queue-5.4/usb-dwc3-gadget-restart-dwc3-gadget-when-enabling-pullup.patch @@ -0,0 +1,72 @@ +From foo@baz Fri Aug 13 10:48:08 AM CEST 2021 +From: Sam Protsenko +Date: Thu, 12 Aug 2021 20:16:48 +0300 +Subject: usb: dwc3: gadget: Restart DWC3 gadget when enabling pullup +To: Greg Kroah-Hartman +Cc: stable@vger.kernel.org, Wesley Cheng +Message-ID: <20210812171652.23803-4-semen.protsenko@linaro.org> + +From: Wesley Cheng + +[ 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 +Cc: stable +Reported-by: Michael Tretter +Signed-off-by: Wesley Cheng +Link: https://lore.kernel.org/r/1609282837-21666-1-git-send-email-wcheng@codeaurora.org +Signed-off-by: Greg Kroah-Hartman +--- + 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); + diff --git a/queue-5.4/usb-dwc3-gadget-use-list_replace_init-before-travers.patch b/queue-5.4/usb-dwc3-gadget-use-list_replace_init-before-travers.patch deleted file mode 100644 index 1ad9182214a..00000000000 --- a/queue-5.4/usb-dwc3-gadget-use-list_replace_init-before-travers.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 3b6405938fd74df7b35ae997af0f481e0ce80d52 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 29 Jul 2021 00:33:14 -0700 -Subject: usb: dwc3: gadget: Use list_replace_init() before traversing lists - -From: Wesley Cheng - -[ 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 -Acked-by: Felipe Balbi -Signed-off-by: Wesley Cheng -Link: https://lore.kernel.org/r/1627543994-20327-1-git-send-email-wcheng@codeaurora.org -Signed-off-by: Greg Kroah-Hartman -Signed-off-by: Sasha Levin ---- - 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 - diff --git a/queue-5.4/usb-dwc3-stop-active-transfers-before-halting-the-controller.patch b/queue-5.4/usb-dwc3-stop-active-transfers-before-halting-the-controller.patch new file mode 100644 index 00000000000..71ed8197b68 --- /dev/null +++ b/queue-5.4/usb-dwc3-stop-active-transfers-before-halting-the-controller.patch @@ -0,0 +1,143 @@ +From foo@baz Fri Aug 13 10:48:40 AM CEST 2021 +From: Sam Protsenko +Date: Thu, 12 Aug 2021 20:16:46 +0300 +Subject: usb: dwc3: Stop active transfers before halting the controller +To: Greg Kroah-Hartman +Cc: stable@vger.kernel.org, Wesley Cheng +Message-ID: <20210812171652.23803-2-semen.protsenko@linaro.org> + +From: Wesley Cheng + +[ 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 +Reviewed-by: Thinh Nguyen +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman +--- + 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; diff --git a/queue-5.4/usb-ehci-fix-kunpeng920-ehci-hardware-problem.patch b/queue-5.4/usb-ehci-fix-kunpeng920-ehci-hardware-problem.patch new file mode 100644 index 00000000000..2bb3273d838 --- /dev/null +++ b/queue-5.4/usb-ehci-fix-kunpeng920-ehci-hardware-problem.patch @@ -0,0 +1,42 @@ +From 26b75952ca0b8b4b3050adb9582c8e2f44d49687 Mon Sep 17 00:00:00 2001 +From: Longfang Liu +Date: Fri, 9 Apr 2021 16:48:01 +0800 +Subject: USB:ehci:fix Kunpeng920 ehci hardware problem + +From: Longfang Liu + +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 +Signed-off-by: Longfang Liu +Link: https://lore.kernel.org/r/1617958081-17999-1-git-send-email-liulongfang@huawei.com +Signed-off-by: Greg Kroah-Hartman +--- + 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); +