mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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:56f5b1cff2("staging: Core files for the DWC2 driver") Fixes:20f2eb9c4c("staging: dwc2: add microframe scheduler from downstream Pi kernel") Fixes:c17b337c1e("usb: dwc2: host: program descriptor for next frame") Fixes:dc4c76e7b2("staging: HCD descriptor DMA support for the DWC2 driver") Fixes:762d3a1a9c("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>
This commit is contained in:
		
							parent
							
								
									bae2bc73a5
								
							
						
					
					
						commit
						b258e42688
					
				
					 3 changed files with 22 additions and 9 deletions
				
			
		| 
						 | 
				
			
			@ -2701,8 +2701,11 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions(
 | 
			
		|||
			hsotg->available_host_channels--;
 | 
			
		||||
		}
 | 
			
		||||
		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;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * Move the QH from the periodic ready schedule to the
 | 
			
		||||
| 
						 | 
				
			
			@ -2735,8 +2738,11 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions(
 | 
			
		|||
			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;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * 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,
 | 
			
		|||
			 urb->actual_length);
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
		for (i = 0; i < urb->number_of_packets; ++i) {
 | 
			
		||||
			urb->iso_frame_desc[i].actual_length =
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -559,7 +559,7 @@ static void dwc2_init_isoc_dma_desc(struct dwc2_hsotg *hsotg,
 | 
			
		|||
	idx = qh->td_last;
 | 
			
		||||
	inc = qh->host_interval;
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
| 
						 | 
				
			
			@ -866,6 +866,8 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
 | 
			
		|||
{
 | 
			
		||||
	struct dwc2_dma_desc *dma_desc;
 | 
			
		||||
	struct dwc2_hcd_iso_packet_desc *frame_desc;
 | 
			
		||||
	u16 frame_desc_idx;
 | 
			
		||||
	struct urb *usb_urb = qtd->urb->priv;
 | 
			
		||||
	u16 remain = 0;
 | 
			
		||||
	int rc = 0;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -878,8 +880,11 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
 | 
			
		|||
				DMA_FROM_DEVICE);
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
	if (chan->ep_is_in)
 | 
			
		||||
		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,
 | 
			
		|||
		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
 | 
			
		||||
		 * individual frame_desc status are used instead.
 | 
			
		||||
| 
						 | 
				
			
			@ -1005,11 +1010,11 @@ static void dwc2_complete_isoc_xfer_ddma(struct dwc2_hsotg *hsotg,
 | 
			
		|||
				return;
 | 
			
		||||
			idx = dwc2_desclist_idx_inc(idx, qh->host_interval,
 | 
			
		||||
						    chan->speed);
 | 
			
		||||
			if (!rc)
 | 
			
		||||
			if (rc == 0)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			if (rc == DWC2_CMPL_DONE)
 | 
			
		||||
				break;
 | 
			
		||||
			if (rc == DWC2_CMPL_DONE || rc == DWC2_CMPL_STOP)
 | 
			
		||||
				goto stop_scan;
 | 
			
		||||
 | 
			
		||||
			/* rc == DWC2_CMPL_STOP */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -698,7 +698,7 @@
 | 
			
		|||
#define TXSTS_QTOP_TOKEN_MASK		(0x3 << 25)
 | 
			
		||||
#define TXSTS_QTOP_TOKEN_SHIFT		25
 | 
			
		||||
#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_FSPCAVAIL_MASK		(0xffff << 0)
 | 
			
		||||
#define TXSTS_FSPCAVAIL_SHIFT		0
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue