1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
From 7efb6dbd0d825899955fd4035504823bb5c1124c Mon Sep 17 00:00:00 2001
From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Date: Tue, 04 Mar 2014 22:28:16 +0000
Subject: Revert "xhci 1.0: Limit arbitrarily-aligned scatter gather."
This reverts commit 247bf557273dd775505fb9240d2d152f4f20d304, since it
causes USB 3.0 mass storage devices to fail on xHCI 1.0 hosts.
The block layer may submit scatter-gather lists with entries that
are multiples of 512-byte blocks. That's fine for USB 2.0 devices,
where the bulk endpoint max packet size is 512 bytes. But USB 3.0
devices have bulk endpoints with a 1024 byte max packet size.
That means when the block layer submits a scatter-gather list with one
entry that includes, say, three 512-byte blocks, this code will reject
the URB if it's submitted to a USB 3.0 bulk endpoint:
int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
{
...
max = usb_endpoint_maxp(&ep->desc);
...
} else if (urb->num_sgs && !urb->dev->bus->no_sg_constraint &&
dev->speed != USB_SPEED_WIRELESS) {
struct scatterlist *sg;
int i;
for_each_sg(urb->sg, sg, urb->num_sgs - 1, i)
if (sg->length % max)
return -EINVAL;
}
This results in failures with USB 3.0 drives. For me, a failure to
auto-mount the device. For others, a read or write SCSI command
failure.
This commit was put in place so that we could get scatter-gather support
for the ASIX USB ethernet adapter on non-1.0 hosts. It was a quick fix
until we implemented TD fragments properly in the driver. Since it
breaks USB 3.0 mass storage, we need to revert it, and revert
scatter-gather support for the ASIX devices.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Cc: stable@vger.kernel.org # 3.12
---
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 652be21..8fe4e12 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -4762,6 +4762,9 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
/* Accept arbitrarily long scatter-gather lists */
hcd->self.sg_tablesize = ~0;
+ /* support to build packet from discontinuous buffers */
+ hcd->self.no_sg_constraint = 1;
+
/* XHCI controllers don't stop the ep queue on short packets :| */
hcd->self.no_stop_on_short = 1;
@@ -4786,14 +4789,6 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
/* xHCI private pointer was set in xhci_pci_probe for the second
* registered roothub.
*/
- xhci = hcd_to_xhci(hcd);
- /*
- * Support arbitrarily aligned sg-list entries on hosts without
- * TD fragment rules (which are currently unsupported).
- */
- if (xhci->hci_version < 0x100)
- hcd->self.no_sg_constraint = 1;
-
return 0;
}
@@ -4822,9 +4817,6 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
if (xhci->hci_version > 0x96)
xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
- if (xhci->hci_version < 0x100)
- hcd->self.no_sg_constraint = 1;
-
/* Make sure the HC is halted. */
retval = xhci_halt(xhci);
if (retval)
--
cgit v0.9.2
|