aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2011-09-02 14:05:48 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-09-09 18:52:53 -0400
commit9af5d71d8e1fc404ad2ac1b568dafa1a2f9b3be2 (patch)
treed3f3732ada05aaef7ffb76cfbc5d849b0fc421ac /drivers/usb/host
parent839c817ce67178ca3c7c7ad534c571bba1e69ebe (diff)
xhci: Store endpoint bandwidth information.
In the upcoming patches, we'll use some stored endpoint information to make software keep track of the worst-case bandwidth schedule. We need to store several variables associated with each periodic endpoint: - the type of endpoint - Max Packet Size - Mult - Max ESIT payload - Max Burst Size (aka number of packets, stored in one-based form) - the endpoint interval (normalized to powers of 2 microframes) All this information is available to the hardware, and stored in its device output context. However, we need to ensure that the new information is stored before the xHCI driver drops the xhci->lock to wait on the Configure Endpoint command, so that another driver requesting a configuration or alt setting change will see the update. The Configure Endpoint command will never fail on the hardware that needs this software bandwidth checking (assuming the slot is enabled and the flags are set properly), so updating the endpoint info before the command completes should be fine. Until we add in the bandwidth checking code, just update the endpoint information after the Configure Endpoint command completes, and after a Reset Device command completes. Don't bother to clear the endpoint bandwidth info when a device is being freed, since the xhci_virt_ep is just going to be freed anyway. 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')
-rw-r--r--drivers/usb/host/xhci-mem.c63
-rw-r--r--drivers/usb/host/xhci.c2
-rw-r--r--drivers/usb/host/xhci.h31
3 files changed, 96 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 5efb0afff5f6..9451d94b78d9 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1410,6 +1410,69 @@ void xhci_endpoint_zero(struct xhci_hcd *xhci,
1410 */ 1410 */
1411} 1411}
1412 1412
1413void xhci_clear_endpoint_bw_info(struct xhci_bw_info *bw_info)
1414{
1415 bw_info->ep_interval = 0;
1416 bw_info->mult = 0;
1417 bw_info->num_packets = 0;
1418 bw_info->max_packet_size = 0;
1419 bw_info->type = 0;
1420 bw_info->max_esit_payload = 0;
1421}
1422
1423void xhci_update_bw_info(struct xhci_hcd *xhci,
1424 struct xhci_container_ctx *in_ctx,
1425 struct xhci_input_control_ctx *ctrl_ctx,
1426 struct xhci_virt_device *virt_dev)
1427{
1428 struct xhci_bw_info *bw_info;
1429 struct xhci_ep_ctx *ep_ctx;
1430 unsigned int ep_type;
1431 int i;
1432
1433 for (i = 1; i < 31; ++i) {
1434 bw_info = &virt_dev->eps[i].bw_info;
1435
1436 /* We can't tell what endpoint type is being dropped, but
1437 * unconditionally clearing the bandwidth info for non-periodic
1438 * endpoints should be harmless because the info will never be
1439 * set in the first place.
1440 */
1441 if (!EP_IS_ADDED(ctrl_ctx, i) && EP_IS_DROPPED(ctrl_ctx, i)) {
1442 /* Dropped endpoint */
1443 xhci_clear_endpoint_bw_info(bw_info);
1444 continue;
1445 }
1446
1447 if (EP_IS_ADDED(ctrl_ctx, i)) {
1448 ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, i);
1449 ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2));
1450
1451 /* Ignore non-periodic endpoints */
1452 if (ep_type != ISOC_OUT_EP && ep_type != INT_OUT_EP &&
1453 ep_type != ISOC_IN_EP &&
1454 ep_type != INT_IN_EP)
1455 continue;
1456
1457 /* Added or changed endpoint */
1458 bw_info->ep_interval = CTX_TO_EP_INTERVAL(
1459 le32_to_cpu(ep_ctx->ep_info));
1460 bw_info->mult = CTX_TO_EP_MULT(
1461 le32_to_cpu(ep_ctx->ep_info));
1462 /* Number of packets is zero-based in the input context,
1463 * but we want one-based for the interval table.
1464 */
1465 bw_info->num_packets = CTX_TO_MAX_BURST(
1466 le32_to_cpu(ep_ctx->ep_info2)) + 1;
1467 bw_info->max_packet_size = MAX_PACKET_DECODED(
1468 le32_to_cpu(ep_ctx->ep_info2));
1469 bw_info->type = ep_type;
1470 bw_info->max_esit_payload = CTX_TO_MAX_ESIT_PAYLOAD(
1471 le32_to_cpu(ep_ctx->tx_info));
1472 }
1473 }
1474}
1475
1413/* Copy output xhci_ep_ctx to the input xhci_ep_ctx copy. 1476/* Copy output xhci_ep_ctx to the input xhci_ep_ctx copy.
1414 * Useful when you want to change one particular aspect of the endpoint and then 1477 * Useful when you want to change one particular aspect of the endpoint and then
1415 * issue a configure endpoint command. 1478 * issue a configure endpoint command.
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 1657041c19cf..827914643f3e 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1912,6 +1912,7 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
1912 !(le32_to_cpu(ctrl_ctx->add_flags) & (1 << (i + 1)))) 1912 !(le32_to_cpu(ctrl_ctx->add_flags) & (1 << (i + 1))))
1913 xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i); 1913 xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
1914 } 1914 }
1915 xhci_update_bw_info(xhci, virt_dev->in_ctx, ctrl_ctx, virt_dev);
1915 xhci_zero_in_ctx(xhci, virt_dev); 1916 xhci_zero_in_ctx(xhci, virt_dev);
1916 /* 1917 /*
1917 * Install any rings for completely new endpoints or changed endpoints, 1918 * Install any rings for completely new endpoints or changed endpoints,
@@ -2668,6 +2669,7 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
2668 xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i); 2669 xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
2669 last_freed_endpoint = i; 2670 last_freed_endpoint = i;
2670 } 2671 }
2672 xhci_clear_endpoint_bw_info(&virt_dev->eps[i].bw_info);
2671 } 2673 }
2672 xhci_dbg(xhci, "Output context after successful reset device cmd:\n"); 2674 xhci_dbg(xhci, "Output context after successful reset device cmd:\n");
2673 xhci_dbg_ctx(xhci, virt_dev->out_ctx, last_freed_endpoint); 2675 xhci_dbg_ctx(xhci, virt_dev->out_ctx, last_freed_endpoint);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index eee47c8a6ee8..af15b903e061 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -611,11 +611,13 @@ struct xhci_ep_ctx {
611#define EP_STATE_ERROR 4 611#define EP_STATE_ERROR 4
612/* Mult - Max number of burtst within an interval, in EP companion desc. */ 612/* Mult - Max number of burtst within an interval, in EP companion desc. */
613#define EP_MULT(p) (((p) & 0x3) << 8) 613#define EP_MULT(p) (((p) & 0x3) << 8)
614#define CTX_TO_EP_MULT(p) (((p) >> 8) & 0x3)
614/* bits 10:14 are Max Primary Streams */ 615/* bits 10:14 are Max Primary Streams */
615/* bit 15 is Linear Stream Array */ 616/* bit 15 is Linear Stream Array */
616/* Interval - period between requests to an endpoint - 125u increments. */ 617/* Interval - period between requests to an endpoint - 125u increments. */
617#define EP_INTERVAL(p) (((p) & 0xff) << 16) 618#define EP_INTERVAL(p) (((p) & 0xff) << 16)
618#define EP_INTERVAL_TO_UFRAMES(p) (1 << (((p) >> 16) & 0xff)) 619#define EP_INTERVAL_TO_UFRAMES(p) (1 << (((p) >> 16) & 0xff))
620#define CTX_TO_EP_INTERVAL(p) (((p) >> 16) & 0xff)
619#define EP_MAXPSTREAMS_MASK (0x1f << 10) 621#define EP_MAXPSTREAMS_MASK (0x1f << 10)
620#define EP_MAXPSTREAMS(p) (((p) << 10) & EP_MAXPSTREAMS_MASK) 622#define EP_MAXPSTREAMS(p) (((p) << 10) & EP_MAXPSTREAMS_MASK)
621/* Endpoint is set up with a Linear Stream Array (vs. Secondary Stream Array) */ 623/* Endpoint is set up with a Linear Stream Array (vs. Secondary Stream Array) */
@@ -640,6 +642,7 @@ struct xhci_ep_ctx {
640/* bit 6 reserved */ 642/* bit 6 reserved */
641/* bit 7 is Host Initiate Disable - for disabling stream selection */ 643/* bit 7 is Host Initiate Disable - for disabling stream selection */
642#define MAX_BURST(p) (((p)&0xff) << 8) 644#define MAX_BURST(p) (((p)&0xff) << 8)
645#define CTX_TO_MAX_BURST(p) (((p) >> 8) & 0xff)
643#define MAX_PACKET(p) (((p)&0xffff) << 16) 646#define MAX_PACKET(p) (((p)&0xffff) << 16)
644#define MAX_PACKET_MASK (0xffff << 16) 647#define MAX_PACKET_MASK (0xffff << 16)
645#define MAX_PACKET_DECODED(p) (((p) >> 16) & 0xffff) 648#define MAX_PACKET_DECODED(p) (((p) >> 16) & 0xffff)
@@ -652,6 +655,7 @@ struct xhci_ep_ctx {
652/* tx_info bitmasks */ 655/* tx_info bitmasks */
653#define AVG_TRB_LENGTH_FOR_EP(p) ((p) & 0xffff) 656#define AVG_TRB_LENGTH_FOR_EP(p) ((p) & 0xffff)
654#define MAX_ESIT_PAYLOAD_FOR_EP(p) (((p) & 0xffff) << 16) 657#define MAX_ESIT_PAYLOAD_FOR_EP(p) (((p) & 0xffff) << 16)
658#define CTX_TO_MAX_ESIT_PAYLOAD(p) (((p) >> 16) & 0xffff)
655 659
656/* deq bitmasks */ 660/* deq bitmasks */
657#define EP_CTX_CYCLE_MASK (1 << 0) 661#define EP_CTX_CYCLE_MASK (1 << 0)
@@ -670,6 +674,11 @@ struct xhci_input_control_ctx {
670 __le32 rsvd2[6]; 674 __le32 rsvd2[6];
671}; 675};
672 676
677#define EP_IS_ADDED(ctrl_ctx, i) \
678 (le32_to_cpu(ctrl_ctx->add_flags) & (1 << (i + 1)))
679#define EP_IS_DROPPED(ctrl_ctx, i) \
680 (le32_to_cpu(ctrl_ctx->drop_flags) & (1 << (i + 1)))
681
673/* Represents everything that is needed to issue a command on the command ring. 682/* Represents everything that is needed to issue a command on the command ring.
674 * It's useful to pre-allocate these for commands that cannot fail due to 683 * It's useful to pre-allocate these for commands that cannot fail due to
675 * out-of-memory errors, like freeing streams. 684 * out-of-memory errors, like freeing streams.
@@ -731,6 +740,22 @@ struct xhci_stream_info {
731#define SMALL_STREAM_ARRAY_SIZE 256 740#define SMALL_STREAM_ARRAY_SIZE 256
732#define MEDIUM_STREAM_ARRAY_SIZE 1024 741#define MEDIUM_STREAM_ARRAY_SIZE 1024
733 742
743/* Some Intel xHCI host controllers need software to keep track of the bus
744 * bandwidth. Keep track of endpoint info here. Each root port is allocated
745 * the full bus bandwidth. We must also treat TTs (including each port under a
746 * multi-TT hub) as a separate bandwidth domain. The direct memory interface
747 * (DMI) also limits the total bandwidth (across all domains) that can be used.
748 */
749struct xhci_bw_info {
750 unsigned int ep_interval;
751 /* mult and num_packets are zero-based */
752 unsigned int mult;
753 unsigned int num_packets;
754 unsigned int max_packet_size;
755 unsigned int max_esit_payload;
756 unsigned int type;
757};
758
734struct xhci_virt_ep { 759struct xhci_virt_ep {
735 struct xhci_ring *ring; 760 struct xhci_ring *ring;
736 /* Related to endpoints that are configured to use stream IDs only */ 761 /* Related to endpoints that are configured to use stream IDs only */
@@ -772,6 +797,7 @@ struct xhci_virt_ep {
772 * process the missed tds on the endpoint ring. 797 * process the missed tds on the endpoint ring.
773 */ 798 */
774 bool skip; 799 bool skip;
800 struct xhci_bw_info bw_info;
775}; 801};
776 802
777enum xhci_overhead_type { 803enum xhci_overhead_type {
@@ -1485,6 +1511,11 @@ unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc);
1485unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index); 1511unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index);
1486unsigned int xhci_last_valid_endpoint(u32 added_ctxs); 1512unsigned int xhci_last_valid_endpoint(u32 added_ctxs);
1487void xhci_endpoint_zero(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, struct usb_host_endpoint *ep); 1513void xhci_endpoint_zero(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, struct usb_host_endpoint *ep);
1514void xhci_clear_endpoint_bw_info(struct xhci_bw_info *bw_info);
1515void xhci_update_bw_info(struct xhci_hcd *xhci,
1516 struct xhci_container_ctx *in_ctx,
1517 struct xhci_input_control_ctx *ctrl_ctx,
1518 struct xhci_virt_device *virt_dev);
1488void xhci_endpoint_copy(struct xhci_hcd *xhci, 1519void xhci_endpoint_copy(struct xhci_hcd *xhci,
1489 struct xhci_container_ctx *in_ctx, 1520 struct xhci_container_ctx *in_ctx,
1490 struct xhci_container_ctx *out_ctx, 1521 struct xhci_container_ctx *out_ctx,