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(+) (limited to 'drivers') 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 v1.2.3 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(-) (limited to 'drivers') 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 v1.2.3 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(+) (limited to 'drivers') 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 v1.2.3 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(+) (limited to 'drivers') 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 v1.2.3 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(+) (limited to 'drivers') 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 v1.2.3 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(-) (limited to 'drivers') 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 v1.2.3 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(-) (limited to 'drivers') 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 v1.2.3 From 47fcae0d2a5fc77123fc14b0db9fe0025a1a829a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 18 Apr 2018 08:53:46 +0200 Subject: sh: introduce a sh_cacheop_vaddr helper And use it in the maple bus code to avoid a dma API dependency. Signed-off-by: Christoph Hellwig Acked-by: Yoshinori Sato --- drivers/sh/maple/maple.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c index 2e45988d1259..e5d7fb81ad66 100644 --- a/drivers/sh/maple/maple.c +++ b/drivers/sh/maple/maple.c @@ -300,8 +300,8 @@ static void maple_send(void) mutex_unlock(&maple_wlist_lock); if (maple_packets > 0) { for (i = 0; i < (1 << MAPLE_DMA_PAGES); i++) - sh_sync_dma_for_device(maple_sendbuf + i * PAGE_SIZE, - PAGE_SIZE, DMA_BIDIRECTIONAL); + __flush_purge_region(maple_sendbuf + i * PAGE_SIZE, + PAGE_SIZE); } finish: @@ -642,7 +642,8 @@ static void maple_dma_handler(struct work_struct *work) list_for_each_entry_safe(mq, nmq, &maple_sentq, list) { mdev = mq->dev; recvbuf = mq->recvbuf->buf; - sh_sync_dma_for_device(recvbuf, 0x400, DMA_FROM_DEVICE); + __flush_invalidate_region(sh_cacheop_vaddr(recvbuf), + 0x400); code = recvbuf[0]; kfree(mq->sendbuf); list_del_init(&mq->list); -- cgit v1.2.3