Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1258210

[PATCH 3.12 007/123] xhci: rework cycle bit checking for new dequeue pointers

From Jiri Slaby <jslaby@suse.cz>
Newsgroups linux.kernel
Subject [PATCH 3.12 007/123] xhci: rework cycle bit checking for new dequeue pointers
Date 2015-10-28 15:50 +0100
Message-ID <qoAd4-3T1-23@gated-at.bofh.it> (permalink)
References <qozqF-3k6-9@gated-at.bofh.it>
Organization linux.* mail to news gateway

Show all headers | View raw


From: Mathias Nyman <mathias.nyman@linux.intel.com>

3.12-stable review patch.  If anyone has any objections, please let me know.

===============

commit 365038d83313951d6ace15342eb24624bbef1666 upstream.

When we manually need to move the TR dequeue pointer we need to set the
correct cycle bit as well. Previously we used the trb pointer from the
last event received as a base, but this was changed in
commit 1f81b6d22a59 ("usb: xhci: Prefer endpoint context dequeue pointer")
to use the dequeue pointer from the endpoint context instead

It turns out some Asmedia controllers advance the dequeue pointer
stored in the endpoint context past the event triggering TRB, and
this messed up the way the cycle bit was calculated.

Instead of adding a quirk or complicating the already hard to follow cycle bit
code, the whole cycle bit calculation is now simplified and adapted to handle
event and endpoint context dequeue pointer differences.

[js] do not touch find_trb_seg, it is still in use in other portions
     of the code

Fixes: 1f81b6d22a59 ("usb: xhci: Prefer endpoint context dequeue pointer")
Reported-by: Maciej Puzio <mx34567@gmail.com>
Reported-by: Evan Langlois <uudruid74@gmail.com>
Reviewed-by: Julius Werner <jwerner@chromium.org>
Tested-by: Maciej Puzio <mx34567@gmail.com>
Tested-by: Evan Langlois <uudruid74@gmail.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 drivers/usb/host/xhci-ring.c | 75 +++++++++++++++++++++++---------------------
 drivers/usb/host/xhci.c      |  3 ++
 2 files changed, 42 insertions(+), 36 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 66deb0af258e..d5652d21826a 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -554,9 +554,12 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
 	struct xhci_virt_device *dev = xhci->devs[slot_id];
 	struct xhci_virt_ep *ep = &dev->eps[ep_index];
 	struct xhci_ring *ep_ring;
-	struct xhci_generic_trb *trb;
+	struct xhci_segment *new_seg;
+	union xhci_trb *new_deq;
 	dma_addr_t addr;
 	u64 hw_dequeue;
+	bool cycle_found = false;
+	bool td_last_trb_found = false;
 
 	ep_ring = xhci_triad_to_transfer_ring(xhci, slot_id,
 			ep_index, stream_id);
@@ -581,45 +584,45 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
 		hw_dequeue = le64_to_cpu(ep_ctx->deq);
 	}
 
-	/* Find virtual address and segment of hardware dequeue pointer */
-	state->new_deq_seg = ep_ring->deq_seg;
-	state->new_deq_ptr = ep_ring->dequeue;
-	while (xhci_trb_virt_to_dma(state->new_deq_seg, state->new_deq_ptr)
-			!= (dma_addr_t)(hw_dequeue & ~0xf)) {
-		next_trb(xhci, ep_ring, &state->new_deq_seg,
-					&state->new_deq_ptr);
-		if (state->new_deq_ptr == ep_ring->dequeue) {
-			WARN_ON(1);
-			return;
-		}
-	}
+	new_seg = ep_ring->deq_seg;
+	new_deq = ep_ring->dequeue;
+	state->new_cycle_state = hw_dequeue & 0x1;
+
 	/*
-	 * Find cycle state for last_trb, starting at old cycle state of
-	 * hw_dequeue. If there is only one segment ring, find_trb_seg() will
-	 * return immediately and cannot toggle the cycle state if this search
-	 * wraps around, so add one more toggle manually in that case.
+	 * We want to find the pointer, segment and cycle state of the new trb
+	 * (the one after current TD's last_trb). We know the cycle state at
+	 * hw_dequeue, so walk the ring until both hw_dequeue and last_trb are
+	 * found.
 	 */
-	state->new_cycle_state = hw_dequeue & 0x1;
-	if (ep_ring->first_seg == ep_ring->first_seg->next &&
-			cur_td->last_trb < state->new_deq_ptr)
-		state->new_cycle_state ^= 0x1;
+	do {
+		if (!cycle_found && xhci_trb_virt_to_dma(new_seg, new_deq)
+		    == (dma_addr_t)(hw_dequeue & ~0xf)) {
+			cycle_found = true;
+			if (td_last_trb_found)
+				break;
+		}
+		if (new_deq == cur_td->last_trb)
+			td_last_trb_found = true;
 
-	state->new_deq_ptr = cur_td->last_trb;
-	xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
-			"Finding segment containing last TRB in TD.");
-	state->new_deq_seg = find_trb_seg(state->new_deq_seg,
-			state->new_deq_ptr, &state->new_cycle_state);
-	if (!state->new_deq_seg) {
-		WARN_ON(1);
-		return;
-	}
+		if (cycle_found &&
+		    TRB_TYPE_LINK_LE32(new_deq->generic.field[3]) &&
+		    new_deq->generic.field[3] & cpu_to_le32(LINK_TOGGLE))
+			state->new_cycle_state ^= 0x1;
+
+		next_trb(xhci, ep_ring, &new_seg, &new_deq);
+
+		/* Search wrapped around, bail out */
+		if (new_deq == ep->ring->dequeue) {
+			xhci_err(xhci, "Error: Failed finding new dequeue state\n");
+			state->new_deq_seg = NULL;
+			state->new_deq_ptr = NULL;
+			return;
+		}
+
+	} while (!cycle_found || !td_last_trb_found);
 
-	/* Increment to find next TRB after last_trb. Cycle if appropriate. */
-	trb = &state->new_deq_ptr->generic;
-	if (TRB_TYPE_LINK_LE32(trb->field[3]) &&
-	    (trb->field[3] & cpu_to_le32(LINK_TOGGLE)))
-		state->new_cycle_state ^= 0x1;
-	next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr);
+	state->new_deq_seg = new_seg;
+	state->new_deq_ptr = new_deq;
 
 	/* Don't update the ring cycle state for the producer (us). */
 	xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 00686a8c4fa0..1dd08da9652a 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -2902,6 +2902,9 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
 			ep_index, ep->stopped_stream, ep->stopped_td,
 			&deq_state);
 
+	if (!deq_state.new_deq_ptr || !deq_state.new_deq_seg)
+		return;
+
 	/* HW with the reset endpoint quirk will use the saved dequeue state to
 	 * issue a configure endpoint command later.
 	 */
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Back to linux.kernel | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

[PATCH 3.12 001/123] x86/nmi/64: Fix a paravirt stack-clobbering bug in the NMI code Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:00 +0100
  [PATCH 3.12 027/123] ARM: dts: omap5-uevm.dts: fix i2c5 pinctrl offsets Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:00 +0100
  [PATCH 3.12 035/123] arc,hexagon: Delete asm/barrier.h Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:00 +0100
  [PATCH 3.12 037/123] spi: Fix documentation of spi_alloc_master() Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:00 +0100
  [PATCH 3.12 029/123] x86/apic: Serialize LVTT and TSC_DEADLINE writes Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:00 +0100
  [PATCH 3.12 026/123] windfarm: decrement client count when unregistering Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:00 +0100
  [PATCH 3.12 021/123] perf stat: Get correct cpu id for print_aggr Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:30 +0100
  [PATCH 3.12 030/123] x86/platform: Fix Geode LX timekeeping in the generic x86 build Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:30 +0100
  [PATCH 3.12 031/123] x86/mm: Set NX on gap between __ex_table and rodata Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:30 +0100
  [PATCH 3.12 033/123] arch: Clean up asm/barrier.h implementations using asm-generic/barrier.h Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:30 +0100
  [PATCH 3.12 032/123] x86/xen: Support kexec/kdump in HVM guests by doing a soft reset Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:30 +0100
    Re: [PATCH 3.12 032/123] x86/xen: Support kexec/kdump in HVM guests  by doing a soft reset Luis Henriques <luis.henriques@canonical.com> - 2015-10-28 16:30 +0100
      Re: [PATCH 3.12 032/123] x86/xen: Support kexec/kdump in HVM guests  by doing a soft reset Jiri Slaby <jslaby@suse.cz> - 2015-10-28 16:40 +0100
  [PATCH 3.12 022/123] perf header: Fixup reading of HEADER_NRCPUS feature Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:30 +0100
  [PATCH 3.12 034/123] arch: Move smp_mb__{before,after}_atomic_{inc,dec}.h into asm/atomic.h Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:30 +0100
  [PATCH 3.12 025/123] ARM: 8429/1: disable GCC SRA optimization Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:30 +0100
  [PATCH 3.12 028/123] dmaengine: dw: properly read DWC_PARAMS register Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:30 +0100
  [PATCH 3.12 014/123] ARM: 7880/1: Clear the IT state independent of the Thumb-2 mode Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:40 +0100
  [PATCH 3.12 036/123] sched/core: Fix TASK_DEAD race in finish_task_switch() Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:40 +0100
  [PATCH 3.12 012/123] s390/3270: redraw screen on unsolicited device end Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:40 +0100
  [PATCH 3.12 013/123] Use WARN_ON_ONCE for missing X86_FEATURE_NRIPS Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:40 +0100
  [PATCH 3.12 023/123] hwmon: (nct6775) Swap STEP_UP_TIME and STEP_DOWN_TIME registers for most chips Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:40 +0100
  [PATCH 3.12 017/123] kvm: fix zero length mmio searching Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:40 +0100
  [PATCH 3.12 018/123] scsi: fix scsi_error_handler vs. scsi_host_dev_release race Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:40 +0100
  [PATCH 3.12 002/123] x86/paravirt: Replace the paravirt nop with a bona fide empty function Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:40 +0100
  [PATCH 3.12 020/123] perf hists: Update the column width for the "srcline" sort key Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:40 +0100
  [PATCH 3.12 019/123] iser-target: remove command with state ISTATE_REMOVE Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:40 +0100
  [PATCH 3.12 024/123] ARM: fix Thumb2 signal handling when ARMv6 is enabled Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:40 +0100
  [PATCH 3.12 016/123] ALSA: hda - Control SPDIF out pin on MacBookPro 11,2 Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:40 +0100
  [PATCH 3.12 015/123] net: add length argument to skb_copy_and_csum_datagram_iovec Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:40 +0100
  [PATCH 3.12 004/123] rcu: Reject memory-order-induced stall-warning false positives Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:50 +0100
  [PATCH 3.12 005/123] sched: Fix cpu_active_mask/cpu_online_mask race Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:50 +0100
  [PATCH 3.12 007/123] xhci: rework cycle bit checking for new dequeue pointers Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:50 +0100
  [PATCH 3.12 006/123] xhci: Workaround for PME stuck issues in Intel xhci Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:50 +0100
  [PATCH 3.12 009/123] USB: usbtmc: add device quirk for Rigol DS6104 Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:50 +0100
    Re: [PATCH 3.12 009/123] USB: usbtmc: add device quirk for Rigol DS6104 Teunis van Beelen <teuniz@gmail.com> - 2015-10-28 16:40 +0100
  [PATCH 3.12 008/123] usb: core: Fix USB 3.0 devices lost in NOTATTACHED state after a hub port reset Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:50 +0100
  [PATCH 3.12 010/123] client MUST ignore EncryptionKeyLength if CAP_EXTENDED_SECURITY is set Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:50 +0100
  [PATCH 3.12 011/123] iommu/amd: Handle integer overflow in dma_ops_area_alloc Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:50 +0100
  [PATCH 3.12 003/123] jbd2: avoid infinite loop when destroying aborted journal Jiri Slaby <jslaby@suse.cz> - 2015-10-28 15:50 +0100

csiph-web