Re: [PATCH v10 2/6] usb: gadget: configfs: Check USB configuration before adding

From: Greg KH
Date: Thu Jun 24 2021 - 08:09:11 EST


On Wed, Jun 23, 2021 at 02:44:31PM -0700, Wesley Cheng wrote:
>
>
> On 6/23/2021 4:35 AM, Greg KH wrote:
> > On Wed, Jun 23, 2021 at 02:38:55AM -0700, Wesley Cheng wrote:
> >>
> >>
> >> On 6/21/2021 11:05 PM, Greg KH wrote:
> >>> On Mon, Jun 21, 2021 at 10:27:09PM -0700, Wesley Cheng wrote:
> >>>>
> >>>>
> >>>> On 6/17/2021 4:07 AM, Greg KH wrote:
> >>>>> On Thu, Jun 17, 2021 at 02:58:15AM -0700, Wesley Cheng wrote:
> >>>>>> Ensure that the USB gadget is able to support the configuration being
> >>>>>> added based on the number of endpoints required from all interfaces. This
> >>>>>> is for accounting for any bandwidth or space limitations.
> >>>>>>
> >>>>>> Signed-off-by: Wesley Cheng <wcheng@xxxxxxxxxxxxxx>
> >>>>>> ---
> >>>>>> drivers/usb/gadget/configfs.c | 22 ++++++++++++++++++++++
> >>>>>> 1 file changed, 22 insertions(+)
> >>>>>>
> >>>>>> diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
> >>>>>> index 15a607c..76b9983 100644
> >>>>>> --- a/drivers/usb/gadget/configfs.c
> >>>>>> +++ b/drivers/usb/gadget/configfs.c
> >>>>>> @@ -1374,6 +1374,7 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
> >>>>>> struct usb_function *f;
> >>>>>> struct usb_function *tmp;
> >>>>>> struct gadget_config_name *cn;
> >>>>>> + unsigned long ep_map = 0;
> >>>>>>
> >>>>>> if (gadget_is_otg(gadget))
> >>>>>> c->descriptors = otg_desc;
> >>>>>> @@ -1403,7 +1404,28 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
> >>>>>> list_add(&f->list, &cfg->func_list);
> >>>>>> goto err_purge_funcs;
> >>>>>> }
> >>>>>> + if (f->fs_descriptors) {
> >>>>>> + struct usb_descriptor_header **d;
> >>>>>> +
> >>>>>> + d = f->fs_descriptors;
> >>>>>> + for (; *d; ++d) {
> >>>>
> >>>> Hi Greg,
> >>>>
> >>>> Thanks for the review and feedback.
> >>>>
> >>>>>
> >>>>> With this check, there really is not a need to check for
> >>>>> f->fs_descriptors above in the if statement, right?
> >>>>>
> >>>>
> >>>> f->fs_descriptor will carry the table of descriptors that a particular
> >>>> function driver has assigned to it. The for loop here, will dereference
> >>>> the individual descriptors within that descriptor array, so we need to
> >>>> first ensure the descriptor array is present before traversing through
> >>>> the individual entries/elements.
> >>>
> >>> Ah, it's a dereference of an array element. Subtle. Tricky. Messy :(
> >>>
> >>>>>> + struct usb_endpoint_descriptor *ep;
> >>>>>> + int addr;
> >>>>>> +
> >>>>>> + if ((*d)->bDescriptorType != USB_DT_ENDPOINT)
> >>>>>> + continue;
> >>>>>> +
> >>>>>> + ep = (struct usb_endpoint_descriptor *)*d;
> >>>>>> + addr = ((ep->bEndpointAddress & 0x80) >> 3) |
> >>>>>> + (ep->bEndpointAddress & 0x0f);
> >>>>>
> >>>>> Don't we have direction macros for this type of check?
> >>>>>
> >>>>
> >>>> I don't believe we have a macro which would be able to convert the
> >>>> bEndpointAddress field into the bit which needs to be set, assuming that
> >>>> the 32bit ep_map has the lower 16bits carrying OUT EPs, and the upper
> >>>> 16bits carrying the IN EPs.
> >>
> >> Hi Greg,
> >>
> >>>
> >>> We have macros to tell if an endpoint is IN or OUT, please use those.
> >>>
> >>> And this "cram the whole thing into 64 bits" is not obvious at all.
> >>> Just pass around the original pointer to the descriptors if someone
> >>> wants to use it or not, don't make up yet-another-data-structure here
> >>> for no good reason. We aren't so memory constrained we need to pack
> >>> stuff into bits here.
> >>>
> >>
> >> Hmm ok, what I can do is to move this logic into the check_config()
> >> callback itself, which is implemented by the UDC driver. So now, the
> >> DWC3 will have to do something similar to what is done here, ie loop the
> >> EP descriptors for each function to determine the number of IN endpoints
> >> being used.
>
> Hi Greg,
>
> >
> > We have common USB core functions for this, why can't you just use them?
> >
>
> So, I've tried to use pre-existing mechanisms there in the USB core, but
> they are not populated correctly at the time of function binding. I
> will highlight some of the things I've tried, and why they do not work.
> If possible, if you could point which core functions can achieve what
> we are trying to do here, that would help as well.

We have functions to detect the IN/OUT of an endpoint, use them.

We also have functions that determine how many endpoints of each type
that a device has, why can you not use them as well? Are they only
valid for driver structures, not gadget ones?

> - f->endpoints - This is a bitmap which carries the endpoints used by
> a particular function driver. This does not work, as this is set during
> receiving the SET_CONFIG packet. (we need this during the function
> driver binding stage)
>
> - gadget->in_epnum/gadget->out_epnum - This carries the count of
> endpoints used per configuration. This would be perfect, but this count
> is only incremented when we are not matching EPs using the EP name. So
> in designs where the EP name is used to match, it can not be used.
>
> - gadget->ep_list - I can use this now in the check_config() to iterate
> through the list of eps to see which ones have been claimed for a
> particular configuration.
>
> So just to re-iterate, the TXFIFO resize logic kicks in when the host
> sends the SET_CONFIG packet, which is the "end" of USB enumeration. We
> had discussed a concern previously where, what if we run the resize
> logic, and there is not enough internal memory. We'd end up with an
> enumerated device w/ certain functions broken.

Where are you running out of memory? In the gadget kernel? Or
somewhere else?

> This is where the check_config() comes into the picture. It uses the
> number of endpoints collected during the bind() stage, and checks to
> make sure the resize logic can at least allocate 1 TXFIFO per endpoint.
> If it can not, then it will fail the bind sequence.

That's fine, I am just worried about your crazy "pack all the bits into
a u64 for no good reason" logic here.

thanks,

greg k-h