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

USB: address-0 handling during device initialization

This patch (as947) changes the device initialization and enumeration
code in hub.c; now udev->devnum will be set to 0 while the device is
being accessed at address 0.  Until now this wasn't needed because the
address value was passed as part of urb->pipe; without that field the
device address must be stored elsewhere.
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 5e60a161
...@@ -1481,6 +1481,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1, ...@@ -1481,6 +1481,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
case 0: case 0:
/* TRSTRCY = 10 ms; plus some extra */ /* TRSTRCY = 10 ms; plus some extra */
msleep(10 + 40); msleep(10 + 40);
udev->devnum = 0; /* Device now at address 0 */
/* FALL THROUGH */ /* FALL THROUGH */
case -ENOTCONN: case -ENOTCONN:
case -ENODEV: case -ENODEV:
...@@ -2005,20 +2006,21 @@ static void ep0_reinit(struct usb_device *udev) ...@@ -2005,20 +2006,21 @@ static void ep0_reinit(struct usb_device *udev)
#define usb_sndaddr0pipe() (PIPE_CONTROL << 30) #define usb_sndaddr0pipe() (PIPE_CONTROL << 30)
#define usb_rcvaddr0pipe() ((PIPE_CONTROL << 30) | USB_DIR_IN) #define usb_rcvaddr0pipe() ((PIPE_CONTROL << 30) | USB_DIR_IN)
static int hub_set_address(struct usb_device *udev) static int hub_set_address(struct usb_device *udev, int devnum)
{ {
int retval; int retval;
if (udev->devnum == 0) if (devnum <= 1)
return -EINVAL; return -EINVAL;
if (udev->state == USB_STATE_ADDRESS) if (udev->state == USB_STATE_ADDRESS)
return 0; return 0;
if (udev->state != USB_STATE_DEFAULT) if (udev->state != USB_STATE_DEFAULT)
return -EINVAL; return -EINVAL;
retval = usb_control_msg(udev, usb_sndaddr0pipe(), retval = usb_control_msg(udev, usb_sndaddr0pipe(),
USB_REQ_SET_ADDRESS, 0, udev->devnum, 0, USB_REQ_SET_ADDRESS, 0, devnum, 0,
NULL, 0, USB_CTRL_SET_TIMEOUT); NULL, 0, USB_CTRL_SET_TIMEOUT);
if (retval == 0) { if (retval == 0) {
udev->devnum = devnum; /* Device now using proper address */
usb_set_device_state(udev, USB_STATE_ADDRESS); usb_set_device_state(udev, USB_STATE_ADDRESS);
ep0_reinit(udev); ep0_reinit(udev);
} }
...@@ -2045,6 +2047,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, ...@@ -2045,6 +2047,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
unsigned delay = HUB_SHORT_RESET_TIME; unsigned delay = HUB_SHORT_RESET_TIME;
enum usb_device_speed oldspeed = udev->speed; enum usb_device_speed oldspeed = udev->speed;
char *speed, *type; char *speed, *type;
int devnum = udev->devnum;
/* root hub ports have a slightly longer reset period /* root hub ports have a slightly longer reset period
* (from USB 2.0 spec, section 7.1.7.5) * (from USB 2.0 spec, section 7.1.7.5)
...@@ -2115,7 +2118,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, ...@@ -2115,7 +2118,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
dev_info (&udev->dev, dev_info (&udev->dev,
"%s %s speed %sUSB device using %s and address %d\n", "%s %s speed %sUSB device using %s and address %d\n",
(udev->config) ? "reset" : "new", speed, type, (udev->config) ? "reset" : "new", speed, type,
udev->bus->controller->driver->name, udev->devnum); udev->bus->controller->driver->name, devnum);
/* Set up TT records, if needed */ /* Set up TT records, if needed */
if (hdev->tt) { if (hdev->tt) {
...@@ -2202,7 +2205,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, ...@@ -2202,7 +2205,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
} }
for (j = 0; j < SET_ADDRESS_TRIES; ++j) { for (j = 0; j < SET_ADDRESS_TRIES; ++j) {
retval = hub_set_address(udev); retval = hub_set_address(udev, devnum);
if (retval >= 0) if (retval >= 0)
break; break;
msleep(200); msleep(200);
...@@ -2210,7 +2213,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, ...@@ -2210,7 +2213,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
if (retval < 0) { if (retval < 0) {
dev_err(&udev->dev, dev_err(&udev->dev,
"device not accepting address %d, error %d\n", "device not accepting address %d, error %d\n",
udev->devnum, retval); devnum, retval);
goto fail; goto fail;
} }
...@@ -2263,8 +2266,10 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, ...@@ -2263,8 +2266,10 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
retval = 0; retval = 0;
fail: fail:
if (retval) if (retval) {
hub_port_disable(hub, port1, 0); hub_port_disable(hub, port1, 0);
udev->devnum = devnum; /* for disconnect processing */
}
mutex_unlock(&usb_address0_mutex); mutex_unlock(&usb_address0_mutex);
return retval; return retval;
} }
......
...@@ -284,9 +284,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) ...@@ -284,9 +284,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
if (!urb || urb->hcpriv || !urb->complete) if (!urb || urb->hcpriv || !urb->complete)
return -EINVAL; return -EINVAL;
if (!(dev = urb->dev) || if (!(dev = urb->dev) || dev->state < USB_STATE_DEFAULT)
(dev->state < USB_STATE_DEFAULT) ||
(!dev->bus) || (dev->devnum <= 0))
return -ENODEV; return -ENODEV;
if (dev->bus->controller->power.power_state.event != PM_EVENT_ON if (dev->bus->controller->power.power_state.event != PM_EVENT_ON
|| dev->state == USB_STATE_SUSPENDED) || dev->state == USB_STATE_SUSPENDED)
......
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