From 594c82329eef335ad90f5276ae0d2dff4d6d2668 Mon Sep 17 00:00:00 2001 From: WangYuli Date: Tue, 7 Jan 2025 21:38:54 +0800 Subject: [PATCH 01/16] usb: host: xhci-plat: Assign shared_hcd->rsrc_start When inserting a USB device, examining hcd->rsrc_start can be helpful in identifying which hcd is mounted, as the physical address represented here is typically unique. The following code snippet demonstrates this: struct usb_hcd *hcd = bus_to_hcd(udev->bus); unsigned long long usb_hcd_addr = (unsigned long long)hcd->rsrc_start; However, this approach has limitations now. For USB hosts with an MMIO interface, the effectiveness of this method is restricted to USB 2.0. Because commit 3429e91a661e ("usb: host: xhci: add platform driver support") assigned res->start to hcd->rsrc_start. But shared_hcd->rsrc_start remains unassigned, which is also necessary in certain scenarios. Fixes: 3429e91a661e ("usb: host: xhci: add platform driver support") Co-developed-by: Xu Rao Signed-off-by: Xu Rao Signed-off-by: WangYuli Link: https://lore.kernel.org/r/186B9F56972457B4+20250107133854.172309-1-wangyuli@uniontech.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-plat.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index e6c9006bd568..457e839b9b53 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -329,6 +329,8 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s usb3_hcd->can_do_streams = 1; if (xhci->shared_hcd) { + xhci->shared_hcd->rsrc_start = hcd->rsrc_start; + xhci->shared_hcd->rsrc_len = hcd->rsrc_len; ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); if (ret) goto put_usb3_hcd; -- 2.51.0 From 87ecfdbc699cc95fac73291b52650283ddcf929d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sun, 12 Jan 2025 10:34:44 +0100 Subject: [PATCH 02/16] KVM: e500: always restore irqs If find_linux_pte fails, IRQs will not be restored. This is unlikely to happen in practice since it would have been reported as hanging hosts, but it should of course be fixed anyway. Cc: stable@vger.kernel.org Reported-by: Sean Christopherson Signed-off-by: Paolo Bonzini --- arch/powerpc/kvm/e500_mmu_host.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c index e5a145b578a4..6824e8139801 100644 --- a/arch/powerpc/kvm/e500_mmu_host.c +++ b/arch/powerpc/kvm/e500_mmu_host.c @@ -479,7 +479,6 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, if (pte_present(pte)) { wimg = (pte_val(pte) >> PTE_WIMGE_SHIFT) & MAS2_WIMGE_MASK; - local_irq_restore(flags); } else { local_irq_restore(flags); pr_err_ratelimited("%s: pte not present: gfn %lx,pfn %lx\n", @@ -488,8 +487,9 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, goto out; } } - writable = kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg); + local_irq_restore(flags); + writable = kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg); kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize, ref, gvaddr, stlbe); -- 2.51.0 From e97fbb43fb1b2e909dfd726204af3cdcb971517e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 8 Jan 2025 16:19:28 +0100 Subject: [PATCH 03/16] KVM: e500: use shadow TLB entry as witness for writability kvmppc_e500_ref_setup is returning whether the guest TLB entry is writable, which is than passed to kvm_release_faultin_page. This makes little sense for two reasons: first, because the function sets up the private data for the page and the return value feels like it has been bolted on the side; second, because what really matters is whether the _shadow_ TLB entry is writable. If it is not writable, the page can be released as non-dirty. Shift from using tlbe_is_writable(gtlbe) to doing the same check on the shadow TLB entry. Signed-off-by: Paolo Bonzini --- arch/powerpc/kvm/e500_mmu_host.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c index 6824e8139801..c266c02f120f 100644 --- a/arch/powerpc/kvm/e500_mmu_host.c +++ b/arch/powerpc/kvm/e500_mmu_host.c @@ -242,7 +242,7 @@ static inline int tlbe_is_writable(struct kvm_book3e_206_tlb_entry *tlbe) return tlbe->mas7_3 & (MAS3_SW|MAS3_UW); } -static inline bool kvmppc_e500_ref_setup(struct tlbe_ref *ref, +static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref, struct kvm_book3e_206_tlb_entry *gtlbe, kvm_pfn_t pfn, unsigned int wimg) { @@ -251,8 +251,6 @@ static inline bool kvmppc_e500_ref_setup(struct tlbe_ref *ref, /* Use guest supplied MAS2_G and MAS2_E */ ref->flags |= (gtlbe->mas2 & MAS2_ATTRIB_MASK) | wimg; - - return tlbe_is_writable(gtlbe); } static inline void kvmppc_e500_ref_release(struct tlbe_ref *ref) @@ -489,9 +487,10 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, } local_irq_restore(flags); - writable = kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg); + kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg); kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize, ref, gvaddr, stlbe); + writable = tlbe_is_writable(stlbe); /* Clear i-cache for new pages */ kvmppc_mmu_flush_icache(pfn); -- 2.51.0 From f2104bf22f0475a08a0feeee40d8e45ce38ed5a1 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 8 Jan 2025 16:21:38 +0100 Subject: [PATCH 04/16] KVM: e500: track host-writability of pages Add the possibility of marking a page so that the UW and SW bits are force-cleared. This is stored in the private info so that it persists across multiple calls to kvmppc_e500_setup_stlbe. Signed-off-by: Paolo Bonzini --- arch/powerpc/kvm/e500.h | 2 ++ arch/powerpc/kvm/e500_mmu_host.c | 15 +++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h index 6d0d329cbb35..f9acf866c709 100644 --- a/arch/powerpc/kvm/e500.h +++ b/arch/powerpc/kvm/e500.h @@ -34,6 +34,8 @@ enum vcpu_ftr { #define E500_TLB_BITMAP (1 << 30) /* TLB1 entry is mapped by host TLB0 */ #define E500_TLB_TLB0 (1 << 29) +/* entry is writable on the host */ +#define E500_TLB_WRITABLE (1 << 28) /* bits [6-5] MAS2_X1 and MAS2_X0 and [4-0] bits for WIMGE */ #define E500_TLB_MAS2_ATTR (0x7f) diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c index c266c02f120f..b1be39639d4a 100644 --- a/arch/powerpc/kvm/e500_mmu_host.c +++ b/arch/powerpc/kvm/e500_mmu_host.c @@ -45,11 +45,14 @@ static inline unsigned int tlb1_max_shadow_size(void) return host_tlb_params[1].entries - tlbcam_index - 1; } -static inline u32 e500_shadow_mas3_attrib(u32 mas3, int usermode) +static inline u32 e500_shadow_mas3_attrib(u32 mas3, bool writable, int usermode) { /* Mask off reserved bits. */ mas3 &= MAS3_ATTRIB_MASK; + if (!writable) + mas3 &= ~(MAS3_UW|MAS3_SW); + #ifndef CONFIG_KVM_BOOKE_HV if (!usermode) { /* Guest is in supervisor mode, @@ -244,10 +247,13 @@ static inline int tlbe_is_writable(struct kvm_book3e_206_tlb_entry *tlbe) static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref, struct kvm_book3e_206_tlb_entry *gtlbe, - kvm_pfn_t pfn, unsigned int wimg) + kvm_pfn_t pfn, unsigned int wimg, + bool writable) { ref->pfn = pfn; ref->flags = E500_TLB_VALID; + if (writable) + ref->flags |= E500_TLB_WRITABLE; /* Use guest supplied MAS2_G and MAS2_E */ ref->flags |= (gtlbe->mas2 & MAS2_ATTRIB_MASK) | wimg; @@ -303,6 +309,7 @@ static void kvmppc_e500_setup_stlbe( { kvm_pfn_t pfn = ref->pfn; u32 pr = vcpu->arch.shared->msr & MSR_PR; + bool writable = !!(ref->flags & E500_TLB_WRITABLE); BUG_ON(!(ref->flags & E500_TLB_VALID)); @@ -310,7 +317,7 @@ static void kvmppc_e500_setup_stlbe( stlbe->mas1 = MAS1_TSIZE(tsize) | get_tlb_sts(gtlbe) | MAS1_VALID; stlbe->mas2 = (gvaddr & MAS2_EPN) | (ref->flags & E500_TLB_MAS2_ATTR); stlbe->mas7_3 = ((u64)pfn << PAGE_SHIFT) | - e500_shadow_mas3_attrib(gtlbe->mas7_3, pr); + e500_shadow_mas3_attrib(gtlbe->mas7_3, writable, pr); } static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, @@ -487,7 +494,7 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, } local_irq_restore(flags); - kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg); + kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg, true); kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize, ref, gvaddr, stlbe); writable = tlbe_is_writable(stlbe); -- 2.51.0 From 03b755b2aa48d242440cbfbd365e153b4b20fe54 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 8 Jan 2025 16:14:55 +0100 Subject: [PATCH 05/16] KVM: e500: map readonly host pages for read The new __kvm_faultin_pfn() function is upset by the fact that e500 KVM ignores host page permissions - __kvm_faultin requires a "writable" outgoing argument, but e500 KVM is nonchalantly passing NULL. If the host page permissions do not include writability, the shadow TLB entry is forcibly mapped read-only. Signed-off-by: Paolo Bonzini --- arch/powerpc/kvm/e500_mmu_host.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c index b1be39639d4a..b38679e5821b 100644 --- a/arch/powerpc/kvm/e500_mmu_host.c +++ b/arch/powerpc/kvm/e500_mmu_host.c @@ -374,6 +374,7 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, unsigned long slot_start, slot_end; pfnmap = 1; + writable = vma->vm_flags & VM_WRITE; start = vma->vm_pgoff; end = start + @@ -449,7 +450,7 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, if (likely(!pfnmap)) { tsize_pages = 1UL << (tsize + 10 - PAGE_SHIFT); - pfn = __kvm_faultin_pfn(slot, gfn, FOLL_WRITE, NULL, &page); + pfn = __kvm_faultin_pfn(slot, gfn, FOLL_WRITE, &writable, &page); if (is_error_noslot_pfn(pfn)) { if (printk_ratelimit()) pr_err("%s: real page not found for gfn %lx\n", @@ -494,7 +495,7 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, } local_irq_restore(flags); - kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg, true); + kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg, writable); kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize, ref, gvaddr, stlbe); writable = tlbe_is_writable(stlbe); -- 2.51.0 From 55f4db79c4d94d4bb757f7a31a7f14de22fe517d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 8 Jan 2025 16:49:50 +0100 Subject: [PATCH 06/16] KVM: e500: perform hugepage check after looking up the PFN e500 KVM tries to bypass __kvm_faultin_pfn() in order to map VM_PFNMAP VMAs as huge pages. This is a Bad Idea because VM_PFNMAP VMAs could become noncontiguous as a result of callsto remap_pfn_range(). Instead, use the already existing host PTE lookup to retrieve a valid host-side mapping level after __kvm_faultin_pfn() has returned. Then find the largest size that will satisfy the guest's request while staying within a single host PTE. Signed-off-by: Paolo Bonzini --- arch/powerpc/kvm/e500_mmu_host.c | 178 ++++++++++++------------------- 1 file changed, 69 insertions(+), 109 deletions(-) diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c index b38679e5821b..06caf8bbbe2b 100644 --- a/arch/powerpc/kvm/e500_mmu_host.c +++ b/arch/powerpc/kvm/e500_mmu_host.c @@ -326,15 +326,14 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, struct tlbe_ref *ref) { struct kvm_memory_slot *slot; - unsigned long pfn = 0; /* silence GCC warning */ + unsigned int psize; + unsigned long pfn; struct page *page = NULL; unsigned long hva; - int pfnmap = 0; int tsize = BOOK3E_PAGESZ_4K; int ret = 0; unsigned long mmu_seq; struct kvm *kvm = vcpu_e500->vcpu.kvm; - unsigned long tsize_pages = 0; pte_t *ptep; unsigned int wimg = 0; pgd_t *pgdir; @@ -356,111 +355,12 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, slot = gfn_to_memslot(vcpu_e500->vcpu.kvm, gfn); hva = gfn_to_hva_memslot(slot, gfn); - if (tlbsel == 1) { - struct vm_area_struct *vma; - mmap_read_lock(kvm->mm); - - vma = find_vma(kvm->mm, hva); - if (vma && hva >= vma->vm_start && - (vma->vm_flags & VM_PFNMAP)) { - /* - * This VMA is a physically contiguous region (e.g. - * /dev/mem) that bypasses normal Linux page - * management. Find the overlap between the - * vma and the memslot. - */ - - unsigned long start, end; - unsigned long slot_start, slot_end; - - pfnmap = 1; - writable = vma->vm_flags & VM_WRITE; - - start = vma->vm_pgoff; - end = start + - vma_pages(vma); - - pfn = start + ((hva - vma->vm_start) >> PAGE_SHIFT); - - slot_start = pfn - (gfn - slot->base_gfn); - slot_end = slot_start + slot->npages; - - if (start < slot_start) - start = slot_start; - if (end > slot_end) - end = slot_end; - - tsize = (gtlbe->mas1 & MAS1_TSIZE_MASK) >> - MAS1_TSIZE_SHIFT; - - /* - * e500 doesn't implement the lowest tsize bit, - * or 1K pages. - */ - tsize = max(BOOK3E_PAGESZ_4K, tsize & ~1); - - /* - * Now find the largest tsize (up to what the guest - * requested) that will cover gfn, stay within the - * range, and for which gfn and pfn are mutually - * aligned. - */ - - for (; tsize > BOOK3E_PAGESZ_4K; tsize -= 2) { - unsigned long gfn_start, gfn_end; - tsize_pages = 1UL << (tsize - 2); - - gfn_start = gfn & ~(tsize_pages - 1); - gfn_end = gfn_start + tsize_pages; - - if (gfn_start + pfn - gfn < start) - continue; - if (gfn_end + pfn - gfn > end) - continue; - if ((gfn & (tsize_pages - 1)) != - (pfn & (tsize_pages - 1))) - continue; - - gvaddr &= ~((tsize_pages << PAGE_SHIFT) - 1); - pfn &= ~(tsize_pages - 1); - break; - } - } else if (vma && hva >= vma->vm_start && - is_vm_hugetlb_page(vma)) { - unsigned long psize = vma_kernel_pagesize(vma); - - tsize = (gtlbe->mas1 & MAS1_TSIZE_MASK) >> - MAS1_TSIZE_SHIFT; - - /* - * Take the largest page size that satisfies both host - * and guest mapping - */ - tsize = min(__ilog2(psize) - 10, tsize); - - /* - * e500 doesn't implement the lowest tsize bit, - * or 1K pages. - */ - tsize = max(BOOK3E_PAGESZ_4K, tsize & ~1); - } - - mmap_read_unlock(kvm->mm); - } - - if (likely(!pfnmap)) { - tsize_pages = 1UL << (tsize + 10 - PAGE_SHIFT); - pfn = __kvm_faultin_pfn(slot, gfn, FOLL_WRITE, &writable, &page); - if (is_error_noslot_pfn(pfn)) { - if (printk_ratelimit()) - pr_err("%s: real page not found for gfn %lx\n", - __func__, (long)gfn); - return -EINVAL; - } - - /* Align guest and physical address to page map boundaries */ - pfn &= ~(tsize_pages - 1); - gvaddr &= ~((tsize_pages << PAGE_SHIFT) - 1); + pfn = __kvm_faultin_pfn(slot, gfn, FOLL_WRITE, &writable, &page); + if (is_error_noslot_pfn(pfn)) { + if (printk_ratelimit()) + pr_err("%s: real page not found for gfn %lx\n", + __func__, (long)gfn); + return -EINVAL; } spin_lock(&kvm->mmu_lock); @@ -478,7 +378,7 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, * can't run hence pfn won't change. */ local_irq_save(flags); - ptep = find_linux_pte(pgdir, hva, NULL, NULL); + ptep = find_linux_pte(pgdir, hva, NULL, &psize); if (ptep) { pte_t pte = READ_ONCE(*ptep); @@ -495,6 +395,66 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, } local_irq_restore(flags); + if (psize && tlbsel == 1) { + unsigned long psize_pages, tsize_pages; + unsigned long start, end; + unsigned long slot_start, slot_end; + + psize_pages = 1UL << (psize - PAGE_SHIFT); + start = pfn & ~(psize_pages - 1); + end = start + psize_pages; + + slot_start = pfn - (gfn - slot->base_gfn); + slot_end = slot_start + slot->npages; + + if (start < slot_start) + start = slot_start; + if (end > slot_end) + end = slot_end; + + tsize = (gtlbe->mas1 & MAS1_TSIZE_MASK) >> + MAS1_TSIZE_SHIFT; + + /* + * Any page size that doesn't satisfy the host mapping + * will fail the start and end tests. + */ + tsize = min(psize - PAGE_SHIFT + BOOK3E_PAGESZ_4K, tsize); + + /* + * e500 doesn't implement the lowest tsize bit, + * or 1K pages. + */ + tsize = max(BOOK3E_PAGESZ_4K, tsize & ~1); + + /* + * Now find the largest tsize (up to what the guest + * requested) that will cover gfn, stay within the + * range, and for which gfn and pfn are mutually + * aligned. + */ + + for (; tsize > BOOK3E_PAGESZ_4K; tsize -= 2) { + unsigned long gfn_start, gfn_end; + tsize_pages = 1UL << (tsize - 2); + + gfn_start = gfn & ~(tsize_pages - 1); + gfn_end = gfn_start + tsize_pages; + + if (gfn_start + pfn - gfn < start) + continue; + if (gfn_end + pfn - gfn > end) + continue; + if ((gfn & (tsize_pages - 1)) != + (pfn & (tsize_pages - 1))) + continue; + + gvaddr &= ~((tsize_pages << PAGE_SHIFT) - 1); + pfn &= ~(tsize_pages - 1); + break; + } + } + kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg, writable); kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize, ref, gvaddr, stlbe); -- 2.51.0 From 5bc55a333a2f7316b58edc7573e8e893f7acb532 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 12 Jan 2025 14:37:56 -0800 Subject: [PATCH 07/16] Linux 6.13-rc7 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7904d5d88088..e20a62ad397f 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VERSION = 6 PATCHLEVEL = 13 SUBLEVEL = 0 -EXTRAVERSION = -rc6 +EXTRAVERSION = -rc7 NAME = Baby Opossum Posse # *DOCUMENTATION* -- 2.51.0 From 2eb3da037c2c20fa30bc502bc092479b2a1aaae2 Mon Sep 17 00:00:00 2001 From: Jos Wang Date: Sun, 5 Jan 2025 21:52:45 +0800 Subject: [PATCH 08/16] usb: typec: tcpm: set SRC_SEND_CAPABILITIES timeout to PD_T_SENDER_RESPONSE As PD2.0 spec ("8.3.3.2.3 PE_SRC_Send_Capabilities state"), after the Source receives the GoodCRC Message from the Sink in response to the Source_Capabilities message, it should start the SenderResponseTimer, after the timer times out, the state machine transitions to the HARD_RESET state. Fixes: f0690a25a140 ("staging: typec: USB Type-C Port Manager (tcpm)") Cc: stable@vger.kernel.org Signed-off-by: Jos Wang Reviewed-by: Badhri Jagan Sridharan Link: https://lore.kernel.org/r/20250105135245.7493-1-joswang1221@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/tcpm/tcpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 460dbde9fe22..57fae1118ac9 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -4821,7 +4821,7 @@ static void run_state_machine(struct tcpm_port *port) port->caps_count = 0; port->pd_capable = true; tcpm_set_state_cond(port, SRC_SEND_CAPABILITIES_TIMEOUT, - PD_T_SEND_SOURCE_CAP); + PD_T_SENDER_RESPONSE); } break; case SRC_SEND_CAPABILITIES_TIMEOUT: -- 2.51.0 From 26a6cc10f19a058c24cbe3be2a4a10048e66d9c9 Mon Sep 17 00:00:00 2001 From: Zijun Hu Date: Sun, 12 Jan 2025 18:33:52 +0800 Subject: [PATCH 09/16] usb: phy: Remove API devm_usb_put_phy() Static devm_usb_phy_match() is only called by API devm_usb_put_phy(), and the API has no caller now. Remove the API and the static function. Signed-off-by: Zijun Hu Link: https://lore.kernel.org/r/20250112-remove_api-v1-1-49cc8f792ac9@quicinc.com Signed-off-by: Greg Kroah-Hartman --- .../driver-api/driver-model/devres.rst | 1 - drivers/usb/phy/phy.c | 26 ------------------- include/linux/usb/phy.h | 5 ---- 3 files changed, 32 deletions(-) diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst index d594d0ea0e9d..d75728eb05f8 100644 --- a/Documentation/driver-api/driver-model/devres.rst +++ b/Documentation/driver-api/driver-model/devres.rst @@ -404,7 +404,6 @@ PHY devm_usb_get_phy() devm_usb_get_phy_by_node() devm_usb_get_phy_by_phandle() - devm_usb_put_phy() PINCTRL devm_pinctrl_get() diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c index 1ce134505cee..e1435bc59662 100644 --- a/drivers/usb/phy/phy.c +++ b/drivers/usb/phy/phy.c @@ -346,13 +346,6 @@ static void devm_usb_phy_release2(struct device *dev, void *_res) usb_put_phy(res->phy); } -static int devm_usb_phy_match(struct device *dev, void *res, void *match_data) -{ - struct usb_phy **phy = res; - - return *phy == match_data; -} - static void usb_charger_init(struct usb_phy *usb_phy) { usb_phy->chg_type = UNKNOWN_TYPE; @@ -614,25 +607,6 @@ struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev, } EXPORT_SYMBOL_GPL(devm_usb_get_phy_by_phandle); -/** - * devm_usb_put_phy - release the USB PHY - * @dev: device that wants to release this phy - * @phy: the phy returned by devm_usb_get_phy() - * - * destroys the devres associated with this phy and invokes usb_put_phy - * to release the phy. - * - * For use by USB host and peripheral drivers. - */ -void devm_usb_put_phy(struct device *dev, struct usb_phy *phy) -{ - int r; - - r = devres_release(dev, devm_usb_phy_release, devm_usb_phy_match, phy); - dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n"); -} -EXPORT_SYMBOL_GPL(devm_usb_put_phy); - /** * usb_put_phy - release the USB PHY * @x: the phy returned by usb_get_phy() diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h index e4de6bc1f69b..0fa9885a1038 100644 --- a/include/linux/usb/phy.h +++ b/include/linux/usb/phy.h @@ -223,7 +223,6 @@ extern struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev, extern struct usb_phy *devm_usb_get_phy_by_node(struct device *dev, struct device_node *node, struct notifier_block *nb); extern void usb_put_phy(struct usb_phy *); -extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x); extern void usb_phy_set_event(struct usb_phy *x, unsigned long event); extern void usb_phy_set_charger_current(struct usb_phy *usb_phy, unsigned int mA); @@ -259,10 +258,6 @@ static inline void usb_put_phy(struct usb_phy *x) { } -static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x) -{ -} - static inline void usb_phy_set_event(struct usb_phy *x, unsigned long event) { } -- 2.51.0 From bd693544854b025765514e8948469c618000993a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 14 Jan 2025 21:05:34 +0100 Subject: [PATCH 10/16] USB: Replace own str_plural with common one Use existing str_plural() helper from string_choices.h to reduce amount of duplicated code. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20250114-str-enable-disable-usb-v1-1-c8405df47c19@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/config.c | 19 +++++++------------ drivers/usb/core/generic.c | 12 ++++-------- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 25a00f974934..f7bf8d1de3ad 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include "usb.h" @@ -18,12 +19,6 @@ #define USB_MAXCONFIG 8 /* Arbitrary limit */ - -static inline const char *plural(int n) -{ - return (n == 1 ? "" : "s"); -} - static int find_next_descriptor(unsigned char *buffer, int size, int dt1, int dt2, int *num_skipped) { @@ -484,7 +479,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, retval = buffer - buffer0 + i; if (n > 0) dev_dbg(ddev, "skipped %d descriptor%s after %s\n", - n, plural(n), "endpoint"); + n, str_plural(n), "endpoint"); return retval; skip_to_next_endpoint_or_interface_descriptor: @@ -563,7 +558,7 @@ static int usb_parse_interface(struct device *ddev, int cfgno, alt->extralen = i; if (n > 0) dev_dbg(ddev, "skipped %d descriptor%s after %s\n", - n, plural(n), "interface"); + n, str_plural(n), "interface"); buffer += i; size -= i; @@ -605,7 +600,7 @@ static int usb_parse_interface(struct device *ddev, int cfgno, dev_notice(ddev, "config %d interface %d altsetting %d has %d " "endpoint descriptor%s, different from the interface " "descriptor's value: %d\n", - cfgno, inum, asnum, n, plural(n), num_ep_orig); + cfgno, inum, asnum, n, str_plural(n), num_ep_orig); return buffer - buffer0; skip_to_next_interface_descriptor: @@ -664,7 +659,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx, if (size2 < sizeof(struct usb_descriptor_header)) { dev_notice(ddev, "config %d descriptor has %d excess " "byte%s, ignoring\n", - cfgno, size2, plural(size2)); + cfgno, size2, str_plural(size2)); break; } @@ -754,7 +749,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx, if (n != nintf) dev_notice(ddev, "config %d has %d interface%s, different from " "the descriptor's value: %d\n", - cfgno, n, plural(n), nintf_orig); + cfgno, n, str_plural(n), nintf_orig); else if (n == 0) dev_notice(ddev, "config %d has no interfaces?\n", cfgno); config->desc.bNumInterfaces = nintf = n; @@ -798,7 +793,7 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx, config->extralen = i; if (n > 0) dev_dbg(ddev, "skipped %d descriptor%s after %s\n", - n, plural(n), "configuration"); + n, str_plural(n), "configuration"); buffer += i; size -= i; diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index b134bff5c3fe..9c6ae5e1198b 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c @@ -21,14 +21,10 @@ #include #include +#include #include #include "usb.h" -static inline const char *plural(int n) -{ - return (n == 1 ? "" : "s"); -} - static int is_rndis(struct usb_interface_descriptor *desc) { return desc->bInterfaceClass == USB_CLASS_COMM @@ -194,18 +190,18 @@ int usb_choose_configuration(struct usb_device *udev) if (insufficient_power > 0) dev_info(&udev->dev, "rejected %d configuration%s " "due to insufficient available bus power\n", - insufficient_power, plural(insufficient_power)); + insufficient_power, str_plural(insufficient_power)); if (best) { i = best->desc.bConfigurationValue; dev_dbg(&udev->dev, "configuration #%d chosen from %d choice%s\n", - i, num_configs, plural(num_configs)); + i, num_configs, str_plural(num_configs)); } else { i = -1; dev_warn(&udev->dev, "no configuration chosen from %d choice%s\n", - num_configs, plural(num_configs)); + num_configs, str_plural(num_configs)); } return i; } -- 2.51.0 From 789a1714292a0e6e87cd8fb7deedc1784bb959e3 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 14 Jan 2025 21:05:35 +0100 Subject: [PATCH 11/16] USB: host: Use str_enable_disable-like helpers Replace ternary (condition ? "enable" : "disable") syntax with helpers from string_choices.h because: 1. Simple function call with one argument is easier to read. Ternary operator has three arguments and with wrapping might lead to quite long code. 2. Is slightly shorter thus also easier to read. 3. It brings uniformity in the text - same string. 4. Allows deduping by the linker, which results in a smaller binary file. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20250114-str-enable-disable-usb-v1-2-c8405df47c19@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/oxu210hp-hcd.c | 3 ++- drivers/usb/host/sl811-hcd.c | 3 ++- drivers/usb/host/xhci-ring.c | 5 +++-- drivers/usb/host/xhci-tegra.c | 5 +++-- drivers/usb/host/xhci.c | 3 ++- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index a6c20facf945..fce800ba4c61 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -2756,7 +2757,7 @@ static void ehci_port_power(struct oxu_hcd *oxu, int is_on) if (!HCS_PPC(oxu->hcs_params)) return; - oxu_dbg(oxu, "...power%s ports...\n", is_on ? "up" : "down"); + oxu_dbg(oxu, "...power%s ports...\n", str_up_down(is_on)); for (port = HCS_N_PORTS(oxu->hcs_params); port > 0; ) { if (is_on) oxu_hub_control(oxu_to_hcd(oxu), SetPortFeature, diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index 036f5fd6d159..fa2e4badd288 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -98,7 +99,7 @@ static void port_power(struct sl811 *sl811, int is_on) if (sl811->board && sl811->board->port_power) { /* switch VBUS, at 500mA unless hub power budget gets set */ dev_dbg(hcd->self.controller, "power %s\n", - is_on ? "on" : "off"); + str_on_off(is_on)); sl811->board->port_power(hcd->self.controller, is_on); } diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 3d66ed240dc3..965bffce301e 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include "xhci.h" #include "xhci-trace.h" @@ -3441,8 +3442,8 @@ static void check_interval(struct urb *urb, struct xhci_ep_ctx *ep_ctx) if (xhci_interval != ep_interval) { dev_dbg_ratelimited(&urb->dev->dev, "Driver uses different interval (%d microframe%s) than xHCI (%d microframe%s)\n", - ep_interval, ep_interval == 1 ? "" : "s", - xhci_interval, xhci_interval == 1 ? "" : "s"); + ep_interval, str_plural(ep_interval), + xhci_interval, str_plural(xhci_interval)); urb->interval = xhci_interval; /* Convert back to frames for LS/FS devices */ if (urb->dev->speed == USB_SPEED_LOW || diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c index 06ae193ec874..a51ce71a6a77 100644 --- a/drivers/usb/host/xhci-tegra.c +++ b/drivers/usb/host/xhci-tegra.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -724,7 +725,7 @@ static void tegra_xusb_mbox_handle(struct tegra_xusb *tegra, if (err < 0) { dev_err(dev, "failed to %s LFPS detection on USB3#%u: %d\n", - enable ? "enable" : "disable", port, err); + str_enable_disable(enable), port, err); rsp.cmd = MBOX_CMD_NAK; } else { rsp.cmd = MBOX_CMD_ACK; @@ -1349,7 +1350,7 @@ static void tegra_xhci_id_work(struct work_struct *work) u32 status; int ret; - dev_dbg(tegra->dev, "host mode %s\n", tegra->host_mode ? "on" : "off"); + dev_dbg(tegra->dev, "host mode %s\n", str_on_off(tegra->host_mode)); mutex_lock(&tegra->lock); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 5ebde8cae4fc..45653114ccd7 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -4523,7 +4524,7 @@ static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, hlpm_addr = ports[port_num]->addr + PORTHLPMC; xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n", - enable ? "enable" : "disable", port_num + 1); + str_enable_disable(enable), port_num + 1); if (enable) { /* Host supports BESL timeout instead of HIRD */ -- 2.51.0 From 13b3af26a41538e5051baedba8678eba521a27d3 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 14 Jan 2025 21:05:36 +0100 Subject: [PATCH 12/16] USB: typec: Use str_enable_disable-like helpers Replace ternary (condition ? "enable" : "disable") syntax with helpers from string_choices.h because: 1. Simple function call with one argument is easier to read. Ternary operator has three arguments and with wrapping might lead to quite long code. 2. Is slightly shorter thus also easier to read. 3. It brings uniformity in the text - same string. 4. Allows deduping by the linker, which results in a smaller binary file. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20250114-str-enable-disable-usb-v1-3-c8405df47c19@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/class.c | 7 +++--- drivers/usb/typec/tcpm/fusb302.c | 24 +++++++++---------- .../typec/tcpm/qcom/qcom_pmic_typec_pdphy.c | 3 ++- .../tcpm/qcom/qcom_pmic_typec_pdphy_stub.c | 3 ++- .../typec/tcpm/qcom/qcom_pmic_typec_port.c | 4 +++- drivers/usb/typec/tcpm/tcpm.c | 7 +++--- 6 files changed, 27 insertions(+), 21 deletions(-) diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c index b5e67a57762c..a137e105cc55 100644 --- a/drivers/usb/typec/class.c +++ b/drivers/usb/typec/class.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -361,7 +362,7 @@ active_show(struct device *dev, struct device_attribute *attr, char *buf) { struct typec_altmode *alt = to_typec_altmode(dev); - return sprintf(buf, "%s\n", alt->active ? "yes" : "no"); + return sprintf(buf, "%s\n", str_yes_no(alt->active)); } static ssize_t active_store(struct device *dev, struct device_attribute *attr, @@ -707,7 +708,7 @@ static ssize_t supports_usb_power_delivery_show(struct device *dev, { struct typec_partner *p = to_typec_partner(dev); - return sprintf(buf, "%s\n", p->usb_pd ? "yes" : "no"); + return sprintf(buf, "%s\n", str_yes_no(p->usb_pd)); } static DEVICE_ATTR_RO(supports_usb_power_delivery); @@ -1859,7 +1860,7 @@ static ssize_t vconn_source_show(struct device *dev, struct typec_port *port = to_typec_port(dev); return sprintf(buf, "%s\n", - port->vconn_role == TYPEC_SOURCE ? "yes" : "no"); + str_yes_no(port->vconn_role == TYPEC_SOURCE)); } static DEVICE_ATTR_RW(vconn_source); diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c index e2fe479e16ad..f15c63d3a8f4 100644 --- a/drivers/usb/typec/tcpm/fusb302.c +++ b/drivers/usb/typec/tcpm/fusb302.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -733,7 +734,7 @@ static int tcpm_set_vconn(struct tcpc_dev *dev, bool on) mutex_lock(&chip->lock); if (chip->vconn_on == on) { - fusb302_log(chip, "vconn is already %s", on ? "On" : "Off"); + fusb302_log(chip, "vconn is already %s", str_on_off(on)); goto done; } if (on) { @@ -746,7 +747,7 @@ static int tcpm_set_vconn(struct tcpc_dev *dev, bool on) if (ret < 0) goto done; chip->vconn_on = on; - fusb302_log(chip, "vconn := %s", on ? "On" : "Off"); + fusb302_log(chip, "vconn := %s", str_on_off(on)); done: mutex_unlock(&chip->lock); @@ -761,7 +762,7 @@ static int tcpm_set_vbus(struct tcpc_dev *dev, bool on, bool charge) mutex_lock(&chip->lock); if (chip->vbus_on == on) { - fusb302_log(chip, "vbus is already %s", on ? "On" : "Off"); + fusb302_log(chip, "vbus is already %s", str_on_off(on)); } else { if (on) ret = regulator_enable(chip->vbus); @@ -769,15 +770,14 @@ static int tcpm_set_vbus(struct tcpc_dev *dev, bool on, bool charge) ret = regulator_disable(chip->vbus); if (ret < 0) { fusb302_log(chip, "cannot %s vbus regulator, ret=%d", - on ? "enable" : "disable", ret); + str_enable_disable(on), ret); goto done; } chip->vbus_on = on; - fusb302_log(chip, "vbus := %s", on ? "On" : "Off"); + fusb302_log(chip, "vbus := %s", str_on_off(on)); } if (chip->charge_on == charge) - fusb302_log(chip, "charge is already %s", - charge ? "On" : "Off"); + fusb302_log(chip, "charge is already %s", str_on_off(charge)); else chip->charge_on = charge; @@ -854,16 +854,16 @@ static int tcpm_set_pd_rx(struct tcpc_dev *dev, bool on) ret = fusb302_pd_set_auto_goodcrc(chip, on); if (ret < 0) { fusb302_log(chip, "cannot turn %s auto GCRC, ret=%d", - on ? "on" : "off", ret); + str_on_off(on), ret); goto done; } ret = fusb302_pd_set_interrupts(chip, on); if (ret < 0) { fusb302_log(chip, "cannot turn %s pd interrupts, ret=%d", - on ? "on" : "off", ret); + str_on_off(on), ret); goto done; } - fusb302_log(chip, "pd := %s", on ? "on" : "off"); + fusb302_log(chip, "pd := %s", str_on_off(on)); done: mutex_unlock(&chip->lock); @@ -1531,7 +1531,7 @@ static void fusb302_irq_work(struct work_struct *work) if (interrupt & FUSB_REG_INTERRUPT_VBUSOK) { vbus_present = !!(status0 & FUSB_REG_STATUS0_VBUSOK); fusb302_log(chip, "IRQ: VBUS_OK, vbus=%s", - vbus_present ? "On" : "Off"); + str_on_off(vbus_present)); if (vbus_present != chip->vbus_present) { chip->vbus_present = vbus_present; tcpm_vbus_change(chip->tcpm_port); @@ -1562,7 +1562,7 @@ static void fusb302_irq_work(struct work_struct *work) if ((interrupt & FUSB_REG_INTERRUPT_COMP_CHNG) && intr_comp_chng) { comp_result = !!(status0 & FUSB_REG_STATUS0_COMP); fusb302_log(chip, "IRQ: COMP_CHNG, comp=%s", - comp_result ? "true" : "false"); + str_true_false(comp_result)); if (comp_result) { /* cc level > Rd_threshold, detach */ chip->cc1 = TYPEC_CC_OPEN; diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c index 726423684bae..18303b34594b 100644 --- a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c +++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include "qcom_pmic_typec.h" @@ -418,7 +419,7 @@ static int qcom_pmic_typec_pdphy_set_pd_rx(struct tcpc_dev *tcpc, bool on) spin_unlock_irqrestore(&pmic_typec_pdphy->lock, flags); - dev_dbg(pmic_typec_pdphy->dev, "set_pd_rx: %s\n", on ? "on" : "off"); + dev_dbg(pmic_typec_pdphy->dev, "set_pd_rx: %s\n", str_on_off(on)); return ret; } diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy_stub.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy_stub.c index df79059cda67..8fac171778da 100644 --- a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy_stub.c +++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy_stub.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include "qcom_pmic_typec.h" @@ -38,7 +39,7 @@ static int qcom_pmic_typec_pdphy_stub_set_pd_rx(struct tcpc_dev *tcpc, bool on) struct pmic_typec *tcpm = tcpc_to_tcpm(tcpc); struct device *dev = tcpm->dev; - dev_dbg(dev, "set_pd_rx: %s\n", on ? "on" : "off"); + dev_dbg(dev, "set_pd_rx: %s\n", str_on_off(on)); return 0; } diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c index c37dede62e12..4fc83dcfae64 100644 --- a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c +++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_port.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -562,7 +563,8 @@ done: spin_unlock_irqrestore(&pmic_typec_port->lock, flags); dev_dbg(dev, "set_vconn: orientation %d control 0x%08x state %s cc %s vconn %s\n", - orientation, value, on ? "on" : "off", misc_to_vconn(misc), misc_to_cc(misc)); + orientation, value, str_on_off(on), misc_to_vconn(misc), + misc_to_cc(misc)); return ret; } diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 57fae1118ac9..ec14a4bc492f 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -892,8 +893,8 @@ static int tcpm_enable_auto_vbus_discharge(struct tcpm_port *port, bool enable) if (port->tcpc->enable_auto_vbus_discharge) { ret = port->tcpc->enable_auto_vbus_discharge(port->tcpc, enable); - tcpm_log_force(port, "%s vbus discharge ret:%d", enable ? "enable" : "disable", - ret); + tcpm_log_force(port, "%s vbus discharge ret:%d", + str_enable_disable(enable), ret); if (!ret) port->auto_vbus_discharge_enabled = enable; } @@ -4439,7 +4440,7 @@ static void tcpm_unregister_altmodes(struct tcpm_port *port) static void tcpm_set_partner_usb_comm_capable(struct tcpm_port *port, bool capable) { - tcpm_log(port, "Setting usb_comm capable %s", capable ? "true" : "false"); + tcpm_log(port, "Setting usb_comm capable %s", str_true_false(capable)); if (port->tcpc->set_partner_usb_comm_capable) port->tcpc->set_partner_usb_comm_capable(port->tcpc, capable); -- 2.51.0 From 2d913c1b0cac0aeacc20870000ff3cddb040e69a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 14 Jan 2025 21:05:37 +0100 Subject: [PATCH 13/16] USB: phy: Use str_enable_disable-like helpers Replace ternary (condition ? "enable" : "disable") syntax with helpers from string_choices.h because: 1. Simple function call with one argument is easier to read. Ternary operator has three arguments and with wrapping might lead to quite long code. 2. Is slightly shorter thus also easier to read. 3. It brings uniformity in the text - same string. 4. Allows deduping by the linker, which results in a smaller binary file. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20250114-str-enable-disable-usb-v1-4-c8405df47c19@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/phy/phy-fsl-usb.c | 3 ++- drivers/usb/phy/phy-mv-usb.c | 3 ++- drivers/usb/phy/phy-tahvo.c | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c index 42c42e193232..40ac68e52cee 100644 --- a/drivers/usb/phy/phy-fsl-usb.c +++ b/drivers/usb/phy/phy-fsl-usb.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -529,7 +530,7 @@ int fsl_otg_start_gadget(struct otg_fsm *fsm, int on) if (!otg->gadget || !otg->gadget->dev.parent) return -ENODEV; - VDBG("gadget %s\n", on ? "on" : "off"); + VDBG("gadget %s\n", str_on_off(on)); dev = otg->gadget->dev.parent; if (on) { diff --git a/drivers/usb/phy/phy-mv-usb.c b/drivers/usb/phy/phy-mv-usb.c index a7a102f2e163..30d6c8840a5e 100644 --- a/drivers/usb/phy/phy-mv-usb.c +++ b/drivers/usb/phy/phy-mv-usb.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -217,7 +218,7 @@ static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on) if (!otg->gadget) return; - dev_info(mvotg->phy.dev, "gadget %s\n", on ? "on" : "off"); + dev_info(mvotg->phy.dev, "gadget %s\n", str_on_off(on)); if (on) usb_gadget_vbus_connect(otg->gadget); diff --git a/drivers/usb/phy/phy-tahvo.c b/drivers/usb/phy/phy-tahvo.c index ae7bf3ff89ee..88607d0edb01 100644 --- a/drivers/usb/phy/phy-tahvo.c +++ b/drivers/usb/phy/phy-tahvo.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -63,7 +64,7 @@ static ssize_t vbus_show(struct device *device, struct device_attribute *attr, char *buf) { struct tahvo_usb *tu = dev_get_drvdata(device); - return sprintf(buf, "%s\n", tu->vbus_state ? "on" : "off"); + return sprintf(buf, "%s\n", str_on_off(tu->vbus_state)); } static DEVICE_ATTR_RO(vbus); -- 2.51.0 From 5b6dc50e9ed870fffbf2ae6de77b30fb0d15eab8 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 14 Jan 2025 21:05:38 +0100 Subject: [PATCH 14/16] USB: gadget: Use str_enable_disable-like helpers Replace ternary (condition ? "enable" : "disable") syntax with helpers from string_choices.h because: 1. Simple function call with one argument is easier to read. Ternary operator has three arguments and with wrapping might lead to quite long code. 2. Is slightly shorter thus also easier to read. 3. It brings uniformity in the text - same string. 4. Allows deduping by the linker, which results in a smaller binary file. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20250114-str-enable-disable-usb-v1-5-c8405df47c19@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/function/f_ecm.c | 4 ++-- drivers/usb/gadget/function/f_ncm.c | 3 ++- drivers/usb/gadget/function/u_serial.c | 3 ++- drivers/usb/gadget/legacy/inode.c | 3 ++- drivers/usb/gadget/udc/aspeed-vhub/hub.c | 3 ++- drivers/usb/gadget/udc/at91_udc.c | 3 ++- drivers/usb/gadget/udc/cdns2/cdns2-gadget.c | 13 +++++++------ drivers/usb/gadget/udc/dummy_hcd.c | 3 ++- drivers/usb/gadget/udc/fsl_udc_core.c | 3 ++- drivers/usb/gadget/udc/omap_udc.c | 3 ++- drivers/usb/gadget/udc/pxa27x_udc.c | 3 ++- 11 files changed, 27 insertions(+), 17 deletions(-) diff --git a/drivers/usb/gadget/function/f_ecm.c b/drivers/usb/gadget/function/f_ecm.c index 6cb7771e8a69..80841de845b0 100644 --- a/drivers/usb/gadget/function/f_ecm.c +++ b/drivers/usb/gadget/function/f_ecm.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "u_ether.h" #include "u_ether_configfs.h" @@ -387,8 +388,7 @@ static void ecm_do_notify(struct f_ecm *ecm) event->wLength = 0; req->length = sizeof *event; - DBG(cdev, "notify connect %s\n", - ecm->is_open ? "true" : "false"); + DBG(cdev, "notify connect %s\n", str_true_false(ecm->is_open)); ecm->notify_state = ECM_NOTIFY_SPEED; break; diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c index 8e761249d672..f60576a65ca6 100644 --- a/drivers/usb/gadget/function/f_ncm.c +++ b/drivers/usb/gadget/function/f_ncm.c @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -558,7 +559,7 @@ static void ncm_do_notify(struct f_ncm *ncm) req->length = sizeof *event; DBG(cdev, "notify connect %s\n", - ncm->is_open ? "true" : "false"); + str_true_false(ncm->is_open)); ncm->notify_state = NCM_NOTIFY_NONE; break; diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index bc143a86c2dd..5413882b1498 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -1545,7 +1546,7 @@ static int __init userial_init(void) pr_debug("%s: registered %d ttyGS* device%s\n", __func__, MAX_U_SERIAL_PORTS, - (MAX_U_SERIAL_PORTS == 1) ? "" : "s"); + str_plural(MAX_U_SERIAL_PORTS)); return status; fail: diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index 9c7381661016..b6a30d88a800 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -1182,7 +1183,7 @@ ep0_fasync (int f, struct file *fd, int on) { struct dev_data *dev = fd->private_data; // caller must F_SETOWN before signal delivery happens - VDEBUG (dev, "%s %s\n", __func__, on ? "on" : "off"); + VDEBUG(dev, "%s %s\n", __func__, str_on_off(on)); return fasync_helper (f, fd, on, &dev->fasync); } diff --git a/drivers/usb/gadget/udc/aspeed-vhub/hub.c b/drivers/usb/gadget/udc/aspeed-vhub/hub.c index a63e4af60a56..02fe1a08d575 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/hub.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/hub.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -219,7 +220,7 @@ static int ast_vhub_hub_dev_feature(struct ast_vhub_ep *ep, if (wValue == USB_DEVICE_REMOTE_WAKEUP) { ep->vhub->wakeup_en = is_set; EPDBG(ep, "Hub remote wakeup %s\n", - is_set ? "enabled" : "disabled"); + str_enabled_disabled(is_set)); return std_req_complete; } diff --git a/drivers/usb/gadget/udc/at91_udc.c b/drivers/usb/gadget/udc/at91_udc.c index e3af4ec3794e..aa4c61094dc6 100644 --- a/drivers/usb/gadget/udc/at91_udc.c +++ b/drivers/usb/gadget/udc/at91_udc.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -131,7 +132,7 @@ static void proc_ep_show(struct seq_file *s, struct at91_ep *ep) seq_printf(s, "csr %08x rxbytes=%d %s %s %s" EIGHTBITS "\n", csr, (csr & 0x07ff0000) >> 16, - (csr & (1 << 15)) ? "enabled" : "disabled", + str_enabled_disabled(csr & (1 << 15)), (csr & (1 << 11)) ? "DATA1" : "DATA0", types[(csr & 0x700) >> 8], diff --git a/drivers/usb/gadget/udc/cdns2/cdns2-gadget.c b/drivers/usb/gadget/udc/cdns2/cdns2-gadget.c index 62fce42ef2da..7e69944ef18a 100644 --- a/drivers/usb/gadget/udc/cdns2/cdns2-gadget.c +++ b/drivers/usb/gadget/udc/cdns2/cdns2-gadget.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -2233,12 +2234,12 @@ static int cdns2_init_eps(struct cdns2_device *pdev) dev_dbg(pdev->dev, "Init %s, SupType: CTRL: %s, INT: %s, " "BULK: %s, ISOC %s, SupDir IN: %s, OUT: %s\n", pep->name, - (pep->endpoint.caps.type_control) ? "yes" : "no", - (pep->endpoint.caps.type_int) ? "yes" : "no", - (pep->endpoint.caps.type_bulk) ? "yes" : "no", - (pep->endpoint.caps.type_iso) ? "yes" : "no", - (pep->endpoint.caps.dir_in) ? "yes" : "no", - (pep->endpoint.caps.dir_out) ? "yes" : "no"); + str_yes_no(pep->endpoint.caps.type_control), + str_yes_no(pep->endpoint.caps.type_int), + str_yes_no(pep->endpoint.caps.type_bulk), + str_yes_no(pep->endpoint.caps.type_iso), + str_yes_no(pep->endpoint.caps.dir_in), + str_yes_no(pep->endpoint.caps.dir_out)); INIT_LIST_HEAD(&pep->pending_list); INIT_LIST_HEAD(&pep->deferred_list); diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c index a7e8fa45776b..bda08c5ba7c0 100644 --- a/drivers/usb/gadget/udc/dummy_hcd.c +++ b/drivers/usb/gadget/udc/dummy_hcd.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -625,7 +626,7 @@ static int dummy_enable(struct usb_ep *_ep, desc->bEndpointAddress & 0x0f, (desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out", usb_ep_type_string(usb_endpoint_type(desc)), - max, ep->stream_en ? "enabled" : "disabled"); + max, str_enabled_disabled(ep->stream_en)); /* at this point real hardware should be NAKing transfers * to that endpoint, until a buffer is queued to it. diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c index 8b7f7f961774..4dea8bc30cf6 100644 --- a/drivers/usb/gadget/udc/fsl_udc_core.c +++ b/drivers/usb/gadget/udc/fsl_udc_core.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -1181,7 +1182,7 @@ static int fsl_vbus_session(struct usb_gadget *gadget, int is_active) udc = container_of(gadget, struct fsl_udc, gadget); spin_lock_irqsave(&udc->lock, flags); - dev_vdbg(&gadget->dev, "VBUS %s\n", is_active ? "on" : "off"); + dev_vdbg(&gadget->dev, "VBUS %s\n", str_on_off(is_active)); udc->vbus_active = (is_active != 0); if (can_pullup(udc)) fsl_writel((fsl_readl(&dr_regs->usbcmd) | USB_CMD_RUN_STOP), diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c index 698463bf697b..8902abe3ca76 100644 --- a/drivers/usb/gadget/udc/omap_udc.c +++ b/drivers/usb/gadget/udc/omap_udc.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -1252,7 +1253,7 @@ static int omap_vbus_session(struct usb_gadget *gadget, int is_active) udc = container_of(gadget, struct omap_udc, gadget); spin_lock_irqsave(&udc->lock, flags); - VDBG("VBUS %s\n", is_active ? "on" : "off"); + VDBG("VBUS %s\n", str_on_off(is_active)); udc->vbus_active = (is_active != 0); if (cpu_is_omap15xx()) { /* "software" detect, ignored if !VBUS_MODE_1510 */ diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c index f9a55d4f189f..897f53601b5b 100644 --- a/drivers/usb/gadget/udc/pxa27x_udc.c +++ b/drivers/usb/gadget/udc/pxa27x_udc.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -1083,7 +1084,7 @@ static int pxa_ep_queue(struct usb_ep *_ep, struct usb_request *_req, is_first_req = list_empty(&ep->queue); ep_dbg(ep, "queue req %p(first=%s), len %d buf %p\n", - _req, is_first_req ? "yes" : "no", + _req, str_yes_no(is_first_req), _req->length, _req->buf); if (!ep->enabled) { -- 2.51.0 From f386bfad038d07fc356df267592f5fd812c8cf3e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 14 Jan 2025 21:05:39 +0100 Subject: [PATCH 15/16] USB: Use str_enable_disable-like helpers Replace ternary (condition ? "enable" : "disable") syntax with helpers from string_choices.h because: 1. Simple function call with one argument is easier to read. Ternary operator has three arguments and with wrapping might lead to quite long code. 2. Is slightly shorter thus also easier to read. 3. It brings uniformity in the text - same string. 4. Allows deduping by the linker, which results in a smaller binary file. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20250114-str-enable-disable-usb-v1-6-c8405df47c19@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/cdns3/cdnsp-gadget.c | 13 +++++++------ drivers/usb/chipidea/host.c | 3 ++- drivers/usb/common/usb-conn-gpio.c | 3 ++- drivers/usb/core/hub.c | 10 +++++----- drivers/usb/core/port.c | 3 ++- drivers/usb/fotg210/fotg210-core.c | 5 +++-- drivers/usb/mtu3/mtu3_debugfs.c | 3 ++- drivers/usb/mtu3/mtu3_dr.c | 3 ++- drivers/usb/mtu3/mtu3_gadget.c | 3 ++- drivers/usb/musb/da8xx.c | 3 ++- drivers/usb/musb/musb_core.c | 3 ++- drivers/usb/musb/musb_dsps.c | 3 ++- drivers/usb/musb/musb_gadget.c | 3 ++- drivers/usb/musb/musb_host.c | 3 ++- drivers/usb/storage/shuttle_usbat.c | 4 ++-- drivers/usb/usbip/vhci_hcd.c | 3 ++- 16 files changed, 41 insertions(+), 27 deletions(-) diff --git a/drivers/usb/cdns3/cdnsp-gadget.c b/drivers/usb/cdns3/cdnsp-gadget.c index 4a3f0f958256..97edf767ecee 100644 --- a/drivers/usb/cdns3/cdnsp-gadget.c +++ b/drivers/usb/cdns3/cdnsp-gadget.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -1671,12 +1672,12 @@ static int cdnsp_gadget_init_endpoints(struct cdnsp_device *pdev) "CTRL: %s, INT: %s, BULK: %s, ISOC %s, " "SupDir IN: %s, OUT: %s\n", pep->name, 1024, - (pep->endpoint.caps.type_control) ? "yes" : "no", - (pep->endpoint.caps.type_int) ? "yes" : "no", - (pep->endpoint.caps.type_bulk) ? "yes" : "no", - (pep->endpoint.caps.type_iso) ? "yes" : "no", - (pep->endpoint.caps.dir_in) ? "yes" : "no", - (pep->endpoint.caps.dir_out) ? "yes" : "no"); + str_yes_no(pep->endpoint.caps.type_control), + str_yes_no(pep->endpoint.caps.type_int), + str_yes_no(pep->endpoint.caps.type_bulk), + str_yes_no(pep->endpoint.caps.type_iso), + str_yes_no(pep->endpoint.caps.dir_in), + str_yes_no(pep->endpoint.caps.dir_out)); INIT_LIST_HEAD(&pep->pending_list); } diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index 442d79e32a65..ced6076a8248 100644 --- a/drivers/usb/chipidea/host.c +++ b/drivers/usb/chipidea/host.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "../host/ehci.h" @@ -56,7 +57,7 @@ static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable) if (ret) { dev_err(dev, "Failed to %s vbus regulator, ret=%d\n", - enable ? "enable" : "disable", ret); + str_enable_disable(enable), ret); return ret; } priv->enabled = enable; diff --git a/drivers/usb/common/usb-conn-gpio.c b/drivers/usb/common/usb-conn-gpio.c index c84b4a700084..aa710b50791b 100644 --- a/drivers/usb/common/usb-conn-gpio.c +++ b/drivers/usb/common/usb-conn-gpio.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #define USB_GPIO_DEB_MS 20 /* ms */ @@ -111,7 +112,7 @@ static void usb_conn_detect_cable(struct work_struct *work) if (info->vbus) dev_dbg(info->dev, "vbus regulator is %s\n", - regulator_is_enabled(info->vbus) ? "enabled" : "disabled"); + str_enabled_disabled(regulator_is_enabled(info->vbus))); power_supply_changed(info->charger); } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 21ac9b464696..c3f839637cb5 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -1496,7 +1497,7 @@ static int hub_configure(struct usb_hub *hub, maxchild = hub->descriptor->bNbrPorts; dev_info(hub_dev, "%d port%s detected\n", maxchild, - (maxchild == 1) ? "" : "s"); + str_plural(maxchild)); hub->ports = kcalloc(maxchild, sizeof(struct usb_port *), GFP_KERNEL); if (!hub->ports) { @@ -4139,14 +4140,14 @@ static int usb_set_device_initiated_lpm(struct usb_device *udev, break; default: dev_warn(&udev->dev, "%s: Can't %s non-U1 or U2 state.\n", - __func__, enable ? "enable" : "disable"); + __func__, str_enable_disable(enable)); return -EINVAL; } if (udev->state != USB_STATE_CONFIGURED) { dev_dbg(&udev->dev, "%s: Can't %s %s state " "for unconfigured device.\n", - __func__, enable ? "enable" : "disable", + __func__, str_enable_disable(enable), usb3_lpm_names[state]); return 0; } @@ -4172,8 +4173,7 @@ static int usb_set_device_initiated_lpm(struct usb_device *udev, } if (ret < 0) { dev_warn(&udev->dev, "%s of device-initiated %s failed.\n", - enable ? "Enable" : "Disable", - usb3_lpm_names[state]); + str_enable_disable(enable), usb3_lpm_names[state]); return -EBUSY; } return 0; diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index e857e532b35a..f54198171b6a 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -25,7 +26,7 @@ static ssize_t early_stop_show(struct device *dev, { struct usb_port *port_dev = to_usb_port(dev); - return sysfs_emit(buf, "%s\n", port_dev->early_stop ? "yes" : "no"); + return sysfs_emit(buf, "%s\n", str_yes_no(port_dev->early_stop)); } static ssize_t early_stop_store(struct device *dev, struct device_attribute *attr, diff --git a/drivers/usb/fotg210/fotg210-core.c b/drivers/usb/fotg210/fotg210-core.c index 49f25a70b32e..7fb4d4715e9f 100644 --- a/drivers/usb/fotg210/fotg210-core.c +++ b/drivers/usb/fotg210/fotg210-core.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -119,8 +120,8 @@ void fotg210_vbus(struct fotg210 *fotg, bool enable) ret = regmap_update_bits(fotg->map, GEMINI_GLOBAL_MISC_CTRL, mask, val); if (ret) dev_err(fotg->dev, "failed to %s VBUS\n", - enable ? "enable" : "disable"); - dev_info(fotg->dev, "%s: %s VBUS\n", __func__, enable ? "enable" : "disable"); + str_enable_disable(enable)); + dev_info(fotg->dev, "%s: %s VBUS\n", __func__, str_enable_disable(enable)); } static int fotg210_probe(struct platform_device *pdev) diff --git a/drivers/usb/mtu3/mtu3_debugfs.c b/drivers/usb/mtu3/mtu3_debugfs.c index f0de99858353..9bd74c505872 100644 --- a/drivers/usb/mtu3/mtu3_debugfs.c +++ b/drivers/usb/mtu3/mtu3_debugfs.c @@ -7,6 +7,7 @@ * Author: Chunfeng Yun */ +#include #include #include "mtu3.h" @@ -479,7 +480,7 @@ static int ssusb_vbus_show(struct seq_file *sf, void *unused) struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; seq_printf(sf, "vbus state: %s\n(echo on/off)\n", - regulator_is_enabled(otg_sx->vbus) ? "on" : "off"); + str_on_off(regulator_is_enabled(otg_sx->vbus))); return 0; } diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c index 8191b7ed3852..ffa5b9401dad 100644 --- a/drivers/usb/mtu3/mtu3_dr.c +++ b/drivers/usb/mtu3/mtu3_dr.c @@ -7,6 +7,7 @@ * Author: Chunfeng Yun */ +#include #include "mtu3.h" #include "mtu3_dr.h" #include "mtu3_debug.h" @@ -109,7 +110,7 @@ int ssusb_set_vbus(struct otg_switch_mtk *otg_sx, int is_on) if (!vbus) return 0; - dev_dbg(ssusb->dev, "%s: turn %s\n", __func__, is_on ? "on" : "off"); + dev_dbg(ssusb->dev, "%s: turn %s\n", __func__, str_on_off(is_on)); if (is_on) { ret = regulator_enable(vbus); diff --git a/drivers/usb/mtu3/mtu3_gadget.c b/drivers/usb/mtu3/mtu3_gadget.c index ad0eeac4332d..bf73fbc29976 100644 --- a/drivers/usb/mtu3/mtu3_gadget.c +++ b/drivers/usb/mtu3/mtu3_gadget.c @@ -7,6 +7,7 @@ * Author: Chunfeng Yun */ +#include #include "mtu3.h" #include "mtu3_trace.h" @@ -490,7 +491,7 @@ static int mtu3_gadget_pullup(struct usb_gadget *gadget, int is_on) unsigned long flags; dev_dbg(mtu->dev, "%s (%s) for %sactive device\n", __func__, - is_on ? "on" : "off", mtu->is_active ? "" : "in"); + str_on_off(is_on), mtu->is_active ? "" : "in"); pm_runtime_get_sync(mtu->dev); diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index f772aa272bea..26fd71a5f9b2 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -306,7 +307,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) } dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n", - drvvbus ? "on" : "off", + str_on_off(drvvbus), usb_otg_state_string(musb->xceiv->otg->state), err ? " ERROR" : "", devctl); diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 03b1154a6014..7f349f5e781d 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -72,6 +72,7 @@ #include #include #include +#include #include #include #include @@ -1937,7 +1938,7 @@ vbus_show(struct device *dev, struct device_attribute *attr, char *buf) pm_runtime_put_sync(dev); return sprintf(buf, "Vbus %s, timeout %lu msec\n", - vbus ? "on" : "off", val); + str_on_off(vbus), val); } static DEVICE_ATTR_RW(vbus); diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 2542239ec64e..f877faf5a930 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -378,7 +379,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) /* NOTE: this must complete power-on within 100 ms. */ dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n", - drvvbus ? "on" : "off", + str_on_off(drvvbus), usb_otg_state_string(musb->xceiv->otg->state), err ? " ERROR" : "", devctl); diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index c6076df0d50c..6869c58367f2 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -1606,7 +1607,7 @@ static void musb_pullup(struct musb *musb, int is_on) /* FIXME if on, HdrcStart; if off, HdrcStop */ musb_dbg(musb, "gadget D+ pullup %s", - is_on ? "on" : "off"); + str_on_off(is_on)); musb_writeb(musb->mregs, MUSB_POWER, power); } diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 732ba981e607..6b4481a867c5 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -1028,7 +1029,7 @@ static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb) + urb->actual_length); musb_dbg(musb, "Sending %d byte%s to ep0 fifo %p", fifo_count, - (fifo_count == 1) ? "" : "s", + str_plural(fifo_count), fifo_dest); musb_write_fifo(hw_ep, fifo_count, fifo_dest); diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index 087c706bb315..c33cbf177e6f 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -651,8 +652,7 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us, return USB_STOR_TRANSPORT_FAILED; usb_stor_dbg(us, "Redoing %s\n", - direction == DMA_TO_DEVICE - ? "write" : "read"); + str_write_read(direction == DMA_TO_DEVICE)); } else if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c index 2f722849dfc9..f4843ea5080c 100644 --- a/drivers/usb/usbip/vhci_hcd.c +++ b/drivers/usb/usbip/vhci_hcd.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "usbip_common.h" #include "vhci.h" @@ -1449,7 +1450,7 @@ static int vhci_hcd_suspend(struct platform_device *pdev, pm_message_t state) if (connected > 0) { dev_info(&pdev->dev, "We have %d active connection%s. Do not suspend.\n", - connected, (connected == 1 ? "" : "s")); + connected, str_plural(connected)); ret = -EBUSY; } else { dev_info(&pdev->dev, "suspend vhci_hcd"); -- 2.51.0 From dcfe437492e27d54f3ac491aed024da760f5c43c Mon Sep 17 00:00:00 2001 From: Thinh Nguyen Date: Tue, 14 Jan 2025 01:50:38 +0000 Subject: [PATCH 16/16] usb: dwc3: gadget: Reinitiate stream for all host NoStream behavior There are too many different host behaviors when it comes to NoStream handling, and not everyone follows the USB and xHCI spec. The DWC3 driver attempts to do some guess work to interop with different hosts, but it can't cover everything. Let's keep it simple and treat every host the same: just retry on NoStream after a 100ms of no response delay. Note that some hosts cannot handle frequent retries. This may affect performance on certain defective hosts, but NoStream is a rare occurrence and interoperability is more important. Signed-off-by: Thinh Nguyen Link: https://lore.kernel.org/r/b92ae94c86f01f165d5f178b7767898573b6dc75.1736819308.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/core.h | 3 +- drivers/usb/dwc3/gadget.c | 109 ++++++++++++++++++++------------------ 2 files changed, 59 insertions(+), 53 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 914fe79d08e8..ac7c730f81ac 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -743,6 +743,7 @@ struct dwc3_event_buffer { */ struct dwc3_ep { struct usb_ep endpoint; + struct delayed_work nostream_work; struct list_head cancelled_list; struct list_head pending_list; struct list_head started_list; @@ -765,7 +766,7 @@ struct dwc3_ep { #define DWC3_EP_WAIT_TRANSFER_COMPLETE BIT(7) #define DWC3_EP_IGNORE_NEXT_NOSTREAM BIT(8) #define DWC3_EP_FORCE_RESTART_STREAM BIT(9) -#define DWC3_EP_FIRST_STREAM_PRIMED BIT(10) +#define DWC3_EP_STREAM_PRIMED BIT(10) #define DWC3_EP_PENDING_CLEAR_STALL BIT(11) #define DWC3_EP_TXFIFO_RESIZED BIT(12) #define DWC3_EP_DELAY_STOP BIT(13) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 7270f092329a..d27af65eb08a 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -996,8 +996,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action) /* * All stream eps will reinitiate stream on NoStream - * rejection until we can determine that the host can - * prime after the first transfer. + * rejection. * * However, if the controller is capable of * TXF_FLUSH_BYPASS, then IN direction endpoints will @@ -3300,6 +3299,50 @@ static int dwc3_gadget_init_out_endpoint(struct dwc3_ep *dep) return dwc3_alloc_trb_pool(dep); } +#define nostream_work_to_dep(w) (container_of(to_delayed_work(w), struct dwc3_ep, nostream_work)) +static void dwc3_nostream_work(struct work_struct *work) +{ + struct dwc3_ep *dep = nostream_work_to_dep(work); + struct dwc3 *dwc = dep->dwc; + unsigned long flags; + + spin_lock_irqsave(&dwc->lock, flags); + if (dep->flags & DWC3_EP_STREAM_PRIMED) + goto out; + + if ((dep->flags & DWC3_EP_IGNORE_NEXT_NOSTREAM) || + (!DWC3_MST_CAPABLE(&dwc->hwparams) && + !(dep->flags & DWC3_EP_WAIT_TRANSFER_COMPLETE))) + goto out; + /* + * If the host rejects a stream due to no active stream, by the + * USB and xHCI spec, the endpoint will be put back to idle + * state. When the host is ready (buffer added/updated), it will + * prime the endpoint to inform the usb device controller. This + * triggers the device controller to issue ERDY to restart the + * stream. However, some hosts don't follow this and keep the + * endpoint in the idle state. No prime will come despite host + * streams are updated, and the device controller will not be + * triggered to generate ERDY to move the next stream data. To + * workaround this and maintain compatibility with various + * hosts, force to reinitiate the stream until the host is ready + * instead of waiting for the host to prime the endpoint. + */ + if (DWC3_VER_IS_WITHIN(DWC32, 100A, ANY)) { + unsigned int cmd = DWC3_DGCMD_SET_ENDPOINT_PRIME; + + dwc3_send_gadget_generic_command(dwc, cmd, dep->number); + } else { + dep->flags |= DWC3_EP_DELAY_START; + dwc3_stop_active_transfer(dep, true, true); + spin_unlock_irqrestore(&dwc->lock, flags); + return; + } +out: + dep->flags &= ~DWC3_EP_IGNORE_NEXT_NOSTREAM; + spin_unlock_irqrestore(&dwc->lock, flags); +} + static int dwc3_gadget_init_endpoint(struct dwc3 *dwc, u8 epnum) { struct dwc3_ep *dep; @@ -3345,6 +3388,7 @@ static int dwc3_gadget_init_endpoint(struct dwc3 *dwc, u8 epnum) INIT_LIST_HEAD(&dep->pending_list); INIT_LIST_HEAD(&dep->started_list); INIT_LIST_HEAD(&dep->cancelled_list); + INIT_DELAYED_WORK(&dep->nostream_work, dwc3_nostream_work); dwc3_debugfs_create_endpoint_dir(dep); @@ -3744,66 +3788,27 @@ static void dwc3_gadget_endpoint_command_complete(struct dwc3_ep *dep, static void dwc3_gadget_endpoint_stream_event(struct dwc3_ep *dep, const struct dwc3_event_depevt *event) { - struct dwc3 *dwc = dep->dwc; - if (event->status == DEPEVT_STREAMEVT_FOUND) { - dep->flags |= DWC3_EP_FIRST_STREAM_PRIMED; - goto out; + cancel_delayed_work(&dep->nostream_work); + dep->flags |= DWC3_EP_STREAM_PRIMED; + dep->flags &= ~DWC3_EP_IGNORE_NEXT_NOSTREAM; + return; } /* Note: NoStream rejection event param value is 0 and not 0xFFFF */ switch (event->parameters) { case DEPEVT_STREAM_PRIME: - /* - * If the host can properly transition the endpoint state from - * idle to prime after a NoStream rejection, there's no need to - * force restarting the endpoint to reinitiate the stream. To - * simplify the check, assume the host follows the USB spec if - * it primed the endpoint more than once. - */ - if (dep->flags & DWC3_EP_FORCE_RESTART_STREAM) { - if (dep->flags & DWC3_EP_FIRST_STREAM_PRIMED) - dep->flags &= ~DWC3_EP_FORCE_RESTART_STREAM; - else - dep->flags |= DWC3_EP_FIRST_STREAM_PRIMED; - } - + cancel_delayed_work(&dep->nostream_work); + dep->flags |= DWC3_EP_STREAM_PRIMED; + dep->flags &= ~DWC3_EP_IGNORE_NEXT_NOSTREAM; break; case DEPEVT_STREAM_NOSTREAM: - if ((dep->flags & DWC3_EP_IGNORE_NEXT_NOSTREAM) || - !(dep->flags & DWC3_EP_FORCE_RESTART_STREAM) || - (!DWC3_MST_CAPABLE(&dwc->hwparams) && - !(dep->flags & DWC3_EP_WAIT_TRANSFER_COMPLETE))) - break; - - /* - * If the host rejects a stream due to no active stream, by the - * USB and xHCI spec, the endpoint will be put back to idle - * state. When the host is ready (buffer added/updated), it will - * prime the endpoint to inform the usb device controller. This - * triggers the device controller to issue ERDY to restart the - * stream. However, some hosts don't follow this and keep the - * endpoint in the idle state. No prime will come despite host - * streams are updated, and the device controller will not be - * triggered to generate ERDY to move the next stream data. To - * workaround this and maintain compatibility with various - * hosts, force to reinitiate the stream until the host is ready - * instead of waiting for the host to prime the endpoint. - */ - if (DWC3_VER_IS_WITHIN(DWC32, 100A, ANY)) { - unsigned int cmd = DWC3_DGCMD_SET_ENDPOINT_PRIME; - - dwc3_send_gadget_generic_command(dwc, cmd, dep->number); - } else { - dep->flags |= DWC3_EP_DELAY_START; - dwc3_stop_active_transfer(dep, true, true); - return; - } + dep->flags &= ~DWC3_EP_STREAM_PRIMED; + if (dep->flags & DWC3_EP_FORCE_RESTART_STREAM) + queue_delayed_work(system_wq, &dep->nostream_work, + msecs_to_jiffies(100)); break; } - -out: - dep->flags &= ~DWC3_EP_IGNORE_NEXT_NOSTREAM; } static void dwc3_endpoint_interrupt(struct dwc3 *dwc, -- 2.51.0