aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/message.c
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-04-27 22:58:26 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-16 00:44:49 -0400
commit79abb1ab13cee5ba488210798b6e7bbae0b391ac (patch)
tree9bb008003d30146a092609a59882925640a5c93c /drivers/usb/core/message.c
parent663c30d0829d556efabd5fbd98fb8473da7fe694 (diff)
USB: Support for bandwidth allocation.
Originally, the USB core had no support for allocating bandwidth when a particular configuration or alternate setting for an interface was selected. Instead, the device driver's URB submission would fail if there was not enough bandwidth for a periodic endpoint. Drivers could work around this, by using the scatter-gather list API to guarantee bandwidth. This patch adds host controller API to allow the USB core to allocate or deallocate bandwidth for an endpoint. Endpoints are added to or dropped from a copy of the current schedule by calling add_endpoint() or drop_endpoint(), and then the schedule is atomically evaluated with a call to check_bandwidth(). This allows all the endpoints for a new configuration or alternate setting to be added at the same time that the endpoints from the old configuration or alt setting are dropped. Endpoints must be added to the schedule before any URBs are submitted to them. The HCD must be allowed to reject a new configuration or alt setting before the control transfer is sent to the device requesting the change. It may reject the change because there is not enough bandwidth, not enough internal resources (such as memory on an embedded host controller), or perhaps even for security reasons in a virtualized environment. If the call to check_bandwidth() fails, the USB core must call reset_bandwidth(). This causes the schedule to be reverted back to the state it was in just after the last successful check_bandwidth() call. If the call succeeds, the host controller driver (and hardware) will have changed its internal state to match the new configuration or alternate setting. The USB core can then issue a control transfer to the device to change the configuration or alt setting. This allows the core to test new configurations or alternate settings before unbinding drivers bound to interfaces in the old configuration. WIP: The USB core must add endpoints from all interfaces in a configuration to the schedule, because a driver may claim that interface at any time. A slight optimization might be to add the endpoints to the schedule once a driver claims that interface. FIXME This patch does not cover changing alternate settings, but it does handle a configuration change or de-configuration. FIXME The code for managing the schedule is currently HCD specific. A generic scheduling algorithm could be added for host controllers without built-in scheduling support. For now, if a host controller does not define the check_bandwidth() function, the call to usb_hcd_check_bandwidth() will always succeed. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core/message.c')
-rw-r--r--drivers/usb/core/message.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 9bd26dec7599..3a2e69ec2f29 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -510,6 +510,10 @@ EXPORT_SYMBOL_GPL(usb_sg_init);
510 * could be transferred. That capability is less useful for low or full 510 * could be transferred. That capability is less useful for low or full
511 * speed interrupt endpoints, which allow at most one packet per millisecond, 511 * speed interrupt endpoints, which allow at most one packet per millisecond,
512 * of at most 8 or 64 bytes (respectively). 512 * of at most 8 or 64 bytes (respectively).
513 *
514 * It is not necessary to call this function to reserve bandwidth for devices
515 * under an xHCI host controller, as the bandwidth is reserved when the
516 * configuration or interface alt setting is selected.
513 */ 517 */
514void usb_sg_wait(struct usb_sg_request *io) 518void usb_sg_wait(struct usb_sg_request *io)
515{ 519{
@@ -1653,6 +1657,21 @@ free_interfaces:
1653 if (ret) 1657 if (ret)
1654 goto free_interfaces; 1658 goto free_interfaces;
1655 1659
1660 /* Make sure we have bandwidth (and available HCD resources) for this
1661 * configuration. Remove endpoints from the schedule if we're dropping
1662 * this configuration to set configuration 0. After this point, the
1663 * host controller will not allow submissions to dropped endpoints. If
1664 * this call fails, the device state is unchanged.
1665 */
1666 if (cp)
1667 ret = usb_hcd_check_bandwidth(dev, cp, NULL);
1668 else
1669 ret = usb_hcd_check_bandwidth(dev, NULL, NULL);
1670 if (ret < 0) {
1671 usb_autosuspend_device(dev);
1672 goto free_interfaces;
1673 }
1674
1656 /* if it's already configured, clear out old state first. 1675 /* if it's already configured, clear out old state first.
1657 * getting rid of old interfaces means unbinding their drivers. 1676 * getting rid of old interfaces means unbinding their drivers.
1658 */ 1677 */
@@ -1675,6 +1694,7 @@ free_interfaces:
1675 dev->actconfig = cp; 1694 dev->actconfig = cp;
1676 if (!cp) { 1695 if (!cp) {
1677 usb_set_device_state(dev, USB_STATE_ADDRESS); 1696 usb_set_device_state(dev, USB_STATE_ADDRESS);
1697 usb_hcd_check_bandwidth(dev, NULL, NULL);
1678 usb_autosuspend_device(dev); 1698 usb_autosuspend_device(dev);
1679 goto free_interfaces; 1699 goto free_interfaces;
1680 } 1700 }