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: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
5e60a16139
commit
4326ed0be9
@@ -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)
|
|||||||
#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,
|
|||||||
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)
|
||||||
@@ -2074,7 +2077,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
oldspeed = udev->speed;
|
oldspeed = udev->speed;
|
||||||
|
|
||||||
/* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
|
/* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
|
||||||
* it's fixed size except for full speed devices.
|
* it's fixed size except for full speed devices.
|
||||||
* For Wireless USB devices, ep0 max packet is always 512 (tho
|
* For Wireless USB devices, ep0 max packet is always 512 (tho
|
||||||
@@ -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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
||||||
|
Reference in New Issue
Block a user