Skip to content

Commit b258e42

Browse files
Minas Harutyunyangregkh
authored andcommitted
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: 56f5b1c ("staging: Core files for the DWC2 driver") Fixes: 20f2eb9 ("staging: dwc2: add microframe scheduler from downstream Pi kernel") Fixes: c17b337 ("usb: dwc2: host: program descriptor for next frame") Fixes: dc4c76e ("staging: HCD descriptor DMA support for the DWC2 driver") Fixes: 762d3a1 ("usb: dwc2: host: process all completed urbs") CC: stable@vger.kernel.org Signed-off-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com> Link: https://lore.kernel.org/r/a8b1e1711cc6cabfb45d92ede12e35445c66f06c.1708944698.git.Minas.Harutyunyan@synopsys.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent bae2bc7 commit b258e42

3 files changed

Lines changed: 22 additions & 9 deletions

File tree

drivers/usb/dwc2/hcd.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2701,8 +2701,11 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions(
27012701
hsotg->available_host_channels--;
27022702
}
27032703
qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry);
2704-
if (dwc2_assign_and_init_hc(hsotg, qh))
2704+
if (dwc2_assign_and_init_hc(hsotg, qh)) {
2705+
if (hsotg->params.uframe_sched)
2706+
hsotg->available_host_channels++;
27052707
break;
2708+
}
27062709

27072710
/*
27082711
* Move the QH from the periodic ready schedule to the
@@ -2735,8 +2738,11 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions(
27352738
hsotg->available_host_channels--;
27362739
}
27372740

2738-
if (dwc2_assign_and_init_hc(hsotg, qh))
2741+
if (dwc2_assign_and_init_hc(hsotg, qh)) {
2742+
if (hsotg->params.uframe_sched)
2743+
hsotg->available_host_channels++;
27392744
break;
2745+
}
27402746

27412747
/*
27422748
* 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,
41434149
urb->actual_length);
41444150

41454151
if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
4152+
if (!hsotg->params.dma_desc_enable)
4153+
urb->start_frame = qtd->qh->start_active_frame;
41464154
urb->error_count = dwc2_hcd_urb_get_error_count(qtd->urb);
41474155
for (i = 0; i < urb->number_of_packets; ++i) {
41484156
urb->iso_frame_desc[i].actual_length =

drivers/usb/dwc2/hcd_ddma.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ static void dwc2_init_isoc_dma_desc(struct dwc2_hsotg *hsotg,
559559
idx = qh->td_last;
560560
inc = qh->host_interval;
561561
hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg);
562-
cur_idx = dwc2_frame_list_idx(hsotg->frame_number);
562+
cur_idx = idx;
563563
next_idx = dwc2_desclist_idx_inc(qh->td_last, inc, qh->dev_speed);
564564

565565
/*
@@ -866,6 +866,8 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
866866
{
867867
struct dwc2_dma_desc *dma_desc;
868868
struct dwc2_hcd_iso_packet_desc *frame_desc;
869+
u16 frame_desc_idx;
870+
struct urb *usb_urb = qtd->urb->priv;
869871
u16 remain = 0;
870872
int rc = 0;
871873

@@ -878,8 +880,11 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
878880
DMA_FROM_DEVICE);
879881

880882
dma_desc = &qh->desc_list[idx];
883+
frame_desc_idx = (idx - qtd->isoc_td_first) & (usb_urb->number_of_packets - 1);
881884

882-
frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last];
885+
frame_desc = &qtd->urb->iso_descs[frame_desc_idx];
886+
if (idx == qtd->isoc_td_first)
887+
usb_urb->start_frame = dwc2_hcd_get_frame_number(hsotg);
883888
dma_desc->buf = (u32)(qtd->urb->dma + frame_desc->offset);
884889
if (chan->ep_is_in)
885890
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,
900905
frame_desc->status = 0;
901906
}
902907

903-
if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
908+
if (++qtd->isoc_frame_index == usb_urb->number_of_packets) {
904909
/*
905910
* urb->status is not used for isoc transfers here. The
906911
* individual frame_desc status are used instead.
@@ -1005,11 +1010,11 @@ static void dwc2_complete_isoc_xfer_ddma(struct dwc2_hsotg *hsotg,
10051010
return;
10061011
idx = dwc2_desclist_idx_inc(idx, qh->host_interval,
10071012
chan->speed);
1008-
if (!rc)
1013+
if (rc == 0)
10091014
continue;
10101015

1011-
if (rc == DWC2_CMPL_DONE)
1012-
break;
1016+
if (rc == DWC2_CMPL_DONE || rc == DWC2_CMPL_STOP)
1017+
goto stop_scan;
10131018

10141019
/* rc == DWC2_CMPL_STOP */
10151020

drivers/usb/dwc2/hw.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,7 @@
698698
#define TXSTS_QTOP_TOKEN_MASK (0x3 << 25)
699699
#define TXSTS_QTOP_TOKEN_SHIFT 25
700700
#define TXSTS_QTOP_TERMINATE BIT(24)
701-
#define TXSTS_QSPCAVAIL_MASK (0xff << 16)
701+
#define TXSTS_QSPCAVAIL_MASK (0x7f << 16)
702702
#define TXSTS_QSPCAVAIL_SHIFT 16
703703
#define TXSTS_FSPCAVAIL_MASK (0xffff << 0)
704704
#define TXSTS_FSPCAVAIL_SHIFT 0

0 commit comments

Comments
 (0)