Commit ad12579b authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

[PATCH] USB: Add usb_release_address() and move usb_set_address()

This patch adds usb_release_address() as a complement to
usb_choose_address(), to centralize the work required when freeing an
allocated device address.  It also moves the usb_set_address() routine
from usb.c to hub.c -- which is the only place it is ever used -- and
renames it to hub_set_address().
parent d7a3f44d
......@@ -243,13 +243,13 @@ extern void usb_hc_died (struct usb_hcd *hcd);
extern struct usb_device *usb_alloc_dev(struct usb_device *parent,
struct usb_bus *, unsigned port);
extern int usb_new_device(struct usb_device *dev);
extern void usb_choose_address(struct usb_device *dev);
extern void usb_disconnect(struct usb_device **);
extern void usb_choose_address(struct usb_device *dev);
extern void usb_release_address(struct usb_device *dev);
/* exported to hub driver ONLY to support usb_reset_device () */
extern int usb_get_configuration(struct usb_device *dev);
extern void usb_destroy_configuration(struct usb_device *dev);
extern int usb_set_address(struct usb_device *dev);
/* use these only before the device's address has been set */
#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30))
......
......@@ -1030,6 +1030,21 @@ static int hub_port_debounce(struct usb_device *hub, int port)
return ((portstatus&USB_PORT_STAT_CONNECTION)) ? 0 : 1;
}
static int hub_set_address(struct usb_device *dev)
{
int retval;
if (dev->devnum == 0)
return -EINVAL;
if (dev->state != USB_STATE_DEFAULT && dev->state != USB_STATE_ADDRESS)
return -EINVAL;
retval = usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS,
0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
if (retval == 0)
dev->state = USB_STATE_ADDRESS;
return retval;
}
/* reset device, (re)assign address, get device descriptor.
* device connection is stable, no more debouncing needed.
* returns device in USB_STATE_ADDRESS, except on error.
......@@ -1143,7 +1158,7 @@ hub_port_init (struct usb_device *hub, struct usb_device *dev, int port)
*/
for (i = 0; i < GET_DESCRIPTOR_TRIES; ++i) {
for (j = 0; j < SET_ADDRESS_TRIES; ++j) {
retval = usb_set_address(dev);
retval = hub_set_address(dev);
if (retval >= 0)
break;
msleep(200);
......@@ -1154,8 +1169,7 @@ hub_port_init (struct usb_device *hub, struct usb_device *dev, int port)
dev->devnum, retval);
fail:
hub_port_disable(hub, port);
clear_bit(dev->devnum, dev->bus->devmap.devicemap);
dev->devnum = -1;
usb_release_address(dev);
usb_put_dev(dev);
up(&usb_address0_sem);
return retval;
......
......@@ -998,12 +998,10 @@ void usb_disconnect(struct usb_device **pdev)
*/
usb_disable_device(dev, 0);
dev_dbg (&dev->dev, "unregistering device\n");
/* Free the device number and remove the /proc/bus/usb entry */
if (dev->devnum > 0) {
clear_bit(dev->devnum, dev->bus->devmap.devicemap);
dev_dbg (&dev->dev, "unregistering device\n");
usb_release_address(dev);
usbfs_remove_device(dev);
}
up(&dev->serialize);
device_unregister(&dev->dev);
}
......@@ -1038,24 +1036,23 @@ void usb_choose_address(struct usb_device *dev)
}
}
// hub-only!! ... and only exported for reset/reinit path.
// otherwise used internally, for usb_new_device()
int usb_set_address(struct usb_device *dev)
/**
* usb_release_address - deallocate device address (usbcore-internal)
* @dev: newly removed device
*
* Removes and deallocates the address assigned to a device.
* Only hub drivers (but not virtual root hub drivers for host
* controllers) should ever call this.
*/
void usb_release_address(struct usb_device *dev)
{
int retval;
if (dev->devnum == 0)
return -EINVAL;
if (dev->state != USB_STATE_DEFAULT && dev->state != USB_STATE_ADDRESS)
return -EINVAL;
retval = usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS,
0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
if (retval == 0)
dev->state = USB_STATE_ADDRESS;
return retval;
if (dev->devnum > 0) {
clear_bit(dev->devnum, dev->bus->devmap.devicemap);
dev->devnum = -1;
}
}
static inline void usb_show_string(struct usb_device *dev, char *id, int index)
{
char *buf;
......@@ -1166,8 +1163,7 @@ int usb_new_device(struct usb_device *dev)
return 0;
fail:
dev->state = USB_STATE_NOTATTACHED;
clear_bit(dev->devnum, dev->bus->devmap.devicemap);
dev->devnum = -1;
usb_release_address(dev);
usb_put_dev(dev);
return err;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment