USB: keep track of whether interface sysfs files exist
authorAlan Stern <stern@rowland.harvard.edu>
Tue, 6 Nov 2007 16:43:42 +0000 (11:43 -0500)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 28 Nov 2007 21:58:35 +0000 (13:58 -0800)
This patch (as1009) solves the problem of multiple registrations for
USB sysfs files in a more satisfying way than the existing code.  It
simply adds a flag to keep track of whether or not the files have been
created; that way the files can be created or removed as needed.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
drivers/usb/core/message.c
drivers/usb/core/sysfs.c
include/linux/usb.h

index 316a746e0080ef8a0eface2341fbd8f3e612c60d..40fd39de5bf972eea93f8f2de8d02e6f0ae1d5c2 100644 (file)
@@ -1172,7 +1172,6 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
        struct usb_host_interface *alt;
        int ret;
        int manual = 0;
-       int changed;
 
        if (dev->state == USB_STATE_SUSPENDED)
                return -EHOSTUNREACH;
@@ -1212,8 +1211,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
         */
 
        /* prevent submissions using previous endpoint settings */
-       changed = (iface->cur_altsetting != alt);
-       if (changed && device_is_registered(&iface->dev))
+       if (iface->cur_altsetting != alt && device_is_registered(&iface->dev))
                usb_remove_sysfs_intf_files(iface);
        usb_disable_interface(dev, iface);
 
@@ -1250,7 +1248,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
         * (Likewise, EP0 never "halts" on well designed devices.)
         */
        usb_enable_interface(dev, iface);
-       if (changed && device_is_registered(&iface->dev))
+       if (device_is_registered(&iface->dev))
                usb_create_sysfs_intf_files(iface);
 
        return 0;
@@ -1641,12 +1639,6 @@ free_interfaces:
                                intf->dev.bus_id, ret);
                        continue;
                }
-
-               /* The driver's probe method can call usb_set_interface(),
-                * which would mean the interface's sysfs files are already
-                * created.  Just in case, we'll remove them first.
-                */
-               usb_remove_sysfs_intf_files(intf);
                usb_create_sysfs_intf_files(intf);
        }
 
index b04afd06e502131f97024360fd5e1ad3279af9f4..32bd130b1eed33fc542fc39bc5f10c1de4695916 100644 (file)
@@ -735,6 +735,8 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf)
        struct usb_host_interface *alt = intf->cur_altsetting;
        int retval;
 
+       if (intf->sysfs_files_created)
+               return 0;
        retval = sysfs_create_group(&dev->kobj, &intf_attr_grp);
        if (retval)
                return retval;
@@ -746,6 +748,7 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf)
        if (intf->intf_assoc)
                retval = sysfs_create_group(&dev->kobj, &intf_assoc_attr_grp);
        usb_create_intf_ep_files(intf, udev);
+       intf->sysfs_files_created = 1;
        return 0;
 }
 
@@ -753,8 +756,11 @@ void usb_remove_sysfs_intf_files(struct usb_interface *intf)
 {
        struct device *dev = &intf->dev;
 
+       if (!intf->sysfs_files_created)
+               return;
        usb_remove_intf_ep_files(intf);
        device_remove_file(dev, &dev_attr_interface);
        sysfs_remove_group(&dev->kobj, &intf_attr_grp);
        sysfs_remove_group(&intf->dev.kobj, &intf_assoc_attr_grp);
+       intf->sysfs_files_created = 0;
 }
index c5c8f169d3cffe001f893d09c0b93272efeb1986..416ee7617d9eac56ad07b320c814742d19998d65 100644 (file)
@@ -157,6 +157,7 @@ struct usb_interface {
                                         * bound to */
        enum usb_interface_condition condition;         /* state of binding */
        unsigned is_active:1;           /* the interface is not suspended */
+       unsigned sysfs_files_created:1; /* the sysfs attributes exist */
        unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */
 
        struct device dev;              /* interface specific device info */