diff options
author | Hans de Goede <hdegoede@redhat.com> | 2014-08-20 09:41:51 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-09-24 00:46:11 -0400 |
commit | cffb9be80f8a6d51d025780864c781ba83541720 (patch) | |
tree | 46241acbb049df4d65082b4665ee67044c909c72 /drivers/usb | |
parent | f85c9fb62c59b78a1169b269f4ca697b1e06ee98 (diff) |
xhci: Log extra info on "ERROR Transfer event TRB DMA ptr not part of current TD"
Lately (with the use of uas / bulk-streams) we have been seeing several
cases where this error triggers (which should never happen).
Add some extra logging to make debugging these errors easier.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/xhci-mem.c | 4 | ||||
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 26 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 6 |
3 files changed, 27 insertions, 9 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 8936211b161d..5cb3d7a10017 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c | |||
@@ -1904,7 +1904,7 @@ static int xhci_test_trb_in_td(struct xhci_hcd *xhci, | |||
1904 | start_dma = xhci_trb_virt_to_dma(input_seg, start_trb); | 1904 | start_dma = xhci_trb_virt_to_dma(input_seg, start_trb); |
1905 | end_dma = xhci_trb_virt_to_dma(input_seg, end_trb); | 1905 | end_dma = xhci_trb_virt_to_dma(input_seg, end_trb); |
1906 | 1906 | ||
1907 | seg = trb_in_td(input_seg, start_trb, end_trb, input_dma); | 1907 | seg = trb_in_td(xhci, input_seg, start_trb, end_trb, input_dma, false); |
1908 | if (seg != result_seg) { | 1908 | if (seg != result_seg) { |
1909 | xhci_warn(xhci, "WARN: %s TRB math test %d failed!\n", | 1909 | xhci_warn(xhci, "WARN: %s TRB math test %d failed!\n", |
1910 | test_name, test_number); | 1910 | test_name, test_number); |
@@ -1918,6 +1918,8 @@ static int xhci_test_trb_in_td(struct xhci_hcd *xhci, | |||
1918 | end_trb, end_dma); | 1918 | end_trb, end_dma); |
1919 | xhci_warn(xhci, "Expected seg %p, got seg %p\n", | 1919 | xhci_warn(xhci, "Expected seg %p, got seg %p\n", |
1920 | result_seg, seg); | 1920 | result_seg, seg); |
1921 | trb_in_td(xhci, input_seg, start_trb, end_trb, input_dma, | ||
1922 | true); | ||
1921 | return -1; | 1923 | return -1; |
1922 | } | 1924 | } |
1923 | return 0; | 1925 | return 0; |
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 4e1c34f45b52..bc6fcbc16f61 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -1660,10 +1660,12 @@ cleanup: | |||
1660 | * TRB in this TD, this function returns that TRB's segment. Otherwise it | 1660 | * TRB in this TD, this function returns that TRB's segment. Otherwise it |
1661 | * returns 0. | 1661 | * returns 0. |
1662 | */ | 1662 | */ |
1663 | struct xhci_segment *trb_in_td(struct xhci_segment *start_seg, | 1663 | struct xhci_segment *trb_in_td(struct xhci_hcd *xhci, |
1664 | struct xhci_segment *start_seg, | ||
1664 | union xhci_trb *start_trb, | 1665 | union xhci_trb *start_trb, |
1665 | union xhci_trb *end_trb, | 1666 | union xhci_trb *end_trb, |
1666 | dma_addr_t suspect_dma) | 1667 | dma_addr_t suspect_dma, |
1668 | bool debug) | ||
1667 | { | 1669 | { |
1668 | dma_addr_t start_dma; | 1670 | dma_addr_t start_dma; |
1669 | dma_addr_t end_seg_dma; | 1671 | dma_addr_t end_seg_dma; |
@@ -1682,6 +1684,15 @@ struct xhci_segment *trb_in_td(struct xhci_segment *start_seg, | |||
1682 | /* If the end TRB isn't in this segment, this is set to 0 */ | 1684 | /* If the end TRB isn't in this segment, this is set to 0 */ |
1683 | end_trb_dma = xhci_trb_virt_to_dma(cur_seg, end_trb); | 1685 | end_trb_dma = xhci_trb_virt_to_dma(cur_seg, end_trb); |
1684 | 1686 | ||
1687 | if (debug) | ||
1688 | xhci_warn(xhci, | ||
1689 | "Looking for event-dma %016llx trb-start %016llx trb-end %016llx seg-start %016llx seg-end %016llx\n", | ||
1690 | (unsigned long long)suspect_dma, | ||
1691 | (unsigned long long)start_dma, | ||
1692 | (unsigned long long)end_trb_dma, | ||
1693 | (unsigned long long)cur_seg->dma, | ||
1694 | (unsigned long long)end_seg_dma); | ||
1695 | |||
1685 | if (end_trb_dma > 0) { | 1696 | if (end_trb_dma > 0) { |
1686 | /* The end TRB is in this segment, so suspect should be here */ | 1697 | /* The end TRB is in this segment, so suspect should be here */ |
1687 | if (start_dma <= end_trb_dma) { | 1698 | if (start_dma <= end_trb_dma) { |
@@ -2414,8 +2425,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
2414 | td_num--; | 2425 | td_num--; |
2415 | 2426 | ||
2416 | /* Is this a TRB in the currently executing TD? */ | 2427 | /* Is this a TRB in the currently executing TD? */ |
2417 | event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue, | 2428 | event_seg = trb_in_td(xhci, ep_ring->deq_seg, ep_ring->dequeue, |
2418 | td->last_trb, event_dma); | 2429 | td->last_trb, event_dma, false); |
2419 | 2430 | ||
2420 | /* | 2431 | /* |
2421 | * Skip the Force Stopped Event. The event_trb(event_dma) of FSE | 2432 | * Skip the Force Stopped Event. The event_trb(event_dma) of FSE |
@@ -2447,7 +2458,12 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
2447 | /* HC is busted, give up! */ | 2458 | /* HC is busted, give up! */ |
2448 | xhci_err(xhci, | 2459 | xhci_err(xhci, |
2449 | "ERROR Transfer event TRB DMA ptr not " | 2460 | "ERROR Transfer event TRB DMA ptr not " |
2450 | "part of current TD\n"); | 2461 | "part of current TD ep_index %d " |
2462 | "comp_code %u\n", ep_index, | ||
2463 | trb_comp_code); | ||
2464 | trb_in_td(xhci, ep_ring->deq_seg, | ||
2465 | ep_ring->dequeue, td->last_trb, | ||
2466 | event_dma, true); | ||
2451 | return -ESHUTDOWN; | 2467 | return -ESHUTDOWN; |
2452 | } | 2468 | } |
2453 | 2469 | ||
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index f4d12f6fcfe8..276fd8efd171 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h | |||
@@ -1804,9 +1804,9 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev); | |||
1804 | 1804 | ||
1805 | /* xHCI ring, segment, TRB, and TD functions */ | 1805 | /* xHCI ring, segment, TRB, and TD functions */ |
1806 | dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, union xhci_trb *trb); | 1806 | dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, union xhci_trb *trb); |
1807 | struct xhci_segment *trb_in_td(struct xhci_segment *start_seg, | 1807 | struct xhci_segment *trb_in_td(struct xhci_hcd *xhci, |
1808 | union xhci_trb *start_trb, union xhci_trb *end_trb, | 1808 | struct xhci_segment *start_seg, union xhci_trb *start_trb, |
1809 | dma_addr_t suspect_dma); | 1809 | union xhci_trb *end_trb, dma_addr_t suspect_dma, bool debug); |
1810 | int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code); | 1810 | int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code); |
1811 | void xhci_ring_cmd_db(struct xhci_hcd *xhci); | 1811 | void xhci_ring_cmd_db(struct xhci_hcd *xhci); |
1812 | int xhci_queue_slot_control(struct xhci_hcd *xhci, struct xhci_command *cmd, | 1812 | int xhci_queue_slot_control(struct xhci_hcd *xhci, struct xhci_command *cmd, |