On Mon, 26 Jan 2004, Greg KH wrote:

> On Mon, Jan 26, 2004 at 04:41:11PM -0500, Alan Stern wrote:
> 
> > P.S.: Since device_unregister_wait() is going away, does that mean that 
> > struct device ->complete is also going to be removed?
> 
> Yup.  Don't need to burden all users of struct device with that.  Is
> that ok with you?

Yes.  I've sent a patch by way of David Brownell to remove some uses of 
device_unregister_wait() and dev->complete in the new File Storage 
Gadget code.

Below is a revised version of patch as163, which also removes
dev->complete and is meant to apply to a clean kernel (i.e., without
as121b already installed).  To summarize the purpose of this patch: When a
new configuration is loaded, instead of calling device_add() for the 
embedded struct devices in the new interfaces, it calls 
device_register().  Likewise, it unregisters the old interfaces instead of 
doing device_del().

This isn't a matter of optimization or redistributing effort; it is
necessary for proper interaction with the driver-model core.  So long as
you retain the change from last December whereby a device isn't released
until all its children have been released, any device_add() - device_del()
- device_add() sequence will result in messed-up refcounts.  Without this
patch, the current code creates just such a sequence when you change from
one configuration to another and then back.  Also it fails ever to
release a struct usb_device, since the children interface devices don't 
get released until the usb_device's release() function calls 
usb_destroy_configuration().

If that change is ever reverted from the driver-model core, this patch
won't be needed any more.

Alan Stern


===== config.c 1.28 vs edited =====
--- 1.28/drivers/usb/core/config.c      Fri Sep 26 12:37:44 2003
+++ edited/drivers/usb/core/config.c    Mon Jan 26 14:19:25 2004
@@ -72,13 +72,10 @@
        return buffer - buffer0;
 }
 
-static void usb_release_intf(struct device *dev)
+static void usb_free_intf(struct usb_interface *intf)
 {
-       struct usb_interface *intf;
        int j;
 
-       intf = to_usb_interface(dev);
-
        if (intf->altsetting) {
                for (j = 0; j < intf->num_altsetting; j++) {
                        struct usb_host_interface *as = &intf->altsetting[j];
@@ -235,8 +232,6 @@
                        return -ENOMEM;
                }
                memset(interface, 0, sizeof(struct usb_interface));
-               interface->dev.release = usb_release_intf;
-               device_initialize(&interface->dev);
        }
 
        /* Go through the descriptors, checking their length and counting the
@@ -374,7 +369,7 @@
                        struct usb_interface *ifp = cf->interface[i];
 
                        if (ifp)
-                               put_device(&ifp->dev);
+                               usb_free_intf(ifp);
                }
        }
        kfree(dev->config);
===== message.c 1.65 vs edited =====
--- 1.65/drivers/usb/core/message.c     Tue Dec 30 13:25:12 2003
+++ edited/drivers/usb/core/message.c   Mon Jan 26 14:47:23 2004
@@ -775,6 +787,13 @@
        }
 }
 
+static void release_interface(struct device *dev)
+{
+       struct usb_interface *interface = to_usb_interface(dev);
+
+       complete(interface->released);
+}
+
 /*
  * usb_disable_device - Disable all the endpoints for a USB device
  * @dev: the device whose endpoints are being disabled
@@ -804,12 +823,16 @@
        if (dev->actconfig) {
                for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
                        struct usb_interface    *interface;
+                       struct completion       intf_completion;
 
                        /* remove this interface */
                        interface = dev->actconfig->interface[i];
                        dev_dbg (&dev->dev, "unregistering interface %s\n",
                                interface->dev.bus_id);
-                       device_del(&interface->dev);
+                       init_completion (&intf_completion);
+                       interface->released = &intf_completion;
+                       device_unregister (&interface->dev);
+                       wait_for_completion (&intf_completion);
                }
                dev->actconfig = 0;
                if (dev->state == USB_STATE_CONFIGURED)
@@ -1127,6 +1150,7 @@
                        intf->dev.driver = NULL;
                        intf->dev.bus = &usb_bus_type;
                        intf->dev.dma_mask = dev->dev.dma_mask;
+                       intf->dev.release = release_interface;
                        sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
                                 dev->bus->busnum, dev->devpath,
                                 configuration,
@@ -1135,7 +1159,7 @@
                                "registering %s (config #%d, interface %d)\n",
                                intf->dev.bus_id, configuration,
                                desc->bInterfaceNumber);
-                       device_add (&intf->dev);
+                       device_register (&intf->dev);
                        usb_create_driverfs_intf_files (intf);
                }
        }
===== include/linux/usb.h 1.166 vs edited =====
--- 1.166/include/linux/usb.h   Tue Dec 30 13:25:15 2003
+++ edited/include/linux/usb.h  Mon Jan 26 14:49:08 2004
@@ -89,6 +89,8 @@
  *     number from the USB core by calling usb_register_dev().
  * @dev: driver model's view of this device
  * @class_dev: driver model's class view of this device.
+ * @released: wait for the interface to be released when changing
+ *     configurations.
  *
  * USB device drivers attach to interfaces on a physical device.  Each
  * interface encapsulates a single high level function, such as feeding
@@ -122,6 +124,7 @@
        int minor;                      /* minor number this interface is bound to */
        struct device dev;              /* interface specific device info */
        struct class_device *class_dev;
+       struct completion *released;    /* wait for release */
 };
 #define        to_usb_interface(d) container_of(d, struct usb_interface, dev)
 #define        interface_to_usbdev(intf) \
@@ -210,6 +213,7 @@
 
        struct class_device class_dev;  /* class device for this bus */
        void (*release)(struct usb_bus *bus);   /* function to destroy this bus's 
memory */
+       struct completion *released;    /* wait for release */
 };
 #define        to_usb_bus(d) container_of(d, struct usb_bus, class_dev)
 



-------------------------------------------------------
The SF.Net email is sponsored by EclipseCon 2004
Premiere Conference on Open Tools Development and Integration
See the breadth of Eclipse activity. February 3-5 in Anaheim, CA.
http://www.eclipsecon.org/osdn
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to