435 lines
16 KiB
Diff
435 lines
16 KiB
Diff
From a5516219b10218a87abb3352c82248ce3088e94a Mon Sep 17 00:00:00 2001
|
|
From: Robin Murphy <robin.murphy@arm.com>
|
|
Date: Fri, 27 Jul 2018 15:14:15 +0100
|
|
Subject: of/platform: Initialise default DMA masks
|
|
|
|
When of_dma_configure() was first born in 591c1ee465ce ("of: configure
|
|
the platform device dma parameters"), everything DMA-related was
|
|
factored out of of_platform_device_create_pdata() as seemed appropriate
|
|
at the time. However, now that of_dma_configure() has grown into the
|
|
generic handler for processing DMA-related properties from DT for all
|
|
kinds of devices, it is no longer an appropriate place to be doing
|
|
OF-platform-specific business. Since there are still plenty of platform
|
|
drivers not setting their own masks and depending on the bus default,
|
|
let's reinstate that inialisation in the OF-platform code itself, and
|
|
restore the long-standing status quo from 0589342c2794 ("of: set
|
|
dma_mask to point to coherent_dma_mask")
|
|
|
|
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
|
|
Acked-by: Rob Herring <robh@kernel.org>
|
|
Signed-off-by: Christoph Hellwig <hch@lst.de>
|
|
---
|
|
drivers/of/platform.c | 3 +++
|
|
1 file changed, 3 insertions(+)
|
|
|
|
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
|
|
index 6925d993e1f0..7ba90c290a42 100644
|
|
--- a/drivers/of/platform.c
|
|
+++ b/drivers/of/platform.c
|
|
@@ -185,6 +185,9 @@ static struct platform_device *of_platform_device_create_pdata(
|
|
if (!dev)
|
|
goto err_clear_flag;
|
|
|
|
+ dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
|
|
+ if (!dev->dev.dma_mask)
|
|
+ dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
|
|
dev->dev.bus = &platform_bus_type;
|
|
dev->dev.platform_data = platform_data;
|
|
of_msi_configure(&dev->dev, dev->dev.of_node);
|
|
--
|
|
cgit 1.2-0.3.lf.el7
|
|
From 5ac65e8c89410892189ef778f567da4adafb2e2f Mon Sep 17 00:00:00 2001
|
|
From: Robin Murphy <robin.murphy@arm.com>
|
|
Date: Mon, 23 Jul 2018 23:16:06 +0100
|
|
Subject: ACPI/IORT: Support address size limit for root complexes
|
|
|
|
IORT revision D allows PCI root complex nodes to specify a memory
|
|
address size limit equivalently to named components, to help describe
|
|
straightforward integrations which don't really warrant a full-blown
|
|
_DMA method. Now that our headers are up-to-date, plumb it in.
|
|
|
|
If both _DMA and an address size limit are present, we would always
|
|
expect the former to be a more specific subset of the latter (since it
|
|
makes little sense for a _DMA range to involve bits which IORT says
|
|
aren't wired up), thus we can save calculating an explicit intersection
|
|
of the two effective masks and simply use short-circuit logic instead.
|
|
|
|
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
|
|
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
|
|
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
|
|
Acked-by: Will Deacon <will.deacon@arm.com>
|
|
Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
|
|
Signed-off-by: Christoph Hellwig <hch@lst.de>
|
|
---
|
|
drivers/acpi/arm64/iort.c | 25 +++++++++++++++++++++++--
|
|
1 file changed, 23 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
|
|
index 7a3a541046ed..4a66896e2aa3 100644
|
|
--- a/drivers/acpi/arm64/iort.c
|
|
+++ b/drivers/acpi/arm64/iort.c
|
|
@@ -947,6 +947,24 @@ static int nc_dma_get_range(struct device *dev, u64 *size)
|
|
return 0;
|
|
}
|
|
|
|
+static int rc_dma_get_range(struct device *dev, u64 *size)
|
|
+{
|
|
+ struct acpi_iort_node *node;
|
|
+ struct acpi_iort_root_complex *rc;
|
|
+
|
|
+ node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
|
|
+ iort_match_node_callback, dev);
|
|
+ if (!node || node->revision < 1)
|
|
+ return -ENODEV;
|
|
+
|
|
+ rc = (struct acpi_iort_root_complex *)node->node_data;
|
|
+
|
|
+ *size = rc->memory_address_limit >= 64 ? U64_MAX :
|
|
+ 1ULL<<rc->memory_address_limit;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/**
|
|
* iort_dma_setup() - Set-up device DMA parameters.
|
|
*
|
|
@@ -975,10 +993,13 @@ void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size)
|
|
|
|
size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
|
|
|
|
- if (dev_is_pci(dev))
|
|
+ if (dev_is_pci(dev)) {
|
|
ret = acpi_dma_get_range(dev, &dmaaddr, &offset, &size);
|
|
- else
|
|
+ if (ret == -ENODEV)
|
|
+ ret = rc_dma_get_range(dev, &size);
|
|
+ } else {
|
|
ret = nc_dma_get_range(dev, &size);
|
|
+ }
|
|
|
|
if (!ret) {
|
|
msb = fls64(dmaaddr + size - 1);
|
|
--
|
|
cgit 1.2-0.3.lf.el7
|
|
From f07d141fe9430cdf9f8a65a87c4136bd83b8ab2e Mon Sep 17 00:00:00 2001
|
|
From: Robin Murphy <robin.murphy@arm.com>
|
|
Date: Mon, 23 Jul 2018 23:16:07 +0100
|
|
Subject: dma-mapping: Generalise dma_32bit_limit flag
|
|
|
|
Whilst the notion of an upstream DMA restriction is most commonly seen
|
|
in PCI host bridges saddled with a 32-bit native interface, a more
|
|
general version of the same issue can exist on complex SoCs where a bus
|
|
or point-to-point interconnect link from a device's DMA master interface
|
|
to another component along the path to memory (often an IOMMU) may carry
|
|
fewer address bits than the interfaces at both ends nominally support.
|
|
In order to properly deal with this, the first step is to expand the
|
|
dma_32bit_limit flag into an arbitrary mask.
|
|
|
|
To minimise the impact on existing code, we'll make sure to only
|
|
consider this new mask valid if set. That makes sense anyway, since a
|
|
mask of zero would represent DMA not being wired up at all, and that
|
|
would be better handled by not providing valid ops in the first place.
|
|
|
|
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
|
|
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
|
|
Signed-off-by: Christoph Hellwig <hch@lst.de>
|
|
---
|
|
arch/x86/kernel/pci-dma.c | 2 +-
|
|
include/linux/device.h | 6 +++---
|
|
kernel/dma/direct.c | 6 +++---
|
|
3 files changed, 7 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
|
|
index ab5d9dd668d2..80f9fe8d27d0 100644
|
|
--- a/arch/x86/kernel/pci-dma.c
|
|
+++ b/arch/x86/kernel/pci-dma.c
|
|
@@ -175,7 +175,7 @@ rootfs_initcall(pci_iommu_init);
|
|
|
|
static int via_no_dac_cb(struct pci_dev *pdev, void *data)
|
|
{
|
|
- pdev->dev.dma_32bit_limit = true;
|
|
+ pdev->dev.bus_dma_mask = DMA_BIT_MASK(32);
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/include/linux/device.h b/include/linux/device.h
|
|
index 055a69dbcd18..6d3b000be57e 100644
|
|
--- a/include/linux/device.h
|
|
+++ b/include/linux/device.h
|
|
@@ -886,6 +886,8 @@ struct dev_links_info {
|
|
* @coherent_dma_mask: Like dma_mask, but for alloc_coherent mapping as not all
|
|
* hardware supports 64-bit addresses for consistent allocations
|
|
* such descriptors.
|
|
+ * @bus_dma_mask: Mask of an upstream bridge or bus which imposes a smaller DMA
|
|
+ * limit than the device itself supports.
|
|
* @dma_pfn_offset: offset of DMA memory range relatively of RAM
|
|
* @dma_parms: A low level driver may set these to teach IOMMU code about
|
|
* segment limitations.
|
|
@@ -912,8 +914,6 @@ 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.
|
|
- * @dma_32bit_limit: bridge limited to 32bit DMA even if the device itself
|
|
- * indicates support for a higher limit in the dma_mask field.
|
|
*
|
|
* At the lowest level, every device in a Linux system is represented by an
|
|
* instance of struct device. The device structure contains the information
|
|
@@ -967,6 +967,7 @@ struct device {
|
|
not all hardware supports
|
|
64 bit addresses for consistent
|
|
allocations such descriptors. */
|
|
+ u64 bus_dma_mask; /* upstream dma_mask constraint */
|
|
unsigned long dma_pfn_offset;
|
|
|
|
struct device_dma_parameters *dma_parms;
|
|
@@ -1002,7 +1003,6 @@ struct device {
|
|
bool offline_disabled:1;
|
|
bool offline:1;
|
|
bool of_node_reused:1;
|
|
- bool dma_32bit_limit:1;
|
|
};
|
|
|
|
static inline struct device *kobj_to_dev(struct kobject *kobj)
|
|
diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
|
|
index 8be8106270c2..c2860c5a9e96 100644
|
|
--- a/kernel/dma/direct.c
|
|
+++ b/kernel/dma/direct.c
|
|
@@ -180,10 +180,10 @@ int dma_direct_supported(struct device *dev, u64 mask)
|
|
return 0;
|
|
#endif
|
|
/*
|
|
- * Various PCI/PCIe bridges have broken support for > 32bit DMA even
|
|
- * if the device itself might support it.
|
|
+ * Upstream PCI/PCIe bridges or SoC interconnects may not carry
|
|
+ * as many DMA address bits as the device itself supports.
|
|
*/
|
|
- if (dev->dma_32bit_limit && mask > DMA_BIT_MASK(32))
|
|
+ if (dev->bus_dma_mask && mask > dev->bus_dma_mask)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
--
|
|
cgit 1.2-0.3.lf.el7
|
|
From d74ea7100b0d065f2008c4e1ddf637483bc3d28c Mon Sep 17 00:00:00 2001
|
|
From: Robin Murphy <robin.murphy@arm.com>
|
|
Date: Mon, 23 Jul 2018 23:16:08 +0100
|
|
Subject: ACPI/IORT: Set bus DMA mask as appropriate
|
|
|
|
When an explicit DMA limit is described by firmware, we need to remember
|
|
it regardless of how drivers might subsequently update their devices'
|
|
masks. The new bus_dma_mask field does that.
|
|
|
|
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
|
|
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
|
|
Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
|
|
Signed-off-by: Christoph Hellwig <hch@lst.de>
|
|
---
|
|
drivers/acpi/arm64/iort.c | 1 +
|
|
1 file changed, 1 insertion(+)
|
|
|
|
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
|
|
index 4a66896e2aa3..bc51cff5505e 100644
|
|
--- a/drivers/acpi/arm64/iort.c
|
|
+++ b/drivers/acpi/arm64/iort.c
|
|
@@ -1014,6 +1014,7 @@ void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size)
|
|
* Limit coherent and dma mask based on size
|
|
* retrieved from firmware.
|
|
*/
|
|
+ dev->bus_dma_mask = mask;
|
|
dev->coherent_dma_mask = mask;
|
|
*dev->dma_mask = mask;
|
|
}
|
|
--
|
|
cgit 1.2-0.3.lf.el7
|
|
From 6c2fb2ea76361da9b420a8e23a2a19e7842cbdda Mon Sep 17 00:00:00 2001
|
|
From: Robin Murphy <robin.murphy@arm.com>
|
|
Date: Mon, 23 Jul 2018 23:16:09 +0100
|
|
Subject: of/device: Set bus DMA mask as appropriate
|
|
|
|
When an explicit DMA limit is described by firmware, we need to remember
|
|
it regardless of how drivers might subsequently update their devices'
|
|
masks. The new bus_dma_mask field does that.
|
|
|
|
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
|
|
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
|
|
Signed-off-by: Christoph Hellwig <hch@lst.de>
|
|
---
|
|
drivers/of/device.c | 1 +
|
|
1 file changed, 1 insertion(+)
|
|
|
|
diff --git a/drivers/of/device.c b/drivers/of/device.c
|
|
index 33d85511d790..0d39633e8545 100644
|
|
--- a/drivers/of/device.c
|
|
+++ b/drivers/of/device.c
|
|
@@ -149,6 +149,7 @@ int of_dma_configure(struct device *dev, struct device_node *np, bool force_dma)
|
|
* set by the driver.
|
|
*/
|
|
mask = DMA_BIT_MASK(ilog2(dma_addr + size - 1) + 1);
|
|
+ dev->bus_dma_mask = mask;
|
|
dev->coherent_dma_mask &= mask;
|
|
*dev->dma_mask &= mask;
|
|
|
|
--
|
|
cgit 1.2-0.3.lf.el7
|
|
From 03bfdc31176cbe21e456f889ccbbf67568831149 Mon Sep 17 00:00:00 2001
|
|
From: Robin Murphy <robin.murphy@arm.com>
|
|
Date: Mon, 23 Jul 2018 23:16:10 +0100
|
|
Subject: iommu/dma: Respect bus DMA limit for IOVAs
|
|
|
|
Take the new bus limit into account (when present) for IOVA allocations,
|
|
to accommodate those SoCs which integrate off-the-shelf IP blocks with
|
|
narrower interconnects such that the link between a device output and an
|
|
IOMMU input can truncate DMA addresses to even fewer bits than the
|
|
native size of either block's interface would imply.
|
|
|
|
Eventually it might make sense for the DMA core to apply this constraint
|
|
up-front in dma_set_mask() and friends, but for now this seems like the
|
|
least risky approach.
|
|
|
|
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
|
|
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
|
|
Acked-by: Joerg Roedel <jroedel@suse.de>
|
|
Signed-off-by: Christoph Hellwig <hch@lst.de>
|
|
---
|
|
drivers/iommu/dma-iommu.c | 3 +++
|
|
1 file changed, 3 insertions(+)
|
|
|
|
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
|
|
index ddcbbdb5d658..511ff9a1d6d9 100644
|
|
--- a/drivers/iommu/dma-iommu.c
|
|
+++ b/drivers/iommu/dma-iommu.c
|
|
@@ -367,6 +367,9 @@ static dma_addr_t iommu_dma_alloc_iova(struct iommu_domain *domain,
|
|
if (iova_len < (1 << (IOVA_RANGE_CACHE_MAX_SIZE - 1)))
|
|
iova_len = roundup_pow_of_two(iova_len);
|
|
|
|
+ if (dev->bus_dma_mask)
|
|
+ dma_limit &= dev->bus_dma_mask;
|
|
+
|
|
if (domain->geometry.force_aperture)
|
|
dma_limit = min(dma_limit, domain->geometry.aperture_end);
|
|
|
|
--
|
|
cgit 1.2-0.3.lf.el7
|
|
From 6757cdae44449dec2af68cd4db0a5f9a30e66b38 Mon Sep 17 00:00:00 2001
|
|
From: Robin Murphy <robin.murphy@arm.com>
|
|
Date: Mon, 23 Jul 2018 23:16:11 +0100
|
|
Subject: ACPI/IORT: Don't set default coherent DMA mask
|
|
|
|
Now that we can track upstream DMA constraints properly with
|
|
bus_dma_mask instead of trying (and failing) to maintain it in
|
|
coherent_dma_mask, it doesn't make much sense for the firmware code to
|
|
be touching the latter at all. It's merely papering over bugs wherein a
|
|
driver has failed to call dma_set_coherent_mask() *and* the bus code has
|
|
not initialised any default value.
|
|
|
|
We don't really want to encourage more drivers coercing dma_mask so
|
|
we'll continue to fix that up if necessary, but add a warning to help
|
|
flush out any such buggy bus code that remains.
|
|
|
|
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
|
|
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
|
|
Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
|
|
Signed-off-by: Christoph Hellwig <hch@lst.de>
|
|
---
|
|
drivers/acpi/arm64/iort.c | 22 +++++++++++-----------
|
|
1 file changed, 11 insertions(+), 11 deletions(-)
|
|
|
|
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
|
|
index bc51cff5505e..08f26db2da7e 100644
|
|
--- a/drivers/acpi/arm64/iort.c
|
|
+++ b/drivers/acpi/arm64/iort.c
|
|
@@ -978,20 +978,20 @@ void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size)
|
|
int ret, msb;
|
|
|
|
/*
|
|
- * Set default coherent_dma_mask to 32 bit. Drivers are expected to
|
|
- * setup the correct supported mask.
|
|
+ * If @dev is expected to be DMA-capable then the bus code that created
|
|
+ * it should have initialised its dma_mask pointer by this point. For
|
|
+ * now, we'll continue the legacy behaviour of coercing it to the
|
|
+ * coherent mask if not, but we'll no longer do so quietly.
|
|
*/
|
|
- if (!dev->coherent_dma_mask)
|
|
- dev->coherent_dma_mask = DMA_BIT_MASK(32);
|
|
-
|
|
- /*
|
|
- * Set it to coherent_dma_mask by default if the architecture
|
|
- * code has not set it.
|
|
- */
|
|
- if (!dev->dma_mask)
|
|
+ if (!dev->dma_mask) {
|
|
+ dev_warn(dev, "DMA mask not set\n");
|
|
dev->dma_mask = &dev->coherent_dma_mask;
|
|
+ }
|
|
|
|
- size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
|
|
+ if (dev->coherent_dma_mask)
|
|
+ size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
|
|
+ else
|
|
+ size = 1ULL << 32;
|
|
|
|
if (dev_is_pci(dev)) {
|
|
ret = acpi_dma_get_range(dev, &dmaaddr, &offset, &size);
|
|
--
|
|
cgit 1.2-0.3.lf.el7
|
|
From 4d8bde883bfba3e8dd3335f91b640e5a70ec0aa6 Mon Sep 17 00:00:00 2001
|
|
From: Robin Murphy <robin.murphy@arm.com>
|
|
Date: Mon, 23 Jul 2018 23:16:12 +0100
|
|
Subject: OF: Don't set default coherent DMA mask
|
|
|
|
Now that we can track upstream DMA constraints properly with
|
|
bus_dma_mask instead of trying (and failing) to maintain it in
|
|
coherent_dma_mask, it doesn't make much sense for the firmware code to
|
|
be touching the latter at all. It's merely papering over bugs wherein a
|
|
driver has failed to call dma_set_coherent_mask() *and* the bus code has
|
|
not initialised any default value.
|
|
|
|
We don't really want to encourage more drivers coercing dma_mask so
|
|
we'll continue to fix that up if necessary, but add a warning to help
|
|
flush out any such buggy bus code that remains.
|
|
|
|
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
|
|
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
|
|
Signed-off-by: Christoph Hellwig <hch@lst.de>
|
|
---
|
|
drivers/of/device.c | 20 ++++++++++----------
|
|
1 file changed, 10 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/drivers/of/device.c b/drivers/of/device.c
|
|
index 0d39633e8545..5957cd4fa262 100644
|
|
--- a/drivers/of/device.c
|
|
+++ b/drivers/of/device.c
|
|
@@ -127,20 +127,20 @@ int of_dma_configure(struct device *dev, struct device_node *np, bool force_dma)
|
|
}
|
|
|
|
/*
|
|
- * Set default coherent_dma_mask to 32 bit. Drivers are expected to
|
|
- * setup the correct supported mask.
|
|
+ * If @dev is expected to be DMA-capable then the bus code that created
|
|
+ * it should have initialised its dma_mask pointer by this point. For
|
|
+ * now, we'll continue the legacy behaviour of coercing it to the
|
|
+ * coherent mask if not, but we'll no longer do so quietly.
|
|
*/
|
|
- if (!dev->coherent_dma_mask)
|
|
- dev->coherent_dma_mask = DMA_BIT_MASK(32);
|
|
- /*
|
|
- * Set it to coherent_dma_mask by default if the architecture
|
|
- * code has not set it.
|
|
- */
|
|
- if (!dev->dma_mask)
|
|
+ if (!dev->dma_mask) {
|
|
+ dev_warn(dev, "DMA mask not set\n");
|
|
dev->dma_mask = &dev->coherent_dma_mask;
|
|
+ }
|
|
|
|
- if (!size)
|
|
+ if (!size && dev->coherent_dma_mask)
|
|
size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
|
|
+ else if (!size)
|
|
+ size = 1ULL << 32;
|
|
|
|
dev->dma_pfn_offset = offset;
|
|
|
|
--
|
|
cgit 1.2-0.3.lf.el7
|