Re: [RFC v4 1/3] usb: dwc3: Resize TX FIFOs to meet EP bursting requirements

Wesley Cheng
2020-08-18T19:59:03Z

On 8/12/2020 11:34 AM, Wesley Cheng wrote:
>>
>> awesome, thanks a lot for this :-) It's a considerable increase in your
>> setup. My only fear here is that we may end up creating a situation
>> where we can't allocate enough FIFO for all endpoints. This is, of
>> course, a consequence of the fact that we enable one endpoint at a
>> time.
>>
>> Perhaps we could envision a way where function driver requests endpoints
>> in bulk, i.e. combines all endpoint requirements into a single method
>> call for gadget framework and, consequently, for UDC.
>>
> Hi Felipe,
>
> I agree...Resizing the txfifo is not as straightforward as it sounds :).
> Would be interesting to see how this affects tput on other platforms as
> well. We had a few discussions within our team, and came up with the
> logic implemented in this patch to reserve at least 1 txfifo per
> endpoint. Then we allocate any additional fifo space requests based on
> the remaining space left. That way we could avoid over allocating, but
> the trade off is that we may have unused EPs taking up fifo space.
>
> I didn't consider branching out to changing the gadget framework, so let
> me take a look at your suggestion to see how it turns out.
>

Hi Felipe,

Instead of catching the out of FIFO memory issue during the ep enable
stage, I was thinking if we could do it somewhere during the bind. Then
this would allow for at least failing the bind instead of having an
enumerated device which doesn't work. (will happen if we bail out during
ep enable phase) The idea I had was the following:

Introduce a new USB gadget function pointer, say
usb_gadget_check_config(struct usb_gadget *gadget, unsigned long ep_map)

The purpose for the ep_map is to carry information about the endpoints
the configuration requires, since each function driver will define the
endpoint descriptor(s) it will advertise to the host. We have access to
these ep desc after the bind() routine is executed for the function
driver, so we can update this map after every bind. The configfs driver
will call the check config API every time a configuration is added.

static int configfs_composite_bind(struct usb_gadget *gadget,
struct usb_gadget_driver *gdriver)
{
...
/* Go through all configs, attach all functions */
list_for_each_entry(c, &gi->cdev.configs, list) {
...
list_for_each_entry_safe(f, tmp, &cfg->func_list, list) {
...
if (f->ss_descriptors) {
struct usb_descriptor_header **descriptors;
descriptors = f->ss_descriptors;
for (; *descriptors; ++descriptors) {
struct usb_endpoint_descriptor *ep;
int addr;

if ((*descriptors)->bDescriptorType != USB_DT_ENDPOINT)
continue;

ep = (struct usb_endpoint_descriptor *)*descriptors;
addr = ((ep->bEndpointAddress & 0x80) >> 3)
| (ep->bEndpointAddress & 0x0f);
set_bit(addr, &ep_map);
}
}
usb_gadget_check_config(cdev->gadget, ep_map);

What it'll allow us to do is to decode the ep_map in the dwc3/udc driver
to determine if we have enough fifo space. Also, if we wanted to utilize
this ep map for the actual resizing stage, we could eliminate the issue
of not knowing how many EPs will be enabled, and allocating potentially
unused fifos due to unused eps.

Thanks
Wesley