From nobody Fri Dec 19 20:13:27 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 2476B157E63; Wed, 13 Mar 2024 16:47:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1710348439; cv=none; b=nJz8FRebA/Y4ikloQiIN6NHdU+9Fy65pvrie1pcJQ0/yQcDCMlI6khhAT6tY4HG3zBk1ALZwlG4h89sTmPtkmp3tfNTPY7f2N6KzXGFE3OeOJNGHHAolqKFmW5/hzjoa0tzIsrxI5eGw4I/J/V4Gsv3W1L2/CZkKcK9KqmFlo84= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1710348439; c=relaxed/simple; bh=RIVemwWILV1Ivhuy6i7UoQRPSNXn4l1ZvxG6KdWc4Ik=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XR+08yDgWZP8rCGOdHJsOMpt4LMDuRek2ZUbe2jNKVXZhVjSw+HHNnBi8vtJq0b7EWxzpYQnQVBSW4sb6cuSaMvpP1A3X79fJAX7XaHEsQraC4iiMCGnVRtjmjzjvjdWpDfBtOJ9LPd+T4QAaPSNDeebNde0RsfYCxq4tZ7cD/I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FaKQHxp0; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FaKQHxp0" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 05867C433B1; Wed, 13 Mar 2024 16:47:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1710348438; bh=RIVemwWILV1Ivhuy6i7UoQRPSNXn4l1ZvxG6KdWc4Ik=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FaKQHxp09dNWfWgSrVpxraTs37MFws+aJN24AJ8Cb+/tZ5XBqy+hJ6t9pOZ8SupFi KCY6k6qEXTs2vhaRtTB4VQwoKP4M3zWZ6An2Tn5jpz0iAHnfhoGPpjYIF4uOIfpkSM u8nX/xYSYwc4aFw6SkMoxU3e6AJuFz4ULEDG9RbwscPqksczNSHb9ZJg9h1/Zzf7xZ NJHlDbfBq0Tuig786P0uCsa792ZBtFYT5eL78q0LcqVSh9/QSAJJBnJpkYvnXPzuav sbL5vHGBseTrHXVpGhoXOTXESXMN5QDQgbsTEvZMmV5C/XuylrdXA3zgdJ93/czrYn AJKVsEPJDHavw== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Mathias Nyman , Greg Kroah-Hartman , Sasha Levin Subject: [PATCH 5.10 33/73] xhci: remove extra loop in interrupt context Date: Wed, 13 Mar 2024 12:46:00 -0400 Message-ID: <20240313164640.616049-34-sashal@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240313164640.616049-1-sashal@kernel.org> References: <20240313164640.616049-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-KernelTest-Patch: http://kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.213-rc1.gz X-KernelTest-Tree: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git X-KernelTest-Branch: linux-5.10.y X-KernelTest-Patches: git://git.kernel.org/pub/scm/linux/kernel/git/stable/stable-queue.git X-KernelTest-Version: 5.10.213-rc1 X-KernelTest-Deadline: 2024-03-15T16:46+00:00 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Mathias Nyman [ Upstream commit 55f6153d8cc8eff0852d108f80087fdf41dc2169 ] When finishing a TD we walk the endpoint dequeue trb pointer until it matches the last TRB of the TD. TDs can contain over 100 TRBs, meaning we call a function 100 times, do a few comparisons and increase a couple values for each of these calls, all in interrupt context. This can all be avoided by adding a pointer to the last TRB segment, and a number of TRBs in the TD. So instead of walking through each TRB just set the new dequeue segment, pointer, and number of free TRBs directly. Getting rid of the while loop also reduces the risk of getting stuck in a infinite loop in the interrupt handler. Loop relied on valid matching dequeue and last_trb values to break. Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20210129130044.206855-12-mathias.nyman@linu= x.intel.com Signed-off-by: Greg Kroah-Hartman Stable-dep-of: 5372c65e1311 ("xhci: process isoc TD properly when there was= a transaction error mid TD.") Signed-off-by: Sasha Levin --- drivers/usb/host/xhci-ring.c | 21 ++++++++++++++------- drivers/usb/host/xhci.h | 2 ++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index eb70f07e3623a..b814dc07116da 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2099,8 +2099,9 @@ static int finish_td(struct xhci_hcd *xhci, struct xh= ci_td *td, EP_HARD_RESET); } else { /* Update ring dequeue pointer */ - while (ep_ring->dequeue !=3D td->last_trb) - inc_deq(xhci, ep_ring); + ep_ring->dequeue =3D td->last_trb; + ep_ring->deq_seg =3D td->last_trb_seg; + ep_ring->num_trbs_free +=3D td->num_trbs - 1; inc_deq(xhci, ep_ring); } =20 @@ -2321,8 +2322,9 @@ static int skip_isoc_td(struct xhci_hcd *xhci, struct= xhci_td *td, frame->actual_length =3D 0; =20 /* Update ring dequeue pointer */ - while (ep->ring->dequeue !=3D td->last_trb) - inc_deq(xhci, ep->ring); + ep->ring->dequeue =3D td->last_trb; + ep->ring->deq_seg =3D td->last_trb_seg; + ep->ring->num_trbs_free +=3D td->num_trbs - 1; inc_deq(xhci, ep->ring); =20 return xhci_td_cleanup(xhci, td, ep->ring, status); @@ -3487,7 +3489,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t m= em_flags, field |=3D TRB_IOC; more_trbs_coming =3D false; td->last_trb =3D ring->enqueue; - + td->last_trb_seg =3D ring->enq_seg; if (xhci_urb_suitable_for_idt(urb)) { memcpy(&send_addr, urb->transfer_buffer, trb_buff_len); @@ -3513,7 +3515,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t m= em_flags, upper_32_bits(send_addr), length_field, field); - + td->num_trbs++; addr +=3D trb_buff_len; sent_len =3D trb_buff_len; =20 @@ -3537,8 +3539,10 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t = mem_flags, ep_index, urb->stream_id, 1, urb, 1, mem_flags); urb_priv->td[1].last_trb =3D ring->enqueue; + urb_priv->td[1].last_trb_seg =3D ring->enq_seg; field =3D TRB_TYPE(TRB_NORMAL) | ring->cycle_state | TRB_IOC; queue_trb(xhci, ring, 0, 0, 0, TRB_INTR_TARGET(0), field); + urb_priv->td[1].num_trbs++; } =20 check_trb_math(urb, enqd_len); @@ -3589,6 +3593,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t m= em_flags, =20 urb_priv =3D urb->hcpriv; td =3D &urb_priv->td[0]; + td->num_trbs =3D num_trbs; =20 /* * Don't give the first TRB to the hardware (by toggling the cycle bit) @@ -3661,6 +3666,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t m= em_flags, =20 /* Save the DMA address of the last TRB in the TD */ td->last_trb =3D ep_ring->enqueue; + td->last_trb_seg =3D ep_ring->enq_seg; =20 /* Queue status TRB - see Table 7 and sections 4.11.2.2 and 6.4.1.2.3 */ /* If the device sent data, the status stage is an OUT transfer */ @@ -3905,7 +3911,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, = gfp_t mem_flags, goto cleanup; } td =3D &urb_priv->td[i]; - + td->num_trbs =3D trbs_per_td; /* use SIA as default, if frame id is used overwrite it */ sia_frame_id =3D TRB_SIA; if (!(urb->transfer_flags & URB_ISO_ASAP) && @@ -3948,6 +3954,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, = gfp_t mem_flags, } else { more_trbs_coming =3D false; td->last_trb =3D ep_ring->enqueue; + td->last_trb_seg =3D ep_ring->enq_seg; field |=3D TRB_IOC; if (trb_block_event_intr(xhci, num_tds, i)) field |=3D TRB_BEI; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index bb3c362a194b2..85ab213c7940a 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1550,9 +1550,11 @@ struct xhci_td { struct xhci_segment *start_seg; union xhci_trb *first_trb; union xhci_trb *last_trb; + struct xhci_segment *last_trb_seg; struct xhci_segment *bounce_seg; /* actual_length of the URB has already been set */ bool urb_length_set; + unsigned int num_trbs; }; =20 /* xHCI command default timeout value */ --=20 2.43.0