Re: More dynamic EP allocation

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

 



Hi,

Benjamin Herrenschmidt <benh@xxxxxxxxxxxxxxxxxxx> writes:
> Hi !
>
> So for the aspeed virtual hub, I'm in a situation where I have up to 5
> devices sharing a pool of 15 "generic" endpoints (not counting EP0's,
> those have dedicated HW).
>
> I was originally thinking of having some device-tree construct
> assigning fixed number of EPs from the pool to the various devices, but
> that sucks...
>
> I'm trying to figure out if I can do something more dynamic.
>
> My idea is to not put the EPs in the gadget ep_list at first, but
> provide a match_ep() callback that effectively "allocates" an EP from
> the pool.

but that's how the framework is implemented. Endpoints are kept in the
ep_list but they aren't allocated until an endpoint match happens.

> It looks from a cursory glance at the code that it might work, with a
> reasonable failure mode since running out of EPs would typically make
> functions fail at bind() time.
>
> However we're missing a "free" :-)

We don't need a free. Once a function is unbound, endpoints *must* be
free.

> I *think* (please correct me if I'm wrong) that adding a callback for
> that and plumbing it this way would work, let me know what you think.

I'm not entirely sure you need it.

> If you agree with the approach (and it ends up working once I'm done
> coding), I'll submit it as a pre-req patch to the driver.
>
> diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
> index e4516e9..f8d2135 100644
> --- a/include/linux/usb/gadget.h
> +++ b/include/linux/usb/gadget.h
> @@ -307,6 +307,7 @@ struct usb_gadget_ops {
>         struct usb_ep *(*match_ep)(struct usb_gadget *,
>                         struct usb_endpoint_descriptor *,
>                         struct usb_ss_ep_comp_descriptor *);
> +       void    (*release_ep)(struct usb_gadget *, struct usb_ep *);
>  };
>  
>  /**
> --- a/drivers/usb/gadget/epautoconf.c
> +++ b/drivers/usb/gadget/epautoconf.c
> @@ -185,6 +185,9 @@ void usb_ep_autoconfig_release(struct usb_ep *ep)
>  {
>         ep->claimed = false;
>         ep->driver_data = NULL;
> +
> +       if (gadget->ops->release_ep)
> +               gadget->relase->release_ep(gadget, ep);
>  }
>  EXPORT_SYMBOL_GPL(usb_ep_autoconfig_release);
>  
> @@ -201,10 +204,8 @@ void usb_ep_autoconfig_reset (struct usb_gadget *gadget)
>  {
>         struct usb_ep   *ep;
>  
> -       list_for_each_entry (ep, &gadget->ep_list, ep_list) {
> -               ep->claimed = false;
> -               ep->driver_data = NULL;
> -       }
> +       list_for_each_entry_safe (ep, &gadget->ep_list, ep_list)
> +               usb_ep_autoconfig_release(ep);
>         gadget->in_epnum = 0;
>         gadget->out_epnum = 0;
>  }

I really don't see the difference.

-- 
balbi

Attachment: signature.asc
Description: PGP signature


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

  Powered by Linux