diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/xhci-hcd.c | 12 | ||||
-rw-r--r-- | drivers/usb/host/xhci-mem.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 15 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 9 |
4 files changed, 35 insertions, 4 deletions
diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c index 816c39caca1c..994f4c0dda24 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci-hcd.c | |||
@@ -22,12 +22,18 @@ | |||
22 | 22 | ||
23 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/moduleparam.h> | ||
25 | 26 | ||
26 | #include "xhci.h" | 27 | #include "xhci.h" |
27 | 28 | ||
28 | #define DRIVER_AUTHOR "Sarah Sharp" | 29 | #define DRIVER_AUTHOR "Sarah Sharp" |
29 | #define DRIVER_DESC "'eXtensible' Host Controller (xHC) Driver" | 30 | #define DRIVER_DESC "'eXtensible' Host Controller (xHC) Driver" |
30 | 31 | ||
32 | /* Some 0.95 hardware can't handle the chain bit on a Link TRB being cleared */ | ||
33 | static int link_quirk; | ||
34 | module_param(link_quirk, int, S_IRUGO | S_IWUSR); | ||
35 | MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB"); | ||
36 | |||
31 | /* TODO: copied from ehci-hcd.c - can this be refactored? */ | 37 | /* TODO: copied from ehci-hcd.c - can this be refactored? */ |
32 | /* | 38 | /* |
33 | * handshake - spin reading hc until handshake completes or fails | 39 | * handshake - spin reading hc until handshake completes or fails |
@@ -214,6 +220,12 @@ int xhci_init(struct usb_hcd *hcd) | |||
214 | 220 | ||
215 | xhci_dbg(xhci, "xhci_init\n"); | 221 | xhci_dbg(xhci, "xhci_init\n"); |
216 | spin_lock_init(&xhci->lock); | 222 | spin_lock_init(&xhci->lock); |
223 | if (link_quirk) { | ||
224 | xhci_dbg(xhci, "QUIRK: Not clearing Link TRB chain bits.\n"); | ||
225 | xhci->quirks |= XHCI_LINK_TRB_QUIRK; | ||
226 | } else { | ||
227 | xhci_dbg(xhci, "xHCI has no QUIRKS\n"); | ||
228 | } | ||
217 | retval = xhci_mem_init(xhci, GFP_KERNEL); | 229 | retval = xhci_mem_init(xhci, GFP_KERNEL); |
218 | xhci_dbg(xhci, "Finished xhci_init\n"); | 230 | xhci_dbg(xhci, "Finished xhci_init\n"); |
219 | 231 | ||
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index e6b9a1c6002d..cb2033879ae3 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c | |||
@@ -94,6 +94,9 @@ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev, | |||
94 | val = prev->trbs[TRBS_PER_SEGMENT-1].link.control; | 94 | val = prev->trbs[TRBS_PER_SEGMENT-1].link.control; |
95 | val &= ~TRB_TYPE_BITMASK; | 95 | val &= ~TRB_TYPE_BITMASK; |
96 | val |= TRB_TYPE(TRB_LINK); | 96 | val |= TRB_TYPE(TRB_LINK); |
97 | /* Always set the chain bit with 0.95 hardware */ | ||
98 | if (xhci_link_trb_quirk(xhci)) | ||
99 | val |= TRB_CHAIN; | ||
97 | prev->trbs[TRBS_PER_SEGMENT-1].link.control = val; | 100 | prev->trbs[TRBS_PER_SEGMENT-1].link.control = val; |
98 | } | 101 | } |
99 | xhci_dbg(xhci, "Linking segment 0x%llx to segment 0x%llx (DMA)\n", | 102 | xhci_dbg(xhci, "Linking segment 0x%llx to segment 0x%llx (DMA)\n", |
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index aa88a067148b..011458f4d9ce 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -172,8 +172,9 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer | |||
172 | * have their chain bit cleared (so that each Link TRB is a separate TD). | 172 | * have their chain bit cleared (so that each Link TRB is a separate TD). |
173 | * | 173 | * |
174 | * Section 6.4.4.1 of the 0.95 spec says link TRBs cannot have the chain bit | 174 | * Section 6.4.4.1 of the 0.95 spec says link TRBs cannot have the chain bit |
175 | * set, but other sections talk about dealing with the chain bit set. | 175 | * set, but other sections talk about dealing with the chain bit set. This was |
176 | * Assume section 6.4.4.1 is wrong, and the chain bit can be set in a Link TRB. | 176 | * fixed in the 0.96 specification errata, but we have to assume that all 0.95 |
177 | * xHCI hardware can't handle the chain bit being cleared on a link TRB. | ||
177 | */ | 178 | */ |
178 | static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer) | 179 | static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer) |
179 | { | 180 | { |
@@ -191,8 +192,14 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer | |||
191 | while (last_trb(xhci, ring, ring->enq_seg, next)) { | 192 | while (last_trb(xhci, ring, ring->enq_seg, next)) { |
192 | if (!consumer) { | 193 | if (!consumer) { |
193 | if (ring != xhci->event_ring) { | 194 | if (ring != xhci->event_ring) { |
194 | next->link.control &= ~TRB_CHAIN; | 195 | /* If we're not dealing with 0.95 hardware, |
195 | next->link.control |= chain; | 196 | * carry over the chain bit of the previous TRB |
197 | * (which may mean the chain bit is cleared). | ||
198 | */ | ||
199 | if (!xhci_link_trb_quirk(xhci)) { | ||
200 | next->link.control &= ~TRB_CHAIN; | ||
201 | next->link.control |= chain; | ||
202 | } | ||
196 | /* Give this link TRB to the hardware */ | 203 | /* Give this link TRB to the hardware */ |
197 | wmb(); | 204 | wmb(); |
198 | if (next->link.control & TRB_CYCLE) | 205 | if (next->link.control & TRB_CYCLE) |
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 | ||
1141 | static 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 */ |
1140 | void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int set_num); | 1149 | void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int set_num); |
1141 | void xhci_print_registers(struct xhci_hcd *xhci); | 1150 | void xhci_print_registers(struct xhci_hcd *xhci); |