aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/core/hcd.c56
-rw-r--r--drivers/usb/core/hcd.h19
-rw-r--r--drivers/usb/core/hub.c27
-rw-r--r--drivers/usb/core/message.c69
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 */
1604int usb_hcd_check_bandwidth(struct usb_device *udev, 1618int 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);
1670reset: 1701reset:
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,
290extern void usb_hcd_reset_endpoint(struct usb_device *udev, 304extern void usb_hcd_reset_endpoint(struct usb_device *udev,
291 struct usb_host_endpoint *ep); 305 struct usb_host_endpoint *ep);
292extern void usb_hcd_synchronize_unlinks(struct usb_device *udev); 306extern void usb_hcd_synchronize_unlinks(struct usb_device *udev);
293extern int usb_hcd_check_bandwidth(struct usb_device *udev, 307extern 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);
296extern int usb_hcd_get_frame_number(struct usb_device *udev); 311extern int usb_hcd_get_frame_number(struct usb_device *udev);
297 312
298extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver, 313extern 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) {
1473reset_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