Re: [PATCH 4/5] usb: dwc3: gadget: Handle transfer completion

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

Felipe Balbi wrote:
> Hi,
>
> Thinh Nguyen <Thinh.Nguyen@xxxxxxxxxxxx> writes:
>
>> With the new usb_request->is_last field, now the function drivers can
>> inform which request is the end of a transfer, dwc3 can program its TRBs
>> to let the controller know when to free its resources when a transfer
>> completes. This is required for stream transfers. The controller needs
>> to know where one stream starts and ends to properly allocate resources
>> for different streams.
>>
>> Signed-off-by: Thinh Nguyen <thinhn@xxxxxxxxxxxx>
> from a quick read, it looks like this can be broken down into smaller
> patches.

Ok.

>
>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
>> index 7204a838ec06..b11183a715a7 100644
>> --- a/drivers/usb/dwc3/core.h
>> +++ b/drivers/usb/dwc3/core.h
>> @@ -701,6 +701,7 @@ struct dwc3_ep {
>>   #define DWC3_EP_END_TRANSFER_PENDING BIT(4)
>>   #define DWC3_EP_PENDING_REQUEST	BIT(5)
>>   #define DWC3_EP_DELAY_START	BIT(6)
>> +#define DWC3_EP_WAIT_TRANSFER_COMPLETE	BIT(7)
> this could be its own patch with proper description (and usage)

Will do.

>>   
>>   	/* This last one is specific to EP0 */
>>   #define DWC3_EP0_DIR_IN		BIT(31)
>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>> index 865e6fbb7360..628f9d142876 100644
>> --- a/drivers/usb/dwc3/gadget.c
>> +++ b/drivers/usb/dwc3/gadget.c
>> @@ -579,6 +579,7 @@ static int dwc3_gadget_set_ep_config(struct dwc3_ep *dep, unsigned int action)
>>   
>>   	if (usb_ss_max_streams(comp_desc) && usb_endpoint_xfer_bulk(desc)) {
>>   		params.param1 |= DWC3_DEPCFG_STREAM_CAPABLE
>> +			| DWC3_DEPCFG_XFER_COMPLETE_EN
> adding this bit for stream endpoints could be a separate commit.

Will do.

>
>>   			| DWC3_DEPCFG_STREAM_EVENT_EN;
>>   		dep->stream_capable = true;
>>   	}
>> @@ -917,8 +918,9 @@ static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep)
>>   }
>>   
>>   static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb,
>> -		dma_addr_t dma, unsigned length, unsigned chain, unsigned node,
>> -		unsigned stream_id, unsigned short_not_ok, unsigned no_interrupt)
>> +		dma_addr_t dma, unsigned length, unsigned chain,
>> +		unsigned is_last, unsigned node, unsigned stream_id,
>> +		unsigned short_not_ok, unsigned no_interrupt)
> if you add "is_last" as the last argument, this hunk will look
> smaller. Nitpicking, I know.

No problem :)

>
>> @@ -1223,6 +1231,10 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep)
>>   
>>   		if (!dwc3_calc_trbs_left(dep))
>>   			return;
>> +
>> +		/* Don't prepare ahead. This is not an option for DWC_usb32. */
>> +		if (req->request.is_last)
>> +			return;
> this requires some better description. Why isn't it an option for dwc_usb32?

Internally, DWC_usb32 does some advance caching and burst that we should 
not prepare more TRB until the transfer is completed.
This doesn't apply for isoc, missed a check here. Need to apply on the 
next version.

>
>> @@ -2648,37 +2666,22 @@ static bool dwc3_gadget_ep_should_continue(struct dwc3_ep *dep)
>>   	return !dwc3_gadget_ep_request_completed(req);
>>   }
>>   
>> -static void dwc3_gadget_endpoint_frame_from_event(struct dwc3_ep *dep,
>> -		const struct dwc3_event_depevt *event)
>> -{
>> -	dep->frame_number = event->parameters;
>> -}
> moving these functions around could be a separate patch. The way it's
> done now takes away from review.

You're right, it's a bit difficult to review as is.

>
>> @@ -2704,6 +2707,45 @@ static void dwc3_gadget_endpoint_transfer_in_progress(struct dwc3_ep *dep,
>>   
>>   		dwc->u1u2 = 0;
>>   	}
>> +
>> +	return no_started_trb;
>> +}
>> +
>> +static void dwc3_gadget_endpoint_frame_from_event(struct dwc3_ep *dep,
>> +		const struct dwc3_event_depevt *event)
>> +{
>> +	dep->frame_number = event->parameters;
>> +}
>> +
>> +static void dwc3_gadget_endpoint_transfer_in_progress(struct dwc3_ep *dep,
>> +		const struct dwc3_event_depevt *event)
>> +{
>> +	int status = 0;
>> +
>> +	if (usb_endpoint_xfer_isoc(dep->endpoint.desc))
>> +		dwc3_gadget_endpoint_frame_from_event(dep, event);
>> +
>> +	if (event->status & DEPEVT_STATUS_BUSERR)
>> +		status = -ECONNRESET;
>> +
>> +	if (event->status & DEPEVT_STATUS_MISSED_ISOC)
>> +		status = -EXDEV;
>> +
>> +	dwc3_gadget_endpoint_trbs_complete(dep, event, status);
>> +}
>> +
>> +static void dwc3_gadget_endpoint_transfer_complete(struct dwc3_ep *dep,
>> +		const struct dwc3_event_depevt *event)
>> +{
>> +	int status = 0;
>> +
>> +	dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
>> +
>> +	if (event->status & DEPEVT_STATUS_BUSERR)
>> +		status = -ECONNRESET;
>> +
>> +	if (dwc3_gadget_endpoint_trbs_complete(dep, event, status))
>> +		dep->flags &= ~DWC3_EP_WAIT_TRANSFER_COMPLETE;
>>   }
>>   
>>   static void dwc3_gadget_endpoint_transfer_not_ready(struct dwc3_ep *dep,
>> @@ -2770,7 +2812,10 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
>>   		}
>>   		break;
>>   	case DWC3_DEPEVT_STREAMEVT:
>> +		break;
> Swap these around. Keep all the "nothing to do here" cases
> together.
>

Thanks,
Thinh




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux