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); ...@@ -243,13 +243,13 @@ extern void usb_hc_died (struct usb_hcd *hcd);
extern struct usb_device *usb_alloc_dev(struct usb_device *parent, extern struct usb_device *usb_alloc_dev(struct usb_device *parent,
struct usb_bus *, unsigned port); struct usb_bus *, unsigned port);
extern int usb_new_device(struct usb_device *dev); 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_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 () */ /* exported to hub driver ONLY to support usb_reset_device () */
extern int usb_get_configuration(struct usb_device *dev); extern int usb_get_configuration(struct usb_device *dev);
extern void usb_destroy_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 */ /* use these only before the device's address has been set */
#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30)) #define usb_snddefctrl(dev) ((PIPE_CONTROL << 30))
......
...@@ -1030,6 +1030,21 @@ static int hub_port_debounce(struct usb_device *hub, int port) ...@@ -1030,6 +1030,21 @@ static int hub_port_debounce(struct usb_device *hub, int port)
return ((portstatus&USB_PORT_STAT_CONNECTION)) ? 0 : 1; 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. /* reset device, (re)assign address, get device descriptor.
* device connection is stable, no more debouncing needed. * device connection is stable, no more debouncing needed.
* returns device in USB_STATE_ADDRESS, except on error. * 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) ...@@ -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 (i = 0; i < GET_DESCRIPTOR_TRIES; ++i) {
for (j = 0; j < SET_ADDRESS_TRIES; ++j) { for (j = 0; j < SET_ADDRESS_TRIES; ++j) {
retval = usb_set_address(dev); retval = hub_set_address(dev);
if (retval >= 0) if (retval >= 0)
break; break;
msleep(200); msleep(200);
...@@ -1154,8 +1169,7 @@ hub_port_init (struct usb_device *hub, struct usb_device *dev, int port) ...@@ -1154,8 +1169,7 @@ hub_port_init (struct usb_device *hub, struct usb_device *dev, int port)
dev->devnum, retval); dev->devnum, retval);
fail: fail:
hub_port_disable(hub, port); hub_port_disable(hub, port);
clear_bit(dev->devnum, dev->bus->devmap.devicemap); usb_release_address(dev);
dev->devnum = -1;
usb_put_dev(dev); usb_put_dev(dev);
up(&usb_address0_sem); up(&usb_address0_sem);
return retval; return retval;
......
...@@ -998,12 +998,10 @@ void usb_disconnect(struct usb_device **pdev) ...@@ -998,12 +998,10 @@ void usb_disconnect(struct usb_device **pdev)
*/ */
usb_disable_device(dev, 0); usb_disable_device(dev, 0);
dev_dbg (&dev->dev, "unregistering device\n");
/* Free the device number and remove the /proc/bus/usb entry */ /* Free the device number and remove the /proc/bus/usb entry */
if (dev->devnum > 0) { dev_dbg (&dev->dev, "unregistering device\n");
clear_bit(dev->devnum, dev->bus->devmap.devicemap); usb_release_address(dev);
usbfs_remove_device(dev); usbfs_remove_device(dev);
}
up(&dev->serialize); up(&dev->serialize);
device_unregister(&dev->dev); device_unregister(&dev->dev);
} }
...@@ -1038,24 +1036,23 @@ void usb_choose_address(struct usb_device *dev) ...@@ -1038,24 +1036,23 @@ void usb_choose_address(struct usb_device *dev)
} }
} }
/**
// hub-only!! ... and only exported for reset/reinit path. * usb_release_address - deallocate device address (usbcore-internal)
// otherwise used internally, for usb_new_device() * @dev: newly removed device
int usb_set_address(struct usb_device *dev) *
* 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) {
clear_bit(dev->devnum, dev->bus->devmap.devicemap);
if (dev->devnum == 0) dev->devnum = -1;
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;
} }
static inline void usb_show_string(struct usb_device *dev, char *id, int index) static inline void usb_show_string(struct usb_device *dev, char *id, int index)
{ {
char *buf; char *buf;
...@@ -1166,8 +1163,7 @@ int usb_new_device(struct usb_device *dev) ...@@ -1166,8 +1163,7 @@ int usb_new_device(struct usb_device *dev)
return 0; return 0;
fail: fail:
dev->state = USB_STATE_NOTATTACHED; dev->state = USB_STATE_NOTATTACHED;
clear_bit(dev->devnum, dev->bus->devmap.devicemap); usb_release_address(dev);
dev->devnum = -1;
usb_put_dev(dev); usb_put_dev(dev);
return err; 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