usb: dwc3: gadget: re-factor dwc3_prepare_trbs()
In order to make it easier to add SG support, let's split the big loop out to its own function. Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
		
							parent
							
								
									898c608678
								
							
						
					
					
						commit
						c71fc37c19
					
				| @ -539,6 +539,78 @@ static void dwc3_gadget_ep_free_request(struct usb_ep *ep, | ||||
| 	kfree(req); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * dwc3_prepare_one_trb - setup one TRB from one request | ||||
|  * @dep: endpoint for which this request is prepared | ||||
|  * @req: dwc3_request pointer | ||||
|  */ | ||||
| static int dwc3_prepare_one_trb(struct dwc3_ep *dep, | ||||
| 		struct dwc3_request *req, unsigned last) | ||||
| { | ||||
| 	struct dwc3_trb_hw	*trb_hw; | ||||
| 	struct dwc3_trb		trb; | ||||
| 
 | ||||
| 	unsigned int		cur_slot; | ||||
| 
 | ||||
| 	trb_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK]; | ||||
| 	cur_slot = dep->free_slot; | ||||
| 	dep->free_slot++; | ||||
| 
 | ||||
| 	/* Skip the LINK-TRB on ISOC */ | ||||
| 	if (((cur_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) && | ||||
| 			usb_endpoint_xfer_isoc(dep->desc)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	dwc3_gadget_move_request_queued(req); | ||||
| 	memset(&trb, 0, sizeof(trb)); | ||||
| 
 | ||||
| 	req->trb = trb_hw; | ||||
| 
 | ||||
| 	if (usb_endpoint_xfer_isoc(dep->desc)) { | ||||
| 		trb.isp_imi = true; | ||||
| 		trb.csp = true; | ||||
| 	} else { | ||||
| 		trb.lst = last; | ||||
| 	} | ||||
| 
 | ||||
| 	if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable) | ||||
| 		trb.sid_sofn = req->request.stream_id; | ||||
| 
 | ||||
| 	switch (usb_endpoint_type(dep->desc)) { | ||||
| 	case USB_ENDPOINT_XFER_CONTROL: | ||||
| 		trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP; | ||||
| 		break; | ||||
| 
 | ||||
| 	case USB_ENDPOINT_XFER_ISOC: | ||||
| 		trb.trbctl = DWC3_TRBCTL_ISOCHRONOUS_FIRST; | ||||
| 
 | ||||
| 		/* IOC every DWC3_TRB_NUM / 4 so we can refill */ | ||||
| 		if (!(cur_slot % (DWC3_TRB_NUM / 4))) | ||||
| 			trb.ioc = last; | ||||
| 		break; | ||||
| 
 | ||||
| 	case USB_ENDPOINT_XFER_BULK: | ||||
| 	case USB_ENDPOINT_XFER_INT: | ||||
| 		trb.trbctl = DWC3_TRBCTL_NORMAL; | ||||
| 		break; | ||||
| 	default: | ||||
| 		/*
 | ||||
| 		 * This is only possible with faulty memory because we | ||||
| 		 * checked it already :) | ||||
| 		 */ | ||||
| 		BUG(); | ||||
| 	} | ||||
| 
 | ||||
| 	trb.length	= req->request.length; | ||||
| 	trb.bplh	= req->request.dma; | ||||
| 	trb.hwo		= true; | ||||
| 
 | ||||
| 	dwc3_trb_to_hw(&trb, trb_hw); | ||||
| 	req->trb_dma = dwc3_trb_dma_offset(dep, trb_hw); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * dwc3_prepare_trbs - setup TRBs from requests | ||||
|  * @dep: endpoint for which requests are being prepared | ||||
| @ -552,14 +624,14 @@ static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep, | ||||
| 		bool starting) | ||||
| { | ||||
| 	struct dwc3_request	*req, *n, *ret = NULL; | ||||
| 	struct dwc3_trb_hw	*trb_hw; | ||||
| 	struct dwc3_trb		trb; | ||||
| 	u32			trbs_left; | ||||
| 	unsigned int		last_one = 0; | ||||
| 
 | ||||
| 	BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); | ||||
| 
 | ||||
| 	/* the first request must not be queued */ | ||||
| 	trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * if busy & slot are equal than it is either full or empty. If we are | ||||
| 	 * starting to proceed requests then we are empty. Otherwise we ar | ||||
| @ -594,25 +666,11 @@ static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep, | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	list_for_each_entry_safe(req, n, &dep->request_list, list) { | ||||
| 		unsigned int last_one = 0; | ||||
| 		unsigned int cur_slot; | ||||
| 
 | ||||
| 		trb_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK]; | ||||
| 		cur_slot = dep->free_slot; | ||||
| 		dep->free_slot++; | ||||
| 
 | ||||
| 		/* Skip the LINK-TRB on ISOC */ | ||||
| 		if (((cur_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) && | ||||
| 				usb_endpoint_xfer_isoc(dep->desc)) | ||||
| 			continue; | ||||
| 
 | ||||
| 		dwc3_gadget_move_request_queued(req); | ||||
| 		memset(&trb, 0, sizeof(trb)); | ||||
| 		trbs_left--; | ||||
| 
 | ||||
| 		/* Is our TRB pool empty? */ | ||||
| 		if (!trbs_left) | ||||
| 			last_one = 1; | ||||
| 
 | ||||
| 		/* Is this the last request? */ | ||||
| 		if (list_empty(&dep->request_list)) | ||||
| 			last_one = 1; | ||||
| @ -625,57 +683,9 @@ static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep, | ||||
| 		 * While we're debugging the problem, as a workaround to | ||||
| 		 * multiple TRBs handling, use only one TRB at a time. | ||||
| 		 */ | ||||
| 		last_one = 1; | ||||
| 
 | ||||
| 		req->trb = trb_hw; | ||||
| 		if (!ret) | ||||
| 			ret = req; | ||||
| 
 | ||||
| 		trb.bplh = req->request.dma; | ||||
| 
 | ||||
| 		if (usb_endpoint_xfer_isoc(dep->desc)) { | ||||
| 			trb.isp_imi = true; | ||||
| 			trb.csp = true; | ||||
| 		} else { | ||||
| 			trb.lst = last_one; | ||||
| 		} | ||||
| 
 | ||||
| 		if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable) | ||||
| 			trb.sid_sofn = req->request.stream_id; | ||||
| 
 | ||||
| 		switch (usb_endpoint_type(dep->desc)) { | ||||
| 		case USB_ENDPOINT_XFER_CONTROL: | ||||
| 			trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP; | ||||
| 			break; | ||||
| 
 | ||||
| 		case USB_ENDPOINT_XFER_ISOC: | ||||
| 			trb.trbctl = DWC3_TRBCTL_ISOCHRONOUS_FIRST; | ||||
| 
 | ||||
| 			/* IOC every DWC3_TRB_NUM / 4 so we can refill */ | ||||
| 			if (!(cur_slot % (DWC3_TRB_NUM / 4))) | ||||
| 				trb.ioc = last_one; | ||||
| 			break; | ||||
| 
 | ||||
| 		case USB_ENDPOINT_XFER_BULK: | ||||
| 		case USB_ENDPOINT_XFER_INT: | ||||
| 			trb.trbctl = DWC3_TRBCTL_NORMAL; | ||||
| 			break; | ||||
| 		default: | ||||
| 			/*
 | ||||
| 			 * This is only possible with faulty memory because we | ||||
| 			 * checked it already :) | ||||
| 			 */ | ||||
| 			BUG(); | ||||
| 		} | ||||
| 
 | ||||
| 		trb.length	= req->request.length; | ||||
| 		trb.hwo = true; | ||||
| 
 | ||||
| 		dwc3_trb_to_hw(&trb, trb_hw); | ||||
| 		req->trb_dma = dwc3_trb_dma_offset(dep, trb_hw); | ||||
| 
 | ||||
| 		if (last_one) | ||||
| 			break; | ||||
| 		dwc3_prepare_one_trb(dep, req, true); | ||||
| 		ret = req; | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	return ret; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user