From patchwork Mon May 15 13:40:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mathias Nyman X-Patchwork-Id: 13241518 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6FF96C7EE22 for ; Mon, 15 May 2023 13:40:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241728AbjEONkS (ORCPT ); Mon, 15 May 2023 09:40:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52464 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242184AbjEONkN (ORCPT ); Mon, 15 May 2023 09:40:13 -0400 Received: from mga06.intel.com (mga06b.intel.com [134.134.136.31]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AF5C91FC8; Mon, 15 May 2023 06:40:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1684158012; x=1715694012; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=YIKX4jDL0Bu17PUG+69eHYZuspkIjzYlHvQNZNS4jMk=; b=cnPlsSi8HS42mTNR274BQM1cqiusDnB1fHMf2bauAENR3jFS6K/ZL8G1 c85AUYFf8EFyvOMncY5s8dS9PtKmE0Ajqz4Q9I0lMs9nLOLex32kRw+Ro GrRbMqh1DyPZCS8Ir8OYYLYTR9BWXYI1Ua6Pa4vcV8xCETYD/wMFf1YY8 zn8E0IKzPrL0fa2Fn64q4t2VQEMwLvgf20chr8qKOX4vTuY9JGwBx/ocp M/K2rIV0U/3v5pjZPbp+gBuNjsJZtMGJMKLLqBvmXN0HngiJOhSNwY3MV uhKnwuJpVsyfD3xXRHBflYXwxnr4cbAl6jzKsTM+XMdLtacHHwrqHr4m1 g==; X-IronPort-AV: E=McAfee;i="6600,9927,10711"; a="414598008" X-IronPort-AV: E=Sophos;i="5.99,276,1677571200"; d="scan'208";a="414598008" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 May 2023 06:39:57 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10711"; a="700964226" X-IronPort-AV: E=Sophos;i="5.99,276,1677571200"; d="scan'208";a="700964226" Received: from mattu-haswell.fi.intel.com ([10.237.72.199]) by orsmga002.jf.intel.com with ESMTP; 15 May 2023 06:39:55 -0700 From: Mathias Nyman To: Cc: , Mario Limonciello , Donghun Yoon , stable@vger.kernel.org, Mathias Nyman Subject: [PATCH 1/2] xhci-pci: Only run d3cold avoidance quirk for s2idle Date: Mon, 15 May 2023 16:40:58 +0300 Message-Id: <20230515134059.161110-2-mathias.nyman@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230515134059.161110-1-mathias.nyman@linux.intel.com> References: <20230515134059.161110-1-mathias.nyman@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org From: Mario Limonciello Donghun reports that a notebook that has an AMD Ryzen 5700U but supports S3 has problems with USB after resuming from suspend. The issue was bisected down to commit d1658268e439 ("usb: pci-quirks: disable D3cold on xhci suspend for s2idle on AMD Renoir"). As this issue only happens on S3, narrow the broken D3cold quirk to only run in s2idle. Fixes: d1658268e439 ("usb: pci-quirks: disable D3cold on xhci suspend for s2idle on AMD Renoir") Reported-and-tested-by: Donghun Yoon Cc: stable@vger.kernel.org Signed-off-by: Mario Limonciello Signed-off-by: Mathias Nyman --- drivers/usb/host/xhci-pci.c | 12 ++++++++++-- drivers/usb/host/xhci.h | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index ddb79f23fb3b..79b3691f373f 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "xhci.h" #include "xhci-trace.h" @@ -387,7 +388,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) if (pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == PCI_DEVICE_ID_AMD_RENOIR_XHCI) - xhci->quirks |= XHCI_BROKEN_D3COLD; + xhci->quirks |= XHCI_BROKEN_D3COLD_S2I; if (pdev->vendor == PCI_VENDOR_ID_INTEL) { xhci->quirks |= XHCI_LPM_SUPPORT; @@ -801,9 +802,16 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) * Systems with the TI redriver that loses port status change events * need to have the registers polled during D3, so avoid D3cold. */ - if (xhci->quirks & (XHCI_COMP_MODE_QUIRK | XHCI_BROKEN_D3COLD)) + if (xhci->quirks & XHCI_COMP_MODE_QUIRK) pci_d3cold_disable(pdev); +#ifdef CONFIG_SUSPEND + /* d3cold is broken, but only when s2idle is used */ + if (pm_suspend_target_state == PM_SUSPEND_TO_IDLE && + xhci->quirks & (XHCI_BROKEN_D3COLD_S2I)) + pci_d3cold_disable(pdev); +#endif + if (xhci->quirks & XHCI_PME_STUCK_QUIRK) xhci_pme_quirk(hcd); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 08d721921b7b..6b690ec91ff3 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1901,7 +1901,7 @@ struct xhci_hcd { #define XHCI_DISABLE_SPARSE BIT_ULL(38) #define XHCI_SG_TRB_CACHE_SIZE_QUIRK BIT_ULL(39) #define XHCI_NO_SOFT_RETRY BIT_ULL(40) -#define XHCI_BROKEN_D3COLD BIT_ULL(41) +#define XHCI_BROKEN_D3COLD_S2I BIT_ULL(41) #define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42) #define XHCI_SUSPEND_RESUME_CLKS BIT_ULL(43) #define XHCI_RESET_TO_DEFAULT BIT_ULL(44) From patchwork Mon May 15 13:40:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mathias Nyman X-Patchwork-Id: 13241517 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 503FBC7EE2C for ; Mon, 15 May 2023 13:40:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242078AbjEONkU (ORCPT ); Mon, 15 May 2023 09:40:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52482 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242225AbjEONkO (ORCPT ); Mon, 15 May 2023 09:40:14 -0400 Received: from mga06.intel.com (mga06b.intel.com [134.134.136.31]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 315112690; Mon, 15 May 2023 06:40:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1684158013; x=1715694013; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=WP+yFp91mqP5IhHCOHfOiS43Cj02tZQHbOCUjxgaHRw=; b=nA3HG6Er6PDHP+F12Y+U35DswrBAhawpz/HK0Beoj2BBJrvaIWlQwwrz XqHgrfxscRSeOnZuJyXEo2VE4wUR0ZkfqKP8Ta7101D6wEImVk1WlH/z9 pxXipLQcU0ARKYCJ4hSfc1ME9CIn2EG3kcFNS1/H7ZCUhjFjnJTTs1a2K r2zRTEae4I9Te8mmSbJy9spPE8xXhpggcwn1TF69vvrpndzhmFrZuRX1t /O7/FHYlCvl4SOsxOruxufbR7EnW17hPDNpDkTzBfOG6PvJ0YJQukyGe1 TnGHsUhLX4r+3SRWZFHINVZRiuh8hTZUzB5nXLQXFrpNaws1Tq+mkNWh4 w==; X-IronPort-AV: E=McAfee;i="6600,9927,10711"; a="414598016" X-IronPort-AV: E=Sophos;i="5.99,276,1677571200"; d="scan'208";a="414598016" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 May 2023 06:39:59 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10711"; a="700964227" X-IronPort-AV: E=Sophos;i="5.99,276,1677571200"; d="scan'208";a="700964227" Received: from mattu-haswell.fi.intel.com ([10.237.72.199]) by orsmga002.jf.intel.com with ESMTP; 15 May 2023 06:39:57 -0700 From: Mathias Nyman To: Cc: , Mathias Nyman , stable@vger.kernel.org, Miller Hunter Subject: [PATCH 2/2] xhci: Fix incorrect tracking of free space on transfer rings Date: Mon, 15 May 2023 16:40:59 +0300 Message-Id: <20230515134059.161110-3-mathias.nyman@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230515134059.161110-1-mathias.nyman@linux.intel.com> References: <20230515134059.161110-1-mathias.nyman@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org This incorrect tracking caused unnecessary ring expansion in some usecases which over days of use consume a lot of memory. xhci driver tries to keep track of free transfer blocks (TRBs) on the ring buffer, but failed to add back some cancelled transfers that were turned into no-op operations instead of just moving past them. This can happen if there are several queued pending transfers which then are cancelled in reverse order. Solve this by counting the numer of steps we move the dequeue pointer once we complete a transfer, and add it to the number of free trbs instead of just adding the trb number of the current transfer. This way we ensure we count the no-op trbs on the way as well. Fixes: 55f6153d8cc8 ("xhci: remove extra loop in interrupt context") Cc: stable@vger.kernel.org Reported-by: Miller Hunter Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217242 Tested-by: Miller Hunter Signed-off-by: Mathias Nyman --- drivers/usb/host/xhci-ring.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 1ad12d5a4857..2bc82b3a2f98 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -276,6 +276,26 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, trace_xhci_inc_enq(ring); } +static int xhci_num_trbs_to(struct xhci_segment *start_seg, union xhci_trb *start, + struct xhci_segment *end_seg, union xhci_trb *end, + unsigned int num_segs) +{ + union xhci_trb *last_on_seg; + int num = 0; + int i = 0; + + do { + if (start_seg == end_seg && end >= start) + return num + (end - start); + last_on_seg = &start_seg->trbs[TRBS_PER_SEGMENT - 1]; + num += last_on_seg - start; + start_seg = start_seg->next; + start = start_seg->trbs; + } while (i++ <= num_segs); + + return -EINVAL; +} + /* * Check to see if there's room to enqueue num_trbs on the ring and make sure * enqueue pointer will not advance into dequeue segment. See rules above. @@ -2140,6 +2160,7 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, u32 trb_comp_code) { struct xhci_ep_ctx *ep_ctx; + int trbs_freed; ep_ctx = xhci_get_ep_ctx(xhci, ep->vdev->out_ctx, ep->ep_index); @@ -2209,9 +2230,15 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, } /* Update ring dequeue pointer */ + trbs_freed = xhci_num_trbs_to(ep_ring->deq_seg, ep_ring->dequeue, + td->last_trb_seg, td->last_trb, + ep_ring->num_segs); + if (trbs_freed < 0) + xhci_dbg(xhci, "Failed to count freed trbs at TD finish\n"); + else + ep_ring->num_trbs_free += trbs_freed; ep_ring->dequeue = td->last_trb; ep_ring->deq_seg = td->last_trb_seg; - ep_ring->num_trbs_free += td->num_trbs - 1; inc_deq(xhci, ep_ring); return xhci_td_cleanup(xhci, td, ep_ring, td->status);