Skip to content

Commit

Permalink
Intel xhci: Ignore spurious successful event.
Browse files Browse the repository at this point in the history
The xHCI host controller in the Panther Point chipset sometimes produces
spurious events on the event ring.  If it receives a short packet, it
first puts a Transfer Event with a short transfer completion code on the
event ring.  Then it puts a Transfer Event with a successful completion
code on the ring for the same TD.  The xHCI driver correctly processes the
short transfer completion code, gives the URB back to the driver, and then
prints a warning in dmesg about the spurious event.  These warning
messages really fill up dmesg when an HD webcam is plugged into xHCI.

This spurious successful event behavior isn't technically disallowed by
the xHCI specification, so make the xHCI driver just ignore the spurious
completion event.

Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
  • Loading branch information
Sarah Sharp committed May 27, 2011
1 parent 69e848c commit ad80833
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 0 deletions.
4 changes: 4 additions & 0 deletions drivers/usb/host/xhci-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
/* AMD PLL quirk */
if (pdev->vendor == PCI_VENDOR_ID_AMD && usb_amd_find_chipset_info())
xhci->quirks |= XHCI_AMD_PLL_FIX;
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI) {
xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
}

/* Make sure the HC is halted. */
retval = xhci_halt(xhci);
Expand Down
14 changes: 14 additions & 0 deletions drivers/usb/host/xhci-ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -2061,6 +2061,16 @@ static int handle_tx_event(struct xhci_hcd *xhci,
if (!event_seg) {
if (!ep->skip ||
!usb_endpoint_xfer_isoc(&td->urb->ep->desc)) {
/* Some host controllers give a spurious
* successful event after a short transfer.
* Ignore it.
*/
if ((xhci->quirks & XHCI_SPURIOUS_SUCCESS) &&
ep_ring->last_td_was_short) {
ep_ring->last_td_was_short = false;
ret = 0;
goto cleanup;
}
/* HC is busted, give up! */
xhci_err(xhci,
"ERROR Transfer event TRB DMA ptr not "
Expand All @@ -2071,6 +2081,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
ret = skip_isoc_td(xhci, td, event, ep, &status);
goto cleanup;
}
if (trb_comp_code == COMP_SHORT_TX)
ep_ring->last_td_was_short = true;
else
ep_ring->last_td_was_short = false;

if (ep->skip) {
xhci_dbg(xhci, "Found td. Clear skip flag.\n");
Expand Down
2 changes: 2 additions & 0 deletions drivers/usb/host/xhci.h
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,7 @@ struct xhci_ring {
*/
u32 cycle_state;
unsigned int stream_id;
bool last_td_was_short;
};

struct xhci_erst_entry {
Expand Down Expand Up @@ -1290,6 +1291,7 @@ struct xhci_hcd {
#define XHCI_RESET_EP_QUIRK (1 << 1)
#define XHCI_NEC_HOST (1 << 2)
#define XHCI_AMD_PLL_FIX (1 << 3)
#define XHCI_SPURIOUS_SUCCESS (1 << 4)
/* There are two roothubs to keep track of bus suspend info for */
struct xhci_bus_state bus_state[2];
/* Is each xHCI roothub port a USB 3.0, USB 2.0, or USB 1.1 port? */
Expand Down

0 comments on commit ad80833

Please sign in to comment.