]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - queue-5.10/usb-dwc2-host-fix-isoc-flow-in-ddma-mode.patch
Fixes for 5.10
[thirdparty/kernel/stable-queue.git] / queue-5.10 / usb-dwc2-host-fix-isoc-flow-in-ddma-mode.patch
CommitLineData
30daf967
GKH
1From b258e42688501cadb1a6dd658d6f015df9f32d8f Mon Sep 17 00:00:00 2001
2From: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
3Date: Wed, 13 Mar 2024 09:21:32 +0000
4Subject: usb: dwc2: host: Fix ISOC flow in DDMA mode
5
6From: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
7
8commit b258e42688501cadb1a6dd658d6f015df9f32d8f upstream.
9
10Fixed ISOC completion flow in DDMA mode. Added isoc
11descriptor actual length value and update urb's start_frame
12value.
13Fixed initialization of ISOC DMA descriptors flow.
14
15Fixes: 56f5b1cff22a ("staging: Core files for the DWC2 driver")
16Fixes: 20f2eb9c4cf8 ("staging: dwc2: add microframe scheduler from downstream Pi kernel")
17Fixes: c17b337c1ea4 ("usb: dwc2: host: program descriptor for next frame")
18Fixes: dc4c76e7b22c ("staging: HCD descriptor DMA support for the DWC2 driver")
19Fixes: 762d3a1a9cd7 ("usb: dwc2: host: process all completed urbs")
20CC: stable@vger.kernel.org
21Signed-off-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
22Link: https://lore.kernel.org/r/a8b1e1711cc6cabfb45d92ede12e35445c66f06c.1708944698.git.Minas.Harutyunyan@synopsys.com
23Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
24---
25 drivers/usb/dwc2/hcd.c | 12 ++++++++++--
26 drivers/usb/dwc2/hcd_ddma.c | 17 +++++++++++------
27 drivers/usb/dwc2/hw.h | 2 +-
28 3 files changed, 22 insertions(+), 9 deletions(-)
29
30--- a/drivers/usb/dwc2/hcd.c
31+++ b/drivers/usb/dwc2/hcd.c
32@@ -2736,8 +2736,11 @@ enum dwc2_transaction_type dwc2_hcd_sele
33 hsotg->available_host_channels--;
34 }
35 qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry);
36- if (dwc2_assign_and_init_hc(hsotg, qh))
37+ if (dwc2_assign_and_init_hc(hsotg, qh)) {
38+ if (hsotg->params.uframe_sched)
39+ hsotg->available_host_channels++;
40 break;
41+ }
42
43 /*
44 * Move the QH from the periodic ready schedule to the
45@@ -2770,8 +2773,11 @@ enum dwc2_transaction_type dwc2_hcd_sele
46 hsotg->available_host_channels--;
47 }
48
49- if (dwc2_assign_and_init_hc(hsotg, qh))
50+ if (dwc2_assign_and_init_hc(hsotg, qh)) {
51+ if (hsotg->params.uframe_sched)
52+ hsotg->available_host_channels++;
53 break;
54+ }
55
56 /*
57 * Move the QH from the non-periodic inactive schedule to the
58@@ -4125,6 +4131,8 @@ void dwc2_host_complete(struct dwc2_hsot
59 urb->actual_length);
60
61 if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
62+ if (!hsotg->params.dma_desc_enable)
63+ urb->start_frame = qtd->qh->start_active_frame;
64 urb->error_count = dwc2_hcd_urb_get_error_count(qtd->urb);
65 for (i = 0; i < urb->number_of_packets; ++i) {
66 urb->iso_frame_desc[i].actual_length =
67--- a/drivers/usb/dwc2/hcd_ddma.c
68+++ b/drivers/usb/dwc2/hcd_ddma.c
69@@ -589,7 +589,7 @@ static void dwc2_init_isoc_dma_desc(stru
70 idx = qh->td_last;
71 inc = qh->host_interval;
72 hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg);
73- cur_idx = dwc2_frame_list_idx(hsotg->frame_number);
74+ cur_idx = idx;
75 next_idx = dwc2_desclist_idx_inc(qh->td_last, inc, qh->dev_speed);
76
77 /*
78@@ -896,6 +896,8 @@ static int dwc2_cmpl_host_isoc_dma_desc(
79 {
80 struct dwc2_dma_desc *dma_desc;
81 struct dwc2_hcd_iso_packet_desc *frame_desc;
82+ u16 frame_desc_idx;
83+ struct urb *usb_urb = qtd->urb->priv;
84 u16 remain = 0;
85 int rc = 0;
86
87@@ -908,8 +910,11 @@ static int dwc2_cmpl_host_isoc_dma_desc(
88 DMA_FROM_DEVICE);
89
90 dma_desc = &qh->desc_list[idx];
91+ frame_desc_idx = (idx - qtd->isoc_td_first) & (usb_urb->number_of_packets - 1);
92
93- frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last];
94+ frame_desc = &qtd->urb->iso_descs[frame_desc_idx];
95+ if (idx == qtd->isoc_td_first)
96+ usb_urb->start_frame = dwc2_hcd_get_frame_number(hsotg);
97 dma_desc->buf = (u32)(qtd->urb->dma + frame_desc->offset);
98 if (chan->ep_is_in)
99 remain = (dma_desc->status & HOST_DMA_ISOC_NBYTES_MASK) >>
100@@ -930,7 +935,7 @@ static int dwc2_cmpl_host_isoc_dma_desc(
101 frame_desc->status = 0;
102 }
103
104- if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
105+ if (++qtd->isoc_frame_index == usb_urb->number_of_packets) {
106 /*
107 * urb->status is not used for isoc transfers here. The
108 * individual frame_desc status are used instead.
109@@ -1035,11 +1040,11 @@ static void dwc2_complete_isoc_xfer_ddma
110 return;
111 idx = dwc2_desclist_idx_inc(idx, qh->host_interval,
112 chan->speed);
113- if (!rc)
114+ if (rc == 0)
115 continue;
116
117- if (rc == DWC2_CMPL_DONE)
118- break;
119+ if (rc == DWC2_CMPL_DONE || rc == DWC2_CMPL_STOP)
120+ goto stop_scan;
121
122 /* rc == DWC2_CMPL_STOP */
123
124--- a/drivers/usb/dwc2/hw.h
125+++ b/drivers/usb/dwc2/hw.h
126@@ -727,7 +727,7 @@
127 #define TXSTS_QTOP_TOKEN_MASK (0x3 << 25)
128 #define TXSTS_QTOP_TOKEN_SHIFT 25
129 #define TXSTS_QTOP_TERMINATE BIT(24)
130-#define TXSTS_QSPCAVAIL_MASK (0xff << 16)
131+#define TXSTS_QSPCAVAIL_MASK (0x7f << 16)
132 #define TXSTS_QSPCAVAIL_SHIFT 16
133 #define TXSTS_FSPCAVAIL_MASK (0xffff << 0)
134 #define TXSTS_FSPCAVAIL_SHIFT 0