xhci: Log extra info on "ERROR Transfer event TRB DMA ptr not part of current TD"
authorHans de Goede <hdegoede@redhat.com>
Wed, 20 Aug 2014 13:41:51 +0000 (16:41 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 24 Sep 2014 04:46:11 +0000 (21:46 -0700)
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>
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.h

index 8936211b161d3ed6b0a2989359707287f2721b21..5cb3d7a10017a3eea2ad55a2fe9f487e4472b891 100644 (file)
@@ -1904,7 +1904,7 @@ static int xhci_test_trb_in_td(struct xhci_hcd *xhci,
        start_dma = xhci_trb_virt_to_dma(input_seg, start_trb);
        end_dma = xhci_trb_virt_to_dma(input_seg, end_trb);
 
-       seg = trb_in_td(input_seg, start_trb, end_trb, input_dma);
+       seg = trb_in_td(xhci, input_seg, start_trb, end_trb, input_dma, false);
        if (seg != result_seg) {
                xhci_warn(xhci, "WARN: %s TRB math test %d failed!\n",
                                test_name, test_number);
@@ -1918,6 +1918,8 @@ static int xhci_test_trb_in_td(struct xhci_hcd *xhci,
                                end_trb, end_dma);
                xhci_warn(xhci, "Expected seg %p, got seg %p\n",
                                result_seg, seg);
+               trb_in_td(xhci, input_seg, start_trb, end_trb, input_dma,
+                         true);
                return -1;
        }
        return 0;
index 4e1c34f45b52cc118eb20c13263a17fa052650d0..bc6fcbc16f61ec820ba93d5fb6700cfcbd0ae2a2 100644 (file)
@@ -1660,10 +1660,12 @@ cleanup:
  * TRB in this TD, this function returns that TRB's segment.  Otherwise it
  * returns 0.
  */
-struct xhci_segment *trb_in_td(struct xhci_segment *start_seg,
+struct xhci_segment *trb_in_td(struct xhci_hcd *xhci,
+               struct xhci_segment *start_seg,
                union xhci_trb  *start_trb,
                union xhci_trb  *end_trb,
-               dma_addr_t      suspect_dma)
+               dma_addr_t      suspect_dma,
+               bool            debug)
 {
        dma_addr_t start_dma;
        dma_addr_t end_seg_dma;
@@ -1682,6 +1684,15 @@ struct xhci_segment *trb_in_td(struct xhci_segment *start_seg,
                /* If the end TRB isn't in this segment, this is set to 0 */
                end_trb_dma = xhci_trb_virt_to_dma(cur_seg, end_trb);
 
+               if (debug)
+                       xhci_warn(xhci,
+                               "Looking for event-dma %016llx trb-start %016llx trb-end %016llx seg-start %016llx seg-end %016llx\n",
+                               (unsigned long long)suspect_dma,
+                               (unsigned long long)start_dma,
+                               (unsigned long long)end_trb_dma,
+                               (unsigned long long)cur_seg->dma,
+                               (unsigned long long)end_seg_dma);
+
                if (end_trb_dma > 0) {
                        /* The end TRB is in this segment, so suspect should be here */
                        if (start_dma <= end_trb_dma) {
@@ -2414,8 +2425,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                        td_num--;
 
                /* Is this a TRB in the currently executing TD? */
-               event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue,
-                               td->last_trb, event_dma);
+               event_seg = trb_in_td(xhci, ep_ring->deq_seg, ep_ring->dequeue,
+                               td->last_trb, event_dma, false);
 
                /*
                 * 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,
                                /* HC is busted, give up! */
                                xhci_err(xhci,
                                        "ERROR Transfer event TRB DMA ptr not "
-                                       "part of current TD\n");
+                                       "part of current TD ep_index %d "
+                                       "comp_code %u\n", ep_index,
+                                       trb_comp_code);
+                               trb_in_td(xhci, ep_ring->deq_seg,
+                                         ep_ring->dequeue, td->last_trb,
+                                         event_dma, true);
                                return -ESHUTDOWN;
                        }
 
index f4d12f6fcfe8a566386ba88c0ea20165c2fef3c7..276fd8efd171d753e3b6de2d5dfa50d33623ffaf 100644 (file)
@@ -1804,9 +1804,9 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
 
 /* xHCI ring, segment, TRB, and TD functions */
 dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, union xhci_trb *trb);
-struct xhci_segment *trb_in_td(struct xhci_segment *start_seg,
-               union xhci_trb *start_trb, union xhci_trb *end_trb,
-               dma_addr_t suspect_dma);
+struct xhci_segment *trb_in_td(struct xhci_hcd *xhci,
+               struct xhci_segment *start_seg, union xhci_trb *start_trb,
+               union xhci_trb *end_trb, dma_addr_t suspect_dma, bool debug);
 int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code);
 void xhci_ring_cmd_db(struct xhci_hcd *xhci);
 int xhci_queue_slot_control(struct xhci_hcd *xhci, struct xhci_command *cmd,