Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 127278
b: refs/heads/master
c: 3b23dd6
h: refs/heads/master
v: v3
  • Loading branch information
Alan Stern authored and Greg Kroah-Hartman committed Jan 7, 2009
1 parent bea54a0 commit c7c2429
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 45 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b9cef6c31913c34fb1065b1d01e04c3b92c59016
refs/heads/master: 3b23dd6f8a718e5339de4f7d86ce76a078b5f771
4 changes: 2 additions & 2 deletions trunk/drivers/usb/core/endpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ static void ep_device_release(struct device *dev)
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)
{
Expand Down Expand Up @@ -340,7 +340,7 @@ int usb_create_ep_files(struct device *parent,
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;

Expand Down
18 changes: 6 additions & 12 deletions trunk/drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -1437,17 +1437,12 @@ void usb_disconnect(struct usb_device **pdev)
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);

Expand Down Expand Up @@ -1654,17 +1649,16 @@ int usb_new_device(struct usb_device *udev)
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) {
dev_err(&udev->dev, "can't device_add, error %d\n", 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:
Expand Down
50 changes: 43 additions & 7 deletions trunk/drivers/usb/core/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand All @@ -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;
}
Expand Down Expand Up @@ -1682,7 +1718,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
dev_name(&intf->dev), ret);
continue;
}
usb_create_sysfs_intf_files(intf);
create_intf_ep_devs(intf);
}

usb_autosuspend_device(dev);
Expand Down
22 changes: 1 addition & 21 deletions trunk/drivers/usb/core/sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -629,9 +629,6 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
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;
Expand All @@ -643,11 +640,7 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
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;
Expand All @@ -657,7 +650,6 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
{
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);
Expand Down Expand Up @@ -816,36 +808,24 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf)
{
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;
}
37 changes: 37 additions & 0 deletions trunk/drivers/usb/core/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,37 @@ int usb_disabled(void)
}
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
*/
Expand All @@ -987,6 +1018,9 @@ static int __init usb_init(void)
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;
Expand Down Expand Up @@ -1021,6 +1055,8 @@ static int __init usb_init(void)
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();
Expand All @@ -1044,6 +1080,7 @@ static void __exit usb_exit(void)
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();
}
Expand Down
4 changes: 2 additions & 2 deletions trunk/drivers/usb/core/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ extern int usb_create_sysfs_dev_files(struct usb_device *dev);
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);
Expand Down
2 changes: 2 additions & 0 deletions trunk/include/linux/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ enum usb_interface_condition {
* (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.
Expand Down Expand Up @@ -169,6 +170,7 @@ struct usb_interface {
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 */
Expand Down

0 comments on commit c7c2429

Please sign in to comment.