From patchwork Fri Oct 25 11:27:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Neronin X-Patchwork-Id: 13850547 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 640881FBF66 for ; Fri, 25 Oct 2024 11:28:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.10 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729855683; cv=none; b=AD6ZyFxEMDgiWNDJTc9BRQCkOcCBwPfIy5vvBOOKEW3Eb2yNP/08e0BfZ6DqwnQ5cD9meWmdgkFrFnKV6PmGeBvDikjztTxo71d5uw6vCLMl9YIKSNQM1vwy5R02hoCDOA9EQjhacWfyZZeaoH9MymDa2QkRDX+uDAqW5Rj8H4g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729855683; c=relaxed/simple; bh=MM677giUgOH6Uk13G2JwgP4NkOeaA71KmmEEiSUmJOA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AS6ao18gvkgDl2t+e0Y+RwQKtX72gWo9kWS1MRDYq7pLTuc2rXrfh6igpqAB82Jc38n5++t+b/CUqbHyOrQFwkidilkFLtTysbT0m7kmvwEXPbfWc88FoVPnWvdYf9yDdKWhTYvdKrk1dDsrtyNBD0zhChe10JsRB3oV8FAPg7w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=SxGcJZQp; arc=none smtp.client-ip=192.198.163.10 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="SxGcJZQp" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1729855681; x=1761391681; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=MM677giUgOH6Uk13G2JwgP4NkOeaA71KmmEEiSUmJOA=; b=SxGcJZQpIrwGRIJkdKO0rSD9eQh5rHO7AincWWG0djPwmSf0dhi/bnyn VEqQQ174FljtgDdgLRbhcg8Tc9pDUkPEGxkBWO4sWk46CzMGlAU+s5/8u Xk4WVQTD/gVTWGu4LZSxTOOVrnSwS1HA2FPbwm1RD8aNQgecP16mvTuQE jDMe/Jl0hK/OHVL8wYN7vGYFoB+0hAIs9XgIt3BBtKbot1fcjwEdXYyq4 r7WJV0youyk5SbSTnvgImswATnn6yloMYQADLKzMcyLlaqGc9SjG7petn F2TKkS5Rxye4qn/mBAX6+LzzH6wSryQbiJ7vzdEeJi1wuH06x/GTFqZvv Q==; X-CSE-ConnectionGUID: Ss/lrF2uQwGkxpfQ/Og4kw== X-CSE-MsgGUID: /aTDu86RTbmFUHGX9c+sDw== X-IronPort-AV: E=McAfee;i="6700,10204,11236"; a="40896753" X-IronPort-AV: E=Sophos;i="6.11,231,1725346800"; d="scan'208";a="40896753" Received: from fmviesa001.fm.intel.com ([10.60.135.141]) by fmvoesa104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Oct 2024 04:28:01 -0700 X-CSE-ConnectionGUID: R9qw+M17Qv607L1dxFnEWQ== X-CSE-MsgGUID: TuymiUWQR8aL+RQ/p6VU+A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.11,231,1725346800"; d="scan'208";a="111699179" Received: from black.fi.intel.com ([10.237.72.28]) by fmviesa001.fm.intel.com with ESMTP; 25 Oct 2024 04:28:00 -0700 Received: by black.fi.intel.com (Postfix, from userid 1058) id 94D9A35B; Fri, 25 Oct 2024 14:27:58 +0300 (EEST) From: Niklas Neronin To: mathias.nyman@linux.intel.com Cc: linux-usb@vger.kernel.org, Niklas Neronin Subject: [PATCH 1/2] usb: xhci: improve HCD page size validation and setting Date: Fri, 25 Oct 2024 14:27:00 +0300 Message-ID: <20241025112701.303035-2-niklas.neronin@linux.intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241025112701.303035-1-niklas.neronin@linux.intel.com> References: <20241025112701.303035-1-niklas.neronin@linux.intel.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 xHC supports a page size of (2^(n+12)), where 'n' is the Page Size Bit. The page size of 4096 bytes is common and always supported. Consequently, the xHCI driver always sets the 'page_size' to 4096 (i.e., (1 << 12)). At present, the xHCI driver reads the Page Size register but does not use the value, except for printing a two useless debug traces. This introduces unnecessary code into xhci_mem_init(), which is already quite large. Although the page size is not currently modified, it may be in the future. To balance both current and future needs, the page size setting code is moved to a separate function. This rework ensures that the Page Size register is not read for the minimum value (4096). However, if a different value is provided, it will not be ignored, rather clamped between the valid min and max page size. Signed-off-by: Niklas Neronin --- drivers/usb/host/xhci-mem.c | 40 ++++++++++++++++++++++--------------- drivers/usb/host/xhci.h | 9 ++++++--- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index d2900197a49e..8a6b91862cae 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1959,7 +1959,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci->interrupters = NULL; xhci->page_size = 0; - xhci->page_shift = 0; xhci->usb2_rhub.bus_state.bus_suspended = 0; xhci->usb3_rhub.bus_state.bus_suspended = 0; } @@ -2378,6 +2377,27 @@ xhci_create_secondary_interrupter(struct usb_hcd *hcd, unsigned int segs, } EXPORT_SYMBOL_GPL(xhci_create_secondary_interrupter); +static void xhci_hcd_page_size(struct xhci_hcd *xhci) +{ + u32 page_size; + + if (xhci->page_size <= HCD_PAGE_MIN) { + xhci->page_size = HCD_PAGE_MIN; + } else { + /* Max page size is 2^(n+12), where 'n' is the first 15:0 bit set */ + page_size = readl(&xhci->op_regs->page_size) & HCD_PAGE_SIZE_MASK; + page_size = 1 << (ffs(page_size) + 12); + + if (page_size < xhci->page_size) + xhci->page_size = page_size; + else + xhci->page_size = (1 << ffs(xhci->page_size)); + } + + xhci_dbg_trace(xhci, trace_xhci_dbg_init, "HCD page size set to %iK", + xhci->page_size / 1024); +} + int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) { struct xhci_interrupter *ir; @@ -2385,7 +2405,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) dma_addr_t dma; unsigned int val, val2; u64 val_64; - u32 page_size, temp; + u32 temp; int i; INIT_LIST_HEAD(&xhci->cmd_list); @@ -2394,20 +2414,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) INIT_DELAYED_WORK(&xhci->cmd_timer, xhci_handle_command_timeout); init_completion(&xhci->cmd_ring_stop_completion); - page_size = readl(&xhci->op_regs->page_size); - xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "Supported page size register = 0x%x", page_size); - i = ffs(page_size); - if (i < 16) - xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "Supported page size of %iK", (1 << (i+12)) / 1024); - else - xhci_warn(xhci, "WARN: no supported page size\n"); - /* Use 4K pages, since that's common and the minimum the HC supports */ - xhci->page_shift = 12; - xhci->page_size = 1 << xhci->page_shift; - xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "HCD page size set to %iK", xhci->page_size / 1024); + /* If 'page_size' is not set, use 4K pages, since that's common and always supported */ + xhci_hcd_page_size(xhci); /* * Program the Number of Device Slots Enabled field in the CONFIG diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index f0fb696d5619..f998df70f80f 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -211,6 +211,11 @@ struct xhci_op_regs { #define CONFIG_CIE (1 << 9) /* bits 10:31 - reserved and should be preserved */ +/* bits 15:0 - HCD page shift bit */ +#define HCD_PAGE_SIZE_MASK 0xffff +/* HCD page size 4KB up to 128MB, Rev 1.2 Section 5.4.3. */ +#define HCD_PAGE_MIN (1 << 12) + /** * struct xhci_intr_reg - Interrupt Register Set * @irq_pending: IMAN - Interrupt Management Register. Used to enable @@ -1502,10 +1507,8 @@ struct xhci_hcd { u16 max_interrupters; /* imod_interval in ns (I * 250ns) */ u32 imod_interval; - /* 4KB min, 128MB max */ + /* Always set to HCD_PAGE_MIN (4KB) */ int page_size; - /* Valid values are 12 to 20, inclusive */ - int page_shift; /* MSI-X/MSI vectors */ int nvecs; /* optional clocks */ From patchwork Fri Oct 25 11:27:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Neronin X-Patchwork-Id: 13850548 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5D6662003DC for ; Fri, 25 Oct 2024 11:28:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.10 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729855684; cv=none; b=oZtUEh14IRIcwUc3dQBEHVaDHc5SuJh4BMuGdrvIHAMGYh6Y8s7Y0A5HJ91NsVVkAqXTTNc9akQwE3krX4skuKGZnMF1IGSaO3w5Es+PCm7RetymlQnmjn7dcBi9OUMeY+3Lit+d1EvPvr/jsGZ/kHq50AB7W/l67mlLCeS/1d8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729855684; c=relaxed/simple; bh=r4EEMBMHZuNDL9Gs8ckr2W0jEOA8g5BohUX00x84UYs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=etnZbTPnYbNsy3mUorU/AL2vaARpp0veZq9TA/+gZznfH4wVtqEDYhZuXYOaSwiUaWkKZTZiyrkDjL+1tnkQOz1+/Sryk+EDu+s5lSFeJAdjBVD+V8DjyvNu4tMgbImjM7CMmFmSCwFVjlZXX666qH6DaGWW/T+qbSmcdkDo/v0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com; spf=none smtp.mailfrom=linux.intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=hk56Qulf; arc=none smtp.client-ip=192.198.163.10 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="hk56Qulf" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1729855682; x=1761391682; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=r4EEMBMHZuNDL9Gs8ckr2W0jEOA8g5BohUX00x84UYs=; b=hk56QulfE04AeOAjOxAd6sdT1bjnbV7x7Tv/KujuiIL0JDweLFoDo5PE 8xPxq7ZrptDu6G5F8YqP7STkmPso7vL0QY5yQmJG2/CJlbCSvMt9+QWqZ w01YRK/A4HUwqUwPz2VNneRqo1V07JoJ/8/opkMl3XyGco2GzTPCt4bEc aY2hVlI5rzdpG5y/qcaSP3fOLaJIHheoQ54AQVcp7WKRnD9RVMCdf61nd 8a6SfdtCyp68Or+5x85FNWgLHVnoPTdwIOjhCufowWKLJGug5bcF7d2NU EVCRlWf+fwwUptz1sDPO5XKN1uUrXnGIVxzuajrcXU27lWWHf7ktLddV2 Q==; X-CSE-ConnectionGUID: en5HwbPmR/WXTXyrbdiBVg== X-CSE-MsgGUID: NtPkALZVR3SfDXBWBfcRHg== X-IronPort-AV: E=McAfee;i="6700,10204,11236"; a="40896762" X-IronPort-AV: E=Sophos;i="6.11,231,1725346800"; d="scan'208";a="40896762" Received: from fmviesa001.fm.intel.com ([10.60.135.141]) by fmvoesa104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Oct 2024 04:28:02 -0700 X-CSE-ConnectionGUID: /NKfd8miT6CRHlWCnG+GBw== X-CSE-MsgGUID: KgmarfUuRbGor+dsjPRyfw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.11,231,1725346800"; d="scan'208";a="111699182" Received: from black.fi.intel.com ([10.237.72.28]) by fmviesa001.fm.intel.com with ESMTP; 25 Oct 2024 04:28:01 -0700 Received: by black.fi.intel.com (Postfix, from userid 1058) id D4C5735E; Fri, 25 Oct 2024 14:27:59 +0300 (EEST) From: Niklas Neronin To: mathias.nyman@linux.intel.com Cc: linux-usb@vger.kernel.org, Niklas Neronin Subject: [PATCH 2/2] usb: xhci: improve xhci_set_interrupter_moderation() Date: Fri, 25 Oct 2024 14:27:01 +0300 Message-ID: <20241025112701.303035-3-niklas.neronin@linux.intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241025112701.303035-1-niklas.neronin@linux.intel.com> References: <20241025112701.303035-1-niklas.neronin@linux.intel.com> Precedence: bulk X-Mailing-List: linux-usb@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The function sets the interrupt moderation interval through the IMODI 16-bit register, where the interval is represented in increments of 250 nanoseconds. For example, an IMODI register value of 16 is multiplied by 250 to get 4000 nanoseconds, resulting in an interrupt every ~1ms. Currently, the function has the potential to fail, but this failure is not handled, and the xhci driver proceeds as usual. Fix the issue by removing the possibility of failure. Instead, the IMODI is set to the closest valid value. Signed-off-by: Niklas Neronin --- drivers/usb/host/xhci-mem.c | 5 +---- drivers/usb/host/xhci.c | 25 +++++++++++++------------ drivers/usb/host/xhci.h | 4 ++-- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 8a6b91862cae..7355ca85e1b3 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -2365,10 +2365,7 @@ xhci_create_secondary_interrupter(struct usb_hcd *hcd, unsigned int segs, return NULL; } - err = xhci_set_interrupter_moderation(ir, imod_interval); - if (err) - xhci_warn(xhci, "Failed to set interrupter %d moderation to %uns\n", - i, imod_interval); + xhci_set_interrupter_moderation(xhci, ir, imod_interval); xhci_dbg(xhci, "Add secondary interrupter %d, max interrupters %d\n", i, xhci->max_interrupters); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 899c0effb5d3..9bf5d2e09c60 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -346,21 +346,22 @@ static int xhci_disable_interrupter(struct xhci_interrupter *ir) return 0; } -/* interrupt moderation interval imod_interval in nanoseconds */ -int xhci_set_interrupter_moderation(struct xhci_interrupter *ir, - u32 imod_interval) +/* Interrupt moderation interval in 250 nanoseconds increments, 0 means no interrupt throttling. */ +void xhci_set_interrupter_moderation(struct xhci_hcd *xhci, struct xhci_interrupter *ir, + u32 imod_interval) { - u32 imod; + u32 irq_control; - if (!ir || !ir->ir_set || imod_interval > U16_MAX * 250) - return -EINVAL; + imod_interval /= 250; + imod_interval = min(imod_interval, U16_MAX); - imod = readl(&ir->ir_set->irq_control); - imod &= ~ER_IRQ_INTERVAL_MASK; - imod |= (imod_interval / 250) & ER_IRQ_INTERVAL_MASK; - writel(imod, &ir->ir_set->irq_control); + irq_control = readl(&ir->ir_set->irq_control); + irq_control &= ~ER_IRQ_INTERVAL_MASK; + irq_control |= imod_interval & ER_IRQ_INTERVAL_MASK; + writel(irq_control, &ir->ir_set->irq_control); - return 0; + xhci_dbg(xhci, "Interrupt moderation interval set to %uns for interrupt %u\n", + imod_interval * 250, ir->intr_num); } static void compliance_mode_recovery(struct timer_list *t) @@ -567,7 +568,7 @@ int xhci_run(struct usb_hcd *hcd) xhci_dbg_trace(xhci, trace_xhci_dbg_init, "ERST deq = 64'h%0lx", (long unsigned int) temp_64); - xhci_set_interrupter_moderation(ir, xhci->imod_interval); + xhci_set_interrupter_moderation(xhci, ir, xhci->imod_interval); if (xhci->quirks & XHCI_NEC_HOST) { struct xhci_command *command; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index f998df70f80f..8a47cb059582 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1871,8 +1871,8 @@ int xhci_alloc_tt_info(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, struct usb_device *hdev, struct usb_tt *tt, gfp_t mem_flags); -int xhci_set_interrupter_moderation(struct xhci_interrupter *ir, - u32 imod_interval); +void xhci_set_interrupter_moderation(struct xhci_hcd *xhci, struct xhci_interrupter *ir, + u32 imod_interval); /* xHCI ring, segment, TRB, and TD functions */ dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, union xhci_trb *trb);