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
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJQIr7YAAoJEBMGWMLi1Gc5H5cP/0mBdjF4URQgz8djdRCE2IrC
 +E7aNNRNpMrxyyVw5ZJspW0WCvc0H+hbmSQPfagZIxkbeSB0ABG4g3Yb2sJdf3FE
 1zHzCYkQATq2PJwho775Ixa2EygFTh5WxFtqnBVnAe3Enr+joYLNhIO5OSyo3qZJ
 vRPI5Myi07YU6ZSvc4WWjUkdCH1gIZyiWCyxu6Oimv8oXqo9MTpu/+NrQYWxWCJ4
 Zr+M5vG8uMLbLt1H44PHTQr2LA1i+65ApsBDUkAKe6nGqWREf7n/HiXqdN9vBnjz
 SoDQEPbqUHdwt35Y9cCfy7hIUSwm3KogC4WAMJfq5p7IlvDTNq6H9aKunon4O6Jb
 PH1UfizwtnN2CgoAbe2e5Mo3PqA0QmYpzBtT0VXgX7XWr6xj0yrnIMH2b2Y/gtZI
 vGW9p4fCuPxwxAsHh7ZmUh8RKYP8UJlxHIy5UAXsptmH3KqMi+j8PVa0nll+0W33
 3HuQZweXOU6y1g//5RfI4l9lYVJuy0T5tnhNRjitrbbjCzNHkWfVcP0svPl4xHyf
 yM9La9vYakQmFE9sKcY17G2Ft8ATdIl9XvPs/OrRnPKVcEWrVJRviJ/L/hfYHfRM
 luJj166pbG6bC/UnUWPf9fpv3XCm0+ZcbCPUSHY9GFLgUIeAZ8nYc4D+B9ztYPHp
 YAbkBPOpI7zCmnKez7s1
 =yn5e
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Greg Kroah-Hartman 2012-08-09 10:06:13 -07:00
commit ded737fe6a
4 changed files with 30 additions and 18 deletions

View File

@ -99,6 +99,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
xhci->quirks |= XHCI_RESET_ON_RESUME;
xhci_dbg(xhci, "QUIRK: Resetting on resume\n");
xhci->quirks |= XHCI_TRUST_TX_LENGTH;
}
if (pdev->vendor == PCI_VENDOR_ID_VIA)
xhci->quirks |= XHCI_RESET_ON_RESUME;

View File

@ -145,29 +145,37 @@ static void next_trb(struct xhci_hcd *xhci,
*/
static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring)
{
union xhci_trb *next;
unsigned long long addr;
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 &&
!last_trb(xhci, ring, ring->deq_seg, ring->dequeue))
ring->num_trbs_free++;
next = ++(ring->dequeue);
/* Update the dequeue pointer further if that was a link TRB or we're at
* the end of an event ring segment (which doesn't have link TRBS)
*/
while (last_trb(xhci, ring, ring->deq_seg, next)) {
if (ring->type == TYPE_EVENT && last_trb_on_last_seg(xhci,
ring, ring->deq_seg, next)) {
ring->cycle_state = (ring->cycle_state ? 0 : 1);
do {
/*
* Update the dequeue pointer further if that was a link TRB or
* we're at the end of an event ring segment (which doesn't have
* link TRBS)
*/
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->deq_seg = ring->deq_seg->next;
ring->dequeue = ring->deq_seg->trbs;
} else {
ring->dequeue++;
}
ring->deq_seg = ring->deq_seg->next;
ring->dequeue = ring->deq_seg->trbs;
next = 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);
}
@ -2073,8 +2081,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
trb_comp_code = COMP_SHORT_TX;
else
xhci_warn(xhci, "WARN Successful completion on short TX: "
"needs XHCI_TRUST_TX_LENGTH quirk?\n");
xhci_warn_ratelimited(xhci,
"WARN Successful completion on short TX: needs XHCI_TRUST_TX_LENGTH quirk?\n");
case COMP_SHORT_TX:
break;
case COMP_STOP:

View File

@ -166,7 +166,7 @@ int xhci_reset(struct xhci_hcd *xhci)
xhci_writel(xhci, command, &xhci->op_regs->command);
ret = handshake(xhci, &xhci->op_regs->command,
CMD_RESET, 0, 250 * 1000);
CMD_RESET, 0, 10 * 1000 * 1000);
if (ret)
return ret;
@ -175,7 +175,8 @@ int xhci_reset(struct xhci_hcd *xhci)
* xHCI cannot write to any doorbells or operational registers other
* 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) {
xhci->bus_state[i].port_c_suspend = 0;

View File

@ -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)
#define xhci_warn(xhci, 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? */
/* xHCI spec says all registers are little endian */