diff options
| -rw-r--r-- | drivers/usb/core/hcd.c | 56 | ||||
| -rw-r--r-- | drivers/usb/core/hcd.h | 19 | ||||
| -rw-r--r-- | drivers/usb/core/hub.c | 27 | ||||
| -rw-r--r-- | drivers/usb/core/message.c | 69 |
4 files changed, 149 insertions, 22 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index fc235b02ff27..6dac3b802d41 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <asm/unaligned.h> | 38 | #include <asm/unaligned.h> |
| 39 | #include <linux/platform_device.h> | 39 | #include <linux/platform_device.h> |
| 40 | #include <linux/workqueue.h> | 40 | #include <linux/workqueue.h> |
| 41 | #include <linux/mutex.h> | ||
| 41 | 42 | ||
| 42 | #include <linux/usb.h> | 43 | #include <linux/usb.h> |
| 43 | 44 | ||
| @@ -1595,15 +1596,29 @@ rescan: | |||
| 1595 | } | 1596 | } |
| 1596 | } | 1597 | } |
| 1597 | 1598 | ||
| 1598 | /* Check whether a new configuration or alt setting for an interface | 1599 | /** |
| 1599 | * will exceed the bandwidth for the bus (or the host controller resources). | 1600 | * Check whether a new bandwidth setting exceeds the bus bandwidth. |
| 1600 | * Only pass in a non-NULL config or interface, not both! | 1601 | * @new_config: new configuration to install |
| 1601 | * Passing NULL for both new_config and new_intf means the device will be | 1602 | * @cur_alt: the current alternate interface setting |
| 1602 | * de-configured by issuing a set configuration 0 command. | 1603 | * @new_alt: alternate interface setting that is being installed |
| 1604 | * | ||
| 1605 | * To change configurations, pass in the new configuration in new_config, | ||
| 1606 | * and pass NULL for cur_alt and new_alt. | ||
| 1607 | * | ||
| 1608 | * To reset a device's configuration (put the device in the ADDRESSED state), | ||
| 1609 | * pass in NULL for new_config, cur_alt, and new_alt. | ||
| 1610 | * | ||
| 1611 | * To change alternate interface settings, pass in NULL for new_config, | ||
| 1612 | * pass in the current alternate interface setting in cur_alt, | ||
| 1613 | * and pass in the new alternate interface setting in new_alt. | ||
| 1614 | * | ||
| 1615 | * Returns an error if the requested bandwidth change exceeds the | ||
| 1616 | * bus bandwidth or host controller internal resources. | ||
| 1603 | */ | 1617 | */ |
| 1604 | int usb_hcd_check_bandwidth(struct usb_device *udev, | 1618 | int usb_hcd_alloc_bandwidth(struct usb_device *udev, |
| 1605 | struct usb_host_config *new_config, | 1619 | struct usb_host_config *new_config, |
| 1606 | struct usb_interface *new_intf) | 1620 | struct usb_host_interface *cur_alt, |
| 1621 | struct usb_host_interface *new_alt) | ||
| 1607 | { | 1622 | { |
| 1608 | int num_intfs, i, j; | 1623 | int num_intfs, i, j; |
| 1609 | struct usb_host_interface *alt = NULL; | 1624 | struct usb_host_interface *alt = NULL; |
| @@ -1616,7 +1631,7 @@ int usb_hcd_check_bandwidth(struct usb_device *udev, | |||
| 1616 | return 0; | 1631 | return 0; |
| 1617 | 1632 | ||
| 1618 | /* Configuration is being removed - set configuration 0 */ | 1633 | /* Configuration is being removed - set configuration 0 */ |
| 1619 | if (!new_config && !new_intf) { | 1634 | if (!new_config && !cur_alt) { |
| 1620 | for (i = 1; i < 16; ++i) { | 1635 | for (i = 1; i < 16; ++i) { |
| 1621 | ep = udev->ep_out[i]; | 1636 | ep = udev->ep_out[i]; |
| 1622 | if (ep) | 1637 | if (ep) |
| @@ -1655,10 +1670,10 @@ int usb_hcd_check_bandwidth(struct usb_device *udev, | |||
| 1655 | for (i = 0; i < num_intfs; ++i) { | 1670 | for (i = 0; i < num_intfs; ++i) { |
| 1656 | /* Set up endpoints for alternate interface setting 0 */ | 1671 | /* Set up endpoints for alternate interface setting 0 */ |
| 1657 | alt = usb_find_alt_setting(new_config, i, 0); | 1672 | alt = usb_find_alt_setting(new_config, i, 0); |
| 1658 | if (!alt) { | 1673 | if (!alt) |
| 1659 | printk(KERN_DEBUG "Did not find alt setting 0 for intf %d\n", i); | 1674 | /* No alt setting 0? Pick the first setting. */ |
| 1660 | continue; | 1675 | alt = &new_config->intf_cache[i]->altsetting[0]; |
| 1661 | } | 1676 | |
| 1662 | for (j = 0; j < alt->desc.bNumEndpoints; j++) { | 1677 | for (j = 0; j < alt->desc.bNumEndpoints; j++) { |
| 1663 | ret = hcd->driver->add_endpoint(hcd, udev, &alt->endpoint[j]); | 1678 | ret = hcd->driver->add_endpoint(hcd, udev, &alt->endpoint[j]); |
| 1664 | if (ret < 0) | 1679 | if (ret < 0) |
| @@ -1666,6 +1681,22 @@ int usb_hcd_check_bandwidth(struct usb_device *udev, | |||
| 1666 | } | 1681 | } |
| 1667 | } | 1682 | } |
| 1668 | } | 1683 | } |
| 1684 | if (cur_alt && new_alt) { | ||
| 1685 | /* Drop all the endpoints in the current alt setting */ | ||
| 1686 | for (i = 0; i < cur_alt->desc.bNumEndpoints; i++) { | ||
| 1687 | ret = hcd->driver->drop_endpoint(hcd, udev, | ||
| 1688 | &cur_alt->endpoint[i]); | ||
| 1689 | if (ret < 0) | ||
| 1690 | goto reset; | ||
| 1691 | } | ||
| 1692 | /* Add all the endpoints in the new alt setting */ | ||
| 1693 | for (i = 0; i < new_alt->desc.bNumEndpoints; i++) { | ||
| 1694 | ret = hcd->driver->add_endpoint(hcd, udev, | ||
| 1695 | &new_alt->endpoint[i]); | ||
| 1696 | if (ret < 0) | ||
| 1697 | goto reset; | ||
| 1698 | } | ||
| 1699 | } | ||
| 1669 | ret = hcd->driver->check_bandwidth(hcd, udev); | 1700 | ret = hcd->driver->check_bandwidth(hcd, udev); |
| 1670 | reset: | 1701 | reset: |
| 1671 | if (ret < 0) | 1702 | if (ret < 0) |
| @@ -1982,6 +2013,7 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, | |||
| 1982 | #ifdef CONFIG_PM | 2013 | #ifdef CONFIG_PM |
| 1983 | INIT_WORK(&hcd->wakeup_work, hcd_resume_work); | 2014 | INIT_WORK(&hcd->wakeup_work, hcd_resume_work); |
| 1984 | #endif | 2015 | #endif |
| 2016 | mutex_init(&hcd->bandwidth_mutex); | ||
| 1985 | 2017 | ||
| 1986 | hcd->driver = driver; | 2018 | hcd->driver = driver; |
| 1987 | hcd->product_desc = (driver->product_desc) ? driver->product_desc : | 2019 | hcd->product_desc = (driver->product_desc) ? driver->product_desc : |
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 79782a1c43f6..d8b43aee581e 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h | |||
| @@ -111,6 +111,20 @@ struct usb_hcd { | |||
| 111 | u64 rsrc_len; /* memory/io resource length */ | 111 | u64 rsrc_len; /* memory/io resource length */ |
| 112 | unsigned power_budget; /* in mA, 0 = no limit */ | 112 | unsigned power_budget; /* in mA, 0 = no limit */ |
| 113 | 113 | ||
| 114 | /* bandwidth_mutex should be taken before adding or removing | ||
| 115 | * any new bus bandwidth constraints: | ||
| 116 | * 1. Before adding a configuration for a new device. | ||
| 117 | * 2. Before removing the configuration to put the device into | ||
| 118 | * the addressed state. | ||
| 119 | * 3. Before selecting a different configuration. | ||
| 120 | * 4. Before selecting an alternate interface setting. | ||
| 121 | * | ||
| 122 | * bandwidth_mutex should be dropped after a successful control message | ||
| 123 | * to the device, or resetting the bandwidth after a failed attempt. | ||
| 124 | */ | ||
| 125 | struct mutex bandwidth_mutex; | ||
| 126 | |||
| 127 | |||
| 114 | #define HCD_BUFFER_POOLS 4 | 128 | #define HCD_BUFFER_POOLS 4 |
| 115 | struct dma_pool *pool [HCD_BUFFER_POOLS]; | 129 | struct dma_pool *pool [HCD_BUFFER_POOLS]; |
| 116 | 130 | ||
| @@ -290,9 +304,10 @@ extern void usb_hcd_disable_endpoint(struct usb_device *udev, | |||
| 290 | extern void usb_hcd_reset_endpoint(struct usb_device *udev, | 304 | extern void usb_hcd_reset_endpoint(struct usb_device *udev, |
| 291 | struct usb_host_endpoint *ep); | 305 | struct usb_host_endpoint *ep); |
| 292 | extern void usb_hcd_synchronize_unlinks(struct usb_device *udev); | 306 | extern void usb_hcd_synchronize_unlinks(struct usb_device *udev); |
| 293 | extern int usb_hcd_check_bandwidth(struct usb_device *udev, | 307 | extern int usb_hcd_alloc_bandwidth(struct usb_device *udev, |
| 294 | struct usb_host_config *new_config, | 308 | struct usb_host_config *new_config, |
| 295 | struct usb_interface *new_intf); | 309 | struct usb_host_interface *old_alt, |
| 310 | struct usb_host_interface *new_alt); | ||
| 296 | extern int usb_hcd_get_frame_number(struct usb_device *udev); | 311 | extern int usb_hcd_get_frame_number(struct usb_device *udev); |
| 297 | 312 | ||
| 298 | extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver, | 313 | extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver, |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index b38fd6730e2a..e4b0e28f7453 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
| @@ -3599,6 +3599,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) | |||
| 3599 | { | 3599 | { |
| 3600 | struct usb_device *parent_hdev = udev->parent; | 3600 | struct usb_device *parent_hdev = udev->parent; |
| 3601 | struct usb_hub *parent_hub; | 3601 | struct usb_hub *parent_hub; |
| 3602 | struct usb_hcd *hcd = bus_to_hcd(udev->bus); | ||
| 3602 | struct usb_device_descriptor descriptor = udev->descriptor; | 3603 | struct usb_device_descriptor descriptor = udev->descriptor; |
| 3603 | int i, ret = 0; | 3604 | int i, ret = 0; |
| 3604 | int port1 = udev->portnum; | 3605 | int port1 = udev->portnum; |
| @@ -3642,6 +3643,16 @@ static int usb_reset_and_verify_device(struct usb_device *udev) | |||
| 3642 | /* Restore the device's previous configuration */ | 3643 | /* Restore the device's previous configuration */ |
| 3643 | if (!udev->actconfig) | 3644 | if (!udev->actconfig) |
| 3644 | goto done; | 3645 | goto done; |
| 3646 | |||
| 3647 | mutex_lock(&hcd->bandwidth_mutex); | ||
| 3648 | ret = usb_hcd_alloc_bandwidth(udev, udev->actconfig, NULL, NULL); | ||
| 3649 | if (ret < 0) { | ||
| 3650 | dev_warn(&udev->dev, | ||
| 3651 | "Busted HC? Not enough HCD resources for " | ||
| 3652 | "old configuration.\n"); | ||
| 3653 | mutex_unlock(&hcd->bandwidth_mutex); | ||
| 3654 | goto re_enumerate; | ||
| 3655 | } | ||
| 3645 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | 3656 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), |
| 3646 | USB_REQ_SET_CONFIGURATION, 0, | 3657 | USB_REQ_SET_CONFIGURATION, 0, |
| 3647 | udev->actconfig->desc.bConfigurationValue, 0, | 3658 | udev->actconfig->desc.bConfigurationValue, 0, |
| @@ -3650,8 +3661,10 @@ static int usb_reset_and_verify_device(struct usb_device *udev) | |||
| 3650 | dev_err(&udev->dev, | 3661 | dev_err(&udev->dev, |
| 3651 | "can't restore configuration #%d (error=%d)\n", | 3662 | "can't restore configuration #%d (error=%d)\n", |
| 3652 | udev->actconfig->desc.bConfigurationValue, ret); | 3663 | udev->actconfig->desc.bConfigurationValue, ret); |
| 3664 | mutex_unlock(&hcd->bandwidth_mutex); | ||
| 3653 | goto re_enumerate; | 3665 | goto re_enumerate; |
| 3654 | } | 3666 | } |
| 3667 | mutex_unlock(&hcd->bandwidth_mutex); | ||
| 3655 | usb_set_device_state(udev, USB_STATE_CONFIGURED); | 3668 | usb_set_device_state(udev, USB_STATE_CONFIGURED); |
| 3656 | 3669 | ||
| 3657 | /* Put interfaces back into the same altsettings as before. | 3670 | /* Put interfaces back into the same altsettings as before. |
| @@ -3661,7 +3674,8 @@ static int usb_reset_and_verify_device(struct usb_device *udev) | |||
| 3661 | * endpoint state. | 3674 | * endpoint state. |
| 3662 | */ | 3675 | */ |
| 3663 | for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { | 3676 | for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { |
| 3664 | struct usb_interface *intf = udev->actconfig->interface[i]; | 3677 | struct usb_host_config *config = udev->actconfig; |
| 3678 | struct usb_interface *intf = config->interface[i]; | ||
| 3665 | struct usb_interface_descriptor *desc; | 3679 | struct usb_interface_descriptor *desc; |
| 3666 | 3680 | ||
| 3667 | desc = &intf->cur_altsetting->desc; | 3681 | desc = &intf->cur_altsetting->desc; |
| @@ -3670,6 +3684,17 @@ static int usb_reset_and_verify_device(struct usb_device *udev) | |||
| 3670 | usb_enable_interface(udev, intf, true); | 3684 | usb_enable_interface(udev, intf, true); |
| 3671 | ret = 0; | 3685 | ret = 0; |
| 3672 | } else { | 3686 | } else { |
| 3687 | /* We've just reset the device, so it will think alt | ||
| 3688 | * setting 0 is installed. For usb_set_interface() to | ||
| 3689 | * work properly, we need to set the current alternate | ||
| 3690 | * interface setting to 0 (or the first alt setting, if | ||
| 3691 | * the device doesn't have alt setting 0). | ||
| 3692 | */ | ||
| 3693 | intf->cur_altsetting = | ||
| 3694 | usb_find_alt_setting(config, i, 0); | ||
| 3695 | if (!intf->cur_altsetting) | ||
| 3696 | intf->cur_altsetting = | ||
| 3697 | &config->intf_cache[i]->altsetting[0]; | ||
| 3673 | ret = usb_set_interface(udev, desc->bInterfaceNumber, | 3698 | ret = usb_set_interface(udev, desc->bInterfaceNumber, |
| 3674 | desc->bAlternateSetting); | 3699 | desc->bAlternateSetting); |
| 3675 | } | 3700 | } |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index adb9c8ee0c1f..ed83f2b1d551 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
| @@ -1298,6 +1298,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) | |||
| 1298 | { | 1298 | { |
| 1299 | struct usb_interface *iface; | 1299 | struct usb_interface *iface; |
| 1300 | struct usb_host_interface *alt; | 1300 | struct usb_host_interface *alt; |
| 1301 | struct usb_hcd *hcd = bus_to_hcd(dev->bus); | ||
| 1301 | int ret; | 1302 | int ret; |
| 1302 | int manual = 0; | 1303 | int manual = 0; |
| 1303 | unsigned int epaddr; | 1304 | unsigned int epaddr; |
| @@ -1320,6 +1321,18 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) | |||
| 1320 | return -EINVAL; | 1321 | return -EINVAL; |
| 1321 | } | 1322 | } |
| 1322 | 1323 | ||
| 1324 | /* Make sure we have enough bandwidth for this alternate interface. | ||
| 1325 | * Remove the current alt setting and add the new alt setting. | ||
| 1326 | */ | ||
| 1327 | mutex_lock(&hcd->bandwidth_mutex); | ||
| 1328 | ret = usb_hcd_alloc_bandwidth(dev, NULL, iface->cur_altsetting, alt); | ||
| 1329 | if (ret < 0) { | ||
| 1330 | dev_info(&dev->dev, "Not enough bandwidth for altsetting %d\n", | ||
| 1331 | alternate); | ||
| 1332 | mutex_unlock(&hcd->bandwidth_mutex); | ||
| 1333 | return ret; | ||
| 1334 | } | ||
| 1335 | |||
| 1323 | if (dev->quirks & USB_QUIRK_NO_SET_INTF) | 1336 | if (dev->quirks & USB_QUIRK_NO_SET_INTF) |
| 1324 | ret = -EPIPE; | 1337 | ret = -EPIPE; |
| 1325 | else | 1338 | else |
| @@ -1335,8 +1348,13 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) | |||
| 1335 | "manual set_interface for iface %d, alt %d\n", | 1348 | "manual set_interface for iface %d, alt %d\n", |
| 1336 | interface, alternate); | 1349 | interface, alternate); |
| 1337 | manual = 1; | 1350 | manual = 1; |
| 1338 | } else if (ret < 0) | 1351 | } else if (ret < 0) { |
| 1352 | /* Re-instate the old alt setting */ | ||
| 1353 | usb_hcd_alloc_bandwidth(dev, NULL, alt, iface->cur_altsetting); | ||
| 1354 | mutex_unlock(&hcd->bandwidth_mutex); | ||
| 1339 | return ret; | 1355 | return ret; |
| 1356 | } | ||
| 1357 | mutex_unlock(&hcd->bandwidth_mutex); | ||
| 1340 | 1358 | ||
| 1341 | /* FIXME drivers shouldn't need to replicate/bugfix the logic here | 1359 | /* FIXME drivers shouldn't need to replicate/bugfix the logic here |
| 1342 | * when they implement async or easily-killable versions of this or | 1360 | * when they implement async or easily-killable versions of this or |
| @@ -1418,6 +1436,7 @@ int usb_reset_configuration(struct usb_device *dev) | |||
| 1418 | { | 1436 | { |
| 1419 | int i, retval; | 1437 | int i, retval; |
| 1420 | struct usb_host_config *config; | 1438 | struct usb_host_config *config; |
| 1439 | struct usb_hcd *hcd = bus_to_hcd(dev->bus); | ||
| 1421 | 1440 | ||
| 1422 | if (dev->state == USB_STATE_SUSPENDED) | 1441 | if (dev->state == USB_STATE_SUSPENDED) |
| 1423 | return -EHOSTUNREACH; | 1442 | return -EHOSTUNREACH; |
| @@ -1433,12 +1452,46 @@ int usb_reset_configuration(struct usb_device *dev) | |||
| 1433 | } | 1452 | } |
| 1434 | 1453 | ||
| 1435 | config = dev->actconfig; | 1454 | config = dev->actconfig; |
| 1455 | retval = 0; | ||
| 1456 | mutex_lock(&hcd->bandwidth_mutex); | ||
| 1457 | /* Make sure we have enough bandwidth for each alternate setting 0 */ | ||
| 1458 | for (i = 0; i < config->desc.bNumInterfaces; i++) { | ||
| 1459 | struct usb_interface *intf = config->interface[i]; | ||
| 1460 | struct usb_host_interface *alt; | ||
| 1461 | |||
| 1462 | alt = usb_altnum_to_altsetting(intf, 0); | ||
| 1463 | if (!alt) | ||
| 1464 | alt = &intf->altsetting[0]; | ||
| 1465 | if (alt != intf->cur_altsetting) | ||
| 1466 | retval = usb_hcd_alloc_bandwidth(dev, NULL, | ||
| 1467 | intf->cur_altsetting, alt); | ||
| 1468 | if (retval < 0) | ||
| 1469 | break; | ||
| 1470 | } | ||
| 1471 | /* If not, reinstate the old alternate settings */ | ||
| 1472 | if (retval < 0) { | ||
| 1473 | reset_old_alts: | ||
| 1474 | for (; i >= 0; i--) { | ||
| 1475 | struct usb_interface *intf = config->interface[i]; | ||
| 1476 | struct usb_host_interface *alt; | ||
| 1477 | |||
| 1478 | alt = usb_altnum_to_altsetting(intf, 0); | ||
| 1479 | if (!alt) | ||
| 1480 | alt = &intf->altsetting[0]; | ||
| 1481 | if (alt != intf->cur_altsetting) | ||
| 1482 | usb_hcd_alloc_bandwidth(dev, NULL, | ||
| 1483 | alt, intf->cur_altsetting); | ||
| 1484 | } | ||
| 1485 | mutex_unlock(&hcd->bandwidth_mutex); | ||
| 1486 | return retval; | ||
| 1487 | } | ||
| 1436 | retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 1488 | retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
| 1437 | USB_REQ_SET_CONFIGURATION, 0, | 1489 | USB_REQ_SET_CONFIGURATION, 0, |
| 1438 | config->desc.bConfigurationValue, 0, | 1490 | config->desc.bConfigurationValue, 0, |
| 1439 | NULL, 0, USB_CTRL_SET_TIMEOUT); | 1491 | NULL, 0, USB_CTRL_SET_TIMEOUT); |
| 1440 | if (retval < 0) | 1492 | if (retval < 0) |
| 1441 | return retval; | 1493 | goto reset_old_alts; |
| 1494 | mutex_unlock(&hcd->bandwidth_mutex); | ||
| 1442 | 1495 | ||
| 1443 | /* re-init hc/hcd interface/endpoint state */ | 1496 | /* re-init hc/hcd interface/endpoint state */ |
| 1444 | for (i = 0; i < config->desc.bNumInterfaces; i++) { | 1497 | for (i = 0; i < config->desc.bNumInterfaces; i++) { |
| @@ -1647,6 +1700,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) | |||
| 1647 | int i, ret; | 1700 | int i, ret; |
| 1648 | struct usb_host_config *cp = NULL; | 1701 | struct usb_host_config *cp = NULL; |
| 1649 | struct usb_interface **new_interfaces = NULL; | 1702 | struct usb_interface **new_interfaces = NULL; |
| 1703 | struct usb_hcd *hcd = bus_to_hcd(dev->bus); | ||
| 1650 | int n, nintf; | 1704 | int n, nintf; |
| 1651 | 1705 | ||
| 1652 | if (dev->authorized == 0 || configuration == -1) | 1706 | if (dev->authorized == 0 || configuration == -1) |
| @@ -1716,12 +1770,11 @@ free_interfaces: | |||
| 1716 | * host controller will not allow submissions to dropped endpoints. If | 1770 | * host controller will not allow submissions to dropped endpoints. If |
| 1717 | * this call fails, the device state is unchanged. | 1771 | * this call fails, the device state is unchanged. |
| 1718 | */ | 1772 | */ |
| 1719 | if (cp) | 1773 | mutex_lock(&hcd->bandwidth_mutex); |
| 1720 | ret = usb_hcd_check_bandwidth(dev, cp, NULL); | 1774 | ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL); |
| 1721 | else | ||
| 1722 | ret = usb_hcd_check_bandwidth(dev, NULL, NULL); | ||
| 1723 | if (ret < 0) { | 1775 | if (ret < 0) { |
| 1724 | usb_autosuspend_device(dev); | 1776 | usb_autosuspend_device(dev); |
| 1777 | mutex_unlock(&hcd->bandwidth_mutex); | ||
| 1725 | goto free_interfaces; | 1778 | goto free_interfaces; |
| 1726 | } | 1779 | } |
| 1727 | 1780 | ||
| @@ -1747,10 +1800,12 @@ free_interfaces: | |||
| 1747 | dev->actconfig = cp; | 1800 | dev->actconfig = cp; |
| 1748 | if (!cp) { | 1801 | if (!cp) { |
| 1749 | usb_set_device_state(dev, USB_STATE_ADDRESS); | 1802 | usb_set_device_state(dev, USB_STATE_ADDRESS); |
| 1750 | usb_hcd_check_bandwidth(dev, NULL, NULL); | 1803 | usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); |
| 1751 | usb_autosuspend_device(dev); | 1804 | usb_autosuspend_device(dev); |
| 1805 | mutex_unlock(&hcd->bandwidth_mutex); | ||
| 1752 | goto free_interfaces; | 1806 | goto free_interfaces; |
| 1753 | } | 1807 | } |
| 1808 | mutex_unlock(&hcd->bandwidth_mutex); | ||
| 1754 | usb_set_device_state(dev, USB_STATE_CONFIGURED); | 1809 | usb_set_device_state(dev, USB_STATE_CONFIGURED); |
| 1755 | 1810 | ||
| 1756 | /* Initialize the new interface structures and the | 1811 | /* Initialize the new interface structures and the |
