diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/xhci-mem.c | 63 | ||||
-rw-r--r-- | drivers/usb/host/xhci.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 31 |
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 | ||
1413 | void 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 | |||
1423 | void 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 | */ | ||
749 | struct 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 | |||
734 | struct xhci_virt_ep { | 759 | struct 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 | ||
777 | enum xhci_overhead_type { | 803 | enum xhci_overhead_type { |
@@ -1485,6 +1511,11 @@ unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc); | |||
1485 | unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index); | 1511 | unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index); |
1486 | unsigned int xhci_last_valid_endpoint(u32 added_ctxs); | 1512 | unsigned int xhci_last_valid_endpoint(u32 added_ctxs); |
1487 | void xhci_endpoint_zero(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, struct usb_host_endpoint *ep); | 1513 | void xhci_endpoint_zero(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, struct usb_host_endpoint *ep); |
1514 | void xhci_clear_endpoint_bw_info(struct xhci_bw_info *bw_info); | ||
1515 | void 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); | ||
1488 | void xhci_endpoint_copy(struct xhci_hcd *xhci, | 1519 | void 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, |