aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2014-08-20 09:41:51 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-09-24 00:46:11 -0400
commitcffb9be80f8a6d51d025780864c781ba83541720 (patch)
tree46241acbb049df4d65082b4665ee67044c909c72 /drivers/usb
parentf85c9fb62c59b78a1169b269f4ca697b1e06ee98 (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.c4
-rw-r--r--drivers/usb/host/xhci-ring.c26
-rw-r--r--drivers/usb/host/xhci.h6
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 */
1663struct xhci_segment *trb_in_td(struct xhci_segment *start_seg, 1663struct 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 */
1806dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, union xhci_trb *trb); 1806dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, union xhci_trb *trb);
1807struct xhci_segment *trb_in_td(struct xhci_segment *start_seg, 1807struct 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);
1810int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code); 1810int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code);
1811void xhci_ring_cmd_db(struct xhci_hcd *xhci); 1811void xhci_ring_cmd_db(struct xhci_hcd *xhci);
1812int xhci_queue_slot_control(struct xhci_hcd *xhci, struct xhci_command *cmd, 1812int xhci_queue_slot_control(struct xhci_hcd *xhci, struct xhci_command *cmd,