]>
Commit | Line | Data |
---|---|---|
cd033818 SL |
1 | From 5c183a635ac95585b9ac7c7ebae6ad961fb7eabd Mon Sep 17 00:00:00 2001 |
2 | From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> | |
3 | Date: Mon, 18 Mar 2019 18:39:30 +0300 | |
4 | Subject: dmaengine: idma64: Use actual device for DMA transfers | |
5 | ||
6 | [ Upstream commit 5ba846b1ee0792f5a596b9b0b86d6e8cdebfab06 ] | |
7 | ||
8 | Intel IOMMU, when enabled, tries to find the domain of the device, | |
9 | assuming it's a PCI one, during DMA operations, such as mapping or | |
10 | unmapping. Since we are splitting the actual PCI device to couple of | |
11 | children via MFD framework (see drivers/mfd/intel-lpss.c for details), | |
12 | the DMA device appears to be a platform one, and thus not an actual one | |
13 | that performs DMA. In a such situation IOMMU can't find or allocate | |
14 | a proper domain for its operations. As a result, all DMA operations are | |
15 | failed. | |
16 | ||
17 | In order to fix this, supply parent of the platform device | |
18 | to the DMA engine framework and fix filter functions accordingly. | |
19 | ||
20 | We may rely on the fact that parent is a real PCI device, because no | |
21 | other configuration is present in the wild. | |
22 | ||
23 | Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> | |
24 | Acked-by: Mark Brown <broonie@kernel.org> | |
25 | Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> [for tty parts] | |
26 | Signed-off-by: Vinod Koul <vkoul@kernel.org> | |
27 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
28 | --- | |
29 | drivers/dma/idma64.c | 6 ++++-- | |
30 | drivers/dma/idma64.h | 2 ++ | |
31 | drivers/spi/spi-pxa2xx.c | 7 +------ | |
32 | drivers/tty/serial/8250/8250_dw.c | 4 ++-- | |
33 | 4 files changed, 9 insertions(+), 10 deletions(-) | |
34 | ||
35 | diff --git a/drivers/dma/idma64.c b/drivers/dma/idma64.c | |
36 | index 7d56b47e4fcf..25e25b64bc89 100644 | |
37 | --- a/drivers/dma/idma64.c | |
38 | +++ b/drivers/dma/idma64.c | |
39 | @@ -594,7 +594,7 @@ static int idma64_probe(struct idma64_chip *chip) | |
40 | idma64->dma.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); | |
41 | idma64->dma.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; | |
42 | ||
43 | - idma64->dma.dev = chip->dev; | |
44 | + idma64->dma.dev = chip->sysdev; | |
45 | ||
46 | ret = dma_async_device_register(&idma64->dma); | |
47 | if (ret) | |
48 | @@ -632,6 +632,7 @@ static int idma64_platform_probe(struct platform_device *pdev) | |
49 | { | |
50 | struct idma64_chip *chip; | |
51 | struct device *dev = &pdev->dev; | |
52 | + struct device *sysdev = dev->parent; | |
53 | struct resource *mem; | |
54 | int ret; | |
55 | ||
56 | @@ -648,11 +649,12 @@ static int idma64_platform_probe(struct platform_device *pdev) | |
57 | if (IS_ERR(chip->regs)) | |
58 | return PTR_ERR(chip->regs); | |
59 | ||
60 | - ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); | |
61 | + ret = dma_coerce_mask_and_coherent(sysdev, DMA_BIT_MASK(64)); | |
62 | if (ret) | |
63 | return ret; | |
64 | ||
65 | chip->dev = dev; | |
66 | + chip->sysdev = sysdev; | |
67 | ||
68 | ret = idma64_probe(chip); | |
69 | if (ret) | |
70 | diff --git a/drivers/dma/idma64.h b/drivers/dma/idma64.h | |
71 | index f6aeff0af8a5..e40c69bd1fb5 100644 | |
72 | --- a/drivers/dma/idma64.h | |
73 | +++ b/drivers/dma/idma64.h | |
74 | @@ -215,12 +215,14 @@ static inline void idma64_writel(struct idma64 *idma64, int offset, u32 value) | |
75 | /** | |
76 | * struct idma64_chip - representation of iDMA 64-bit controller hardware | |
77 | * @dev: struct device of the DMA controller | |
78 | + * @sysdev: struct device of the physical device that does DMA | |
79 | * @irq: irq line | |
80 | * @regs: memory mapped I/O space | |
81 | * @idma64: struct idma64 that is filed by idma64_probe() | |
82 | */ | |
83 | struct idma64_chip { | |
84 | struct device *dev; | |
85 | + struct device *sysdev; | |
86 | int irq; | |
87 | void __iomem *regs; | |
88 | struct idma64 *idma64; | |
89 | diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c | |
90 | index e87b6fc9f4c6..193aa3da5033 100644 | |
91 | --- a/drivers/spi/spi-pxa2xx.c | |
92 | +++ b/drivers/spi/spi-pxa2xx.c | |
93 | @@ -1371,12 +1371,7 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = { | |
94 | ||
95 | static bool pxa2xx_spi_idma_filter(struct dma_chan *chan, void *param) | |
96 | { | |
97 | - struct device *dev = param; | |
98 | - | |
99 | - if (dev != chan->device->dev->parent) | |
100 | - return false; | |
101 | - | |
102 | - return true; | |
103 | + return param == chan->device->dev; | |
104 | } | |
105 | ||
106 | static struct pxa2xx_spi_master * | |
107 | diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c | |
108 | index a30d68c4b689..039837db65fc 100644 | |
109 | --- a/drivers/tty/serial/8250/8250_dw.c | |
110 | +++ b/drivers/tty/serial/8250/8250_dw.c | |
111 | @@ -258,7 +258,7 @@ static bool dw8250_fallback_dma_filter(struct dma_chan *chan, void *param) | |
112 | ||
113 | static bool dw8250_idma_filter(struct dma_chan *chan, void *param) | |
114 | { | |
115 | - return param == chan->device->dev->parent; | |
116 | + return param == chan->device->dev; | |
117 | } | |
118 | ||
119 | static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) | |
120 | @@ -290,7 +290,7 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) | |
121 | data->uart_16550_compatible = true; | |
122 | } | |
123 | ||
124 | - /* Platforms with iDMA */ | |
125 | + /* Platforms with iDMA 64-bit */ | |
126 | if (platform_get_resource_byname(to_platform_device(p->dev), | |
127 | IORESOURCE_MEM, "lpss_priv")) { | |
128 | p->set_termios = dw8250_set_termios; | |
129 | -- | |
130 | 2.20.1 | |
131 |