summaryrefslogtreecommitdiffstats
path: root/freed-ora/tags/f27/4.15.9-300.fc27.gnu/bcm283x-dma-mapping-skip-USB-devices-when-configuring-DMA-during-probe.patch
blob: c6f7f12de93938ac5fc22695d95f41c43af29c51 (plain)
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
From patchwork Thu Aug  3 15:52:08 2017
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [v3] dma-mapping: skip USB devices when configuring DMA during probe
From: Johan Hovold <johan@kernel.org>
X-Patchwork-Id: 9879371
Message-Id: <20170803155208.22165-1-johan@kernel.org>
To: Christoph Hellwig <hch@lst.de>,
 Marek Szyprowski <m.szyprowski@samsung.com>,
 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: =?UTF-8?q?Andreas=20F=C3=A4rber?= <afaerber@suse.de>,
 linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
 Alan Stern <stern@rowland.harvard.edu>, Johan Hovold <johan@kernel.org>,
 stable <stable@vger.kernel.org>, Robin Murphy <robin.murphy@arm.com>,
 Sricharan R <sricharan@codeaurora.org>,
 Stefan Wahren <stefan.wahren@i2se.com>
Date: Thu,  3 Aug 2017 17:52:08 +0200

USB devices use the DMA mask and offset of the controller, which have
already been setup when a device is probed. Note that modifying the
DMA mask of a USB device would change the mask for the controller (and
all devices on the bus) as the mask is literally shared.

Since commit 2bf698671205 ("USB: of: fix root-hub device-tree node
handling"), of_dma_configure() would be called also for root hubs, which
use the device node of the controller. A separate, long-standing bug
that makes of_dma_configure() generate a 30-bit DMA mask from the RPI3's
"dma-ranges" would thus set a broken mask also for the controller. This
in turn prevents USB devices from enumerating when control transfers
fail:

	dwc2 3f980000.usb: Cannot do DMA to address 0x000000003a166a00

Note that the aforementioned DMA-mask bug was benign for the HCD itself
as the dwc2 driver overwrites the mask previously set by
of_dma_configure() for the platform device in its probe callback. The
mask would only later get corrupted when the root-hub child device was
probed.

Fix this, and similar future problems, by adding a flag to struct device
which prevents driver core from calling dma_configure() during probe and
making sure it is set for USB devices.

Fixes: 09515ef5ddad ("of/acpi: Configure dma operations at probe time for platform/amba/pci bus devices")
Cc: stable <stable@vger.kernel.org>	# 4.12
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Sricharan R <sricharan@codeaurora.org>
Cc: Stefan Wahren <stefan.wahren@i2se.com>
Reported-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Johan Hovold <johan@kernel.org>
---

v3
 - add flag to struct device to prevent DMA configuration during probe instead
   of checking for the USB bus type, which is not available when USB is built
   as a module as noted by Alan
 - drop moderated rpi list from CC

v2
 - amend commit message and point out that the long-standing 30-bit DMA-mask
   bug was benign to the dwc2 HCD itself (Robin)
 - add and use a new dev_is_usb() helper (Robin)


 drivers/base/dma-mapping.c | 6 ++++++
 drivers/usb/core/usb.c     | 1 +
 include/linux/device.h     | 3 +++
 3 files changed, 10 insertions(+)

diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
index b555ff9dd8fc..f9f703be0ad1 100644
--- a/drivers/base/dma-mapping.c
+++ b/drivers/base/dma-mapping.c
@@ -345,6 +345,9 @@ int dma_configure(struct device *dev)
 	enum dev_dma_attr attr;
 	int ret = 0;
 
+	if (dev->skip_dma_configure)
+		return 0;
+
 	if (dev_is_pci(dev)) {
 		bridge = pci_get_host_bridge_device(to_pci_dev(dev));
 		dma_dev = bridge;
@@ -369,6 +372,9 @@ int dma_configure(struct device *dev)
 
 void dma_deconfigure(struct device *dev)
 {
+	if (dev->skip_dma_configure)
+		return;
+
 	of_dma_deconfigure(dev);
 	acpi_dma_deconfigure(dev);
 }
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 17681d5638ac..2a85d905b539 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -588,6 +588,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
 	 * Note: calling dma_set_mask() on a USB device would set the
 	 * mask for the entire HCD, so don't do that.
 	 */
+	dev->dev.skip_dma_configure = true;
 	dev->dev.dma_mask = bus->sysdev->dma_mask;
 	dev->dev.dma_pfn_offset = bus->sysdev->dma_pfn_offset;
 	set_dev_node(&dev->dev, dev_to_node(bus->sysdev));
diff --git a/include/linux/device.h b/include/linux/device.h
index 723cd54b94da..022cf258068b 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -877,6 +877,8 @@ struct dev_links_info {
  * @offline:	Set after successful invocation of bus type's .offline().
  * @of_node_reused: Set if the device-tree node is shared with an ancestor
  *              device.
+ * @skip_dma_configure: Set if driver core should not configure DMA for this
+ *              device during probe.
  *
  * At the lowest level, every device in a Linux system is represented by an
  * instance of struct device. The device structure contains the information
@@ -965,6 +967,7 @@ struct device {
 	bool			offline_disabled:1;
 	bool			offline:1;
 	bool			of_node_reused:1;
+	bool			skip_dma_configure:1;
 };
 
 static inline struct device *kobj_to_dev(struct kobject *kobj)
OpenPOWER on IntegriCloud