aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci.h
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-08-07 17:04:36 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-09-23 09:46:17 -0400
commitb0567b3f635db72c881a0d561cebb544ec085073 (patch)
treeb6294a55ea42d54a352be21c42eaf7594a3c79be /drivers/usb/host/xhci.h
parent11eaf170363d264ff587f300e41c927ba5a33967 (diff)
USB: xhci: Work around for chain bit in link TRBs.
Different sections of the xHCI 0.95 specification had opposing requirements for the chain bit in a link transaction request buffer (TRB). The chain bit is used to designate that adjacent TRBs are all part of the same scatter gather list that should be sent to the device. Link TRBs can be in the middle, or at the beginning or end of these chained TRBs. Sections 4.11.5.1 and 6.4.4.1 both stated the link TRB "shall have the chain bit set to 1", meaning it is always chained to the next TRB. However, section 4.6.9 on the stop endpoint command has specific cases for what the hardware must do for a link TRB with the chain bit set to 0. The 0.96 specification errata later cleared up this issue by fixing the 4.11.5.1 and 6.4.4.1 sections to state that a link TRB can have the chain bit set to 1 or 0. The problem is that the xHCI cancellation code depends on the chain bit of the link TRB being cleared when it's at the end of a TD, and some 0.95 xHCI hardware simply stops processing the ring when it encounters a link TRB with the chain bit cleared. Allow users who are testing 0.95 xHCI prototypes to set a module parameter (link_quirk) to turn on this link TRB work around. Cancellation may not work if the ring is stopped exactly on a link TRB with chain bit set, but cancellation should be a relatively uncommon case. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Cc: stable <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/xhci.h')
-rw-r--r--drivers/usb/host/xhci.h9
1 files changed, 9 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index ffe1625d4e1b..79ea627e8b8a 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1058,6 +1058,8 @@ struct xhci_hcd {
1058 int noops_submitted; 1058 int noops_submitted;
1059 int noops_handled; 1059 int noops_handled;
1060 int error_bitmask; 1060 int error_bitmask;
1061 unsigned int quirks;
1062#define XHCI_LINK_TRB_QUIRK (1 << 0)
1061}; 1063};
1062 1064
1063/* For testing purposes */ 1065/* For testing purposes */
@@ -1136,6 +1138,13 @@ static inline void xhci_write_64(struct xhci_hcd *xhci,
1136 writel(val_hi, ptr + 1); 1138 writel(val_hi, ptr + 1);
1137} 1139}
1138 1140
1141static inline int xhci_link_trb_quirk(struct xhci_hcd *xhci)
1142{
1143 u32 temp = xhci_readl(xhci, &xhci->cap_regs->hc_capbase);
1144 return ((HC_VERSION(temp) == 0x95) &&
1145 (xhci->quirks & XHCI_LINK_TRB_QUIRK));
1146}
1147
1139/* xHCI debugging */ 1148/* xHCI debugging */
1140void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int set_num); 1149void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int set_num);
1141void xhci_print_registers(struct xhci_hcd *xhci); 1150void xhci_print_registers(struct xhci_hcd *xhci);