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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to