Am Freitag, 11. Oktober 2002 01:35 schrieb Greg KH:
> On Fri, Oct 11, 2002 at 01:13:58AM +0200, Oliver Neukum wrote:
> > Hi,
> >
> > this version, though probably horribly broken, should have all features
> > I intended it to have. So could you have a look at this ?
>
> Um, if you know it's broken, do you still want comments?
I strongly suspect it to be broken.
And yes I want comments.
> > diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> > --- a/drivers/usb/core/hub.c Fri Oct 11 01:08:39 2002
> > +++ b/drivers/usb/core/hub.c Fri Oct 11 01:08:39 2002
> > @@ -1236,7 +1236,7 @@
> > return 1;
> > }
> >
> > - ret = usb_set_configuration(dev, dev->actconfig->bConfigurationValue);
> > + ret = do_set_conf(dev, dev->actconfig->bConfigurationValue);
>
> Why call do_set_conf() here, instead of usb_set_configuration()?
So that no attaching of drivers to do interfaces happens prematurely.
> > diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c
> > --- a/drivers/usb/core/message.c Fri Oct 11 01:08:39 2002
> > +++ b/drivers/usb/core/message.c Fri Oct 11 01:08:39 2002
> > @@ -838,6 +838,43 @@
> > }
> >
> > /**
> > + * do_set_conf - send the actual message changing configuration
>
> That name has got to change (along with the other do_* name. You're
> poluting the global namespace with this function, either make it start
> with usb_ or make it static (hint, I think you can do the latter.)
OK.
> > + * @dev: the device whose configuration is being updated
> > + * @configuration: the configuration being chosen.
> > + * Context: !in_interrupt ()
> > + */
> > +int do_set_conf(struct usb_device *dev, int configuration)
> > +{
> > + int r,i;
> > + struct usb_config_descriptor *cp;
> > +printk("Setting configuration.\n");
>
> dbg() works well for these kinds of things :)
Sorry. They were left in accidentally.
> > + for (i=0; i<dev->descriptor.bNumConfigurations; i++) {
> > + if (dev->config[i].bConfigurationValue == configuration) {
> > + cp = &dev->config[i];
> > + goto found;
> > + }
> > + }
> > +
> > + return -EINVAL;
> > +
> > +found:
> > +
> > + r = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
> > + USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
> > + NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
> > + if (r)
> > + return r;
> > +
> > + dev->actconfig = cp;
> > + dev->toggle[0] = 0;
> > + dev->toggle[1] = 0;
> > + usb_set_maxpacket(dev);
> > +
> > + return 0;
>
> You have 3 ways to get out of this function, try to narrow that down to
> 1.
OK. I like goto ;-)
> > +
> > +}
> > +
> > +/**
> > * usb_set_configuration - Makes a particular device setting be current
> > * @dev: the device whose configuration is being updated
> > * @configuration: the configuration being chosen.
> > @@ -871,7 +908,7 @@
> > {
> > int i, ret;
> > struct usb_config_descriptor *cp = NULL;
> > -
> > +
> > for (i=0; i<dev->descriptor.bNumConfigurations; i++) {
> > if (dev->config[i].bConfigurationValue == configuration) {
> > cp = &dev->config[i];
> > @@ -883,17 +920,29 @@
> > return -EINVAL;
> > }
> >
> > - if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
> > - USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
> > - NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0)
> > - return ret;
> > + down(&dev->serialize);
> >
> > - dev->actconfig = cp;
> > - dev->toggle[0] = 0;
> > - dev->toggle[1] = 0;
> > - usb_set_maxpacket(dev);
> > + for (i = 0; i < USB_MAXCHILDREN; i++) {
> > + struct usb_device **child = dev->children + i;
> > + if (*child) {
> > + ret = -EBUSY;
> > + goto err; /* refuse if children were harmed */
> > + }
> > + }
> > +printk("Got lock in usb_set_configuration.\n");
> >
> > - return 0;
> > + usb_reap_interfaces(dev); /* get rid of all interfaces */
> > +
> > + if ((ret = do_set_conf(dev, configuration)))
> > + goto err;
> > +
> > + dev->desired_conf = configuration; /* for pm */
> > +
> > + ret = do_logical_register_dev(dev); /* reevaluate device */
>
> Nope, you just registered the main usb device a second time, you only
> want to register the interfaces, not the main device.
>
> Yes, it's a bit complicated the way USB and the driver model works
> together, if people want, I can try to document it better.
Oh, yes, please. I didn't really know what I was doing there.
> > +printk("Got driver lock.\n");
> > + down (&udev->serialize);
>
> Why grab the main device lock for the interface probe? I don't see how
> it protects you here, and it's starting to get a bit messy...
If this is not taken there's a race with usb_set_configuration().
Not only must we remove all drivers from the interfaces, but
no new attachments of drivers to interfaces of the device must
happen until the configuration has changed.
Regards
Oliver
-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel