summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Robinson <pbrobinson@gmail.com>2018-10-03 19:20:42 +0100
committerPeter Robinson <pbrobinson@gmail.com>2018-10-03 19:20:42 +0100
commita3b5129661a050b3a09799986c80a730a9f85a3d (patch)
tree98b345d8a6ccffded03802dd0dd2aeaeb633a4bc
parentd115630b5280fce16946a2ce2c0f6f97b049b28a (diff)
downloadkernel-a3b5129661a050b3a09799986c80a730a9f85a3d.tar.gz
kernel-a3b5129661a050b3a09799986c80a730a9f85a3d.tar.xz
kernel-a3b5129661a050b3a09799986c80a730a9f85a3d.zip
Fixes for Ampere platforms
-rw-r--r--dma-stop-losing-firmware-set-dma-masks.patch434
-rw-r--r--kernel.spec9
2 files changed, 443 insertions, 0 deletions
diff --git a/dma-stop-losing-firmware-set-dma-masks.patch b/dma-stop-losing-firmware-set-dma-masks.patch
new file mode 100644
index 000000000..966434e7e
--- /dev/null
+++ b/dma-stop-losing-firmware-set-dma-masks.patch
@@ -0,0 +1,434 @@
+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
diff --git a/kernel.spec b/kernel.spec
index fc08a1514..16964ce86 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -626,6 +626,12 @@ Patch350: arm64-arch_timer-Workaround-for-Allwinner-A64-timer-instability.patch
Patch351: arm64-dts-allwinner-a64-Enable-A64-timer-workaround.patch
Patch352: arm64-allwinner-fixes.patch
+# Patch series is in 4.19, needed for Ampere eMAG platform
+# first patch fixes a bug in OF/DT seen on some devices with series
+# http://git.infradead.org/users/hch/dma-mapping.git/commitdiff/a5516219b10218a87abb3352c82248ce3088e94a
+# https://www.spinics.net/lists/linux-acpi/msg83312.html
+Patch360: dma-stop-losing-firmware-set-dma-masks.patch
+
# 400 - IBM (ppc/s390x) patches
# 500 - Temp fixes/CVEs etc
@@ -1936,6 +1942,9 @@ fi
#
#
%changelog
+* Wed Oct 3 2018 Peter Robinson <pbrobinson@fedoraproject.org>
+- Fixes for Ampere platforms
+
* Wed Oct 03 2018 Justin M. Forbes <jforbes@fedoraproject.org>
- Fix arm64 kvm priv escalation (rhbz 1635475 1635476)