aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-mem.c
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2011-09-02 14:05:50 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-09-09 18:52:53 -0400
commit2e27980e6eb78114c4ecbaad1ba71836e3887d18 (patch)
treef87552d67d6a23090ceb97868f7857ccf2ce6f97 /drivers/usb/host/xhci-mem.c
parent9af5d71d8e1fc404ad2ac1b568dafa1a2f9b3be2 (diff)
xhci: Track interval bandwidth tables per port/TT.
In order to update the root port or TT's bandwidth interval table, we will need to keep track of a list of endpoints, per interval. That way we can easily know the new largest max packet size when we have to remove an endpoint. Add an endpoint list for each root port or TT structure, sorted by endpoint max packet size. Insert new endpoints into the list such that the head of the list always has the endpoint with the greatest max packet size. Only insert endpoints and update the interval table with new information when those endpoints are periodic. Make sure to update the number of active TTs when we add or drop periodic endpoints. A TT is only considered active if it has one or more periodic endpoints attached (control and bulk are best effort, and counted in the 20% reserved on the high speed bus). If the number of active endpoints for a TT was zero, and it's now non-zero, increment the number of active TTs for the rootport. If the number of active endpoints was non-zero, and it's now zero, decrement the number of active TTs. We have to be careful when we're checking the bandwidth for a new configuration/alt setting. If we don't have enough bandwidth, we need to be able to "roll back" the bandwidth information stored in the endpoint and the root port/TT interval bandwidth table. We can't just create a copy of the interval bandwidth table, modify it, and check the bandwidth with the copy because we have lists of endpoints and entries can't be on more than one list. Instead, we copy the old endpoint bandwidth information, and use it to revert the interval table when the bandwidth check fails. We don't check the bandwidth after endpoints are dropped from the interval table when a device is reset or freed after a disconnect, because having endpoints use less bandwidth should not push the bandwidth usage over the limits. Besides which, we can't fail a device disconnect. 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/host/xhci-mem.c')
-rw-r--r--drivers/usb/host/xhci-mem.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 9451d94b78d9..1c5c9ba141db 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -783,6 +783,7 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
783{ 783{
784 struct xhci_virt_device *dev; 784 struct xhci_virt_device *dev;
785 int i; 785 int i;
786 int old_active_eps = 0;
786 787
787 /* Slot ID 0 is reserved */ 788 /* Slot ID 0 is reserved */
788 if (slot_id == 0 || !xhci->devs[slot_id]) 789 if (slot_id == 0 || !xhci->devs[slot_id])
@@ -793,15 +794,29 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
793 if (!dev) 794 if (!dev)
794 return; 795 return;
795 796
797 if (dev->tt_info)
798 old_active_eps = dev->tt_info->active_eps;
799
796 for (i = 0; i < 31; ++i) { 800 for (i = 0; i < 31; ++i) {
797 if (dev->eps[i].ring) 801 if (dev->eps[i].ring)
798 xhci_ring_free(xhci, dev->eps[i].ring); 802 xhci_ring_free(xhci, dev->eps[i].ring);
799 if (dev->eps[i].stream_info) 803 if (dev->eps[i].stream_info)
800 xhci_free_stream_info(xhci, 804 xhci_free_stream_info(xhci,
801 dev->eps[i].stream_info); 805 dev->eps[i].stream_info);
806 /* Endpoints on the TT/root port lists should have been removed
807 * when usb_disable_device() was called for the device.
808 * We can't drop them anyway, because the udev might have gone
809 * away by this point, and we can't tell what speed it was.
810 */
811 if (!list_empty(&dev->eps[i].bw_endpoint_list))
812 xhci_warn(xhci, "Slot %u endpoint %u "
813 "not removed from BW list!\n",
814 slot_id, i);
802 } 815 }
803 /* If this is a hub, free the TT(s) from the TT list */ 816 /* If this is a hub, free the TT(s) from the TT list */
804 xhci_free_tt_info(xhci, dev, slot_id); 817 xhci_free_tt_info(xhci, dev, slot_id);
818 /* If necessary, update the number of active TTs on this root port */
819 xhci_update_tt_active_eps(xhci, dev, old_active_eps);
805 820
806 if (dev->ring_cache) { 821 if (dev->ring_cache) {
807 for (i = 0; i < dev->num_rings_cached; i++) 822 for (i = 0; i < dev->num_rings_cached; i++)
@@ -855,6 +870,7 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
855 for (i = 0; i < 31; i++) { 870 for (i = 0; i < 31; i++) {
856 xhci_init_endpoint_timer(xhci, &dev->eps[i]); 871 xhci_init_endpoint_timer(xhci, &dev->eps[i]);
857 INIT_LIST_HEAD(&dev->eps[i].cancelled_td_list); 872 INIT_LIST_HEAD(&dev->eps[i].cancelled_td_list);
873 INIT_LIST_HEAD(&dev->eps[i].bw_endpoint_list);
858 } 874 }
859 875
860 /* Allocate endpoint 0 ring */ 876 /* Allocate endpoint 0 ring */
@@ -1994,7 +2010,7 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
1994 __le32 __iomem *addr; 2010 __le32 __iomem *addr;
1995 u32 offset; 2011 u32 offset;
1996 unsigned int num_ports; 2012 unsigned int num_ports;
1997 int i, port_index; 2013 int i, j, port_index;
1998 2014
1999 addr = &xhci->cap_regs->hcc_params; 2015 addr = &xhci->cap_regs->hcc_params;
2000 offset = XHCI_HCC_EXT_CAPS(xhci_readl(xhci, addr)); 2016 offset = XHCI_HCC_EXT_CAPS(xhci_readl(xhci, addr));
@@ -2012,8 +2028,14 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
2012 xhci->rh_bw = kzalloc(sizeof(*xhci->rh_bw)*num_ports, flags); 2028 xhci->rh_bw = kzalloc(sizeof(*xhci->rh_bw)*num_ports, flags);
2013 if (!xhci->rh_bw) 2029 if (!xhci->rh_bw)
2014 return -ENOMEM; 2030 return -ENOMEM;
2015 for (i = 0; i < num_ports; i++) 2031 for (i = 0; i < num_ports; i++) {
2032 struct xhci_interval_bw_table *bw_table;
2033
2016 INIT_LIST_HEAD(&xhci->rh_bw[i].tts); 2034 INIT_LIST_HEAD(&xhci->rh_bw[i].tts);
2035 bw_table = &xhci->rh_bw[i].bw_table;
2036 for (j = 0; j < XHCI_MAX_INTERVAL; j++)
2037 INIT_LIST_HEAD(&bw_table->interval_bw[j].endpoints);
2038 }
2017 2039
2018 /* 2040 /*
2019 * For whatever reason, the first capability offset is from the 2041 * For whatever reason, the first capability offset is from the