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:
commit
ded737fe6a
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
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)
|
||||
*/
|
||||
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)) {
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue