mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Orgad Shaneh <orgads@gmail.com>
To: gregkh@linuxfoundation.org
Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v2] usb: octeon-hcd: keep SOF interrupts while a pipe needs them
Date: Sun, 11 Oct 2026 08:05:06 +0000	[thread overview]
Message-ID: <20261011080506.2394708-1-orgads@gmail.com> (raw)
In-Reply-To: <20261011072236.2381546-1-orgads@gmail.com>

cvmx_usb_schedule() now sleeps on an hrtimer until the nearest future
periodic deadline instead of counting frames down on every SOF. The scan
that finds that deadline only looks at pipes with

	next_tx_frame > usb->frame_number

which is right for picking the deadline, but two kinds of pipe that
need a SOF to make progress are invisible to the decision:

- A periodic pipe that is due and was *not* started: no idle hardware
  channel this round, its split window is closed
  (cvmx_usb_find_ready_pipe() rejects both), or another pipe owns
  usb->active_split. cvmx_usb_next_pipe() looks at the isochronous and
  interrupt lists only when is_sof is true.

- Any pipe that has sent its start split and waits for the frame its
  split complete may go out in (split_sc_frame, also checked by
  cvmx_usb_find_ready_pipe()). A control or bulk pipe on a full or low
  speed device behind a hub is in this state between its two halves, and
  with SOF masked nothing guarantees an interrupt that brings
  frame_number there.

When some other periodic pipe sets a far deadline - a hub's status pipe,
whenever a hub is attached - the driver masks SOF, arms the timer for
that deadline and these pipes wait for it. That is hundreds of frames;
the code allows up to 8000 (one second) before it falls back to SOF.

Before the hrtimer this could not happen: any pipe with a future
deadline set need_sof, so SOF stayed enabled every frame and the pipe
was retried on the next one.

Note such a pipe and keep SOF enabled while there is one, whether or not
another pipe has a future deadline. Nothing changes when there is none,
which is the case the timer was added for.

Other control and bulk pipes are excluded deliberately: their
next_tx_frame is not updated on completion, so they are almost always
"due" and would keep SOF enabled permanently.

Fixes: aebbc7d63407 ("usb: octeon-hcd: sleep on an hrtimer for far-off periodic transfers")
Assisted-by: LLM
Signed-off-by: Orgad Shaneh <orgads@gmail.com>
---
v2: the Sashiko review bot found that v1 missed two cases:
 - due_now was only looked at when some pipe had a future deadline, so
   a due pipe with none still left SOF masked;
 - a control or bulk pipe waiting for its split complete is in the same
   position as a due periodic pipe, but v1 excluded all control and bulk
   pipes. split_sc_frame tells these apart from the always-due ones.
 Compile-tested only: there is no full or low speed device behind a hub
 on the test board, so the split path is not exercised.
v1: https://lore.kernel.org/all/20260915081724.25637-1-orgads@gmail.com/
    and the resend 20261011072236.2381546-1-orgads@gmail.com

diff --git a/drivers/usb/host/octeon-hcd.c b/drivers/usb/host/octeon-hcd.c
index 256e459..9477a1d 100644
--- a/drivers/usb/host/octeon-hcd.c
+++ b/drivers/usb/host/octeon-hcd.c
@@ -1923,6 +1923,7 @@ static void cvmx_usb_schedule(struct octeon_hcd *usb, int is_sof)
 	struct cvmx_usb_pipe *pipe;
 	int need_sof;
 	u64 min_due;
+	bool due_now;
 	enum cvmx_usb_transfer ttype;
 
 	if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) {
@@ -1964,15 +1965,32 @@ done:
 	 */
 	need_sof = 0;
 	min_due = ~0ull;
+	due_now = false;
 	for (ttype = CVMX_USB_TRANSFER_CONTROL;
 	     ttype <= CVMX_USB_TRANSFER_INTERRUPT; ttype++) {
 		list_for_each_entry(pipe, &usb->active_pipes[ttype], node) {
+			/*
+			 * Do not sleep past a pipe that is only retried from a
+			 * SOF: a periodic one that is due but was not started
+			 * (no idle channel, closed split window, another pipe's
+			 * split active), or any pipe waiting for the frame its
+			 * split complete may go out in. Other control and bulk
+			 * pipes are left out: their next_tx_frame is not updated
+			 * on completion, so they always look due.
+			 */
+			if (pipe->split_sc_frame != -1 ||
+			    (pipe->next_tx_frame <= usb->frame_number &&
+			     (ttype == CVMX_USB_TRANSFER_ISOCHRONOUS ||
+			      ttype == CVMX_USB_TRANSFER_INTERRUPT)))
+				due_now = true;
 			if (pipe->next_tx_frame > usb->frame_number &&
 			    pipe->next_tx_frame < min_due)
 				min_due = pipe->next_tx_frame;
 		}
 	}
-	if (min_due != ~0ull) {
+	if (due_now) {
+		need_sof = 1;
+	} else if (min_due != ~0ull) {
 		u64 delta = min_due - usb->frame_number;
 
 		/*

      reply	other threads:[~2026-10-11  8:05 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-11  7:22 [PATCH RESEND] usb: octeon-hcd: keep SOF interrupts while a periodic pipe is due Orgad Shaneh
2026-10-11  8:05 ` Orgad Shaneh [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=20261011080506.2394708-1-orgads@gmail.com \
    --to=orgads@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®