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