All of lore.kernel.org
 help / color / mirror / Atom feed
From: Niklas Neronin <niklas.neronin@linux.intel.com>
To: mathias.nyman@linux.intel.com
Cc: linux-usb@vger.kernel.org,
	Niklas Neronin <niklas.neronin@linux.intel.com>
Subject: [PATCH 2/2] usb: xhci: improve xhci_set_interrupter_moderation()
Date: Fri, 25 Oct 2024 14:27:01 +0300	[thread overview]
Message-ID: <20241025112701.303035-3-niklas.neronin@linux.intel.com> (raw)
In-Reply-To: <20241025112701.303035-1-niklas.neronin@linux.intel.com>

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 <niklas.neronin@linux.intel.com>
---
 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);
-- 
2.45.2


      parent reply	other threads:[~2024-10-25 11:28 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-25 11:26 [PATCH 0/2] usb: xhci: improve HCD page size & IMODI Niklas Neronin
2024-10-25 11:27 ` [PATCH 1/2] usb: xhci: improve HCD page size validation and setting Niklas Neronin
2024-10-28 13:13   ` Mathias Nyman
2024-10-25 11:27 ` Niklas Neronin [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20241025112701.303035-3-niklas.neronin@linux.intel.com \
    --to=niklas.neronin@linux.intel.com \
    --cc=linux-usb@vger.kernel.org \
    --cc=mathias.nyman@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.