diff options
Diffstat (limited to 'drivers/usb/core/message.c')
| -rw-r--r-- | drivers/usb/core/message.c | 50 | 
1 files changed, 43 insertions, 7 deletions
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index aadf29f09c4..7943901c641 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -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);  |