Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cffb9be8 authored by Hans de Goede's avatar Hans de Goede Committed by Greg Kroah-Hartman
Browse files

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: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f85c9fb6
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -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;
+21 −5
Original line number Diff line number Diff line
@@ -1660,10 +1660,12 @@ static void handle_port_status(struct xhci_hcd *xhci,
 * 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;
			}

+3 −3
Original line number Diff line number Diff line
@@ -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,