diff options
author | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2011-09-02 11:05:50 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-09-09 15:52:53 -0700 |
commit | 2e27980e6eb78114c4ecbaad1ba71836e3887d18 (patch) | |
tree | f87552d67d6a23090ceb97868f7857ccf2ce6f97 /drivers/usb/host/xhci.h | |
parent | 9af5d71d8e1fc404ad2ac1b568dafa1a2f9b3be2 (diff) | |
download | linux-2e27980e6eb78114c4ecbaad1ba71836e3887d18.tar.gz linux-2e27980e6eb78114c4ecbaad1ba71836e3887d18.tar.bz2 linux-2e27980e6eb78114c4ecbaad1ba71836e3887d18.zip |
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.h')
-rw-r--r-- | drivers/usb/host/xhci.h | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index af15b903e061..050f07b1e790 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -797,7 +797,9 @@ struct xhci_virt_ep { * process the missed tds on the endpoint ring. */ bool skip; + /* Bandwidth checking storage */ struct xhci_bw_info bw_info; + struct list_head bw_endpoint_list; }; enum xhci_overhead_type { @@ -808,6 +810,10 @@ enum xhci_overhead_type { struct xhci_interval_bw { unsigned int num_packets; + /* Sorted by max packet size. + * Head of the list is the greatest max packet size. + */ + struct list_head endpoints; /* How many endpoints of each speed are present. */ unsigned int overhead[3]; }; @@ -1511,6 +1517,15 @@ unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc); unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index); unsigned int xhci_last_valid_endpoint(u32 added_ctxs); void xhci_endpoint_zero(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, struct usb_host_endpoint *ep); +void xhci_drop_ep_from_interval_table(struct xhci_hcd *xhci, + struct xhci_bw_info *ep_bw, + struct xhci_interval_bw_table *bw_table, + struct usb_device *udev, + struct xhci_virt_ep *virt_ep, + struct xhci_tt_bw_info *tt_info); +void xhci_update_tt_active_eps(struct xhci_hcd *xhci, + struct xhci_virt_device *virt_dev, + int old_active_eps); void xhci_clear_endpoint_bw_info(struct xhci_bw_info *bw_info); void xhci_update_bw_info(struct xhci_hcd *xhci, struct xhci_container_ctx *in_ctx, |