Commit b258e426 authored by Minas Harutyunyan's avatar Minas Harutyunyan Committed by Greg Kroah-Hartman

usb: dwc2: host: Fix ISOC flow in DDMA mode

Fixed ISOC completion flow in DDMA mode. Added isoc
descriptor actual length value and update urb's start_frame
value.
Fixed initialization of ISOC DMA descriptors flow.

Fixes: 56f5b1cf ("staging: Core files for the DWC2 driver")
Fixes: 20f2eb9c ("staging: dwc2: add microframe scheduler from downstream Pi kernel")
Fixes: c17b337c ("usb: dwc2: host: program descriptor for next frame")
Fixes: dc4c76e7 ("staging: HCD descriptor DMA support for the DWC2 driver")
Fixes: 762d3a1a ("usb: dwc2: host: process all completed urbs")
CC: stable@vger.kernel.org
Signed-off-by: default avatarMinas Harutyunyan <Minas.Harutyunyan@synopsys.com>
Link: https://lore.kernel.org/r/a8b1e1711cc6cabfb45d92ede12e35445c66f06c.1708944698.git.Minas.Harutyunyan@synopsys.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent bae2bc73
...@@ -2701,8 +2701,11 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions( ...@@ -2701,8 +2701,11 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions(
hsotg->available_host_channels--; hsotg->available_host_channels--;
} }
qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry); qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry);
if (dwc2_assign_and_init_hc(hsotg, qh)) if (dwc2_assign_and_init_hc(hsotg, qh)) {
if (hsotg->params.uframe_sched)
hsotg->available_host_channels++;
break; break;
}
/* /*
* Move the QH from the periodic ready schedule to the * Move the QH from the periodic ready schedule to the
...@@ -2735,8 +2738,11 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions( ...@@ -2735,8 +2738,11 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions(
hsotg->available_host_channels--; hsotg->available_host_channels--;
} }
if (dwc2_assign_and_init_hc(hsotg, qh)) if (dwc2_assign_and_init_hc(hsotg, qh)) {
if (hsotg->params.uframe_sched)
hsotg->available_host_channels++;
break; break;
}
/* /*
* Move the QH from the non-periodic inactive schedule to the * Move the QH from the non-periodic inactive schedule to the
...@@ -4143,6 +4149,8 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, ...@@ -4143,6 +4149,8 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
urb->actual_length); urb->actual_length);
if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
if (!hsotg->params.dma_desc_enable)
urb->start_frame = qtd->qh->start_active_frame;
urb->error_count = dwc2_hcd_urb_get_error_count(qtd->urb); urb->error_count = dwc2_hcd_urb_get_error_count(qtd->urb);
for (i = 0; i < urb->number_of_packets; ++i) { for (i = 0; i < urb->number_of_packets; ++i) {
urb->iso_frame_desc[i].actual_length = urb->iso_frame_desc[i].actual_length =
......
...@@ -559,7 +559,7 @@ static void dwc2_init_isoc_dma_desc(struct dwc2_hsotg *hsotg, ...@@ -559,7 +559,7 @@ static void dwc2_init_isoc_dma_desc(struct dwc2_hsotg *hsotg,
idx = qh->td_last; idx = qh->td_last;
inc = qh->host_interval; inc = qh->host_interval;
hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg); hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg);
cur_idx = dwc2_frame_list_idx(hsotg->frame_number); cur_idx = idx;
next_idx = dwc2_desclist_idx_inc(qh->td_last, inc, qh->dev_speed); next_idx = dwc2_desclist_idx_inc(qh->td_last, inc, qh->dev_speed);
/* /*
...@@ -866,6 +866,8 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg, ...@@ -866,6 +866,8 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
{ {
struct dwc2_dma_desc *dma_desc; struct dwc2_dma_desc *dma_desc;
struct dwc2_hcd_iso_packet_desc *frame_desc; struct dwc2_hcd_iso_packet_desc *frame_desc;
u16 frame_desc_idx;
struct urb *usb_urb = qtd->urb->priv;
u16 remain = 0; u16 remain = 0;
int rc = 0; int rc = 0;
...@@ -878,8 +880,11 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg, ...@@ -878,8 +880,11 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
dma_desc = &qh->desc_list[idx]; dma_desc = &qh->desc_list[idx];
frame_desc_idx = (idx - qtd->isoc_td_first) & (usb_urb->number_of_packets - 1);
frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last]; frame_desc = &qtd->urb->iso_descs[frame_desc_idx];
if (idx == qtd->isoc_td_first)
usb_urb->start_frame = dwc2_hcd_get_frame_number(hsotg);
dma_desc->buf = (u32)(qtd->urb->dma + frame_desc->offset); dma_desc->buf = (u32)(qtd->urb->dma + frame_desc->offset);
if (chan->ep_is_in) if (chan->ep_is_in)
remain = (dma_desc->status & HOST_DMA_ISOC_NBYTES_MASK) >> remain = (dma_desc->status & HOST_DMA_ISOC_NBYTES_MASK) >>
...@@ -900,7 +905,7 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg, ...@@ -900,7 +905,7 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
frame_desc->status = 0; frame_desc->status = 0;
} }
if (++qtd->isoc_frame_index == qtd->urb->packet_count) { if (++qtd->isoc_frame_index == usb_urb->number_of_packets) {
/* /*
* urb->status is not used for isoc transfers here. The * urb->status is not used for isoc transfers here. The
* individual frame_desc status are used instead. * individual frame_desc status are used instead.
...@@ -1005,11 +1010,11 @@ static void dwc2_complete_isoc_xfer_ddma(struct dwc2_hsotg *hsotg, ...@@ -1005,11 +1010,11 @@ static void dwc2_complete_isoc_xfer_ddma(struct dwc2_hsotg *hsotg,
return; return;
idx = dwc2_desclist_idx_inc(idx, qh->host_interval, idx = dwc2_desclist_idx_inc(idx, qh->host_interval,
chan->speed); chan->speed);
if (!rc) if (rc == 0)
continue; continue;
if (rc == DWC2_CMPL_DONE) if (rc == DWC2_CMPL_DONE || rc == DWC2_CMPL_STOP)
break; goto stop_scan;
/* rc == DWC2_CMPL_STOP */ /* rc == DWC2_CMPL_STOP */
......
...@@ -698,7 +698,7 @@ ...@@ -698,7 +698,7 @@
#define TXSTS_QTOP_TOKEN_MASK (0x3 << 25) #define TXSTS_QTOP_TOKEN_MASK (0x3 << 25)
#define TXSTS_QTOP_TOKEN_SHIFT 25 #define TXSTS_QTOP_TOKEN_SHIFT 25
#define TXSTS_QTOP_TERMINATE BIT(24) #define TXSTS_QTOP_TERMINATE BIT(24)
#define TXSTS_QSPCAVAIL_MASK (0xff << 16) #define TXSTS_QSPCAVAIL_MASK (0x7f << 16)
#define TXSTS_QSPCAVAIL_SHIFT 16 #define TXSTS_QSPCAVAIL_SHIFT 16
#define TXSTS_FSPCAVAIL_MASK (0xffff << 0) #define TXSTS_FSPCAVAIL_MASK (0xffff << 0)
#define TXSTS_FSPCAVAIL_SHIFT 0 #define TXSTS_FSPCAVAIL_SHIFT 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment