From a3b5129661a050b3a09799986c80a730a9f85a3d Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Wed, 3 Oct 2018 19:20:42 +0100 Subject: Fixes for Ampere platforms --- dma-stop-losing-firmware-set-dma-masks.patch | 434 +++++++++++++++++++++++++++ kernel.spec | 9 + 2 files changed, 443 insertions(+) create mode 100644 dma-stop-losing-firmware-set-dma-masks.patch 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 +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 +Acked-by: Rob Herring +Signed-off-by: Christoph Hellwig +--- + 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 +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 +Signed-off-by: Robin Murphy +Acked-by: Ard Biesheuvel +Acked-by: Will Deacon +Acked-by: Lorenzo Pieralisi +Signed-off-by: Christoph Hellwig +--- + 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<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 +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 +Acked-by: Ard Biesheuvel +Signed-off-by: Christoph Hellwig +--- + 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 +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 +Acked-by: Ard Biesheuvel +Acked-by: Lorenzo Pieralisi +Signed-off-by: Christoph Hellwig +--- + 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 +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 +Acked-by: Ard Biesheuvel +Signed-off-by: Christoph Hellwig +--- + 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 +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 +Acked-by: Ard Biesheuvel +Acked-by: Joerg Roedel +Signed-off-by: Christoph Hellwig +--- + 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 +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 +Acked-by: Ard Biesheuvel +Acked-by: Lorenzo Pieralisi +Signed-off-by: Christoph Hellwig +--- + 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 +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 +Acked-by: Ard Biesheuvel +Signed-off-by: Christoph Hellwig +--- + 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 +- Fixes for Ampere platforms + * Wed Oct 03 2018 Justin M. Forbes - Fix arm64 kvm priv escalation (rhbz 1635475 1635476) -- cgit