On Thu, 14 Mar 2013, Felipe Balbi wrote:
> Here's the diff which needs testing:
Can't test the net2272 part.
> diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
> index 691cc65..d23c1b8 100644
> --- a/drivers/usb/gadget/net2280.c
> +++ b/drivers/usb/gadget/net2280.c
> @@ -1941,6 +1941,13 @@ stop_activity (struct net2280 *dev, struct
> usb_gadget_driver *driver)
> for (i = 0; i < 7; i++)
> nuke (&dev->ep [i]);
>
> + /* report disconnect; the driver is already quiesced */
> + if (driver) {
> + spin_unlock (&dev->lock);
> + driver->disconnect (&dev->gadget);
> + spin_lock (&dev->lock);
> + }
> +
> usb_reinit (dev);
> }
Adding this back in revealed a bug in udc-core. It is fixed as
follows:
Index: usb-3.9/drivers/usb/gadget/udc-core.c
===================================================================
--- usb-3.9.orig/drivers/usb/gadget/udc-core.c
+++ usb-3.9/drivers/usb/gadget/udc-core.c
@@ -216,7 +216,7 @@ static void usb_gadget_remove_driver(str
usb_gadget_disconnect(udc->gadget);
udc->driver->disconnect(udc->gadget);
udc->driver->unbind(udc->gadget);
- usb_gadget_udc_stop(udc->gadget, udc->driver);
+ usb_gadget_udc_stop(udc->gadget, NULL);
udc->driver = NULL;
udc->dev.driver = NULL;
At the point where the UDC driver's stop routine is called, the gadget
no longer has a driver. You might even want to move the line I changed
down below the following two assignments, to make this more clear.
By the way, what happens if the UDC hardware doesn't support software
control of the D+ pullup? The usb_gadget_disconnect call above won't
do anything, and that leaves open a window for a race. The host might
send a SETUP packet between the unbind and stop calls. Should we
insist that all UDC drivers do have a working ->pullup routine?
In addition, code-reading revealed a bug in an error pathway of
net2280.c:
Index: usb-3.9/drivers/usb/gadget/net2280.c
===================================================================
--- usb-3.9.orig/drivers/usb/gadget/net2280.c
+++ usb-3.9/drivers/usb/gadget/net2280.c
@@ -1924,7 +1924,6 @@ static int net2280_start(struct usb_gadg
err_func:
device_remove_file (&dev->pdev->dev, &dev_attr_function);
err_unbind:
- driver->unbind (&dev->gadget);
dev->gadget.dev.driver = NULL;
dev->driver = NULL;
return retval;
If the start method fails, udc_bind_to_driver() calls driver->unbind.
The UDC driver doesn't need to do it. I have not audited the other
gadget drivers for similar problems (i.e., unnecessary cleanup calls in
error pathways); it might be worth taking a quick look. net2272 at
least probably has the same bug.
With these two fixes applied, everything seemed to work okay. Should I
submit them officially?
Alan Stern
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html