kfree(ep_dev);
 }
 
-int usb_create_ep_files(struct device *parent,
+int usb_create_ep_devs(struct device *parent,
                        struct usb_host_endpoint *endpoint,
                        struct usb_device *udev)
 {
        return retval;
 }
 
-void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
+void usb_remove_ep_devs(struct usb_host_endpoint *endpoint)
 {
        struct ep_device *ep_dev = endpoint->ep_dev;
 
 
        usb_disable_device(udev, 0);
        usb_hcd_synchronize_unlinks(udev);
 
+       usb_remove_ep_devs(&udev->ep0);
        usb_unlock_device(udev);
 
-       /* Remove the device-specific files from sysfs.  This must be
-        * done with udev unlocked, because some of the attribute
-        * routines try to acquire the device lock.
-        */
-       usb_remove_sysfs_dev_files(udev);
-
        /* Unregister the device.  The device driver is responsible
-        * for removing the device files from usbfs and sysfs and for
-        * de-configuring the device.
+        * for de-configuring the device and invoking the remove-device
+        * notifier chain (used by usbfs and possibly others).
         */
        device_del(&udev->dev);
 
        announce_device(udev);
 
        /* Register the device.  The device driver is responsible
-        * for adding the device files to sysfs and for configuring
-        * the device.
+        * for configuring the device and invoking the add-device
+        * notifier chain (used by usbfs and possibly others).
         */
        err = device_add(&udev->dev);
        if (err) {
                goto fail;
        }
 
-       /* put device-specific files into sysfs */
-       usb_create_sysfs_dev_files(udev);
+       (void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev);
        return err;
 
 fail:
 
 }
 EXPORT_SYMBOL_GPL(usb_clear_halt);
 
+static int create_intf_ep_devs(struct usb_interface *intf)
+{
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct usb_host_interface *alt = intf->cur_altsetting;
+       int i;
+
+       if (intf->ep_devs_created || intf->unregistering)
+               return 0;
+
+       for (i = 0; i < alt->desc.bNumEndpoints; ++i)
+               (void) usb_create_ep_devs(&intf->dev, &alt->endpoint[i], udev);
+       intf->ep_devs_created = 1;
+       return 0;
+}
+
+static void remove_intf_ep_devs(struct usb_interface *intf)
+{
+       struct usb_host_interface *alt = intf->cur_altsetting;
+       int i;
+
+       if (!intf->ep_devs_created)
+               return;
+
+       for (i = 0; i < alt->desc.bNumEndpoints; ++i)
+               usb_remove_ep_devs(&alt->endpoint[i]);
+       intf->ep_devs_created = 0;
+}
+
 /**
  * usb_disable_endpoint -- Disable an endpoint by address
  * @dev: the device whose endpoint is being disabled
                        dev_dbg(&dev->dev, "unregistering interface %s\n",
                                dev_name(&interface->dev));
                        interface->unregistering = 1;
-                       usb_remove_sysfs_intf_files(interface);
+                       remove_intf_ep_devs(interface);
                        device_del(&interface->dev);
                }
 
         */
 
        /* prevent submissions using previous endpoint settings */
-       if (iface->cur_altsetting != alt)
+       if (iface->cur_altsetting != alt) {
+               remove_intf_ep_devs(iface);
                usb_remove_sysfs_intf_files(iface);
+       }
        usb_disable_interface(dev, iface);
 
        iface->cur_altsetting = alt;
         * (Likewise, EP0 never "halts" on well designed devices.)
         */
        usb_enable_interface(dev, iface);
-       if (device_is_registered(&iface->dev))
+       if (device_is_registered(&iface->dev)) {
                usb_create_sysfs_intf_files(iface);
-
+               create_intf_ep_devs(iface);
+       }
        return 0;
 }
 EXPORT_SYMBOL_GPL(usb_set_interface);
                struct usb_interface *intf = config->interface[i];
                struct usb_host_interface *alt;
 
-               usb_remove_sysfs_intf_files(intf);
                alt = usb_altnum_to_altsetting(intf, 0);
 
                /* No altsetting 0?  We'll assume the first altsetting.
                if (!alt)
                        alt = &intf->altsetting[0];
 
+               if (alt != intf->cur_altsetting) {
+                       remove_intf_ep_devs(intf);
+                       usb_remove_sysfs_intf_files(intf);
+               }
                intf->cur_altsetting = alt;
                usb_enable_interface(dev, intf);
-               if (device_is_registered(&intf->dev))
+               if (device_is_registered(&intf->dev)) {
                        usb_create_sysfs_intf_files(intf);
+                       create_intf_ep_devs(intf);
+               }
        }
        return 0;
 }
                                dev_name(&intf->dev), ret);
                        continue;
                }
-               usb_create_sysfs_intf_files(intf);
+               create_intf_ep_devs(intf);
        }
 
        usb_autosuspend_device(dev);
 
        struct device *dev = &udev->dev;
        int retval;
 
-       /* Unforunately these attributes cannot be created before
-        * the uevent is broadcast.
-        */
        retval = device_create_bin_file(dev, &dev_bin_attr_descriptors);
        if (retval)
                goto error;
        retval = add_power_attributes(dev);
        if (retval)
                goto error;
-
-       retval = usb_create_ep_files(dev, &udev->ep0, udev);
-       if (retval)
-               goto error;
-       return 0;
+       return retval;
 error:
        usb_remove_sysfs_dev_files(udev);
        return retval;
 {
        struct device *dev = &udev->dev;
 
-       usb_remove_ep_files(&udev->ep0);
        remove_power_attributes(dev);
        remove_persist_attributes(dev);
        device_remove_bin_file(dev, &dev_bin_attr_descriptors);
 {
        struct usb_device *udev = interface_to_usbdev(intf);
        struct usb_host_interface *alt = intf->cur_altsetting;
-       int i;
        int retval;
 
        if (intf->sysfs_files_created || intf->unregistering)
                return 0;
 
-       /* The interface string may be present in some altsettings
-        * and missing in others.  Hence its attribute cannot be created
-        * before the uevent is broadcast.
-        */
        if (alt->string == NULL)
                alt->string = usb_cache_string(udev, alt->desc.iInterface);
        if (alt->string)
                retval = device_create_file(&intf->dev, &dev_attr_interface);
-       for (i = 0; i < alt->desc.bNumEndpoints; ++i)
-               usb_create_ep_files(&intf->dev, &alt->endpoint[i], udev);
        intf->sysfs_files_created = 1;
        return 0;
 }
 
 void usb_remove_sysfs_intf_files(struct usb_interface *intf)
 {
-       struct usb_host_interface *alt = intf->cur_altsetting;
-       int i;
-
        if (!intf->sysfs_files_created)
                return;
 
-       for (i = 0; i < alt->desc.bNumEndpoints; ++i)
-               usb_remove_ep_files(&alt->endpoint[i]);
        device_remove_file(&intf->dev, &dev_attr_interface);
        intf->sysfs_files_created = 0;
 }
 
 }
 EXPORT_SYMBOL_GPL(usb_disabled);
 
+/*
+ * Notifications of device and interface registration
+ */
+static int usb_bus_notify(struct notifier_block *nb, unsigned long action,
+               void *data)
+{
+       struct device *dev = data;
+
+       switch (action) {
+       case BUS_NOTIFY_ADD_DEVICE:
+               if (dev->type == &usb_device_type)
+                       (void) usb_create_sysfs_dev_files(to_usb_device(dev));
+               else if (dev->type == &usb_if_device_type)
+                       (void) usb_create_sysfs_intf_files(
+                                       to_usb_interface(dev));
+               break;
+
+       case BUS_NOTIFY_DEL_DEVICE:
+               if (dev->type == &usb_device_type)
+                       usb_remove_sysfs_dev_files(to_usb_device(dev));
+               else if (dev->type == &usb_if_device_type)
+                       usb_remove_sysfs_intf_files(to_usb_interface(dev));
+               break;
+       }
+       return 0;
+}
+
+static struct notifier_block usb_bus_nb = {
+       .notifier_call = usb_bus_notify,
+};
+
 /*
  * Init
  */
        retval = bus_register(&usb_bus_type);
        if (retval)
                goto bus_register_failed;
+       retval = bus_register_notifier(&usb_bus_type, &usb_bus_nb);
+       if (retval)
+               goto bus_notifier_failed;
        retval = usb_host_init();
        if (retval)
                goto host_init_failed;
 major_init_failed:
        usb_host_cleanup();
 host_init_failed:
+       bus_unregister_notifier(&usb_bus_type, &usb_bus_nb);
+bus_notifier_failed:
        bus_unregister(&usb_bus_type);
 bus_register_failed:
        ksuspend_usb_cleanup();
        usb_devio_cleanup();
        usb_hub_cleanup();
        usb_host_cleanup();
+       bus_unregister_notifier(&usb_bus_type, &usb_bus_nb);
        bus_unregister(&usb_bus_type);
        ksuspend_usb_cleanup();
 }
 
 extern void usb_remove_sysfs_dev_files(struct usb_device *dev);
 extern int usb_create_sysfs_intf_files(struct usb_interface *intf);
 extern void usb_remove_sysfs_intf_files(struct usb_interface *intf);
-extern int usb_create_ep_files(struct device *parent,
+extern int usb_create_ep_devs(struct device *parent,
                                struct usb_host_endpoint *endpoint,
                                struct usb_device *udev);
-extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint);
+extern void usb_remove_ep_devs(struct usb_host_endpoint *endpoint);
 
 extern void usb_enable_endpoint(struct usb_device *dev,
                struct usb_host_endpoint *ep);
 
  *     (in probe()), bound to a driver, or unbinding (in disconnect())
  * @is_active: flag set when the interface is bound and not suspended.
  * @sysfs_files_created: sysfs attributes exist
+ * @ep_devs_created: endpoint child pseudo-devices exist
  * @unregistering: flag set when the interface is being unregistered
  * @needs_remote_wakeup: flag set when the driver requires remote-wakeup
  *     capability during autosuspend.
        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 ep_devs_created:1;     /* endpoint "devices" exist */
        unsigned unregistering:1;       /* unregistration is in progress */
        unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */
        unsigned needs_altsetting0:1;   /* switch to altsetting 0 is pending */