Commit ded737fe authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'for-usb-linus-2012-08-08' of...

Merge tag 'for-usb-linus-2012-08-08' of git://git.kernel.org/pub/scm/linux/kernel/git/sarah/xhci into usb-linus

xHCI bug fixes and host quirks.

Hi Greg,

Here's four patches for 3.6.  Most are marked for stable as well.

The first one makes the xHCI driver load properly on newer Rensas hosts.
The next two fix issues with the Etron host incorrectly marking short
transfers as successful, and avoiding log warning spam for hosts that
make the same mistake.

The last patch fixes a really nasty xHCI driver bug that could cause
general protection faults when devices stall transfers.

Sarah Sharp
parents 010ccce0 50d0206f
...@@ -99,6 +99,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) ...@@ -99,6 +99,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
pdev->device == PCI_DEVICE_ID_ASROCK_P67) { pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
xhci->quirks |= XHCI_RESET_ON_RESUME; xhci->quirks |= XHCI_RESET_ON_RESUME;
xhci_dbg(xhci, "QUIRK: Resetting on resume\n"); xhci_dbg(xhci, "QUIRK: Resetting on resume\n");
xhci->quirks |= XHCI_TRUST_TX_LENGTH;
} }
if (pdev->vendor == PCI_VENDOR_ID_VIA) if (pdev->vendor == PCI_VENDOR_ID_VIA)
xhci->quirks |= XHCI_RESET_ON_RESUME; xhci->quirks |= XHCI_RESET_ON_RESUME;
......
...@@ -145,29 +145,37 @@ static void next_trb(struct xhci_hcd *xhci, ...@@ -145,29 +145,37 @@ static void next_trb(struct xhci_hcd *xhci,
*/ */
static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring) static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring)
{ {
union xhci_trb *next;
unsigned long long addr; unsigned long long addr;
ring->deq_updates++; ring->deq_updates++;
/* If this is not event ring, there is one more usable TRB */ /*
* If this is not event ring, and the dequeue pointer
* is not on a link TRB, there is one more usable TRB
*/
if (ring->type != TYPE_EVENT && if (ring->type != TYPE_EVENT &&
!last_trb(xhci, ring, ring->deq_seg, ring->dequeue)) !last_trb(xhci, ring, ring->deq_seg, ring->dequeue))
ring->num_trbs_free++; ring->num_trbs_free++;
next = ++(ring->dequeue);
/* Update the dequeue pointer further if that was a link TRB or we're at do {
* the end of an event ring segment (which doesn't have link TRBS) /*
*/ * Update the dequeue pointer further if that was a link TRB or
while (last_trb(xhci, ring, ring->deq_seg, next)) { * we're at the end of an event ring segment (which doesn't have
if (ring->type == TYPE_EVENT && last_trb_on_last_seg(xhci, * link TRBS)
ring, ring->deq_seg, next)) { */
if (last_trb(xhci, ring, ring->deq_seg, ring->dequeue)) {
if (ring->type == TYPE_EVENT &&
last_trb_on_last_seg(xhci, ring,
ring->deq_seg, ring->dequeue)) {
ring->cycle_state = (ring->cycle_state ? 0 : 1); ring->cycle_state = (ring->cycle_state ? 0 : 1);
} }
ring->deq_seg = ring->deq_seg->next; ring->deq_seg = ring->deq_seg->next;
ring->dequeue = ring->deq_seg->trbs; ring->dequeue = ring->deq_seg->trbs;
next = ring->dequeue; } else {
ring->dequeue++;
} }
} while (last_trb(xhci, ring, ring->deq_seg, ring->dequeue));
addr = (unsigned long long) xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue); addr = (unsigned long long) xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue);
} }
...@@ -2073,8 +2081,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, ...@@ -2073,8 +2081,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
if (xhci->quirks & XHCI_TRUST_TX_LENGTH) if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
trb_comp_code = COMP_SHORT_TX; trb_comp_code = COMP_SHORT_TX;
else else
xhci_warn(xhci, "WARN Successful completion on short TX: " xhci_warn_ratelimited(xhci,
"needs XHCI_TRUST_TX_LENGTH quirk?\n"); "WARN Successful completion on short TX: needs XHCI_TRUST_TX_LENGTH quirk?\n");
case COMP_SHORT_TX: case COMP_SHORT_TX:
break; break;
case COMP_STOP: case COMP_STOP:
......
...@@ -166,7 +166,7 @@ int xhci_reset(struct xhci_hcd *xhci) ...@@ -166,7 +166,7 @@ int xhci_reset(struct xhci_hcd *xhci)
xhci_writel(xhci, command, &xhci->op_regs->command); xhci_writel(xhci, command, &xhci->op_regs->command);
ret = handshake(xhci, &xhci->op_regs->command, ret = handshake(xhci, &xhci->op_regs->command,
CMD_RESET, 0, 250 * 1000); CMD_RESET, 0, 10 * 1000 * 1000);
if (ret) if (ret)
return ret; return ret;
...@@ -175,7 +175,8 @@ int xhci_reset(struct xhci_hcd *xhci) ...@@ -175,7 +175,8 @@ int xhci_reset(struct xhci_hcd *xhci)
* xHCI cannot write to any doorbells or operational registers other * xHCI cannot write to any doorbells or operational registers other
* than status until the "Controller Not Ready" flag is cleared. * than status until the "Controller Not Ready" flag is cleared.
*/ */
ret = handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000); ret = handshake(xhci, &xhci->op_regs->status,
STS_CNR, 0, 10 * 1000 * 1000);
for (i = 0; i < 2; ++i) { for (i = 0; i < 2; ++i) {
xhci->bus_state[i].port_c_suspend = 0; xhci->bus_state[i].port_c_suspend = 0;
......
...@@ -1537,6 +1537,8 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci) ...@@ -1537,6 +1537,8 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci)
dev_err(xhci_to_hcd(xhci)->self.controller , fmt , ## args) dev_err(xhci_to_hcd(xhci)->self.controller , fmt , ## args)
#define xhci_warn(xhci, fmt, args...) \ #define xhci_warn(xhci, fmt, args...) \
dev_warn(xhci_to_hcd(xhci)->self.controller , fmt , ## args) dev_warn(xhci_to_hcd(xhci)->self.controller , fmt , ## args)
#define xhci_warn_ratelimited(xhci, fmt, args...) \
dev_warn_ratelimited(xhci_to_hcd(xhci)->self.controller , fmt , ## args)
/* TODO: copied from ehci.h - can be refactored? */ /* TODO: copied from ehci.h - can be refactored? */
/* xHCI spec says all registers are little endian */ /* xHCI spec says all registers are little endian */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment