USB: utilize the bus notifiers

This patch (as1185) makes usbcore take advantage of the bus
notifications sent out by the driver core.  Now we can create all our
device and interface attribute files before the device or interface
uevent is broadcast.

A side effect is that we no longer create the endpoint "pseudo"
devices at the same time as a device or interface is registered -- it
seems like a bad idea to try registering an endpoint before the
registration of its parent is complete.  So the routines for creating
and removing endpoint devices have been split out and renamed, and
they are called explicitly when needed.  A new bitflag is used for
keeping track of whether or not the interface's endpoint devices have
been created, since (just as with the interface attributes) they vary
with the altsetting and hence can be changed at random times.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Cc: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Alan Stern
2008-12-05 14:10:34 -05:00
committed by Greg Kroah-Hartman
parent b9cef6c319
commit 3b23dd6f8a
7 changed files with 93 additions and 44 deletions

View File

@@ -1004,6 +1004,34 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
}
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
@@ -1092,7 +1120,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
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);
}
@@ -1235,8 +1263,10 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
*/
/* 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;
@@ -1272,9 +1302,10 @@ 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 (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);
@@ -1334,7 +1365,6 @@ int usb_reset_configuration(struct usb_device *dev)
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.
@@ -1345,10 +1375,16 @@ int usb_reset_configuration(struct usb_device *dev)
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;
}
@@ -1682,7 +1718,7 @@ free_interfaces:
dev_name(&intf->dev), ret);
continue;
}
usb_create_sysfs_intf_files(intf);
create_intf_ep_devs(intf);
}
usb_autosuspend_device(dev);